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