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