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 static android.view.DisplayInfoProto.APP_HEIGHT; 20 import static android.view.DisplayInfoProto.APP_WIDTH; 21 import static android.view.DisplayInfoProto.FLAGS; 22 import static android.view.DisplayInfoProto.LOGICAL_HEIGHT; 23 import static android.view.DisplayInfoProto.LOGICAL_WIDTH; 24 import static android.view.DisplayInfoProto.NAME; 25 26 import android.annotation.Nullable; 27 import android.app.WindowConfiguration; 28 import android.compat.annotation.UnsupportedAppUsage; 29 import android.content.res.CompatibilityInfo; 30 import android.content.res.Configuration; 31 import android.graphics.Rect; 32 import android.hardware.display.DeviceProductInfo; 33 import android.os.Build; 34 import android.os.Parcel; 35 import android.os.Parcelable; 36 import android.os.Process; 37 import android.util.ArraySet; 38 import android.util.DisplayMetrics; 39 import android.util.proto.ProtoOutputStream; 40 41 import java.util.Arrays; 42 import java.util.Objects; 43 44 /** 45 * Describes the characteristics of a particular logical display. 46 * @hide 47 */ 48 public final class DisplayInfo implements Parcelable { 49 /** 50 * The surface flinger layer stack associated with this logical display. 51 */ 52 public int layerStack; 53 54 /** 55 * Display flags. 56 */ 57 public int flags; 58 59 /** 60 * Display type. 61 */ 62 public int type; 63 64 /** 65 * Logical display identifier. 66 */ 67 public int displayId; 68 69 /** 70 * Display Group identifier. 71 */ 72 public int displayGroupId; 73 74 /** 75 * Display address, or null if none. 76 * Interpretation varies by display type. 77 */ 78 public DisplayAddress address; 79 80 /** 81 * Product-specific information about the display or the directly connected device on the 82 * display chain. For example, if the display is transitively connected, this field may contain 83 * product information about the intermediate device. 84 */ 85 public DeviceProductInfo deviceProductInfo; 86 87 /** 88 * The human-readable name of the display. 89 */ 90 public String name; 91 92 /** 93 * Unique identifier for the display. Shouldn't be displayed to the user. 94 */ 95 public String uniqueId; 96 97 /** 98 * The width of the portion of the display that is available to applications, in pixels. 99 * Represents the size of the display minus any system decorations. 100 */ 101 public int appWidth; 102 103 /** 104 * The height of the portion of the display that is available to applications, in pixels. 105 * Represents the size of the display minus any system decorations. 106 */ 107 public int appHeight; 108 109 /** 110 * The smallest value of {@link #appWidth} that an application is likely to encounter, 111 * in pixels, excepting cases where the width may be even smaller due to the presence 112 * of a soft keyboard, for example. 113 */ 114 public int smallestNominalAppWidth; 115 116 /** 117 * The smallest value of {@link #appHeight} that an application is likely to encounter, 118 * in pixels, excepting cases where the height may be even smaller due to the presence 119 * of a soft keyboard, for example. 120 */ 121 public int smallestNominalAppHeight; 122 123 /** 124 * The largest value of {@link #appWidth} that an application is likely to encounter, 125 * in pixels, excepting cases where the width may be even larger due to system decorations 126 * such as the status bar being hidden, for example. 127 */ 128 public int largestNominalAppWidth; 129 130 /** 131 * The largest value of {@link #appHeight} that an application is likely to encounter, 132 * in pixels, excepting cases where the height may be even larger due to system decorations 133 * such as the status bar being hidden, for example. 134 */ 135 public int largestNominalAppHeight; 136 137 /** 138 * The logical width of the display, in pixels. 139 * Represents the usable size of the display which may be smaller than the 140 * physical size when the system is emulating a smaller display. 141 */ 142 @UnsupportedAppUsage 143 public int logicalWidth; 144 145 /** 146 * The logical height of the display, in pixels. 147 * Represents the usable size of the display which may be smaller than the 148 * physical size when the system is emulating a smaller display. 149 */ 150 @UnsupportedAppUsage 151 public int logicalHeight; 152 153 /** 154 * The {@link DisplayCutout} if present, otherwise {@code null}. 155 * 156 * @hide 157 */ 158 // Remark on @UnsupportedAppUsage: Display.getCutout should be used instead 159 @Nullable 160 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) 161 public DisplayCutout displayCutout; 162 163 /** 164 * The rotation of the display relative to its natural orientation. 165 * May be one of {@link android.view.Surface#ROTATION_0}, 166 * {@link android.view.Surface#ROTATION_90}, {@link android.view.Surface#ROTATION_180}, 167 * {@link android.view.Surface#ROTATION_270}. 168 * <p> 169 * The value of this field is indeterminate if the logical display is presented on 170 * more than one physical display. 171 * </p> 172 */ 173 @Surface.Rotation 174 @UnsupportedAppUsage 175 public int rotation; 176 177 /** 178 * The active display mode. 179 */ 180 public int modeId; 181 182 /** 183 * The default display mode. 184 */ 185 public int defaultModeId; 186 187 /** 188 * The supported modes of this display. 189 */ 190 public Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY; 191 192 /** The active color mode. */ 193 public int colorMode; 194 195 /** The list of supported color modes */ 196 public int[] supportedColorModes = { Display.COLOR_MODE_DEFAULT }; 197 198 /** The display's HDR capabilities */ 199 public Display.HdrCapabilities hdrCapabilities; 200 201 /** The formats disabled by user **/ 202 public int[] userDisabledHdrTypes = {}; 203 204 /** 205 * Indicates whether the display can be switched into a mode with minimal post 206 * processing. 207 * 208 * @see android.view.Display#isMinimalPostProcessingSupported 209 */ 210 public boolean minimalPostProcessingSupported; 211 212 /** 213 * The logical display density which is the basis for density-independent 214 * pixels. 215 */ 216 public int logicalDensityDpi; 217 218 /** 219 * The exact physical pixels per inch of the screen in the X dimension. 220 * <p> 221 * The value of this field is indeterminate if the logical display is presented on 222 * more than one physical display. 223 * </p> 224 */ 225 public float physicalXDpi; 226 227 /** 228 * The exact physical pixels per inch of the screen in the Y dimension. 229 * <p> 230 * The value of this field is indeterminate if the logical display is presented on 231 * more than one physical display. 232 * </p> 233 */ 234 public float physicalYDpi; 235 236 /** 237 * This is a positive value indicating the phase offset of the VSYNC events provided by 238 * Choreographer relative to the display refresh. For example, if Choreographer reports 239 * that the refresh occurred at time N, it actually occurred at (N - appVsyncOffsetNanos). 240 */ 241 public long appVsyncOffsetNanos; 242 243 /** 244 * This is how far in advance a buffer must be queued for presentation at 245 * a given time. If you want a buffer to appear on the screen at 246 * time N, you must submit the buffer before (N - bufferDeadlineNanos). 247 */ 248 public long presentationDeadlineNanos; 249 250 /** 251 * The state of the display, such as {@link android.view.Display#STATE_ON}. 252 */ 253 public int state; 254 255 /** 256 * The UID of the application that owns this display, or zero if it is owned by the system. 257 * <p> 258 * If the display is private, then only the owner can use it. 259 * </p> 260 */ 261 public int ownerUid; 262 263 /** 264 * The package name of the application that owns this display, or null if it is 265 * owned by the system. 266 * <p> 267 * If the display is private, then only the owner can use it. 268 * </p> 269 */ 270 public String ownerPackageName; 271 272 /** 273 * The refresh rate override for this app. 0 means no override. 274 */ 275 public float refreshRateOverride; 276 277 /** 278 * @hide 279 * Get current remove mode of the display - what actions should be performed with the display's 280 * content when it is removed. 281 * 282 * @see Display#getRemoveMode() 283 */ 284 // TODO (b/114338689): Remove the flag and use IWindowManager#getRemoveContentMode 285 public int removeMode = Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY; 286 287 /** 288 * @hide 289 * The current minimum brightness constraint of the display. Value between 0.0 and 1.0, 290 * derived from the config constraints of the display device of this logical display. 291 */ 292 public float brightnessMinimum; 293 294 /** 295 * @hide 296 * The current maximum brightness constraint of the display. Value between 0.0 and 1.0, 297 * derived from the config constraints of the display device of this logical display. 298 */ 299 public float brightnessMaximum; 300 301 /** 302 * @hide 303 * The current default brightness of the display. Value between 0.0 and 1.0, 304 * derived from the configuration of the display device of this logical display. 305 */ 306 public float brightnessDefault; 307 308 /** 309 * The {@link RoundedCorners} if present, otherwise {@code null}. 310 */ 311 @Nullable 312 public RoundedCorners roundedCorners; 313 314 public static final @android.annotation.NonNull Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() { 315 @Override 316 public DisplayInfo createFromParcel(Parcel source) { 317 return new DisplayInfo(source); 318 } 319 320 @Override 321 public DisplayInfo[] newArray(int size) { 322 return new DisplayInfo[size]; 323 } 324 }; 325 326 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769467) DisplayInfo()327 public DisplayInfo() { 328 } 329 DisplayInfo(DisplayInfo other)330 public DisplayInfo(DisplayInfo other) { 331 copyFrom(other); 332 } 333 DisplayInfo(Parcel source)334 private DisplayInfo(Parcel source) { 335 readFromParcel(source); 336 } 337 338 @Override equals(@ullable Object o)339 public boolean equals(@Nullable Object o) { 340 return o instanceof DisplayInfo && equals((DisplayInfo)o); 341 } 342 equals(DisplayInfo other)343 public boolean equals(DisplayInfo other) { 344 return other != null 345 && layerStack == other.layerStack 346 && flags == other.flags 347 && type == other.type 348 && displayId == other.displayId 349 && displayGroupId == other.displayGroupId 350 && Objects.equals(address, other.address) 351 && Objects.equals(deviceProductInfo, other.deviceProductInfo) 352 && Objects.equals(uniqueId, other.uniqueId) 353 && appWidth == other.appWidth 354 && appHeight == other.appHeight 355 && smallestNominalAppWidth == other.smallestNominalAppWidth 356 && smallestNominalAppHeight == other.smallestNominalAppHeight 357 && largestNominalAppWidth == other.largestNominalAppWidth 358 && largestNominalAppHeight == other.largestNominalAppHeight 359 && logicalWidth == other.logicalWidth 360 && logicalHeight == other.logicalHeight 361 && Objects.equals(displayCutout, other.displayCutout) 362 && rotation == other.rotation 363 && modeId == other.modeId 364 && defaultModeId == other.defaultModeId 365 && Arrays.equals(supportedModes, other.supportedModes) 366 && colorMode == other.colorMode 367 && Arrays.equals(supportedColorModes, other.supportedColorModes) 368 && Objects.equals(hdrCapabilities, other.hdrCapabilities) 369 && Arrays.equals(userDisabledHdrTypes, other.userDisabledHdrTypes) 370 && minimalPostProcessingSupported == other.minimalPostProcessingSupported 371 && logicalDensityDpi == other.logicalDensityDpi 372 && physicalXDpi == other.physicalXDpi 373 && physicalYDpi == other.physicalYDpi 374 && appVsyncOffsetNanos == other.appVsyncOffsetNanos 375 && presentationDeadlineNanos == other.presentationDeadlineNanos 376 && state == other.state 377 && ownerUid == other.ownerUid 378 && Objects.equals(ownerPackageName, other.ownerPackageName) 379 && removeMode == other.removeMode 380 && getRefreshRate() == other.getRefreshRate() 381 && brightnessMinimum == other.brightnessMinimum 382 && brightnessMaximum == other.brightnessMaximum 383 && brightnessDefault == other.brightnessDefault 384 && Objects.equals(roundedCorners, other.roundedCorners); 385 } 386 387 @Override hashCode()388 public int hashCode() { 389 return 0; // don't care 390 } 391 copyFrom(DisplayInfo other)392 public void copyFrom(DisplayInfo other) { 393 layerStack = other.layerStack; 394 flags = other.flags; 395 type = other.type; 396 displayId = other.displayId; 397 displayGroupId = other.displayGroupId; 398 address = other.address; 399 deviceProductInfo = other.deviceProductInfo; 400 name = other.name; 401 uniqueId = other.uniqueId; 402 appWidth = other.appWidth; 403 appHeight = other.appHeight; 404 smallestNominalAppWidth = other.smallestNominalAppWidth; 405 smallestNominalAppHeight = other.smallestNominalAppHeight; 406 largestNominalAppWidth = other.largestNominalAppWidth; 407 largestNominalAppHeight = other.largestNominalAppHeight; 408 logicalWidth = other.logicalWidth; 409 logicalHeight = other.logicalHeight; 410 displayCutout = other.displayCutout; 411 rotation = other.rotation; 412 modeId = other.modeId; 413 defaultModeId = other.defaultModeId; 414 supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length); 415 colorMode = other.colorMode; 416 supportedColorModes = Arrays.copyOf( 417 other.supportedColorModes, other.supportedColorModes.length); 418 hdrCapabilities = other.hdrCapabilities; 419 userDisabledHdrTypes = other.userDisabledHdrTypes; 420 minimalPostProcessingSupported = other.minimalPostProcessingSupported; 421 logicalDensityDpi = other.logicalDensityDpi; 422 physicalXDpi = other.physicalXDpi; 423 physicalYDpi = other.physicalYDpi; 424 appVsyncOffsetNanos = other.appVsyncOffsetNanos; 425 presentationDeadlineNanos = other.presentationDeadlineNanos; 426 state = other.state; 427 ownerUid = other.ownerUid; 428 ownerPackageName = other.ownerPackageName; 429 removeMode = other.removeMode; 430 refreshRateOverride = other.refreshRateOverride; 431 brightnessMinimum = other.brightnessMinimum; 432 brightnessMaximum = other.brightnessMaximum; 433 brightnessDefault = other.brightnessDefault; 434 roundedCorners = other.roundedCorners; 435 } 436 readFromParcel(Parcel source)437 public void readFromParcel(Parcel source) { 438 layerStack = source.readInt(); 439 flags = source.readInt(); 440 type = source.readInt(); 441 displayId = source.readInt(); 442 displayGroupId = source.readInt(); 443 address = source.readParcelable(null); 444 deviceProductInfo = source.readParcelable(null); 445 name = source.readString8(); 446 appWidth = source.readInt(); 447 appHeight = source.readInt(); 448 smallestNominalAppWidth = source.readInt(); 449 smallestNominalAppHeight = source.readInt(); 450 largestNominalAppWidth = source.readInt(); 451 largestNominalAppHeight = source.readInt(); 452 logicalWidth = source.readInt(); 453 logicalHeight = source.readInt(); 454 displayCutout = DisplayCutout.ParcelableWrapper.readCutoutFromParcel(source); 455 rotation = source.readInt(); 456 modeId = source.readInt(); 457 defaultModeId = source.readInt(); 458 int nModes = source.readInt(); 459 supportedModes = new Display.Mode[nModes]; 460 for (int i = 0; i < nModes; i++) { 461 supportedModes[i] = Display.Mode.CREATOR.createFromParcel(source); 462 } 463 colorMode = source.readInt(); 464 int nColorModes = source.readInt(); 465 supportedColorModes = new int[nColorModes]; 466 for (int i = 0; i < nColorModes; i++) { 467 supportedColorModes[i] = source.readInt(); 468 } 469 hdrCapabilities = source.readParcelable(null); 470 minimalPostProcessingSupported = source.readBoolean(); 471 logicalDensityDpi = source.readInt(); 472 physicalXDpi = source.readFloat(); 473 physicalYDpi = source.readFloat(); 474 appVsyncOffsetNanos = source.readLong(); 475 presentationDeadlineNanos = source.readLong(); 476 state = source.readInt(); 477 ownerUid = source.readInt(); 478 ownerPackageName = source.readString8(); 479 uniqueId = source.readString8(); 480 removeMode = source.readInt(); 481 refreshRateOverride = source.readFloat(); 482 brightnessMinimum = source.readFloat(); 483 brightnessMaximum = source.readFloat(); 484 brightnessDefault = source.readFloat(); 485 roundedCorners = source.readTypedObject(RoundedCorners.CREATOR); 486 int numUserDisabledFormats = source.readInt(); 487 userDisabledHdrTypes = new int[numUserDisabledFormats]; 488 for (int i = 0; i < numUserDisabledFormats; i++) { 489 userDisabledHdrTypes[i] = source.readInt(); 490 } 491 } 492 493 @Override writeToParcel(Parcel dest, int flags)494 public void writeToParcel(Parcel dest, int flags) { 495 dest.writeInt(layerStack); 496 dest.writeInt(this.flags); 497 dest.writeInt(type); 498 dest.writeInt(displayId); 499 dest.writeInt(displayGroupId); 500 dest.writeParcelable(address, flags); 501 dest.writeParcelable(deviceProductInfo, flags); 502 dest.writeString8(name); 503 dest.writeInt(appWidth); 504 dest.writeInt(appHeight); 505 dest.writeInt(smallestNominalAppWidth); 506 dest.writeInt(smallestNominalAppHeight); 507 dest.writeInt(largestNominalAppWidth); 508 dest.writeInt(largestNominalAppHeight); 509 dest.writeInt(logicalWidth); 510 dest.writeInt(logicalHeight); 511 DisplayCutout.ParcelableWrapper.writeCutoutToParcel(displayCutout, dest, flags); 512 dest.writeInt(rotation); 513 dest.writeInt(modeId); 514 dest.writeInt(defaultModeId); 515 dest.writeInt(supportedModes.length); 516 for (int i = 0; i < supportedModes.length; i++) { 517 supportedModes[i].writeToParcel(dest, flags); 518 } 519 dest.writeInt(colorMode); 520 dest.writeInt(supportedColorModes.length); 521 for (int i = 0; i < supportedColorModes.length; i++) { 522 dest.writeInt(supportedColorModes[i]); 523 } 524 dest.writeParcelable(hdrCapabilities, flags); 525 dest.writeBoolean(minimalPostProcessingSupported); 526 dest.writeInt(logicalDensityDpi); 527 dest.writeFloat(physicalXDpi); 528 dest.writeFloat(physicalYDpi); 529 dest.writeLong(appVsyncOffsetNanos); 530 dest.writeLong(presentationDeadlineNanos); 531 dest.writeInt(state); 532 dest.writeInt(ownerUid); 533 dest.writeString8(ownerPackageName); 534 dest.writeString8(uniqueId); 535 dest.writeInt(removeMode); 536 dest.writeFloat(refreshRateOverride); 537 dest.writeFloat(brightnessMinimum); 538 dest.writeFloat(brightnessMaximum); 539 dest.writeFloat(brightnessDefault); 540 dest.writeTypedObject(roundedCorners, flags); 541 dest.writeInt(userDisabledHdrTypes.length); 542 for (int i = 0; i < userDisabledHdrTypes.length; i++) { 543 dest.writeInt(userDisabledHdrTypes[i]); 544 } 545 } 546 547 @Override describeContents()548 public int describeContents() { 549 return 0; 550 } 551 552 /** 553 * Returns the refresh rate the application would experience. 554 */ getRefreshRate()555 public float getRefreshRate() { 556 if (refreshRateOverride > 0) { 557 return refreshRateOverride; 558 } 559 560 return getMode().getRefreshRate(); 561 } 562 getMode()563 public Display.Mode getMode() { 564 return findMode(modeId); 565 } 566 getDefaultMode()567 public Display.Mode getDefaultMode() { 568 return findMode(defaultModeId); 569 } 570 findMode(int id)571 private Display.Mode findMode(int id) { 572 for (int i = 0; i < supportedModes.length; i++) { 573 if (supportedModes[i].getModeId() == id) { 574 return supportedModes[i]; 575 } 576 } 577 throw new IllegalStateException("Unable to locate mode " + id); 578 } 579 580 /** 581 * Returns the id of the "default" mode with the given refresh rate, or {@code 0} if no suitable 582 * mode could be found. 583 */ 584 @Nullable findDefaultModeByRefreshRate(float refreshRate)585 public Display.Mode findDefaultModeByRefreshRate(float refreshRate) { 586 Display.Mode[] modes = supportedModes; 587 Display.Mode defaultMode = getDefaultMode(); 588 for (int i = 0; i < modes.length; i++) { 589 if (modes[i].matches( 590 defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), refreshRate)) { 591 return modes[i]; 592 } 593 } 594 return null; 595 } 596 597 /** 598 * Returns the list of supported refresh rates in the default mode. 599 */ getDefaultRefreshRates()600 public float[] getDefaultRefreshRates() { 601 Display.Mode[] modes = supportedModes; 602 ArraySet<Float> rates = new ArraySet<>(); 603 Display.Mode defaultMode = getDefaultMode(); 604 for (int i = 0; i < modes.length; i++) { 605 Display.Mode mode = modes[i]; 606 if (mode.getPhysicalWidth() == defaultMode.getPhysicalWidth() 607 && mode.getPhysicalHeight() == defaultMode.getPhysicalHeight()) { 608 rates.add(mode.getRefreshRate()); 609 } 610 } 611 float[] result = new float[rates.size()]; 612 int i = 0; 613 for (Float rate : rates) { 614 result[i++] = rate; 615 } 616 return result; 617 } 618 getAppMetrics(DisplayMetrics outMetrics)619 public void getAppMetrics(DisplayMetrics outMetrics) { 620 getAppMetrics(outMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 621 } 622 getAppMetrics(DisplayMetrics outMetrics, DisplayAdjustments displayAdjustments)623 public void getAppMetrics(DisplayMetrics outMetrics, DisplayAdjustments displayAdjustments) { 624 getMetricsWithSize(outMetrics, displayAdjustments.getCompatibilityInfo(), 625 displayAdjustments.getConfiguration(), appWidth, appHeight); 626 } 627 getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci, Configuration configuration)628 public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci, 629 Configuration configuration) { 630 getMetricsWithSize(outMetrics, ci, configuration, appWidth, appHeight); 631 } 632 633 /** 634 * Populates {@code outMetrics} with details of the logical display. Bounds are limited 635 * by the logical size of the display. 636 * 637 * @param outMetrics the {@link DisplayMetrics} to be populated 638 * @param compatInfo the {@link CompatibilityInfo} to be applied 639 * @param configuration the {@link Configuration} 640 */ getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, Configuration configuration)641 public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, 642 Configuration configuration) { 643 getMetricsWithSize(outMetrics, compatInfo, configuration, logicalWidth, logicalHeight); 644 } 645 646 /** 647 * Similar to {@link #getLogicalMetrics}, but the limiting bounds are determined from 648 * {@link WindowConfiguration#getMaxBounds()} 649 */ getMaxBoundsMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, Configuration configuration)650 public void getMaxBoundsMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, 651 Configuration configuration) { 652 Rect bounds = configuration.windowConfiguration.getMaxBounds(); 653 // Pass in null configuration to ensure width and height are not overridden to app bounds. 654 getMetricsWithSize(outMetrics, compatInfo, /* configuration= */ null, 655 bounds.width(), bounds.height()); 656 } 657 getNaturalWidth()658 public int getNaturalWidth() { 659 return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ? 660 logicalWidth : logicalHeight; 661 } 662 getNaturalHeight()663 public int getNaturalHeight() { 664 return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ? 665 logicalHeight : logicalWidth; 666 } 667 isHdr()668 public boolean isHdr() { 669 int[] types = hdrCapabilities != null ? hdrCapabilities.getSupportedHdrTypes() : null; 670 return types != null && types.length > 0; 671 } 672 isWideColorGamut()673 public boolean isWideColorGamut() { 674 for (int colorMode : supportedColorModes) { 675 if (colorMode == Display.COLOR_MODE_DCI_P3 || colorMode > Display.COLOR_MODE_SRGB) { 676 return true; 677 } 678 } 679 return false; 680 } 681 682 /** 683 * Returns true if the specified UID has access to this display. 684 */ hasAccess(int uid)685 public boolean hasAccess(int uid) { 686 return Display.hasAccess(uid, flags, ownerUid, displayId); 687 } 688 getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, Configuration configuration, int width, int height)689 private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, 690 Configuration configuration, int width, int height) { 691 outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi; 692 outMetrics.density = outMetrics.noncompatDensity = 693 logicalDensityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; 694 outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density; 695 outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi; 696 outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi; 697 698 final Rect appBounds = configuration != null 699 ? configuration.windowConfiguration.getAppBounds() : null; 700 width = appBounds != null ? appBounds.width() : width; 701 height = appBounds != null ? appBounds.height() : height; 702 703 outMetrics.noncompatWidthPixels = outMetrics.widthPixels = width; 704 outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height; 705 706 if (!compatInfo.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) { 707 compatInfo.applyToDisplayMetrics(outMetrics); 708 } 709 } 710 711 // For debugging purposes 712 @Override toString()713 public String toString() { 714 StringBuilder sb = new StringBuilder(); 715 sb.append("DisplayInfo{\""); 716 sb.append(name); 717 sb.append("\", displayId "); 718 sb.append(displayId); 719 sb.append("\", displayGroupId "); 720 sb.append(displayGroupId); 721 sb.append(flagsToString(flags)); 722 sb.append(", real "); 723 sb.append(logicalWidth); 724 sb.append(" x "); 725 sb.append(logicalHeight); 726 sb.append(", largest app "); 727 sb.append(largestNominalAppWidth); 728 sb.append(" x "); 729 sb.append(largestNominalAppHeight); 730 sb.append(", smallest app "); 731 sb.append(smallestNominalAppWidth); 732 sb.append(" x "); 733 sb.append(smallestNominalAppHeight); 734 sb.append(", appVsyncOff "); 735 sb.append(appVsyncOffsetNanos); 736 sb.append(", presDeadline "); 737 sb.append(presentationDeadlineNanos); 738 sb.append(", mode "); 739 sb.append(modeId); 740 sb.append(", defaultMode "); 741 sb.append(defaultModeId); 742 sb.append(", modes "); 743 sb.append(Arrays.toString(supportedModes)); 744 sb.append(", hdrCapabilities "); 745 sb.append(hdrCapabilities); 746 sb.append(", userDisabledHdrTypes "); 747 sb.append(Arrays.toString(userDisabledHdrTypes)); 748 sb.append(", minimalPostProcessingSupported "); 749 sb.append(minimalPostProcessingSupported); 750 sb.append(", rotation "); 751 sb.append(rotation); 752 sb.append(", state "); 753 sb.append(Display.stateToString(state)); 754 755 if (Process.myUid() != Process.SYSTEM_UID) { 756 sb.append("}"); 757 return sb.toString(); 758 } 759 760 sb.append(", type "); 761 sb.append(Display.typeToString(type)); 762 sb.append(", uniqueId \""); 763 sb.append(uniqueId); 764 sb.append("\", app "); 765 sb.append(appWidth); 766 sb.append(" x "); 767 sb.append(appHeight); 768 sb.append(", density "); 769 sb.append(logicalDensityDpi); 770 sb.append(" ("); 771 sb.append(physicalXDpi); 772 sb.append(" x "); 773 sb.append(physicalYDpi); 774 sb.append(") dpi, layerStack "); 775 sb.append(layerStack); 776 sb.append(", colorMode "); 777 sb.append(colorMode); 778 sb.append(", supportedColorModes "); 779 sb.append(Arrays.toString(supportedColorModes)); 780 if (address != null) { 781 sb.append(", address ").append(address); 782 } 783 sb.append(", deviceProductInfo "); 784 sb.append(deviceProductInfo); 785 if (ownerUid != 0 || ownerPackageName != null) { 786 sb.append(", owner ").append(ownerPackageName); 787 sb.append(" (uid ").append(ownerUid).append(")"); 788 } 789 sb.append(", removeMode "); 790 sb.append(removeMode); 791 sb.append(", refreshRateOverride "); 792 sb.append(refreshRateOverride); 793 sb.append(", brightnessMinimum "); 794 sb.append(brightnessMinimum); 795 sb.append(", brightnessMaximum "); 796 sb.append(brightnessMaximum); 797 sb.append(", brightnessDefault "); 798 sb.append(brightnessDefault); 799 sb.append("}"); 800 return sb.toString(); 801 } 802 803 /** 804 * Write to a protocol buffer output stream. 805 * Protocol buffer message definition at {@link android.view.DisplayInfoProto} 806 * 807 * @param protoOutputStream Stream to write the Rect object to. 808 * @param fieldId Field Id of the DisplayInfoProto as defined in the parent message 809 */ dumpDebug(ProtoOutputStream protoOutputStream, long fieldId)810 public void dumpDebug(ProtoOutputStream protoOutputStream, long fieldId) { 811 final long token = protoOutputStream.start(fieldId); 812 protoOutputStream.write(LOGICAL_WIDTH, logicalWidth); 813 protoOutputStream.write(LOGICAL_HEIGHT, logicalHeight); 814 protoOutputStream.write(APP_WIDTH, appWidth); 815 protoOutputStream.write(APP_HEIGHT, appHeight); 816 protoOutputStream.write(NAME, name); 817 protoOutputStream.write(FLAGS, flags); 818 protoOutputStream.end(token); 819 } 820 flagsToString(int flags)821 private static String flagsToString(int flags) { 822 StringBuilder result = new StringBuilder(); 823 if ((flags & Display.FLAG_SECURE) != 0) { 824 result.append(", FLAG_SECURE"); 825 } 826 if ((flags & Display.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) { 827 result.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS"); 828 } 829 if ((flags & Display.FLAG_PRIVATE) != 0) { 830 result.append(", FLAG_PRIVATE"); 831 } 832 if ((flags & Display.FLAG_PRESENTATION) != 0) { 833 result.append(", FLAG_PRESENTATION"); 834 } 835 if ((flags & Display.FLAG_SCALING_DISABLED) != 0) { 836 result.append(", FLAG_SCALING_DISABLED"); 837 } 838 if ((flags & Display.FLAG_ROUND) != 0) { 839 result.append(", FLAG_ROUND"); 840 } 841 if ((flags & Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) { 842 result.append(", FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD"); 843 } 844 if ((flags & Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0) { 845 result.append(", FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS"); 846 } 847 if ((flags & Display.FLAG_TRUSTED) != 0) { 848 result.append(", FLAG_TRUSTED"); 849 } 850 if ((flags & Display.FLAG_OWN_DISPLAY_GROUP) != 0) { 851 result.append(", FLAG_OWN_DISPLAY_GROUP"); 852 } 853 return result.toString(); 854 } 855 } 856