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