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 current committed state of the display. For example, this becomes 257 * {@link android.view.Display#STATE_ON} only after the power state ON is fully committed. 258 */ 259 public int committedState; 260 261 /** 262 * The UID of the application that owns this display, or zero if it is owned by the system. 263 * <p> 264 * If the display is private, then only the owner can use it. 265 * </p> 266 */ 267 public int ownerUid; 268 269 /** 270 * The package name of the application that owns this display, or null if it is 271 * owned by the system. 272 * <p> 273 * If the display is private, then only the owner can use it. 274 * </p> 275 */ 276 public String ownerPackageName; 277 278 /** 279 * The refresh rate override for this app. 0 means no override. 280 */ 281 public float refreshRateOverride; 282 283 /** 284 * @hide 285 * Get current remove mode of the display - what actions should be performed with the display's 286 * content when it is removed. 287 * 288 * @see Display#getRemoveMode() 289 */ 290 // TODO (b/114338689): Remove the flag and use IWindowManager#getRemoveContentMode 291 public int removeMode = Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY; 292 293 /** 294 * @hide 295 * The current minimum brightness constraint of the display. Value between 0.0 and 1.0, 296 * derived from the config constraints of the display device of this logical display. 297 */ 298 public float brightnessMinimum; 299 300 /** 301 * @hide 302 * The current maximum brightness constraint of the display. Value between 0.0 and 1.0, 303 * derived from the config constraints of the display device of this logical display. 304 */ 305 public float brightnessMaximum; 306 307 /** 308 * @hide 309 * The current default brightness of the display. Value between 0.0 and 1.0, 310 * derived from the configuration of the display device of this logical display. 311 */ 312 public float brightnessDefault; 313 314 /** 315 * The {@link RoundedCorners} if present, otherwise {@code null}. 316 */ 317 @Nullable 318 public RoundedCorners roundedCorners; 319 320 /** 321 * Install orientation of the display relative to its natural orientation. 322 */ 323 @Surface.Rotation 324 public int installOrientation; 325 326 public static final @android.annotation.NonNull Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() { 327 @Override 328 public DisplayInfo createFromParcel(Parcel source) { 329 return new DisplayInfo(source); 330 } 331 332 @Override 333 public DisplayInfo[] newArray(int size) { 334 return new DisplayInfo[size]; 335 } 336 }; 337 338 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769467) DisplayInfo()339 public DisplayInfo() { 340 } 341 DisplayInfo(DisplayInfo other)342 public DisplayInfo(DisplayInfo other) { 343 copyFrom(other); 344 } 345 DisplayInfo(Parcel source)346 private DisplayInfo(Parcel source) { 347 readFromParcel(source); 348 } 349 350 @Override equals(@ullable Object o)351 public boolean equals(@Nullable Object o) { 352 return o instanceof DisplayInfo && equals((DisplayInfo)o); 353 } 354 equals(DisplayInfo other)355 public boolean equals(DisplayInfo other) { 356 return other != null 357 && layerStack == other.layerStack 358 && flags == other.flags 359 && type == other.type 360 && displayId == other.displayId 361 && displayGroupId == other.displayGroupId 362 && Objects.equals(address, other.address) 363 && Objects.equals(deviceProductInfo, other.deviceProductInfo) 364 && Objects.equals(uniqueId, other.uniqueId) 365 && appWidth == other.appWidth 366 && appHeight == other.appHeight 367 && smallestNominalAppWidth == other.smallestNominalAppWidth 368 && smallestNominalAppHeight == other.smallestNominalAppHeight 369 && largestNominalAppWidth == other.largestNominalAppWidth 370 && largestNominalAppHeight == other.largestNominalAppHeight 371 && logicalWidth == other.logicalWidth 372 && logicalHeight == other.logicalHeight 373 && Objects.equals(displayCutout, other.displayCutout) 374 && rotation == other.rotation 375 && modeId == other.modeId 376 && defaultModeId == other.defaultModeId 377 && Arrays.equals(supportedModes, other.supportedModes) 378 && colorMode == other.colorMode 379 && Arrays.equals(supportedColorModes, other.supportedColorModes) 380 && Objects.equals(hdrCapabilities, other.hdrCapabilities) 381 && Arrays.equals(userDisabledHdrTypes, other.userDisabledHdrTypes) 382 && minimalPostProcessingSupported == other.minimalPostProcessingSupported 383 && logicalDensityDpi == other.logicalDensityDpi 384 && physicalXDpi == other.physicalXDpi 385 && physicalYDpi == other.physicalYDpi 386 && appVsyncOffsetNanos == other.appVsyncOffsetNanos 387 && presentationDeadlineNanos == other.presentationDeadlineNanos 388 && state == other.state 389 && committedState == other.committedState 390 && ownerUid == other.ownerUid 391 && Objects.equals(ownerPackageName, other.ownerPackageName) 392 && removeMode == other.removeMode 393 && getRefreshRate() == other.getRefreshRate() 394 && brightnessMinimum == other.brightnessMinimum 395 && brightnessMaximum == other.brightnessMaximum 396 && brightnessDefault == other.brightnessDefault 397 && Objects.equals(roundedCorners, other.roundedCorners) 398 && installOrientation == other.installOrientation; 399 } 400 401 @Override hashCode()402 public int hashCode() { 403 return 0; // don't care 404 } 405 copyFrom(DisplayInfo other)406 public void copyFrom(DisplayInfo other) { 407 layerStack = other.layerStack; 408 flags = other.flags; 409 type = other.type; 410 displayId = other.displayId; 411 displayGroupId = other.displayGroupId; 412 address = other.address; 413 deviceProductInfo = other.deviceProductInfo; 414 name = other.name; 415 uniqueId = other.uniqueId; 416 appWidth = other.appWidth; 417 appHeight = other.appHeight; 418 smallestNominalAppWidth = other.smallestNominalAppWidth; 419 smallestNominalAppHeight = other.smallestNominalAppHeight; 420 largestNominalAppWidth = other.largestNominalAppWidth; 421 largestNominalAppHeight = other.largestNominalAppHeight; 422 logicalWidth = other.logicalWidth; 423 logicalHeight = other.logicalHeight; 424 displayCutout = other.displayCutout; 425 rotation = other.rotation; 426 modeId = other.modeId; 427 defaultModeId = other.defaultModeId; 428 supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length); 429 colorMode = other.colorMode; 430 supportedColorModes = Arrays.copyOf( 431 other.supportedColorModes, other.supportedColorModes.length); 432 hdrCapabilities = other.hdrCapabilities; 433 userDisabledHdrTypes = other.userDisabledHdrTypes; 434 minimalPostProcessingSupported = other.minimalPostProcessingSupported; 435 logicalDensityDpi = other.logicalDensityDpi; 436 physicalXDpi = other.physicalXDpi; 437 physicalYDpi = other.physicalYDpi; 438 appVsyncOffsetNanos = other.appVsyncOffsetNanos; 439 presentationDeadlineNanos = other.presentationDeadlineNanos; 440 state = other.state; 441 committedState = other.committedState; 442 ownerUid = other.ownerUid; 443 ownerPackageName = other.ownerPackageName; 444 removeMode = other.removeMode; 445 refreshRateOverride = other.refreshRateOverride; 446 brightnessMinimum = other.brightnessMinimum; 447 brightnessMaximum = other.brightnessMaximum; 448 brightnessDefault = other.brightnessDefault; 449 roundedCorners = other.roundedCorners; 450 installOrientation = other.installOrientation; 451 } 452 readFromParcel(Parcel source)453 public void readFromParcel(Parcel source) { 454 layerStack = source.readInt(); 455 flags = source.readInt(); 456 type = source.readInt(); 457 displayId = source.readInt(); 458 displayGroupId = source.readInt(); 459 address = source.readParcelable(null, android.view.DisplayAddress.class); 460 deviceProductInfo = source.readParcelable(null, android.hardware.display.DeviceProductInfo.class); 461 name = source.readString8(); 462 appWidth = source.readInt(); 463 appHeight = source.readInt(); 464 smallestNominalAppWidth = source.readInt(); 465 smallestNominalAppHeight = source.readInt(); 466 largestNominalAppWidth = source.readInt(); 467 largestNominalAppHeight = source.readInt(); 468 logicalWidth = source.readInt(); 469 logicalHeight = source.readInt(); 470 displayCutout = DisplayCutout.ParcelableWrapper.readCutoutFromParcel(source); 471 rotation = source.readInt(); 472 modeId = source.readInt(); 473 defaultModeId = source.readInt(); 474 int nModes = source.readInt(); 475 supportedModes = new Display.Mode[nModes]; 476 for (int i = 0; i < nModes; i++) { 477 supportedModes[i] = Display.Mode.CREATOR.createFromParcel(source); 478 } 479 colorMode = source.readInt(); 480 int nColorModes = source.readInt(); 481 supportedColorModes = new int[nColorModes]; 482 for (int i = 0; i < nColorModes; i++) { 483 supportedColorModes[i] = source.readInt(); 484 } 485 hdrCapabilities = source.readParcelable(null, android.view.Display.HdrCapabilities.class); 486 minimalPostProcessingSupported = source.readBoolean(); 487 logicalDensityDpi = source.readInt(); 488 physicalXDpi = source.readFloat(); 489 physicalYDpi = source.readFloat(); 490 appVsyncOffsetNanos = source.readLong(); 491 presentationDeadlineNanos = source.readLong(); 492 state = source.readInt(); 493 committedState = source.readInt(); 494 ownerUid = source.readInt(); 495 ownerPackageName = source.readString8(); 496 uniqueId = source.readString8(); 497 removeMode = source.readInt(); 498 refreshRateOverride = source.readFloat(); 499 brightnessMinimum = source.readFloat(); 500 brightnessMaximum = source.readFloat(); 501 brightnessDefault = source.readFloat(); 502 roundedCorners = source.readTypedObject(RoundedCorners.CREATOR); 503 int numUserDisabledFormats = source.readInt(); 504 userDisabledHdrTypes = new int[numUserDisabledFormats]; 505 for (int i = 0; i < numUserDisabledFormats; i++) { 506 userDisabledHdrTypes[i] = source.readInt(); 507 } 508 installOrientation = source.readInt(); 509 } 510 511 @Override writeToParcel(Parcel dest, int flags)512 public void writeToParcel(Parcel dest, int flags) { 513 dest.writeInt(layerStack); 514 dest.writeInt(this.flags); 515 dest.writeInt(type); 516 dest.writeInt(displayId); 517 dest.writeInt(displayGroupId); 518 dest.writeParcelable(address, flags); 519 dest.writeParcelable(deviceProductInfo, flags); 520 dest.writeString8(name); 521 dest.writeInt(appWidth); 522 dest.writeInt(appHeight); 523 dest.writeInt(smallestNominalAppWidth); 524 dest.writeInt(smallestNominalAppHeight); 525 dest.writeInt(largestNominalAppWidth); 526 dest.writeInt(largestNominalAppHeight); 527 dest.writeInt(logicalWidth); 528 dest.writeInt(logicalHeight); 529 DisplayCutout.ParcelableWrapper.writeCutoutToParcel(displayCutout, dest, flags); 530 dest.writeInt(rotation); 531 dest.writeInt(modeId); 532 dest.writeInt(defaultModeId); 533 dest.writeInt(supportedModes.length); 534 for (int i = 0; i < supportedModes.length; i++) { 535 supportedModes[i].writeToParcel(dest, flags); 536 } 537 dest.writeInt(colorMode); 538 dest.writeInt(supportedColorModes.length); 539 for (int i = 0; i < supportedColorModes.length; i++) { 540 dest.writeInt(supportedColorModes[i]); 541 } 542 dest.writeParcelable(hdrCapabilities, flags); 543 dest.writeBoolean(minimalPostProcessingSupported); 544 dest.writeInt(logicalDensityDpi); 545 dest.writeFloat(physicalXDpi); 546 dest.writeFloat(physicalYDpi); 547 dest.writeLong(appVsyncOffsetNanos); 548 dest.writeLong(presentationDeadlineNanos); 549 dest.writeInt(state); 550 dest.writeInt(committedState); 551 dest.writeInt(ownerUid); 552 dest.writeString8(ownerPackageName); 553 dest.writeString8(uniqueId); 554 dest.writeInt(removeMode); 555 dest.writeFloat(refreshRateOverride); 556 dest.writeFloat(brightnessMinimum); 557 dest.writeFloat(brightnessMaximum); 558 dest.writeFloat(brightnessDefault); 559 dest.writeTypedObject(roundedCorners, flags); 560 dest.writeInt(userDisabledHdrTypes.length); 561 for (int i = 0; i < userDisabledHdrTypes.length; i++) { 562 dest.writeInt(userDisabledHdrTypes[i]); 563 } 564 dest.writeInt(installOrientation); 565 } 566 567 @Override describeContents()568 public int describeContents() { 569 return 0; 570 } 571 572 /** 573 * Returns the refresh rate the application would experience. 574 */ getRefreshRate()575 public float getRefreshRate() { 576 if (refreshRateOverride > 0) { 577 return refreshRateOverride; 578 } 579 580 return getMode().getRefreshRate(); 581 } 582 getMode()583 public Display.Mode getMode() { 584 return findMode(modeId); 585 } 586 getDefaultMode()587 public Display.Mode getDefaultMode() { 588 return findMode(defaultModeId); 589 } 590 findMode(int id)591 private Display.Mode findMode(int id) { 592 for (int i = 0; i < supportedModes.length; i++) { 593 if (supportedModes[i].getModeId() == id) { 594 return supportedModes[i]; 595 } 596 } 597 throw new IllegalStateException("Unable to locate mode " + id); 598 } 599 600 /** 601 * Returns the id of the "default" mode with the given refresh rate, or {@code 0} if no suitable 602 * mode could be found. 603 */ 604 @Nullable findDefaultModeByRefreshRate(float refreshRate)605 public Display.Mode findDefaultModeByRefreshRate(float refreshRate) { 606 Display.Mode[] modes = supportedModes; 607 Display.Mode defaultMode = getDefaultMode(); 608 for (int i = 0; i < modes.length; i++) { 609 if (modes[i].matches( 610 defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), refreshRate)) { 611 return modes[i]; 612 } 613 } 614 return null; 615 } 616 617 /** 618 * Returns the list of supported refresh rates in the default mode. 619 */ getDefaultRefreshRates()620 public float[] getDefaultRefreshRates() { 621 Display.Mode[] modes = supportedModes; 622 ArraySet<Float> rates = new ArraySet<>(); 623 Display.Mode defaultMode = getDefaultMode(); 624 for (int i = 0; i < modes.length; i++) { 625 Display.Mode mode = modes[i]; 626 if (mode.getPhysicalWidth() == defaultMode.getPhysicalWidth() 627 && mode.getPhysicalHeight() == defaultMode.getPhysicalHeight()) { 628 rates.add(mode.getRefreshRate()); 629 } 630 } 631 float[] result = new float[rates.size()]; 632 int i = 0; 633 for (Float rate : rates) { 634 result[i++] = rate; 635 } 636 return result; 637 } 638 getAppMetrics(DisplayMetrics outMetrics)639 public void getAppMetrics(DisplayMetrics outMetrics) { 640 getAppMetrics(outMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 641 } 642 getAppMetrics(DisplayMetrics outMetrics, DisplayAdjustments displayAdjustments)643 public void getAppMetrics(DisplayMetrics outMetrics, DisplayAdjustments displayAdjustments) { 644 getMetricsWithSize(outMetrics, displayAdjustments.getCompatibilityInfo(), 645 displayAdjustments.getConfiguration(), appWidth, appHeight); 646 } 647 getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci, Configuration configuration)648 public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci, 649 Configuration configuration) { 650 getMetricsWithSize(outMetrics, ci, configuration, appWidth, appHeight); 651 } 652 653 /** 654 * Populates {@code outMetrics} with details of the logical display. Bounds are limited 655 * by the logical size of the display. 656 * 657 * @param outMetrics the {@link DisplayMetrics} to be populated 658 * @param compatInfo the {@link CompatibilityInfo} to be applied 659 * @param configuration the {@link Configuration} 660 */ getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, Configuration configuration)661 public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, 662 Configuration configuration) { 663 getMetricsWithSize(outMetrics, compatInfo, configuration, logicalWidth, logicalHeight); 664 } 665 666 /** 667 * Similar to {@link #getLogicalMetrics}, but the limiting bounds are determined from 668 * {@link WindowConfiguration#getMaxBounds()} 669 */ getMaxBoundsMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, Configuration configuration)670 public void getMaxBoundsMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, 671 Configuration configuration) { 672 Rect bounds = configuration.windowConfiguration.getMaxBounds(); 673 // Pass in null configuration to ensure width and height are not overridden to app bounds. 674 getMetricsWithSize(outMetrics, compatInfo, /* configuration= */ null, 675 bounds.width(), bounds.height()); 676 } 677 getNaturalWidth()678 public int getNaturalWidth() { 679 return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ? 680 logicalWidth : logicalHeight; 681 } 682 getNaturalHeight()683 public int getNaturalHeight() { 684 return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ? 685 logicalHeight : logicalWidth; 686 } 687 isHdr()688 public boolean isHdr() { 689 int[] types = hdrCapabilities != null ? hdrCapabilities.getSupportedHdrTypes() : null; 690 return types != null && types.length > 0; 691 } 692 isWideColorGamut()693 public boolean isWideColorGamut() { 694 for (int colorMode : supportedColorModes) { 695 if (colorMode == Display.COLOR_MODE_DCI_P3 || colorMode > Display.COLOR_MODE_SRGB) { 696 return true; 697 } 698 } 699 return false; 700 } 701 702 /** 703 * Returns true if the specified UID has access to this display. 704 */ hasAccess(int uid)705 public boolean hasAccess(int uid) { 706 return Display.hasAccess(uid, flags, ownerUid, displayId); 707 } 708 getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, Configuration configuration, int width, int height)709 private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, 710 Configuration configuration, int width, int height) { 711 outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi; 712 outMetrics.density = outMetrics.noncompatDensity = 713 logicalDensityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; 714 outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density; 715 outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi; 716 outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi; 717 718 final Rect appBounds = configuration != null 719 ? configuration.windowConfiguration.getAppBounds() : null; 720 width = appBounds != null ? appBounds.width() : width; 721 height = appBounds != null ? appBounds.height() : height; 722 723 outMetrics.noncompatWidthPixels = outMetrics.widthPixels = width; 724 outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height; 725 726 if (!compatInfo.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) { 727 compatInfo.applyToDisplayMetrics(outMetrics); 728 } 729 } 730 731 // For debugging purposes 732 @Override toString()733 public String toString() { 734 StringBuilder sb = new StringBuilder(); 735 sb.append("DisplayInfo{\""); 736 sb.append(name); 737 sb.append("\", displayId "); 738 sb.append(displayId); 739 sb.append("\", displayGroupId "); 740 sb.append(displayGroupId); 741 sb.append(flagsToString(flags)); 742 sb.append(", real "); 743 sb.append(logicalWidth); 744 sb.append(" x "); 745 sb.append(logicalHeight); 746 sb.append(", largest app "); 747 sb.append(largestNominalAppWidth); 748 sb.append(" x "); 749 sb.append(largestNominalAppHeight); 750 sb.append(", smallest app "); 751 sb.append(smallestNominalAppWidth); 752 sb.append(" x "); 753 sb.append(smallestNominalAppHeight); 754 sb.append(", appVsyncOff "); 755 sb.append(appVsyncOffsetNanos); 756 sb.append(", presDeadline "); 757 sb.append(presentationDeadlineNanos); 758 sb.append(", mode "); 759 sb.append(modeId); 760 sb.append(", defaultMode "); 761 sb.append(defaultModeId); 762 sb.append(", modes "); 763 sb.append(Arrays.toString(supportedModes)); 764 sb.append(", hdrCapabilities "); 765 sb.append(hdrCapabilities); 766 sb.append(", userDisabledHdrTypes "); 767 sb.append(Arrays.toString(userDisabledHdrTypes)); 768 sb.append(", minimalPostProcessingSupported "); 769 sb.append(minimalPostProcessingSupported); 770 sb.append(", rotation "); 771 sb.append(rotation); 772 sb.append(", state "); 773 sb.append(Display.stateToString(state)); 774 sb.append(", committedState "); 775 sb.append(Display.stateToString(committedState)); 776 777 if (Process.myUid() != Process.SYSTEM_UID) { 778 sb.append("}"); 779 return sb.toString(); 780 } 781 782 sb.append(", type "); 783 sb.append(Display.typeToString(type)); 784 sb.append(", uniqueId \""); 785 sb.append(uniqueId); 786 sb.append("\", app "); 787 sb.append(appWidth); 788 sb.append(" x "); 789 sb.append(appHeight); 790 sb.append(", density "); 791 sb.append(logicalDensityDpi); 792 sb.append(" ("); 793 sb.append(physicalXDpi); 794 sb.append(" x "); 795 sb.append(physicalYDpi); 796 sb.append(") dpi, layerStack "); 797 sb.append(layerStack); 798 sb.append(", colorMode "); 799 sb.append(colorMode); 800 sb.append(", supportedColorModes "); 801 sb.append(Arrays.toString(supportedColorModes)); 802 if (address != null) { 803 sb.append(", address ").append(address); 804 } 805 sb.append(", deviceProductInfo "); 806 sb.append(deviceProductInfo); 807 if (ownerUid != 0 || ownerPackageName != null) { 808 sb.append(", owner ").append(ownerPackageName); 809 sb.append(" (uid ").append(ownerUid).append(")"); 810 } 811 sb.append(", removeMode "); 812 sb.append(removeMode); 813 sb.append(", refreshRateOverride "); 814 sb.append(refreshRateOverride); 815 sb.append(", brightnessMinimum "); 816 sb.append(brightnessMinimum); 817 sb.append(", brightnessMaximum "); 818 sb.append(brightnessMaximum); 819 sb.append(", brightnessDefault "); 820 sb.append(brightnessDefault); 821 sb.append(", installOrientation "); 822 sb.append(Surface.rotationToString(installOrientation)); 823 sb.append("}"); 824 return sb.toString(); 825 } 826 827 /** 828 * Write to a protocol buffer output stream. 829 * Protocol buffer message definition at {@link android.view.DisplayInfoProto} 830 * 831 * @param protoOutputStream Stream to write the Rect object to. 832 * @param fieldId Field Id of the DisplayInfoProto as defined in the parent message 833 */ dumpDebug(ProtoOutputStream protoOutputStream, long fieldId)834 public void dumpDebug(ProtoOutputStream protoOutputStream, long fieldId) { 835 final long token = protoOutputStream.start(fieldId); 836 protoOutputStream.write(LOGICAL_WIDTH, logicalWidth); 837 protoOutputStream.write(LOGICAL_HEIGHT, logicalHeight); 838 protoOutputStream.write(APP_WIDTH, appWidth); 839 protoOutputStream.write(APP_HEIGHT, appHeight); 840 protoOutputStream.write(NAME, name); 841 protoOutputStream.write(FLAGS, flags); 842 protoOutputStream.end(token); 843 } 844 flagsToString(int flags)845 private static String flagsToString(int flags) { 846 StringBuilder result = new StringBuilder(); 847 if ((flags & Display.FLAG_SECURE) != 0) { 848 result.append(", FLAG_SECURE"); 849 } 850 if ((flags & Display.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) { 851 result.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS"); 852 } 853 if ((flags & Display.FLAG_PRIVATE) != 0) { 854 result.append(", FLAG_PRIVATE"); 855 } 856 if ((flags & Display.FLAG_PRESENTATION) != 0) { 857 result.append(", FLAG_PRESENTATION"); 858 } 859 if ((flags & Display.FLAG_SCALING_DISABLED) != 0) { 860 result.append(", FLAG_SCALING_DISABLED"); 861 } 862 if ((flags & Display.FLAG_ROUND) != 0) { 863 result.append(", FLAG_ROUND"); 864 } 865 if ((flags & Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) { 866 result.append(", FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD"); 867 } 868 if ((flags & Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0) { 869 result.append(", FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS"); 870 } 871 if ((flags & Display.FLAG_TRUSTED) != 0) { 872 result.append(", FLAG_TRUSTED"); 873 } 874 if ((flags & Display.FLAG_OWN_DISPLAY_GROUP) != 0) { 875 result.append(", FLAG_OWN_DISPLAY_GROUP"); 876 } 877 if ((flags & Display.FLAG_ALWAYS_UNLOCKED) != 0) { 878 result.append(", FLAG_ALWAYS_UNLOCKED"); 879 } 880 if ((flags & Display.FLAG_TOUCH_FEEDBACK_DISABLED) != 0) { 881 result.append(", FLAG_TOUCH_FEEDBACK_DISABLED"); 882 } 883 return result.toString(); 884 } 885 } 886