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