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 android.view; 18 19 import android.content.res.CompatibilityInfo; 20 import android.os.IBinder; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 import android.util.DisplayMetrics; 24 25 import java.util.Arrays; 26 27 import libcore.util.EmptyArray; 28 import libcore.util.Objects; 29 30 /** 31 * Describes the characteristics of a particular logical display. 32 * @hide 33 */ 34 public final class DisplayInfo implements Parcelable { 35 /** 36 * The surface flinger layer stack associated with this logical display. 37 */ 38 public int layerStack; 39 40 /** 41 * Display flags. 42 */ 43 public int flags; 44 45 /** 46 * Display type. 47 */ 48 public int type; 49 50 /** 51 * Display address, or null if none. 52 * Interpretation varies by display type. 53 */ 54 public String address; 55 56 /** 57 * The human-readable name of the display. 58 */ 59 public String name; 60 61 /** 62 * Unique identifier for the display. Shouldn't be displayed to the user. 63 */ 64 public String uniqueId; 65 66 /** 67 * The width of the portion of the display that is available to applications, in pixels. 68 * Represents the size of the display minus any system decorations. 69 */ 70 public int appWidth; 71 72 /** 73 * The height of the portion of the display that is available to applications, in pixels. 74 * Represents the size of the display minus any system decorations. 75 */ 76 public int appHeight; 77 78 /** 79 * The smallest value of {@link #appWidth} that an application is likely to encounter, 80 * in pixels, excepting cases where the width may be even smaller due to the presence 81 * of a soft keyboard, for example. 82 */ 83 public int smallestNominalAppWidth; 84 85 /** 86 * The smallest value of {@link #appHeight} that an application is likely to encounter, 87 * in pixels, excepting cases where the height may be even smaller due to the presence 88 * of a soft keyboard, for example. 89 */ 90 public int smallestNominalAppHeight; 91 92 /** 93 * The largest value of {@link #appWidth} that an application is likely to encounter, 94 * in pixels, excepting cases where the width may be even larger due to system decorations 95 * such as the status bar being hidden, for example. 96 */ 97 public int largestNominalAppWidth; 98 99 /** 100 * The largest value of {@link #appHeight} that an application is likely to encounter, 101 * in pixels, excepting cases where the height may be even larger due to system decorations 102 * such as the status bar being hidden, for example. 103 */ 104 public int largestNominalAppHeight; 105 106 /** 107 * The logical width of the display, in pixels. 108 * Represents the usable size of the display which may be smaller than the 109 * physical size when the system is emulating a smaller display. 110 */ 111 public int logicalWidth; 112 113 /** 114 * The logical height of the display, in pixels. 115 * Represents the usable size of the display which may be smaller than the 116 * physical size when the system is emulating a smaller display. 117 */ 118 public int logicalHeight; 119 120 /** 121 * @hide 122 * Number of overscan pixels on the left side of the display. 123 */ 124 public int overscanLeft; 125 126 /** 127 * @hide 128 * Number of overscan pixels on the top side of the display. 129 */ 130 public int overscanTop; 131 132 /** 133 * @hide 134 * Number of overscan pixels on the right side of the display. 135 */ 136 public int overscanRight; 137 138 /** 139 * @hide 140 * Number of overscan pixels on the bottom side of the display. 141 */ 142 public int overscanBottom; 143 144 /** 145 * The rotation of the display relative to its natural orientation. 146 * May be one of {@link android.view.Surface#ROTATION_0}, 147 * {@link android.view.Surface#ROTATION_90}, {@link android.view.Surface#ROTATION_180}, 148 * {@link android.view.Surface#ROTATION_270}. 149 * <p> 150 * The value of this field is indeterminate if the logical display is presented on 151 * more than one physical display. 152 * </p> 153 */ 154 @Surface.Rotation 155 public int rotation; 156 157 /** 158 * The refresh rate of this display in frames per second. 159 * <p> 160 * The value of this field is indeterminate if the logical display is presented on 161 * more than one physical display. 162 * </p> 163 */ 164 public float refreshRate; 165 166 /** 167 * The supported refresh rates of this display at the current resolution in frames per second. 168 */ 169 public float[] supportedRefreshRates = EmptyArray.FLOAT; 170 171 /** 172 * The logical display density which is the basis for density-independent 173 * pixels. 174 */ 175 public int logicalDensityDpi; 176 177 /** 178 * The exact physical pixels per inch of the screen in the X dimension. 179 * <p> 180 * The value of this field is indeterminate if the logical display is presented on 181 * more than one physical display. 182 * </p> 183 */ 184 public float physicalXDpi; 185 186 /** 187 * The exact physical pixels per inch of the screen in the Y dimension. 188 * <p> 189 * The value of this field is indeterminate if the logical display is presented on 190 * more than one physical display. 191 * </p> 192 */ 193 public float physicalYDpi; 194 195 /** 196 * This is a positive value indicating the phase offset of the VSYNC events provided by 197 * Choreographer relative to the display refresh. For example, if Choreographer reports 198 * that the refresh occurred at time N, it actually occurred at (N - appVsyncOffsetNanos). 199 */ 200 public long appVsyncOffsetNanos; 201 202 /** 203 * This is how far in advance a buffer must be queued for presentation at 204 * a given time. If you want a buffer to appear on the screen at 205 * time N, you must submit the buffer before (N - bufferDeadlineNanos). 206 */ 207 public long presentationDeadlineNanos; 208 209 /** 210 * The state of the display, such as {@link android.view.Display#STATE_ON}. 211 */ 212 public int state; 213 214 /** 215 * The UID of the application that owns this display, or zero if it is owned by the system. 216 * <p> 217 * If the display is private, then only the owner can use it. 218 * </p> 219 */ 220 public int ownerUid; 221 222 /** 223 * The package name of the application that owns this display, or null if it is 224 * owned by the system. 225 * <p> 226 * If the display is private, then only the owner can use it. 227 * </p> 228 */ 229 public String ownerPackageName; 230 231 public static final Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() { 232 @Override 233 public DisplayInfo createFromParcel(Parcel source) { 234 return new DisplayInfo(source); 235 } 236 237 @Override 238 public DisplayInfo[] newArray(int size) { 239 return new DisplayInfo[size]; 240 } 241 }; 242 DisplayInfo()243 public DisplayInfo() { 244 } 245 DisplayInfo(DisplayInfo other)246 public DisplayInfo(DisplayInfo other) { 247 copyFrom(other); 248 } 249 DisplayInfo(Parcel source)250 private DisplayInfo(Parcel source) { 251 readFromParcel(source); 252 } 253 254 @Override equals(Object o)255 public boolean equals(Object o) { 256 return o instanceof DisplayInfo && equals((DisplayInfo)o); 257 } 258 equals(DisplayInfo other)259 public boolean equals(DisplayInfo other) { 260 return other != null 261 && layerStack == other.layerStack 262 && flags == other.flags 263 && type == other.type 264 && Objects.equal(address, other.address) 265 && Objects.equal(uniqueId, other.uniqueId) 266 && appWidth == other.appWidth 267 && appHeight == other.appHeight 268 && smallestNominalAppWidth == other.smallestNominalAppWidth 269 && smallestNominalAppHeight == other.smallestNominalAppHeight 270 && largestNominalAppWidth == other.largestNominalAppWidth 271 && largestNominalAppHeight == other.largestNominalAppHeight 272 && logicalWidth == other.logicalWidth 273 && logicalHeight == other.logicalHeight 274 && overscanLeft == other.overscanLeft 275 && overscanTop == other.overscanTop 276 && overscanRight == other.overscanRight 277 && overscanBottom == other.overscanBottom 278 && rotation == other.rotation 279 && refreshRate == other.refreshRate 280 && logicalDensityDpi == other.logicalDensityDpi 281 && physicalXDpi == other.physicalXDpi 282 && physicalYDpi == other.physicalYDpi 283 && appVsyncOffsetNanos == other.appVsyncOffsetNanos 284 && presentationDeadlineNanos == other.presentationDeadlineNanos 285 && state == other.state 286 && ownerUid == other.ownerUid 287 && Objects.equal(ownerPackageName, other.ownerPackageName); 288 } 289 290 @Override hashCode()291 public int hashCode() { 292 return 0; // don't care 293 } 294 copyFrom(DisplayInfo other)295 public void copyFrom(DisplayInfo other) { 296 layerStack = other.layerStack; 297 flags = other.flags; 298 type = other.type; 299 address = other.address; 300 name = other.name; 301 uniqueId = other.uniqueId; 302 appWidth = other.appWidth; 303 appHeight = other.appHeight; 304 smallestNominalAppWidth = other.smallestNominalAppWidth; 305 smallestNominalAppHeight = other.smallestNominalAppHeight; 306 largestNominalAppWidth = other.largestNominalAppWidth; 307 largestNominalAppHeight = other.largestNominalAppHeight; 308 logicalWidth = other.logicalWidth; 309 logicalHeight = other.logicalHeight; 310 overscanLeft = other.overscanLeft; 311 overscanTop = other.overscanTop; 312 overscanRight = other.overscanRight; 313 overscanBottom = other.overscanBottom; 314 rotation = other.rotation; 315 refreshRate = other.refreshRate; 316 supportedRefreshRates = Arrays.copyOf( 317 other.supportedRefreshRates, other.supportedRefreshRates.length); 318 logicalDensityDpi = other.logicalDensityDpi; 319 physicalXDpi = other.physicalXDpi; 320 physicalYDpi = other.physicalYDpi; 321 appVsyncOffsetNanos = other.appVsyncOffsetNanos; 322 presentationDeadlineNanos = other.presentationDeadlineNanos; 323 state = other.state; 324 ownerUid = other.ownerUid; 325 ownerPackageName = other.ownerPackageName; 326 } 327 readFromParcel(Parcel source)328 public void readFromParcel(Parcel source) { 329 layerStack = source.readInt(); 330 flags = source.readInt(); 331 type = source.readInt(); 332 address = source.readString(); 333 name = source.readString(); 334 appWidth = source.readInt(); 335 appHeight = source.readInt(); 336 smallestNominalAppWidth = source.readInt(); 337 smallestNominalAppHeight = source.readInt(); 338 largestNominalAppWidth = source.readInt(); 339 largestNominalAppHeight = source.readInt(); 340 logicalWidth = source.readInt(); 341 logicalHeight = source.readInt(); 342 overscanLeft = source.readInt(); 343 overscanTop = source.readInt(); 344 overscanRight = source.readInt(); 345 overscanBottom = source.readInt(); 346 rotation = source.readInt(); 347 refreshRate = source.readFloat(); 348 supportedRefreshRates = source.createFloatArray(); 349 logicalDensityDpi = source.readInt(); 350 physicalXDpi = source.readFloat(); 351 physicalYDpi = source.readFloat(); 352 appVsyncOffsetNanos = source.readLong(); 353 presentationDeadlineNanos = source.readLong(); 354 state = source.readInt(); 355 ownerUid = source.readInt(); 356 ownerPackageName = source.readString(); 357 uniqueId = source.readString(); 358 } 359 360 @Override writeToParcel(Parcel dest, int flags)361 public void writeToParcel(Parcel dest, int flags) { 362 dest.writeInt(layerStack); 363 dest.writeInt(this.flags); 364 dest.writeInt(type); 365 dest.writeString(address); 366 dest.writeString(name); 367 dest.writeInt(appWidth); 368 dest.writeInt(appHeight); 369 dest.writeInt(smallestNominalAppWidth); 370 dest.writeInt(smallestNominalAppHeight); 371 dest.writeInt(largestNominalAppWidth); 372 dest.writeInt(largestNominalAppHeight); 373 dest.writeInt(logicalWidth); 374 dest.writeInt(logicalHeight); 375 dest.writeInt(overscanLeft); 376 dest.writeInt(overscanTop); 377 dest.writeInt(overscanRight); 378 dest.writeInt(overscanBottom); 379 dest.writeInt(rotation); 380 dest.writeFloat(refreshRate); 381 dest.writeFloatArray(supportedRefreshRates); 382 dest.writeInt(logicalDensityDpi); 383 dest.writeFloat(physicalXDpi); 384 dest.writeFloat(physicalYDpi); 385 dest.writeLong(appVsyncOffsetNanos); 386 dest.writeLong(presentationDeadlineNanos); 387 dest.writeInt(state); 388 dest.writeInt(ownerUid); 389 dest.writeString(ownerPackageName); 390 dest.writeString(uniqueId); 391 } 392 393 @Override describeContents()394 public int describeContents() { 395 return 0; 396 } 397 getAppMetrics(DisplayMetrics outMetrics)398 public void getAppMetrics(DisplayMetrics outMetrics) { 399 getAppMetrics(outMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 400 } 401 getAppMetrics(DisplayMetrics outMetrics, DisplayAdjustments displayAdjustments)402 public void getAppMetrics(DisplayMetrics outMetrics, DisplayAdjustments displayAdjustments) { 403 getMetricsWithSize(outMetrics, displayAdjustments.getCompatibilityInfo(), 404 displayAdjustments.getActivityToken(), appWidth, appHeight); 405 } 406 getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci, IBinder token)407 public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci, IBinder token) { 408 getMetricsWithSize(outMetrics, ci, token, appWidth, appHeight); 409 } 410 getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, IBinder token)411 public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, 412 IBinder token) { 413 getMetricsWithSize(outMetrics, compatInfo, token, logicalWidth, logicalHeight); 414 } 415 getNaturalWidth()416 public int getNaturalWidth() { 417 return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ? 418 logicalWidth : logicalHeight; 419 } 420 getNaturalHeight()421 public int getNaturalHeight() { 422 return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ? 423 logicalHeight : logicalWidth; 424 } 425 426 /** 427 * Returns true if the specified UID has access to this display. 428 */ hasAccess(int uid)429 public boolean hasAccess(int uid) { 430 return Display.hasAccess(uid, flags, ownerUid); 431 } 432 getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, IBinder token, int width, int height)433 private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, 434 IBinder token, int width, int height) { 435 outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi; 436 outMetrics.noncompatWidthPixels = outMetrics.widthPixels = width; 437 outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height; 438 439 outMetrics.density = outMetrics.noncompatDensity = 440 logicalDensityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; 441 outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density; 442 outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi; 443 outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi; 444 445 if (!compatInfo.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) { 446 compatInfo.applyToDisplayMetrics(outMetrics); 447 } 448 } 449 450 // For debugging purposes 451 @Override toString()452 public String toString() { 453 StringBuilder sb = new StringBuilder(); 454 sb.append("DisplayInfo{\""); 455 sb.append(name); 456 sb.append("\", uniqueId \""); 457 sb.append(uniqueId); 458 sb.append("\", app "); 459 sb.append(appWidth); 460 sb.append(" x "); 461 sb.append(appHeight); 462 sb.append(", real "); 463 sb.append(logicalWidth); 464 sb.append(" x "); 465 sb.append(logicalHeight); 466 if (overscanLeft != 0 || overscanTop != 0 || overscanRight != 0 || overscanBottom != 0) { 467 sb.append(", overscan ("); 468 sb.append(overscanLeft); 469 sb.append(","); 470 sb.append(overscanTop); 471 sb.append(","); 472 sb.append(overscanRight); 473 sb.append(","); 474 sb.append(overscanBottom); 475 sb.append(")"); 476 } 477 sb.append(", largest app "); 478 sb.append(largestNominalAppWidth); 479 sb.append(" x "); 480 sb.append(largestNominalAppHeight); 481 sb.append(", smallest app "); 482 sb.append(smallestNominalAppWidth); 483 sb.append(" x "); 484 sb.append(smallestNominalAppHeight); 485 sb.append(", "); 486 sb.append(refreshRate); 487 sb.append(" fps, supportedRefreshRates "); 488 sb.append(Arrays.toString(supportedRefreshRates)); 489 sb.append(", rotation "); 490 sb.append(rotation); 491 sb.append(", density "); 492 sb.append(logicalDensityDpi); 493 sb.append(" ("); 494 sb.append(physicalXDpi); 495 sb.append(" x "); 496 sb.append(physicalYDpi); 497 sb.append(") dpi, layerStack "); 498 sb.append(layerStack); 499 sb.append(", appVsyncOff "); 500 sb.append(appVsyncOffsetNanos); 501 sb.append(", presDeadline "); 502 sb.append(presentationDeadlineNanos); 503 sb.append(", type "); 504 sb.append(Display.typeToString(type)); 505 if (address != null) { 506 sb.append(", address ").append(address); 507 } 508 sb.append(", state "); 509 sb.append(Display.stateToString(state)); 510 if (ownerUid != 0 || ownerPackageName != null) { 511 sb.append(", owner ").append(ownerPackageName); 512 sb.append(" (uid ").append(ownerUid).append(")"); 513 } 514 sb.append(flagsToString(flags)); 515 sb.append("}"); 516 return sb.toString(); 517 } 518 flagsToString(int flags)519 private static String flagsToString(int flags) { 520 StringBuilder result = new StringBuilder(); 521 if ((flags & Display.FLAG_SECURE) != 0) { 522 result.append(", FLAG_SECURE"); 523 } 524 if ((flags & Display.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) { 525 result.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS"); 526 } 527 if ((flags & Display.FLAG_PRIVATE) != 0) { 528 result.append(", FLAG_PRIVATE"); 529 } 530 if ((flags & Display.FLAG_PRESENTATION) != 0) { 531 result.append(", FLAG_PRESENTATION"); 532 } 533 return result.toString(); 534 } 535 } 536