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