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