1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.robolectric.android.internal; 18 19 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR2; 20 import static android.os.Build.VERSION_CODES.KITKAT; 21 import static android.os.Build.VERSION_CODES.LOLLIPOP; 22 import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1; 23 import static android.os.Build.VERSION_CODES.M; 24 import static android.os.Build.VERSION_CODES.N; 25 import static android.os.Build.VERSION_CODES.N_MR1; 26 import static android.os.Build.VERSION_CODES.O; 27 import static android.os.Build.VERSION_CODES.Q; 28 29 import android.view.Display; 30 import android.view.DisplayAddress; 31 import android.view.DisplayInfo; 32 import android.view.Surface; 33 import java.util.Arrays; 34 import java.util.Objects; 35 import org.robolectric.RuntimeEnvironment; 36 37 /** 38 * Describes the characteristics of a particular logical display. 39 * 40 * Robolectric internal (for now), do not use. 41 */ 42 public final class DisplayConfig { 43 /** 44 * The surface flinger layer stack associated with this logical display. 45 */ 46 public int layerStack; 47 48 /** 49 * Display flags. 50 */ 51 public int flags; 52 53 /** 54 * Display type. 55 */ 56 public int type; 57 58 /** 59 * Display address, or null if none. 60 * Interpretation varies by display type. 61 */ 62 public DisplayAddress address; 63 64 /** 65 * The human-readable name of the display. 66 */ 67 public String name; 68 69 /** 70 * Unique identifier for the display. Shouldn't be displayed to the user. 71 */ 72 public String uniqueId; 73 74 /** 75 * The width of the portion of the display that is available to applications, in pixels. 76 * Represents the size of the display minus any system decorations. 77 */ 78 public int appWidth; 79 80 /** 81 * The height of the portion of the display that is available to applications, in pixels. 82 * Represents the size of the display minus any system decorations. 83 */ 84 public int appHeight; 85 86 /** 87 * The smallest value of {@link #appWidth} that an application is likely to encounter, 88 * in pixels, excepting cases where the width may be even smaller due to the presence 89 * of a soft keyboard, for example. 90 */ 91 public int smallestNominalAppWidth; 92 93 /** 94 * The smallest value of {@link #appHeight} that an application is likely to encounter, 95 * in pixels, excepting cases where the height may be even smaller due to the presence 96 * of a soft keyboard, for example. 97 */ 98 public int smallestNominalAppHeight; 99 100 /** 101 * The largest value of {@link #appWidth} that an application is likely to encounter, 102 * in pixels, excepting cases where the width may be even larger due to system decorations 103 * such as the status bar being hidden, for example. 104 */ 105 public int largestNominalAppWidth; 106 107 /** 108 * The largest value of {@link #appHeight} that an application is likely to encounter, 109 * in pixels, excepting cases where the height may be even larger due to system decorations 110 * such as the status bar being hidden, for example. 111 */ 112 public int largestNominalAppHeight; 113 114 /** 115 * The logical width of the display, in pixels. 116 * Represents the usable size of the display which may be smaller than the 117 * physical size when the system is emulating a smaller display. 118 */ 119 public int logicalWidth; 120 121 /** 122 * The logical height of the display, in pixels. 123 * Represents the usable size of the display which may be smaller than the 124 * physical size when the system is emulating a smaller display. 125 */ 126 public int logicalHeight; 127 128 /** 129 * The rotation of the display relative to its natural orientation. 130 * May be one of {@link Surface#ROTATION_0}, 131 * {@link Surface#ROTATION_90}, {@link Surface#ROTATION_180}, 132 * {@link Surface#ROTATION_270}. 133 * <p> 134 * The value of this field is indeterminate if the logical display is presented on 135 * more than one physical display. 136 * </p> 137 */ 138 @Surface.Rotation 139 public int rotation; 140 141 /** 142 * The active display mode. 143 */ 144 public int modeId; 145 146 /** 147 * The default display mode. 148 */ 149 public int defaultModeId; 150 151 /** 152 * The supported modes of this display. 153 */ 154 public Display.Mode[] supportedModes = new Display.Mode[0]; 155 156 /** The active color mode. */ 157 public int colorMode; 158 159 /** The list of supported color modes */ 160 public int[] supportedColorModes = { Display.COLOR_MODE_DEFAULT }; 161 162 /** The display's HDR capabilities */ 163 public Display.HdrCapabilities hdrCapabilities; 164 165 /** 166 * The logical display density which is the basis for density-independent 167 * pixels. 168 */ 169 public int logicalDensityDpi; 170 171 /** 172 * The exact physical pixels per inch of the screen in the X dimension. 173 * <p> 174 * The value of this field is indeterminate if the logical display is presented on 175 * more than one physical display. 176 * </p> 177 */ 178 public float physicalXDpi; 179 180 /** 181 * The exact physical pixels per inch of the screen in the Y dimension. 182 * <p> 183 * The value of this field is indeterminate if the logical display is presented on 184 * more than one physical display. 185 * </p> 186 */ 187 public float physicalYDpi; 188 189 /** 190 * This is a positive value indicating the phase offset of the VSYNC events provided by 191 * Choreographer relative to the display refresh. For example, if Choreographer reports 192 * that the refresh occurred at time N, it actually occurred at (N - appVsyncOffsetNanos). 193 */ 194 public long appVsyncOffsetNanos; 195 196 /** 197 * This is how far in advance a buffer must be queued for presentation at 198 * a given time. If you want a buffer to appear on the screen at 199 * time N, you must submit the buffer before (N - bufferDeadlineNanos). 200 */ 201 public long presentationDeadlineNanos; 202 203 /** 204 * The state of the display, such as {@link Display#STATE_ON}. 205 */ 206 public int state; 207 208 /** 209 * The UID of the application that owns this display, or zero if it is owned by the system. 210 * <p> 211 * If the display is private, then only the owner can use it. 212 * </p> 213 */ 214 public int ownerUid; 215 216 /** 217 * The package name of the application that owns this display, or null if it is 218 * owned by the system. 219 * <p> 220 * If the display is private, then only the owner can use it. 221 * </p> 222 */ 223 public String ownerPackageName; 224 225 /** 226 * @hide 227 * Get current remove mode of the display - what actions should be performed with the display's 228 * content when it is removed. 229 * 230 * @see Display#getRemoveMode() 231 */ 232 public int removeMode = Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY; 233 DisplayConfig()234 public DisplayConfig() { 235 } 236 DisplayConfig(DisplayConfig other)237 public DisplayConfig(DisplayConfig other) { 238 copyFrom(other); 239 } 240 DisplayConfig(DisplayInfo other)241 public DisplayConfig(DisplayInfo other) { 242 layerStack = other.layerStack; 243 flags = other.flags; 244 type = other.type; 245 if (RuntimeEnvironment.getApiLevel() >= Q) { 246 address = other.address; 247 } 248 name = other.name; 249 if (RuntimeEnvironment.getApiLevel() >= LOLLIPOP_MR1) { 250 uniqueId = other.uniqueId; 251 } 252 appWidth = other.appWidth; 253 appHeight = other.appHeight; 254 smallestNominalAppWidth = other.smallestNominalAppWidth; 255 smallestNominalAppHeight = other.smallestNominalAppHeight; 256 largestNominalAppWidth = other.largestNominalAppWidth; 257 largestNominalAppHeight = other.largestNominalAppHeight; 258 logicalWidth = other.logicalWidth; 259 logicalHeight = other.logicalHeight; 260 rotation = other.rotation; 261 if (RuntimeEnvironment.getApiLevel() >= M) { 262 modeId = other.modeId; 263 defaultModeId = other.defaultModeId; 264 supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length); 265 } 266 if (RuntimeEnvironment.getApiLevel() >= N_MR1) { 267 colorMode = other.colorMode; 268 supportedColorModes = Arrays.copyOf( 269 other.supportedColorModes, other.supportedColorModes.length); 270 } 271 if (RuntimeEnvironment.getApiLevel() >= N) { 272 hdrCapabilities = other.hdrCapabilities; 273 } 274 logicalDensityDpi = other.logicalDensityDpi; 275 physicalXDpi = other.physicalXDpi; 276 physicalYDpi = other.physicalYDpi; 277 if (RuntimeEnvironment.getApiLevel() >= LOLLIPOP) { 278 appVsyncOffsetNanos = other.appVsyncOffsetNanos; 279 presentationDeadlineNanos = other.presentationDeadlineNanos; 280 state = other.state; 281 } 282 if (RuntimeEnvironment.getApiLevel() >= KITKAT) { 283 ownerUid = other.ownerUid; 284 ownerPackageName = other.ownerPackageName; 285 } 286 if (RuntimeEnvironment.getApiLevel() >= O) { 287 removeMode = other.removeMode; 288 } 289 } 290 291 @Override equals(Object o)292 public boolean equals(Object o) { 293 return o instanceof DisplayConfig && equals((DisplayConfig)o); 294 } 295 296 @SuppressWarnings("NonOverridingEquals") equals(DisplayConfig other)297 public boolean equals(DisplayConfig other) { 298 return other != null 299 && layerStack == other.layerStack 300 && flags == other.flags 301 && type == other.type 302 && Objects.equals(address, other.address) 303 && Objects.equals(uniqueId, other.uniqueId) 304 && appWidth == other.appWidth 305 && appHeight == other.appHeight 306 && smallestNominalAppWidth == other.smallestNominalAppWidth 307 && smallestNominalAppHeight == other.smallestNominalAppHeight 308 && largestNominalAppWidth == other.largestNominalAppWidth 309 && largestNominalAppHeight == other.largestNominalAppHeight 310 && logicalWidth == other.logicalWidth 311 && logicalHeight == other.logicalHeight 312 && rotation == other.rotation 313 && modeId == other.modeId 314 && defaultModeId == other.defaultModeId 315 && colorMode == other.colorMode 316 && Arrays.equals(supportedColorModes, other.supportedColorModes) 317 && Objects.equals(hdrCapabilities, other.hdrCapabilities) 318 && logicalDensityDpi == other.logicalDensityDpi 319 && physicalXDpi == other.physicalXDpi 320 && physicalYDpi == other.physicalYDpi 321 && appVsyncOffsetNanos == other.appVsyncOffsetNanos 322 && presentationDeadlineNanos == other.presentationDeadlineNanos 323 && state == other.state 324 && ownerUid == other.ownerUid 325 && Objects.equals(ownerPackageName, other.ownerPackageName) 326 && removeMode == other.removeMode; 327 } 328 329 @Override hashCode()330 public int hashCode() { 331 return 0; // don't care 332 } 333 copyFrom(DisplayConfig other)334 public void copyFrom(DisplayConfig other) { 335 layerStack = other.layerStack; 336 flags = other.flags; 337 type = other.type; 338 address = other.address; 339 name = other.name; 340 uniqueId = other.uniqueId; 341 appWidth = other.appWidth; 342 appHeight = other.appHeight; 343 smallestNominalAppWidth = other.smallestNominalAppWidth; 344 smallestNominalAppHeight = other.smallestNominalAppHeight; 345 largestNominalAppWidth = other.largestNominalAppWidth; 346 largestNominalAppHeight = other.largestNominalAppHeight; 347 logicalWidth = other.logicalWidth; 348 logicalHeight = other.logicalHeight; 349 rotation = other.rotation; 350 modeId = other.modeId; 351 defaultModeId = other.defaultModeId; 352 supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length); 353 colorMode = other.colorMode; 354 supportedColorModes = Arrays.copyOf( 355 other.supportedColorModes, other.supportedColorModes.length); 356 hdrCapabilities = other.hdrCapabilities; 357 logicalDensityDpi = other.logicalDensityDpi; 358 physicalXDpi = other.physicalXDpi; 359 physicalYDpi = other.physicalYDpi; 360 appVsyncOffsetNanos = other.appVsyncOffsetNanos; 361 presentationDeadlineNanos = other.presentationDeadlineNanos; 362 state = other.state; 363 ownerUid = other.ownerUid; 364 ownerPackageName = other.ownerPackageName; 365 removeMode = other.removeMode; 366 } 367 copyTo(DisplayInfo other)368 public void copyTo(DisplayInfo other) { 369 other.layerStack = layerStack; 370 other.flags = flags; 371 other.type = type; 372 if (RuntimeEnvironment.getApiLevel() >= Q) { 373 other.address = address; 374 } 375 other.name = name; 376 if (RuntimeEnvironment.getApiLevel() >= LOLLIPOP_MR1) { 377 other.uniqueId = uniqueId; 378 } 379 other.appWidth = appWidth; 380 other.appHeight = appHeight; 381 other.smallestNominalAppWidth = smallestNominalAppWidth; 382 other.smallestNominalAppHeight = smallestNominalAppHeight; 383 other.largestNominalAppWidth = largestNominalAppWidth; 384 other.largestNominalAppHeight = largestNominalAppHeight; 385 other.logicalWidth = logicalWidth; 386 other.logicalHeight = logicalHeight; 387 other.rotation = rotation; 388 if (RuntimeEnvironment.getApiLevel() >= M) { 389 other.modeId = modeId; 390 other.defaultModeId = defaultModeId; 391 other.supportedModes = Arrays.copyOf(supportedModes, supportedModes.length); 392 } 393 if (RuntimeEnvironment.getApiLevel() >= N_MR1) { 394 other.colorMode = colorMode; 395 other.supportedColorModes = Arrays.copyOf( 396 supportedColorModes, supportedColorModes.length); 397 } 398 if (RuntimeEnvironment.getApiLevel() >= N) { 399 other.hdrCapabilities = hdrCapabilities; 400 } 401 other.logicalDensityDpi = logicalDensityDpi; 402 other.physicalXDpi = physicalXDpi; 403 other.physicalYDpi = physicalYDpi; 404 if (RuntimeEnvironment.getApiLevel() >= LOLLIPOP) { 405 other.appVsyncOffsetNanos = appVsyncOffsetNanos; 406 other.presentationDeadlineNanos = presentationDeadlineNanos; 407 other.state = state; 408 } 409 if (RuntimeEnvironment.getApiLevel() >= KITKAT) { 410 other.ownerUid = ownerUid; 411 other.ownerPackageName = ownerPackageName; 412 } 413 if (RuntimeEnvironment.getApiLevel() >= O) { 414 other.removeMode = removeMode; 415 } 416 } 417 418 // For debugging purposes 419 @Override toString()420 public String toString() { 421 StringBuilder sb = new StringBuilder(); 422 sb.append("DisplayConfig{\""); 423 sb.append(name); 424 sb.append("\", uniqueId \""); 425 sb.append(uniqueId); 426 sb.append("\", app "); 427 sb.append(appWidth); 428 sb.append(" x "); 429 sb.append(appHeight); 430 sb.append(", real "); 431 sb.append(logicalWidth); 432 sb.append(" x "); 433 sb.append(logicalHeight); 434 sb.append(", largest app "); 435 sb.append(largestNominalAppWidth); 436 sb.append(" x "); 437 sb.append(largestNominalAppHeight); 438 sb.append(", smallest app "); 439 sb.append(smallestNominalAppWidth); 440 sb.append(" x "); 441 sb.append(smallestNominalAppHeight); 442 sb.append(", mode "); 443 sb.append(modeId); 444 sb.append(", defaultMode "); 445 sb.append(defaultModeId); 446 sb.append(", modes "); 447 sb.append(Arrays.toString(supportedModes)); 448 sb.append(", colorMode "); 449 sb.append(colorMode); 450 sb.append(", supportedColorModes "); 451 sb.append(Arrays.toString(supportedColorModes)); 452 sb.append(", hdrCapabilities "); 453 sb.append(hdrCapabilities); 454 sb.append(", rotation "); 455 sb.append(rotation); 456 sb.append(", density "); 457 sb.append(logicalDensityDpi); 458 sb.append(" ("); 459 sb.append(physicalXDpi); 460 sb.append(" x "); 461 sb.append(physicalYDpi); 462 sb.append(") dpi, layerStack "); 463 sb.append(layerStack); 464 sb.append(", appVsyncOff "); 465 sb.append(appVsyncOffsetNanos); 466 sb.append(", presDeadline "); 467 sb.append(presentationDeadlineNanos); 468 sb.append(", type "); 469 sb.append(Display.typeToString(type)); 470 if (address != null) { 471 sb.append(", address ").append(address); 472 } 473 sb.append(", state "); 474 sb.append(Display.stateToString(state)); 475 if (ownerUid != 0 || ownerPackageName != null) { 476 sb.append(", owner ").append(ownerPackageName); 477 sb.append(" (uid ").append(ownerUid).append(")"); 478 } 479 sb.append(flagsToString(flags)); 480 sb.append(", removeMode "); 481 sb.append(removeMode); 482 sb.append("}"); 483 return sb.toString(); 484 } 485 flagsToString(int flags)486 private static String flagsToString(int flags) { 487 StringBuilder result = new StringBuilder(); 488 if ((flags & Display.FLAG_SECURE) != 0) { 489 result.append(", FLAG_SECURE"); 490 } 491 if ((flags & Display.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) { 492 result.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS"); 493 } 494 if ((flags & Display.FLAG_PRIVATE) != 0) { 495 result.append(", FLAG_PRIVATE"); 496 } 497 if ((flags & Display.FLAG_PRESENTATION) != 0) { 498 result.append(", FLAG_PRESENTATION"); 499 } 500 if ((flags & Display.FLAG_SCALING_DISABLED) != 0) { 501 result.append(", FLAG_SCALING_DISABLED"); 502 } 503 if ((flags & Display.FLAG_ROUND) != 0) { 504 result.append(", FLAG_ROUND"); 505 } 506 return result.toString(); 507 } 508 } 509