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 com.android.server.display; 18 19 import android.hardware.display.DeviceProductInfo; 20 import android.hardware.display.DisplayViewport; 21 import android.util.DisplayMetrics; 22 import android.view.Display; 23 import android.view.DisplayAddress; 24 import android.view.DisplayCutout; 25 import android.view.DisplayEventReceiver; 26 import android.view.RoundedCorners; 27 import android.view.Surface; 28 29 import com.android.internal.display.BrightnessSynchronizer; 30 31 import java.util.Arrays; 32 import java.util.Objects; 33 34 /** 35 * Describes the characteristics of a physical display device. 36 */ 37 final class DisplayDeviceInfo { 38 /** 39 * Flag: Indicates that this display device should be considered the default display 40 * device of the system. 41 */ 42 public static final int FLAG_DEFAULT_DISPLAY = 1 << 0; 43 44 /** 45 * Flag: Indicates that the orientation of this display device is coupled to the 46 * rotation of its associated logical display. 47 * <p> 48 * This flag should be applied to the default display to indicate that the user 49 * physically rotates the display when content is presented in a different orientation. 50 * The display manager will apply a coordinate transformation assuming that the 51 * physical orientation of the display matches the logical orientation of its content. 52 * </p><p> 53 * The flag should not be set when the display device is mounted in a fixed orientation 54 * such as on a desk. The display manager will apply a coordinate transformation 55 * such as a scale and translation to letterbox or pillarbox format under the 56 * assumption that the physical orientation of the display is invariant. 57 * </p> 58 */ 59 public static final int FLAG_ROTATES_WITH_CONTENT = 1 << 1; 60 61 /** 62 * Flag: Indicates that this display device has secure video output, such as HDCP. 63 */ 64 public static final int FLAG_SECURE = 1 << 2; 65 66 /** 67 * Flag: Indicates that this display device supports compositing 68 * from gralloc protected buffers. 69 */ 70 public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1 << 3; 71 72 /** 73 * Flag: Indicates that the display device is owned by a particular application 74 * and that no other application should be able to interact with it. 75 * Should typically be used together with {@link #FLAG_OWN_CONTENT_ONLY}. 76 */ 77 public static final int FLAG_PRIVATE = 1 << 4; 78 79 /** 80 * Flag: Indicates that the display device is not blanked automatically by 81 * the power manager. 82 */ 83 public static final int FLAG_NEVER_BLANK = 1 << 5; 84 85 /** 86 * Flag: Indicates that the display is suitable for presentations. 87 */ 88 public static final int FLAG_PRESENTATION = 1 << 6; 89 90 /** 91 * Flag: Only show this display's own content; do not mirror 92 * the content of another display. 93 */ 94 public static final int FLAG_OWN_CONTENT_ONLY = 1 << 7; 95 96 /** 97 * Flag: This display device has a round shape. 98 */ 99 public static final int FLAG_ROUND = 1 << 8; 100 101 /** 102 * Flag: This display can show its content when non-secure keyguard is shown. 103 */ 104 // TODO (b/114338689): Remove the flag and use IWindowManager#shouldShowWithInsecureKeyguard 105 public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 9; 106 107 /** 108 * Flag: This display will destroy its content on removal. 109 * @hide 110 */ 111 // TODO (b/114338689): Remove the flag and use WindowManager#REMOVE_CONTENT_MODE_DESTROY 112 public static final int FLAG_DESTROY_CONTENT_ON_REMOVAL = 1 << 10; 113 114 /** 115 * Flag: The display cutout of this display is masked. 116 * @hide 117 */ 118 public static final int FLAG_MASK_DISPLAY_CUTOUT = 1 << 11; 119 120 /** 121 * Flag: This flag identifies secondary displays that should show system decorations, such as 122 * status bar, navigation bar, home activity or IME. 123 * <p>Note that this flag doesn't work without {@link #FLAG_TRUSTED}</p> 124 * @hide 125 */ 126 // TODO (b/114338689): Remove the flag and use IWindowManager#setShouldShowSystemDecors 127 public static final int FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 12; 128 129 /** 130 * Flag: The display is trusted to show system decorations and receive inputs without users' 131 * touch. 132 * @see #FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS 133 */ 134 public static final int FLAG_TRUSTED = 1 << 13; 135 136 /** 137 * Flag: Indicates that the display should not be a part of the default {@link DisplayGroup} and 138 * instead be part of a new {@link DisplayGroup}. 139 * 140 * @hide 141 */ 142 public static final int FLAG_OWN_DISPLAY_GROUP = 1 << 14; 143 144 /** 145 * Touch attachment: Display does not receive touch. 146 */ 147 public static final int TOUCH_NONE = 0; 148 149 /** 150 * Touch attachment: Touch input is via the internal interface. 151 */ 152 public static final int TOUCH_INTERNAL = 1; 153 154 /** 155 * Touch attachment: Touch input is via an external interface, such as USB. 156 */ 157 public static final int TOUCH_EXTERNAL = 2; 158 159 /** 160 * Touch attachment: Touch input is via an input device matching {@link VirtualDisplay}'s 161 * uniqueId. 162 * @hide 163 */ 164 public static final int TOUCH_VIRTUAL = 3; 165 166 /** 167 * Diff result: The {@link #state} fields differ. 168 */ 169 public static final int DIFF_STATE = 1 << 0; 170 171 /** 172 * Diff result: Other fields differ. 173 */ 174 public static final int DIFF_OTHER = 1 << 1; 175 176 /** 177 * Diff result: The color mode fields differ. 178 */ 179 public static final int DIFF_COLOR_MODE = 1 << 2; 180 181 /** 182 * Gets the name of the display device, which may be derived from EDID or 183 * other sources. The name may be localized and displayed to the user. 184 */ 185 public String name; 186 187 /** 188 * Unique Id of display device. 189 */ 190 public String uniqueId; 191 192 /** 193 * The width of the display in its natural orientation, in pixels. 194 * This value is not affected by display rotation. 195 */ 196 public int width; 197 198 /** 199 * The height of the display in its natural orientation, in pixels. 200 * This value is not affected by display rotation. 201 */ 202 public int height; 203 204 /** 205 * The active mode of the display. 206 */ 207 public int modeId; 208 209 /** 210 * The default mode of the display. 211 */ 212 public int defaultModeId; 213 214 /** 215 * The supported modes of the display. 216 */ 217 public Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY; 218 219 /** The active color mode of the display */ 220 public int colorMode; 221 222 /** The supported color modes of the display */ 223 public int[] supportedColorModes = { Display.COLOR_MODE_DEFAULT }; 224 225 /** 226 * The HDR capabilities this display claims to support. 227 */ 228 public Display.HdrCapabilities hdrCapabilities; 229 230 /** 231 * Indicates whether this display supports Auto Low Latency Mode. 232 */ 233 public boolean allmSupported; 234 235 /** 236 * Indicates whether this display suppors Game content type. 237 */ 238 public boolean gameContentTypeSupported; 239 240 /** 241 * The nominal apparent density of the display in DPI used for layout calculations. 242 * This density is sensitive to the viewing distance. A big TV and a tablet may have 243 * the same apparent density even though the pixels on the TV are much bigger than 244 * those on the tablet. 245 */ 246 public int densityDpi; 247 248 /** 249 * The physical density of the display in DPI in the X direction. 250 * This density should specify the physical size of each pixel. 251 */ 252 public float xDpi; 253 254 /** 255 * The physical density of the display in DPI in the X direction. 256 * This density should specify the physical size of each pixel. 257 */ 258 public float yDpi; 259 260 /** 261 * This is a positive value indicating the phase offset of the VSYNC events provided by 262 * Choreographer relative to the display refresh. For example, if Choreographer reports 263 * that the refresh occurred at time N, it actually occurred at (N - appVsyncOffsetNanos). 264 */ 265 public long appVsyncOffsetNanos; 266 267 /** 268 * This is how far in advance a buffer must be queued for presentation at 269 * a given time. If you want a buffer to appear on the screen at 270 * time N, you must submit the buffer before (N - bufferDeadlineNanos). 271 */ 272 public long presentationDeadlineNanos; 273 274 /** 275 * Display flags. 276 */ 277 public int flags; 278 279 /** 280 * The {@link DisplayCutout} if present or {@code null} otherwise. 281 */ 282 public DisplayCutout displayCutout; 283 284 /** 285 * The {@link RoundedCorners} if present or {@code null} otherwise. 286 */ 287 public RoundedCorners roundedCorners; 288 289 /** 290 * The touch attachment, per {@link DisplayViewport#touch}. 291 */ 292 public int touch; 293 294 /** 295 * The additional rotation to apply to all content presented on the display device 296 * relative to its physical coordinate system. Default is {@link Surface#ROTATION_0}. 297 * <p> 298 * This field can be used to compensate for the fact that the display has been 299 * physically rotated relative to its natural orientation such as an HDMI monitor 300 * that has been mounted sideways to appear to be portrait rather than landscape. 301 * </p> 302 */ 303 public int rotation = Surface.ROTATION_0; 304 305 /** 306 * Display type. 307 */ 308 public int type; 309 310 /** 311 * Display address, or null if none. 312 * Interpretation varies by display type. 313 */ 314 public DisplayAddress address; 315 316 /** 317 * Product-specific information about the display or the directly connected device on the 318 * display chain. For example, if the display is transitively connected, this field may contain 319 * product information about the intermediate device. 320 */ 321 public DeviceProductInfo deviceProductInfo; 322 323 /** 324 * Display state. 325 */ 326 public int state = Display.STATE_ON; 327 328 /** 329 * The UID of the application that owns this display, or zero if it is owned by the system. 330 * <p> 331 * If the display is private, then only the owner can use it. 332 * </p> 333 */ 334 public int ownerUid; 335 336 /** 337 * The package name of the application that owns this display, or null if it is 338 * owned by the system. 339 * <p> 340 * If the display is private, then only the owner can use it. 341 * </p> 342 */ 343 public String ownerPackageName; 344 345 public DisplayEventReceiver.FrameRateOverride[] frameRateOverrides = 346 new DisplayEventReceiver.FrameRateOverride[0]; 347 348 public float brightnessMinimum; 349 public float brightnessMaximum; 350 public float brightnessDefault; 351 setAssumedDensityForExternalDisplay(int width, int height)352 public void setAssumedDensityForExternalDisplay(int width, int height) { 353 densityDpi = Math.min(width, height) * DisplayMetrics.DENSITY_XHIGH / 1080; 354 // Technically, these values should be smaller than the apparent density 355 // but we don't know the physical size of the display. 356 xDpi = densityDpi; 357 yDpi = densityDpi; 358 } 359 360 @Override equals(Object o)361 public boolean equals(Object o) { 362 return o instanceof DisplayDeviceInfo && equals((DisplayDeviceInfo)o); 363 } 364 equals(DisplayDeviceInfo other)365 public boolean equals(DisplayDeviceInfo other) { 366 return other != null && diff(other) == 0; 367 } 368 369 /** 370 * Computes the difference between display device infos. 371 * Assumes other is not null. 372 */ diff(DisplayDeviceInfo other)373 public int diff(DisplayDeviceInfo other) { 374 int diff = 0; 375 if (state != other.state) { 376 diff |= DIFF_STATE; 377 } 378 if (colorMode != other.colorMode) { 379 diff |= DIFF_COLOR_MODE; 380 } 381 if (!Objects.equals(name, other.name) 382 || !Objects.equals(uniqueId, other.uniqueId) 383 || width != other.width 384 || height != other.height 385 || modeId != other.modeId 386 || defaultModeId != other.defaultModeId 387 || !Arrays.equals(supportedModes, other.supportedModes) 388 || !Arrays.equals(supportedColorModes, other.supportedColorModes) 389 || !Objects.equals(hdrCapabilities, other.hdrCapabilities) 390 || allmSupported != other.allmSupported 391 || gameContentTypeSupported != other.gameContentTypeSupported 392 || densityDpi != other.densityDpi 393 || xDpi != other.xDpi 394 || yDpi != other.yDpi 395 || appVsyncOffsetNanos != other.appVsyncOffsetNanos 396 || presentationDeadlineNanos != other.presentationDeadlineNanos 397 || flags != other.flags 398 || !Objects.equals(displayCutout, other.displayCutout) 399 || touch != other.touch 400 || rotation != other.rotation 401 || type != other.type 402 || !Objects.equals(address, other.address) 403 || !Objects.equals(deviceProductInfo, other.deviceProductInfo) 404 || ownerUid != other.ownerUid 405 || !Objects.equals(ownerPackageName, other.ownerPackageName) 406 || !Objects.equals(frameRateOverrides, other.frameRateOverrides) 407 || !BrightnessSynchronizer.floatEquals(brightnessMinimum, other.brightnessMinimum) 408 || !BrightnessSynchronizer.floatEquals(brightnessMaximum, other.brightnessMaximum) 409 || !BrightnessSynchronizer.floatEquals(brightnessDefault, 410 other.brightnessDefault) 411 || !Objects.equals(roundedCorners, other.roundedCorners)) { 412 diff |= DIFF_OTHER; 413 } 414 return diff; 415 } 416 417 @Override hashCode()418 public int hashCode() { 419 return 0; // don't care 420 } 421 copyFrom(DisplayDeviceInfo other)422 public void copyFrom(DisplayDeviceInfo other) { 423 name = other.name; 424 uniqueId = other.uniqueId; 425 width = other.width; 426 height = other.height; 427 modeId = other.modeId; 428 defaultModeId = other.defaultModeId; 429 supportedModes = other.supportedModes; 430 colorMode = other.colorMode; 431 supportedColorModes = other.supportedColorModes; 432 hdrCapabilities = other.hdrCapabilities; 433 allmSupported = other.allmSupported; 434 gameContentTypeSupported = other.gameContentTypeSupported; 435 densityDpi = other.densityDpi; 436 xDpi = other.xDpi; 437 yDpi = other.yDpi; 438 appVsyncOffsetNanos = other.appVsyncOffsetNanos; 439 presentationDeadlineNanos = other.presentationDeadlineNanos; 440 flags = other.flags; 441 displayCutout = other.displayCutout; 442 touch = other.touch; 443 rotation = other.rotation; 444 type = other.type; 445 address = other.address; 446 deviceProductInfo = other.deviceProductInfo; 447 state = other.state; 448 ownerUid = other.ownerUid; 449 ownerPackageName = other.ownerPackageName; 450 frameRateOverrides = other.frameRateOverrides; 451 brightnessMinimum = other.brightnessMinimum; 452 brightnessMaximum = other.brightnessMaximum; 453 brightnessDefault = other.brightnessDefault; 454 roundedCorners = other.roundedCorners; 455 } 456 457 // For debugging purposes 458 @Override toString()459 public String toString() { 460 StringBuilder sb = new StringBuilder(); 461 sb.append("DisplayDeviceInfo{\""); 462 sb.append(name).append("\": uniqueId=\"").append(uniqueId).append("\", "); 463 sb.append(width).append(" x ").append(height); 464 sb.append(", modeId ").append(modeId); 465 sb.append(", defaultModeId ").append(defaultModeId); 466 sb.append(", supportedModes ").append(Arrays.toString(supportedModes)); 467 sb.append(", colorMode ").append(colorMode); 468 sb.append(", supportedColorModes ").append(Arrays.toString(supportedColorModes)); 469 sb.append(", hdrCapabilities ").append(hdrCapabilities); 470 sb.append(", allmSupported ").append(allmSupported); 471 sb.append(", gameContentTypeSupported ").append(gameContentTypeSupported); 472 sb.append(", density ").append(densityDpi); 473 sb.append(", ").append(xDpi).append(" x ").append(yDpi).append(" dpi"); 474 sb.append(", appVsyncOff ").append(appVsyncOffsetNanos); 475 sb.append(", presDeadline ").append(presentationDeadlineNanos); 476 if (displayCutout != null) { 477 sb.append(", cutout ").append(displayCutout); 478 } 479 sb.append(", touch ").append(touchToString(touch)); 480 sb.append(", rotation ").append(rotation); 481 sb.append(", type ").append(Display.typeToString(type)); 482 if (address != null) { 483 sb.append(", address ").append(address); 484 } 485 sb.append(", deviceProductInfo ").append(deviceProductInfo); 486 sb.append(", state ").append(Display.stateToString(state)); 487 if (ownerUid != 0 || ownerPackageName != null) { 488 sb.append(", owner ").append(ownerPackageName); 489 sb.append(" (uid ").append(ownerUid).append(")"); 490 } 491 sb.append(", frameRateOverride "); 492 for (DisplayEventReceiver.FrameRateOverride frameRateOverride : frameRateOverrides) { 493 sb.append(frameRateOverride).append(" "); 494 } 495 sb.append(", brightnessMinimum ").append(brightnessMinimum); 496 sb.append(", brightnessMaximum ").append(brightnessMaximum); 497 sb.append(", brightnessDefault ").append(brightnessDefault); 498 if (roundedCorners != null) { 499 sb.append(", roundedCorners ").append(roundedCorners); 500 } 501 sb.append(flagsToString(flags)); 502 sb.append("}"); 503 return sb.toString(); 504 } 505 touchToString(int touch)506 private static String touchToString(int touch) { 507 switch (touch) { 508 case TOUCH_NONE: 509 return "NONE"; 510 case TOUCH_INTERNAL: 511 return "INTERNAL"; 512 case TOUCH_EXTERNAL: 513 return "EXTERNAL"; 514 case TOUCH_VIRTUAL: 515 return "VIRTUAL"; 516 default: 517 return Integer.toString(touch); 518 } 519 } 520 flagsToString(int flags)521 private static String flagsToString(int flags) { 522 StringBuilder msg = new StringBuilder(); 523 if ((flags & FLAG_DEFAULT_DISPLAY) != 0) { 524 msg.append(", FLAG_DEFAULT_DISPLAY"); 525 } 526 if ((flags & FLAG_ROTATES_WITH_CONTENT) != 0) { 527 msg.append(", FLAG_ROTATES_WITH_CONTENT"); 528 } 529 if ((flags & FLAG_SECURE) != 0) { 530 msg.append(", FLAG_SECURE"); 531 } 532 if ((flags & FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) { 533 msg.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS"); 534 } 535 if ((flags & FLAG_PRIVATE) != 0) { 536 msg.append(", FLAG_PRIVATE"); 537 } 538 if ((flags & FLAG_NEVER_BLANK) != 0) { 539 msg.append(", FLAG_NEVER_BLANK"); 540 } 541 if ((flags & FLAG_PRESENTATION) != 0) { 542 msg.append(", FLAG_PRESENTATION"); 543 } 544 if ((flags & FLAG_OWN_CONTENT_ONLY) != 0) { 545 msg.append(", FLAG_OWN_CONTENT_ONLY"); 546 } 547 if ((flags & FLAG_ROUND) != 0) { 548 msg.append(", FLAG_ROUND"); 549 } 550 if ((flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) { 551 msg.append(", FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD"); 552 } 553 if ((flags & FLAG_MASK_DISPLAY_CUTOUT) != 0) { 554 msg.append(", FLAG_MASK_DISPLAY_CUTOUT"); 555 } 556 return msg.toString(); 557 } 558 } 559