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.content.res.Configuration; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 import android.util.ArraySet; 24 import android.util.DisplayMetrics; 25 26 import java.util.Arrays; 27 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 active display mode. 159 */ 160 public int modeId; 161 162 /** 163 * The default display mode. 164 */ 165 public int defaultModeId; 166 167 /** 168 * The supported modes of this display. 169 */ 170 public Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY; 171 172 /** The active color mode. */ 173 public int colorMode; 174 175 /** The list of supported color modes */ 176 public int[] supportedColorModes = { Display.COLOR_MODE_DEFAULT }; 177 178 /** The display's HDR capabilities */ 179 public Display.HdrCapabilities hdrCapabilities; 180 181 /** 182 * The logical display density which is the basis for density-independent 183 * pixels. 184 */ 185 public int logicalDensityDpi; 186 187 /** 188 * The exact physical pixels per inch of the screen in the X dimension. 189 * <p> 190 * The value of this field is indeterminate if the logical display is presented on 191 * more than one physical display. 192 * </p> 193 */ 194 public float physicalXDpi; 195 196 /** 197 * The exact physical pixels per inch of the screen in the Y dimension. 198 * <p> 199 * The value of this field is indeterminate if the logical display is presented on 200 * more than one physical display. 201 * </p> 202 */ 203 public float physicalYDpi; 204 205 /** 206 * This is a positive value indicating the phase offset of the VSYNC events provided by 207 * Choreographer relative to the display refresh. For example, if Choreographer reports 208 * that the refresh occurred at time N, it actually occurred at (N - appVsyncOffsetNanos). 209 */ 210 public long appVsyncOffsetNanos; 211 212 /** 213 * This is how far in advance a buffer must be queued for presentation at 214 * a given time. If you want a buffer to appear on the screen at 215 * time N, you must submit the buffer before (N - bufferDeadlineNanos). 216 */ 217 public long presentationDeadlineNanos; 218 219 /** 220 * The state of the display, such as {@link android.view.Display#STATE_ON}. 221 */ 222 public int state; 223 224 /** 225 * The UID of the application that owns this display, or zero if it is owned by the system. 226 * <p> 227 * If the display is private, then only the owner can use it. 228 * </p> 229 */ 230 public int ownerUid; 231 232 /** 233 * The package name of the application that owns this display, or null if it is 234 * owned by the system. 235 * <p> 236 * If the display is private, then only the owner can use it. 237 * </p> 238 */ 239 public String ownerPackageName; 240 241 public static final Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() { 242 @Override 243 public DisplayInfo createFromParcel(Parcel source) { 244 return new DisplayInfo(source); 245 } 246 247 @Override 248 public DisplayInfo[] newArray(int size) { 249 return new DisplayInfo[size]; 250 } 251 }; 252 253 public DisplayInfo() { 254 } 255 256 public DisplayInfo(DisplayInfo other) { 257 copyFrom(other); 258 } 259 260 private DisplayInfo(Parcel source) { 261 readFromParcel(source); 262 } 263 264 @Override 265 public boolean equals(Object o) { 266 return o instanceof DisplayInfo && equals((DisplayInfo)o); 267 } 268 269 public boolean equals(DisplayInfo other) { 270 return other != null 271 && layerStack == other.layerStack 272 && flags == other.flags 273 && type == other.type 274 && Objects.equal(address, other.address) 275 && Objects.equal(uniqueId, other.uniqueId) 276 && appWidth == other.appWidth 277 && appHeight == other.appHeight 278 && smallestNominalAppWidth == other.smallestNominalAppWidth 279 && smallestNominalAppHeight == other.smallestNominalAppHeight 280 && largestNominalAppWidth == other.largestNominalAppWidth 281 && largestNominalAppHeight == other.largestNominalAppHeight 282 && logicalWidth == other.logicalWidth 283 && logicalHeight == other.logicalHeight 284 && overscanLeft == other.overscanLeft 285 && overscanTop == other.overscanTop 286 && overscanRight == other.overscanRight 287 && overscanBottom == other.overscanBottom 288 && rotation == other.rotation 289 && modeId == other.modeId 290 && defaultModeId == other.defaultModeId 291 && colorMode == other.colorMode 292 && Arrays.equals(supportedColorModes, other.supportedColorModes) 293 && Objects.equal(hdrCapabilities, other.hdrCapabilities) 294 && logicalDensityDpi == other.logicalDensityDpi 295 && physicalXDpi == other.physicalXDpi 296 && physicalYDpi == other.physicalYDpi 297 && appVsyncOffsetNanos == other.appVsyncOffsetNanos 298 && presentationDeadlineNanos == other.presentationDeadlineNanos 299 && state == other.state 300 && ownerUid == other.ownerUid 301 && Objects.equal(ownerPackageName, other.ownerPackageName); 302 } 303 304 @Override 305 public int hashCode() { 306 return 0; // don't care 307 } 308 309 public void copyFrom(DisplayInfo other) { 310 layerStack = other.layerStack; 311 flags = other.flags; 312 type = other.type; 313 address = other.address; 314 name = other.name; 315 uniqueId = other.uniqueId; 316 appWidth = other.appWidth; 317 appHeight = other.appHeight; 318 smallestNominalAppWidth = other.smallestNominalAppWidth; 319 smallestNominalAppHeight = other.smallestNominalAppHeight; 320 largestNominalAppWidth = other.largestNominalAppWidth; 321 largestNominalAppHeight = other.largestNominalAppHeight; 322 logicalWidth = other.logicalWidth; 323 logicalHeight = other.logicalHeight; 324 overscanLeft = other.overscanLeft; 325 overscanTop = other.overscanTop; 326 overscanRight = other.overscanRight; 327 overscanBottom = other.overscanBottom; 328 rotation = other.rotation; 329 modeId = other.modeId; 330 defaultModeId = other.defaultModeId; 331 supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length); 332 colorMode = other.colorMode; 333 supportedColorModes = Arrays.copyOf( 334 other.supportedColorModes, other.supportedColorModes.length); 335 hdrCapabilities = other.hdrCapabilities; 336 logicalDensityDpi = other.logicalDensityDpi; 337 physicalXDpi = other.physicalXDpi; 338 physicalYDpi = other.physicalYDpi; 339 appVsyncOffsetNanos = other.appVsyncOffsetNanos; 340 presentationDeadlineNanos = other.presentationDeadlineNanos; 341 state = other.state; 342 ownerUid = other.ownerUid; 343 ownerPackageName = other.ownerPackageName; 344 } 345 346 public void readFromParcel(Parcel source) { 347 layerStack = source.readInt(); 348 flags = source.readInt(); 349 type = source.readInt(); 350 address = source.readString(); 351 name = source.readString(); 352 appWidth = source.readInt(); 353 appHeight = source.readInt(); 354 smallestNominalAppWidth = source.readInt(); 355 smallestNominalAppHeight = source.readInt(); 356 largestNominalAppWidth = source.readInt(); 357 largestNominalAppHeight = source.readInt(); 358 logicalWidth = source.readInt(); 359 logicalHeight = source.readInt(); 360 overscanLeft = source.readInt(); 361 overscanTop = source.readInt(); 362 overscanRight = source.readInt(); 363 overscanBottom = source.readInt(); 364 rotation = source.readInt(); 365 modeId = source.readInt(); 366 defaultModeId = source.readInt(); 367 int nModes = source.readInt(); 368 supportedModes = new Display.Mode[nModes]; 369 for (int i = 0; i < nModes; i++) { 370 supportedModes[i] = Display.Mode.CREATOR.createFromParcel(source); 371 } 372 colorMode = source.readInt(); 373 int nColorModes = source.readInt(); 374 supportedColorModes = new int[nColorModes]; 375 for (int i = 0; i < nColorModes; i++) { 376 supportedColorModes[i] = source.readInt(); 377 } 378 hdrCapabilities = source.readParcelable(null); 379 logicalDensityDpi = source.readInt(); 380 physicalXDpi = source.readFloat(); 381 physicalYDpi = source.readFloat(); 382 appVsyncOffsetNanos = source.readLong(); 383 presentationDeadlineNanos = source.readLong(); 384 state = source.readInt(); 385 ownerUid = source.readInt(); 386 ownerPackageName = source.readString(); 387 uniqueId = source.readString(); 388 } 389 390 @Override 391 public void writeToParcel(Parcel dest, int flags) { 392 dest.writeInt(layerStack); 393 dest.writeInt(this.flags); 394 dest.writeInt(type); 395 dest.writeString(address); 396 dest.writeString(name); 397 dest.writeInt(appWidth); 398 dest.writeInt(appHeight); 399 dest.writeInt(smallestNominalAppWidth); 400 dest.writeInt(smallestNominalAppHeight); 401 dest.writeInt(largestNominalAppWidth); 402 dest.writeInt(largestNominalAppHeight); 403 dest.writeInt(logicalWidth); 404 dest.writeInt(logicalHeight); 405 dest.writeInt(overscanLeft); 406 dest.writeInt(overscanTop); 407 dest.writeInt(overscanRight); 408 dest.writeInt(overscanBottom); 409 dest.writeInt(rotation); 410 dest.writeInt(modeId); 411 dest.writeInt(defaultModeId); 412 dest.writeInt(supportedModes.length); 413 for (int i = 0; i < supportedModes.length; i++) { 414 supportedModes[i].writeToParcel(dest, flags); 415 } 416 dest.writeInt(colorMode); 417 dest.writeInt(supportedColorModes.length); 418 for (int i = 0; i < supportedColorModes.length; i++) { 419 dest.writeInt(supportedColorModes[i]); 420 } 421 dest.writeParcelable(hdrCapabilities, flags); 422 dest.writeInt(logicalDensityDpi); 423 dest.writeFloat(physicalXDpi); 424 dest.writeFloat(physicalYDpi); 425 dest.writeLong(appVsyncOffsetNanos); 426 dest.writeLong(presentationDeadlineNanos); 427 dest.writeInt(state); 428 dest.writeInt(ownerUid); 429 dest.writeString(ownerPackageName); 430 dest.writeString(uniqueId); 431 } 432 433 @Override 434 public int describeContents() { 435 return 0; 436 } 437 438 public Display.Mode getMode() { 439 return findMode(modeId); 440 } 441 442 public Display.Mode getDefaultMode() { 443 return findMode(defaultModeId); 444 } 445 446 private Display.Mode findMode(int id) { 447 for (int i = 0; i < supportedModes.length; i++) { 448 if (supportedModes[i].getModeId() == id) { 449 return supportedModes[i]; 450 } 451 } 452 throw new IllegalStateException("Unable to locate mode " + id); 453 } 454 455 /** 456 * Returns the id of the "default" mode with the given refresh rate, or {@code 0} if no suitable 457 * mode could be found. 458 */ 459 public int findDefaultModeByRefreshRate(float refreshRate) { 460 Display.Mode[] modes = supportedModes; 461 Display.Mode defaultMode = getDefaultMode(); 462 for (int i = 0; i < modes.length; i++) { 463 if (modes[i].matches( 464 defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), refreshRate)) { 465 return modes[i].getModeId(); 466 } 467 } 468 return 0; 469 } 470 471 /** 472 * Returns the list of supported refresh rates in the default mode. 473 */ 474 public float[] getDefaultRefreshRates() { 475 Display.Mode[] modes = supportedModes; 476 ArraySet<Float> rates = new ArraySet<>(); 477 Display.Mode defaultMode = getDefaultMode(); 478 for (int i = 0; i < modes.length; i++) { 479 Display.Mode mode = modes[i]; 480 if (mode.getPhysicalWidth() == defaultMode.getPhysicalWidth() 481 && mode.getPhysicalHeight() == defaultMode.getPhysicalHeight()) { 482 rates.add(mode.getRefreshRate()); 483 } 484 } 485 float[] result = new float[rates.size()]; 486 int i = 0; 487 for (Float rate : rates) { 488 result[i++] = rate; 489 } 490 return result; 491 } 492 493 public void getAppMetrics(DisplayMetrics outMetrics) { 494 getAppMetrics(outMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 495 } 496 497 public void getAppMetrics(DisplayMetrics outMetrics, DisplayAdjustments displayAdjustments) { 498 getMetricsWithSize(outMetrics, displayAdjustments.getCompatibilityInfo(), 499 displayAdjustments.getConfiguration(), appWidth, appHeight); 500 } 501 502 public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci, 503 Configuration configuration) { 504 getMetricsWithSize(outMetrics, ci, configuration, appWidth, appHeight); 505 } 506 507 public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, 508 Configuration configuration) { 509 getMetricsWithSize(outMetrics, compatInfo, configuration, logicalWidth, logicalHeight); 510 } 511 512 public int getNaturalWidth() { 513 return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ? 514 logicalWidth : logicalHeight; 515 } 516 517 public int getNaturalHeight() { 518 return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ? 519 logicalHeight : logicalWidth; 520 } 521 522 /** 523 * Returns true if the specified UID has access to this display. 524 */ 525 public boolean hasAccess(int uid) { 526 return Display.hasAccess(uid, flags, ownerUid); 527 } 528 529 private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, 530 Configuration configuration, int width, int height) { 531 outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi; 532 outMetrics.density = outMetrics.noncompatDensity = 533 logicalDensityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; 534 outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density; 535 outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi; 536 outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi; 537 538 width = (configuration != null 539 && configuration.screenWidthDp != Configuration.SCREEN_WIDTH_DP_UNDEFINED) 540 ? (int)((configuration.screenWidthDp * outMetrics.density) + 0.5f) : width; 541 height = (configuration != null 542 && configuration.screenHeightDp != Configuration.SCREEN_HEIGHT_DP_UNDEFINED) 543 ? (int)((configuration.screenHeightDp * outMetrics.density) + 0.5f) : height; 544 545 outMetrics.noncompatWidthPixels = outMetrics.widthPixels = width; 546 outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height; 547 548 if (!compatInfo.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) { 549 compatInfo.applyToDisplayMetrics(outMetrics); 550 } 551 } 552 553 // For debugging purposes 554 @Override 555 public String toString() { 556 StringBuilder sb = new StringBuilder(); 557 sb.append("DisplayInfo{\""); 558 sb.append(name); 559 sb.append("\", uniqueId \""); 560 sb.append(uniqueId); 561 sb.append("\", app "); 562 sb.append(appWidth); 563 sb.append(" x "); 564 sb.append(appHeight); 565 sb.append(", real "); 566 sb.append(logicalWidth); 567 sb.append(" x "); 568 sb.append(logicalHeight); 569 if (overscanLeft != 0 || overscanTop != 0 || overscanRight != 0 || overscanBottom != 0) { 570 sb.append(", overscan ("); 571 sb.append(overscanLeft); 572 sb.append(","); 573 sb.append(overscanTop); 574 sb.append(","); 575 sb.append(overscanRight); 576 sb.append(","); 577 sb.append(overscanBottom); 578 sb.append(")"); 579 } 580 sb.append(", largest app "); 581 sb.append(largestNominalAppWidth); 582 sb.append(" x "); 583 sb.append(largestNominalAppHeight); 584 sb.append(", smallest app "); 585 sb.append(smallestNominalAppWidth); 586 sb.append(" x "); 587 sb.append(smallestNominalAppHeight); 588 sb.append(", mode "); 589 sb.append(modeId); 590 sb.append(", defaultMode "); 591 sb.append(defaultModeId); 592 sb.append(", modes "); 593 sb.append(Arrays.toString(supportedModes)); 594 sb.append(", colorMode "); 595 sb.append(colorMode); 596 sb.append(", supportedColorModes "); 597 sb.append(Arrays.toString(supportedColorModes)); 598 sb.append(", hdrCapabilities "); 599 sb.append(hdrCapabilities); 600 sb.append(", rotation "); 601 sb.append(rotation); 602 sb.append(", density "); 603 sb.append(logicalDensityDpi); 604 sb.append(" ("); 605 sb.append(physicalXDpi); 606 sb.append(" x "); 607 sb.append(physicalYDpi); 608 sb.append(") dpi, layerStack "); 609 sb.append(layerStack); 610 sb.append(", appVsyncOff "); 611 sb.append(appVsyncOffsetNanos); 612 sb.append(", presDeadline "); 613 sb.append(presentationDeadlineNanos); 614 sb.append(", type "); 615 sb.append(Display.typeToString(type)); 616 if (address != null) { 617 sb.append(", address ").append(address); 618 } 619 sb.append(", state "); 620 sb.append(Display.stateToString(state)); 621 if (ownerUid != 0 || ownerPackageName != null) { 622 sb.append(", owner ").append(ownerPackageName); 623 sb.append(" (uid ").append(ownerUid).append(")"); 624 } 625 sb.append(flagsToString(flags)); 626 sb.append("}"); 627 return sb.toString(); 628 } 629 630 private static String flagsToString(int flags) { 631 StringBuilder result = new StringBuilder(); 632 if ((flags & Display.FLAG_SECURE) != 0) { 633 result.append(", FLAG_SECURE"); 634 } 635 if ((flags & Display.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) { 636 result.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS"); 637 } 638 if ((flags & Display.FLAG_PRIVATE) != 0) { 639 result.append(", FLAG_PRIVATE"); 640 } 641 if ((flags & Display.FLAG_PRESENTATION) != 0) { 642 result.append(", FLAG_PRESENTATION"); 643 } 644 if ((flags & Display.FLAG_SCALING_DISABLED) != 0) { 645 result.append(", FLAG_SCALING_DISABLED"); 646 } 647 if ((flags & Display.FLAG_ROUND) != 0) { 648 result.append(", FLAG_ROUND"); 649 } 650 return result.toString(); 651 } 652 } 653