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 * Touch attachment: Display does not receive touch. 97 */ 98 public static final int TOUCH_NONE = 0; 99 100 /** 101 * Touch attachment: Touch input is via the internal interface. 102 */ 103 public static final int TOUCH_INTERNAL = 1; 104 105 /** 106 * Touch attachment: Touch input is via an external interface, such as USB. 107 */ 108 public static final int TOUCH_EXTERNAL = 2; 109 110 /** 111 * Diff result: The {@link #state} fields differ. 112 */ 113 public static final int DIFF_STATE = 1 << 0; 114 115 /** 116 * Diff result: Other fields differ. 117 */ 118 public static final int DIFF_OTHER = 1 << 1; 119 120 /** 121 * Diff result: The color mode fields differ. 122 */ 123 public static final int DIFF_COLOR_MODE = 1 << 2; 124 125 /** 126 * Gets the name of the display device, which may be derived from EDID or 127 * other sources. The name may be localized and displayed to the user. 128 */ 129 public String name; 130 131 /** 132 * Unique Id of display device. 133 */ 134 public String uniqueId; 135 136 /** 137 * The width of the display in its natural orientation, in pixels. 138 * This value is not affected by display rotation. 139 */ 140 public int width; 141 142 /** 143 * The height of the display in its natural orientation, in pixels. 144 * This value is not affected by display rotation. 145 */ 146 public int height; 147 148 /** 149 * The active mode of the display. 150 */ 151 public int modeId; 152 153 /** 154 * The default mode of the display. 155 */ 156 public int defaultModeId; 157 158 /** 159 * The supported modes of the display. 160 */ 161 public Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY; 162 163 /** The active color mode of the display */ 164 public int colorMode; 165 166 /** The supported color modes of the display */ 167 public int[] supportedColorModes = { Display.COLOR_MODE_DEFAULT }; 168 169 /** 170 * The HDR capabilities this display claims to support. 171 */ 172 public Display.HdrCapabilities hdrCapabilities; 173 174 /** 175 * The nominal apparent density of the display in DPI used for layout calculations. 176 * This density is sensitive to the viewing distance. A big TV and a tablet may have 177 * the same apparent density even though the pixels on the TV are much bigger than 178 * those on the tablet. 179 */ 180 public int densityDpi; 181 182 /** 183 * The physical density of the display in DPI in the X direction. 184 * This density should specify the physical size of each pixel. 185 */ 186 public float xDpi; 187 188 /** 189 * The physical density of the display in DPI in the X direction. 190 * This density should specify the physical size of each pixel. 191 */ 192 public float yDpi; 193 194 /** 195 * This is a positive value indicating the phase offset of the VSYNC events provided by 196 * Choreographer relative to the display refresh. For example, if Choreographer reports 197 * that the refresh occurred at time N, it actually occurred at (N - appVsyncOffsetNanos). 198 */ 199 public long appVsyncOffsetNanos; 200 201 /** 202 * This is how far in advance a buffer must be queued for presentation at 203 * a given time. If you want a buffer to appear on the screen at 204 * time N, you must submit the buffer before (N - bufferDeadlineNanos). 205 */ 206 public long presentationDeadlineNanos; 207 208 /** 209 * Display flags. 210 */ 211 public int flags; 212 213 /** 214 * The touch attachment, per {@link DisplayViewport#touch}. 215 */ 216 public int touch; 217 218 /** 219 * The additional rotation to apply to all content presented on the display device 220 * relative to its physical coordinate system. Default is {@link Surface#ROTATION_0}. 221 * <p> 222 * This field can be used to compensate for the fact that the display has been 223 * physically rotated relative to its natural orientation such as an HDMI monitor 224 * that has been mounted sideways to appear to be portrait rather than landscape. 225 * </p> 226 */ 227 public int rotation = Surface.ROTATION_0; 228 229 /** 230 * Display type. 231 */ 232 public int type; 233 234 /** 235 * Display address, or null if none. 236 * Interpretation varies by display type. 237 */ 238 public String address; 239 240 /** 241 * Display state. 242 */ 243 public int state = Display.STATE_ON; 244 245 /** 246 * The UID of the application that owns this display, or zero if it is owned by the system. 247 * <p> 248 * If the display is private, then only the owner can use it. 249 * </p> 250 */ 251 public int ownerUid; 252 253 /** 254 * The package name of the application that owns this display, or null if it is 255 * owned by the system. 256 * <p> 257 * If the display is private, then only the owner can use it. 258 * </p> 259 */ 260 public String ownerPackageName; 261 262 public void setAssumedDensityForExternalDisplay(int width, int height) { 263 densityDpi = Math.min(width, height) * DisplayMetrics.DENSITY_XHIGH / 1080; 264 // Technically, these values should be smaller than the apparent density 265 // but we don't know the physical size of the display. 266 xDpi = densityDpi; 267 yDpi = densityDpi; 268 } 269 270 @Override 271 public boolean equals(Object o) { 272 return o instanceof DisplayDeviceInfo && equals((DisplayDeviceInfo)o); 273 } 274 275 public boolean equals(DisplayDeviceInfo other) { 276 return other != null && diff(other) == 0; 277 } 278 279 /** 280 * Computes the difference between display device infos. 281 * Assumes other is not null. 282 */ 283 public int diff(DisplayDeviceInfo other) { 284 int diff = 0; 285 if (state != other.state) { 286 diff |= DIFF_STATE; 287 } 288 if (colorMode != other.colorMode) { 289 diff |= DIFF_COLOR_MODE; 290 } 291 if (!Objects.equal(name, other.name) 292 || !Objects.equal(uniqueId, other.uniqueId) 293 || width != other.width 294 || height != other.height 295 || modeId != other.modeId 296 || defaultModeId != other.defaultModeId 297 || !Arrays.equals(supportedModes, other.supportedModes) 298 || !Arrays.equals(supportedColorModes, other.supportedColorModes) 299 || !Objects.equal(hdrCapabilities, other.hdrCapabilities) 300 || densityDpi != other.densityDpi 301 || xDpi != other.xDpi 302 || yDpi != other.yDpi 303 || appVsyncOffsetNanos != other.appVsyncOffsetNanos 304 || presentationDeadlineNanos != other.presentationDeadlineNanos 305 || flags != other.flags 306 || touch != other.touch 307 || rotation != other.rotation 308 || type != other.type 309 || !Objects.equal(address, other.address) 310 || ownerUid != other.ownerUid 311 || !Objects.equal(ownerPackageName, other.ownerPackageName)) { 312 diff |= DIFF_OTHER; 313 } 314 return diff; 315 } 316 317 @Override 318 public int hashCode() { 319 return 0; // don't care 320 } 321 322 public void copyFrom(DisplayDeviceInfo other) { 323 name = other.name; 324 uniqueId = other.uniqueId; 325 width = other.width; 326 height = other.height; 327 modeId = other.modeId; 328 defaultModeId = other.defaultModeId; 329 supportedModes = other.supportedModes; 330 colorMode = other.colorMode; 331 supportedColorModes = other.supportedColorModes; 332 hdrCapabilities = other.hdrCapabilities; 333 densityDpi = other.densityDpi; 334 xDpi = other.xDpi; 335 yDpi = other.yDpi; 336 appVsyncOffsetNanos = other.appVsyncOffsetNanos; 337 presentationDeadlineNanos = other.presentationDeadlineNanos; 338 flags = other.flags; 339 touch = other.touch; 340 rotation = other.rotation; 341 type = other.type; 342 address = other.address; 343 state = other.state; 344 ownerUid = other.ownerUid; 345 ownerPackageName = other.ownerPackageName; 346 } 347 348 // For debugging purposes 349 @Override 350 public String toString() { 351 StringBuilder sb = new StringBuilder(); 352 sb.append("DisplayDeviceInfo{\""); 353 sb.append(name).append("\": uniqueId=\"").append(uniqueId).append("\", "); 354 sb.append(width).append(" x ").append(height); 355 sb.append(", modeId ").append(modeId); 356 sb.append(", defaultModeId ").append(defaultModeId); 357 sb.append(", supportedModes ").append(Arrays.toString(supportedModes)); 358 sb.append(", colorMode ").append(colorMode); 359 sb.append(", supportedColorModes ").append(Arrays.toString(supportedColorModes)); 360 sb.append(", HdrCapabilities ").append(hdrCapabilities); 361 sb.append(", density ").append(densityDpi); 362 sb.append(", ").append(xDpi).append(" x ").append(yDpi).append(" dpi"); 363 sb.append(", appVsyncOff ").append(appVsyncOffsetNanos); 364 sb.append(", presDeadline ").append(presentationDeadlineNanos); 365 sb.append(", touch ").append(touchToString(touch)); 366 sb.append(", rotation ").append(rotation); 367 sb.append(", type ").append(Display.typeToString(type)); 368 if (address != null) { 369 sb.append(", address ").append(address); 370 } 371 sb.append(", state ").append(Display.stateToString(state)); 372 if (ownerUid != 0 || ownerPackageName != null) { 373 sb.append(", owner ").append(ownerPackageName); 374 sb.append(" (uid ").append(ownerUid).append(")"); 375 } 376 sb.append(flagsToString(flags)); 377 sb.append("}"); 378 return sb.toString(); 379 } 380 381 private static String touchToString(int touch) { 382 switch (touch) { 383 case TOUCH_NONE: 384 return "NONE"; 385 case TOUCH_INTERNAL: 386 return "INTERNAL"; 387 case TOUCH_EXTERNAL: 388 return "EXTERNAL"; 389 default: 390 return Integer.toString(touch); 391 } 392 } 393 394 private static String flagsToString(int flags) { 395 StringBuilder msg = new StringBuilder(); 396 if ((flags & FLAG_DEFAULT_DISPLAY) != 0) { 397 msg.append(", FLAG_DEFAULT_DISPLAY"); 398 } 399 if ((flags & FLAG_ROTATES_WITH_CONTENT) != 0) { 400 msg.append(", FLAG_ROTATES_WITH_CONTENT"); 401 } 402 if ((flags & FLAG_SECURE) != 0) { 403 msg.append(", FLAG_SECURE"); 404 } 405 if ((flags & FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) { 406 msg.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS"); 407 } 408 if ((flags & FLAG_PRIVATE) != 0) { 409 msg.append(", FLAG_PRIVATE"); 410 } 411 if ((flags & FLAG_NEVER_BLANK) != 0) { 412 msg.append(", FLAG_NEVER_BLANK"); 413 } 414 if ((flags & FLAG_PRESENTATION) != 0) { 415 msg.append(", FLAG_PRESENTATION"); 416 } 417 if ((flags & FLAG_OWN_CONTENT_ONLY) != 0) { 418 msg.append(", FLAG_OWN_CONTENT_ONLY"); 419 } 420 if ((flags & FLAG_ROUND) != 0) { 421 msg.append(", FLAG_ROUND"); 422 } 423 return msg.toString(); 424 } 425 } 426