1 /* 2 * Copyright (C) 2006 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.Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE; 20 import static android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS; 21 22 import android.annotation.IntDef; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.annotation.RequiresPermission; 26 import android.annotation.SuppressLint; 27 import android.annotation.TestApi; 28 import android.app.ActivityThread; 29 import android.app.KeyguardManager; 30 import android.app.WindowConfiguration; 31 import android.compat.annotation.UnsupportedAppUsage; 32 import android.content.ComponentName; 33 import android.content.res.CompatibilityInfo; 34 import android.content.res.Configuration; 35 import android.content.res.Resources; 36 import android.graphics.ColorSpace; 37 import android.graphics.PixelFormat; 38 import android.graphics.Point; 39 import android.graphics.Rect; 40 import android.hardware.display.BrightnessInfo; 41 import android.hardware.display.DeviceProductInfo; 42 import android.hardware.display.DisplayManager; 43 import android.hardware.display.DisplayManagerGlobal; 44 import android.os.Build; 45 import android.os.Parcel; 46 import android.os.Parcelable; 47 import android.os.Process; 48 import android.os.SystemClock; 49 import android.util.ArraySet; 50 import android.util.DisplayMetrics; 51 import android.util.Log; 52 53 import com.android.internal.R; 54 55 import java.lang.annotation.Retention; 56 import java.lang.annotation.RetentionPolicy; 57 import java.util.ArrayList; 58 import java.util.Arrays; 59 import java.util.List; 60 import java.util.Optional; 61 62 /** 63 * Provides information about the size and density of a logical display. 64 * <p> 65 * The display area is described in two different ways. 66 * <ul> 67 * <li>The application display area specifies the part of the display that may contain 68 * an application window, excluding the system decorations. The application display area may 69 * be smaller than the real display area because the system subtracts the space needed 70 * for decor elements such as the status bar. Use {@link WindowMetrics#getBounds()} to query the 71 * application window bounds.</li> 72 * <li>The real display area specifies the part of the display that is accessible to an application 73 * in the current system state. The real display area may be smaller than the physical size of the 74 * display in a few scenarios. Use {@link WindowManager#getCurrentWindowMetrics()} to identify the 75 * current size of the activity window. UI-related work, such as choosing UI layouts, should rely 76 * upon {@link WindowMetrics#getBounds()}. See {@link #getRealSize} / {@link #getRealMetrics} for 77 * details.</li> 78 * </ul> 79 * </p><p> 80 * A logical display does not necessarily represent a particular physical display device 81 * such as the internal display or an external display. The contents of a logical 82 * display may be presented on one or more physical displays according to the devices 83 * that are currently attached and whether mirroring has been enabled. 84 * </p> 85 */ 86 public final class Display { 87 private static final String TAG = "Display"; 88 private static final boolean DEBUG = false; 89 90 private final Object mLock = new Object(); 91 private final DisplayManagerGlobal mGlobal; 92 private final int mDisplayId; 93 private final int mFlags; 94 private final int mType; 95 private final int mOwnerUid; 96 private final String mOwnerPackageName; 97 private final Resources mResources; 98 private DisplayAdjustments mDisplayAdjustments; 99 100 @UnsupportedAppUsage 101 private DisplayInfo mDisplayInfo; // never null 102 private boolean mIsValid; 103 104 // Temporary display metrics structure used for compatibility mode. 105 private final DisplayMetrics mTempMetrics = new DisplayMetrics(); 106 107 // We cache the app width and height properties briefly between calls 108 // to getHeight() and getWidth() to ensure that applications perceive 109 // consistent results when the size changes (most of the time). 110 // Applications should now be using WindowMetrics instead. 111 private static final int CACHED_APP_SIZE_DURATION_MILLIS = 20; 112 private long mLastCachedAppSizeUpdate; 113 private int mCachedAppWidthCompat; 114 private int mCachedAppHeightCompat; 115 116 /** 117 * Indicates that the application is started in a different rotation than the real display, so 118 * the display information may be adjusted. That ensures the methods {@link #getRotation}, 119 * {@link #getRealSize}, {@link #getRealMetrics}, and {@link #getCutout} are consistent with how 120 * the application window is laid out. 121 */ 122 private boolean mMayAdjustByFixedRotation; 123 124 /** 125 * Cache if the application is the recents component. 126 * TODO(b/179308296) Remove once Launcher addresses issue 127 */ 128 private Optional<Boolean> mIsRecentsComponent = Optional.empty(); 129 130 /** 131 * The default Display id, which is the id of the primary display assuming there is one. 132 */ 133 public static final int DEFAULT_DISPLAY = 0; 134 135 /** 136 * Invalid display id. 137 */ 138 public static final int INVALID_DISPLAY = -1; 139 140 /** 141 * The default display group id, which is the display group id of the primary display assuming 142 * there is one. 143 * @hide 144 */ 145 public static final int DEFAULT_DISPLAY_GROUP = 0; 146 147 /** 148 * Invalid display group id. 149 * @hide 150 */ 151 public static final int INVALID_DISPLAY_GROUP = -1; 152 153 /** 154 * Display flag: Indicates that the display supports compositing content 155 * that is stored in protected graphics buffers. 156 * <p> 157 * If this flag is set then the display device supports compositing protected buffers. 158 * </p><p> 159 * If this flag is not set then the display device may not support compositing 160 * protected buffers; the user may see a blank region on the screen instead of 161 * the protected content. 162 * </p><p> 163 * Secure (DRM) video decoders may allocate protected graphics buffers to request that 164 * a hardware-protected path be provided between the video decoder and the external 165 * display sink. If a hardware-protected path is not available, then content stored 166 * in protected graphics buffers may not be composited. 167 * </p><p> 168 * An application can use the absence of this flag as a hint that it should not use protected 169 * buffers for this display because the content may not be visible. For example, 170 * if the flag is not set then the application may choose not to show content on this 171 * display, show an informative error message, select an alternate content stream 172 * or adopt a different strategy for decoding content that does not rely on 173 * protected buffers. 174 * </p> 175 * 176 * @see #getFlags 177 */ 178 public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1 << 0; 179 180 /** 181 * Display flag: Indicates that the display has a secure video output and 182 * supports compositing secure surfaces. 183 * <p> 184 * If this flag is set then the display device has a secure video output 185 * and is capable of showing secure surfaces. It may also be capable of 186 * showing {@link #FLAG_SUPPORTS_PROTECTED_BUFFERS protected buffers}. 187 * </p><p> 188 * If this flag is not set then the display device may not have a secure video 189 * output; the user may see a blank region on the screen instead of 190 * the contents of secure surfaces or protected buffers. 191 * </p><p> 192 * Secure surfaces are used to prevent content rendered into those surfaces 193 * by applications from appearing in screenshots or from being viewed 194 * on non-secure displays. Protected buffers are used by secure video decoders 195 * for a similar purpose. 196 * </p><p> 197 * An application creates a window with a secure surface by specifying the 198 * {@link WindowManager.LayoutParams#FLAG_SECURE} window flag. 199 * Likewise, an application creates a {@link SurfaceView} with a secure surface 200 * by calling {@link SurfaceView#setSecure} before attaching the secure view to 201 * its containing window. 202 * </p><p> 203 * An application can use the absence of this flag as a hint that it should not create 204 * secure surfaces or protected buffers on this display because the content may 205 * not be visible. For example, if the flag is not set then the application may 206 * choose not to show content on this display, show an informative error message, 207 * select an alternate content stream or adopt a different strategy for decoding 208 * content that does not rely on secure surfaces or protected buffers. 209 * </p> 210 * 211 * @see #getFlags 212 */ 213 public static final int FLAG_SECURE = 1 << 1; 214 215 /** 216 * Display flag: Indicates that the display is private. Only the application that 217 * owns the display and apps that are already on the display can create windows on it. 218 * 219 * @see #getFlags 220 */ 221 public static final int FLAG_PRIVATE = 1 << 2; 222 223 /** 224 * Display flag: Indicates that the display is a presentation display. 225 * <p> 226 * This flag identifies secondary displays that are suitable for 227 * use as presentation displays such as external or wireless displays. Applications 228 * may automatically project their content to presentation displays to provide 229 * richer second screen experiences. 230 * </p> 231 * 232 * @see #getFlags 233 */ 234 public static final int FLAG_PRESENTATION = 1 << 3; 235 236 /** 237 * Display flag: Indicates that the display has a round shape. 238 * <p> 239 * This flag identifies displays that are circular, elliptical or otherwise 240 * do not permit the user to see all the way to the logical corners of the display. 241 * </p> 242 * 243 * @see #getFlags 244 */ 245 public static final int FLAG_ROUND = 1 << 4; 246 247 /** 248 * Display flag: Indicates that the display can show its content when non-secure keyguard is 249 * shown. 250 * <p> 251 * This flag identifies secondary displays that will continue showing content if keyguard can be 252 * dismissed without entering credentials. 253 * </p><p> 254 * An example of usage is a virtual display which content is displayed on external hardware 255 * display that is not visible to the system directly. 256 * </p> 257 * 258 * @see DisplayManager#VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD 259 * @see KeyguardManager#isDeviceSecure() 260 * @see KeyguardManager#isDeviceLocked() 261 * @see #getFlags 262 * @hide 263 */ 264 // TODO (b/114338689): Remove the flag and use IWindowManager#shouldShowWithInsecureKeyguard 265 public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5; 266 267 /** 268 * Display flag: Indicates that the display should show system decorations. 269 * <p> 270 * This flag identifies secondary displays that should show system decorations, such as status 271 * bar, navigation bar, home activity or IME. 272 * </p> 273 * <p>Note that this flag doesn't work without {@link #FLAG_TRUSTED}</p> 274 * 275 * @see #getFlags() 276 * @hide 277 */ 278 // TODO (b/114338689): Remove the flag and use IWindowManager#setShouldShowSystemDecors 279 public static final int FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 6; 280 281 /** 282 * Flag: The display is trusted to show system decorations and receive inputs without users' 283 * touch. 284 * @see #FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS 285 * 286 * @see #getFlags() 287 * @hide 288 */ 289 @TestApi 290 public static final int FLAG_TRUSTED = 1 << 7; 291 292 /** 293 * Flag: Indicates that the display should not be a part of the default DisplayGroup and 294 * instead be part of a new DisplayGroup. 295 * 296 * @hide 297 * @see #getFlags() 298 */ 299 public static final int FLAG_OWN_DISPLAY_GROUP = 1 << 8; 300 301 /** 302 * Display flag: Indicates that the contents of the display should not be scaled 303 * to fit the physical screen dimensions. Used for development only to emulate 304 * devices with smaller physicals screens while preserving density. 305 * 306 * @hide 307 */ 308 public static final int FLAG_SCALING_DISABLED = 1 << 30; 309 310 /** 311 * Display type: Unknown display type. 312 * @hide 313 */ 314 @UnsupportedAppUsage 315 @TestApi 316 public static final int TYPE_UNKNOWN = 0; 317 318 /** 319 * Display type: Physical display connected through an internal port. 320 * @hide 321 */ 322 @TestApi 323 public static final int TYPE_INTERNAL = 1; 324 325 /** 326 * Display type: Physical display connected through an external port. 327 * @hide 328 */ 329 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 330 @TestApi 331 public static final int TYPE_EXTERNAL = 2; 332 333 /** 334 * Display type: WiFi display. 335 * @hide 336 */ 337 @UnsupportedAppUsage 338 @TestApi 339 public static final int TYPE_WIFI = 3; 340 341 /** 342 * Display type: Overlay display. 343 * @hide 344 */ 345 @TestApi 346 public static final int TYPE_OVERLAY = 4; 347 348 /** 349 * Display type: Virtual display. 350 * @hide 351 */ 352 @UnsupportedAppUsage 353 @TestApi 354 public static final int TYPE_VIRTUAL = 5; 355 356 /** 357 * Display state: The display state is unknown. 358 * 359 * @see #getState 360 */ 361 public static final int STATE_UNKNOWN = ViewProtoEnums.DISPLAY_STATE_UNKNOWN; // 0 362 363 /** 364 * Display state: The display is off. 365 * 366 * @see #getState 367 */ 368 public static final int STATE_OFF = ViewProtoEnums.DISPLAY_STATE_OFF; // 1 369 370 /** 371 * Display state: The display is on. 372 * 373 * @see #getState 374 */ 375 public static final int STATE_ON = ViewProtoEnums.DISPLAY_STATE_ON; // 2 376 377 /** 378 * Display state: The display is dozing in a low power state; it is still 379 * on but is optimized for showing system-provided content while the 380 * device is non-interactive. 381 * 382 * @see #getState 383 * @see android.os.PowerManager#isInteractive 384 */ 385 public static final int STATE_DOZE = ViewProtoEnums.DISPLAY_STATE_DOZE; // 3 386 387 /** 388 * Display state: The display is dozing in a suspended low power state; it is still 389 * on but the CPU is not updating it. This may be used in one of two ways: to show 390 * static system-provided content while the device is non-interactive, or to allow 391 * a "Sidekick" compute resource to update the display. For this reason, the 392 * CPU must not control the display in this mode. 393 * 394 * @see #getState 395 * @see android.os.PowerManager#isInteractive 396 */ 397 public static final int STATE_DOZE_SUSPEND = ViewProtoEnums.DISPLAY_STATE_DOZE_SUSPEND; // 4 398 399 /** 400 * Display state: The display is on and optimized for VR mode. 401 * 402 * @see #getState 403 * @see android.os.PowerManager#isInteractive 404 */ 405 public static final int STATE_VR = ViewProtoEnums.DISPLAY_STATE_VR; // 5 406 407 /** 408 * Display state: The display is in a suspended full power state; it is still 409 * on but the CPU is not updating it. This may be used in one of two ways: to show 410 * static system-provided content while the device is non-interactive, or to allow 411 * a "Sidekick" compute resource to update the display. For this reason, the 412 * CPU must not control the display in this mode. 413 * 414 * @see #getState 415 * @see android.os.PowerManager#isInteractive 416 */ 417 public static final int STATE_ON_SUSPEND = ViewProtoEnums.DISPLAY_STATE_ON_SUSPEND; // 6 418 419 /* The color mode constants defined below must be kept in sync with the ones in 420 * system/core/include/system/graphics-base.h */ 421 422 /** 423 * Display color mode: The current color mode is unknown or invalid. 424 * @hide 425 */ 426 public static final int COLOR_MODE_INVALID = -1; 427 428 /** 429 * Display color mode: The default or native gamut of the display. 430 * @hide 431 */ 432 public static final int COLOR_MODE_DEFAULT = 0; 433 434 /** @hide */ 435 public static final int COLOR_MODE_BT601_625 = 1; 436 /** @hide */ 437 public static final int COLOR_MODE_BT601_625_UNADJUSTED = 2; 438 /** @hide */ 439 public static final int COLOR_MODE_BT601_525 = 3; 440 /** @hide */ 441 public static final int COLOR_MODE_BT601_525_UNADJUSTED = 4; 442 /** @hide */ 443 public static final int COLOR_MODE_BT709 = 5; 444 /** @hide */ 445 public static final int COLOR_MODE_DCI_P3 = 6; 446 /** @hide */ 447 public static final int COLOR_MODE_SRGB = 7; 448 /** @hide */ 449 public static final int COLOR_MODE_ADOBE_RGB = 8; 450 /** @hide */ 451 public static final int COLOR_MODE_DISPLAY_P3 = 9; 452 453 /** @hide **/ 454 @IntDef(prefix = {"COLOR_MODE_"}, value = { 455 COLOR_MODE_INVALID, 456 COLOR_MODE_DEFAULT, 457 COLOR_MODE_BT601_625, 458 COLOR_MODE_BT601_625_UNADJUSTED, 459 COLOR_MODE_BT601_525, 460 COLOR_MODE_BT601_525_UNADJUSTED, 461 COLOR_MODE_BT709, 462 COLOR_MODE_DCI_P3, 463 COLOR_MODE_SRGB, 464 COLOR_MODE_ADOBE_RGB, 465 COLOR_MODE_DISPLAY_P3 466 }) 467 @Retention(RetentionPolicy.SOURCE) 468 public @interface ColorMode {} 469 470 /** 471 * Indicates that when display is removed, all its activities will be moved to the primary 472 * display and the topmost activity should become focused. 473 * 474 * @hide 475 */ 476 // TODO (b/114338689): Remove the flag and use WindowManager#REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY 477 public static final int REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY = 0; 478 /** 479 * Indicates that when display is removed, all its stacks and tasks will be removed, all 480 * activities will be destroyed according to the usual lifecycle. 481 * 482 * @hide 483 */ 484 // TODO (b/114338689): Remove the flag and use WindowManager#REMOVE_CONTENT_MODE_DESTROY 485 public static final int REMOVE_MODE_DESTROY_CONTENT = 1; 486 487 /** @hide */ 488 public static final int DISPLAY_MODE_ID_FOR_FRAME_RATE_OVERRIDE = 0xFF; 489 490 /** 491 * Internal method to create a display. 492 * The display created with this method will have a static {@link DisplayAdjustments} applied. 493 * Applications should use {@link android.content.Context#getDisplay} with 494 * {@link android.app.Activity} or a context associated with a {@link Display} via 495 * {@link android.content.Context#createDisplayContext(Display)} 496 * to get a display object associated with a {@link android.app.Context}, or 497 * {@link android.hardware.display.DisplayManager#getDisplay} to get a display object by id. 498 * 499 * @see android.content.Context#getDisplay() 500 * @see android.content.Context#createDisplayContext(Display) 501 * @hide 502 */ Display(DisplayManagerGlobal global, int displayId, DisplayInfo displayInfo, DisplayAdjustments daj)503 public Display(DisplayManagerGlobal global, int displayId, /*@NotNull*/ DisplayInfo displayInfo, 504 DisplayAdjustments daj) { 505 this(global, displayId, displayInfo, daj, null /*res*/); 506 } 507 508 /** 509 * Internal method to create a display. 510 * The display created with this method will be adjusted based on the adjustments in the 511 * supplied {@link Resources}. 512 * 513 * @hide 514 */ Display(DisplayManagerGlobal global, int displayId, DisplayInfo displayInfo, Resources res)515 public Display(DisplayManagerGlobal global, int displayId, /*@NotNull*/ DisplayInfo displayInfo, 516 Resources res) { 517 this(global, displayId, displayInfo, null /*daj*/, res); 518 } 519 Display(DisplayManagerGlobal global, int displayId, DisplayInfo displayInfo, DisplayAdjustments daj, Resources res)520 private Display(DisplayManagerGlobal global, int displayId, 521 /*@NotNull*/ DisplayInfo displayInfo, DisplayAdjustments daj, Resources res) { 522 mGlobal = global; 523 mDisplayId = displayId; 524 mDisplayInfo = displayInfo; 525 mResources = res; 526 mDisplayAdjustments = mResources != null 527 ? new DisplayAdjustments(mResources.getConfiguration()) 528 : daj != null ? new DisplayAdjustments(daj) : new DisplayAdjustments(); 529 mIsValid = true; 530 531 // Cache properties that cannot change as long as the display is valid. 532 mFlags = displayInfo.flags; 533 mType = displayInfo.type; 534 mOwnerUid = displayInfo.ownerUid; 535 mOwnerPackageName = displayInfo.ownerPackageName; 536 } 537 538 /** 539 * Gets the display id. 540 * <p> 541 * Each logical display has a unique id. 542 * The default display has id {@link #DEFAULT_DISPLAY}. 543 * </p> 544 */ getDisplayId()545 public int getDisplayId() { 546 return mDisplayId; 547 } 548 549 /** 550 * Gets the display unique id. 551 * <p> 552 * Unique id is different from display id because physical displays have stable unique id across 553 * reboots. 554 * 555 * @see com.android.service.display.DisplayDevice#hasStableUniqueId(). 556 * @hide 557 */ getUniqueId()558 public String getUniqueId() { 559 return mDisplayInfo.uniqueId; 560 } 561 562 /** 563 * Returns true if this display is still valid, false if the display has been removed. 564 * 565 * If the display is invalid, then the methods of this class will 566 * continue to report the most recently observed display information. 567 * However, it is unwise (and rather fruitless) to continue using a 568 * {@link Display} object after the display's demise. 569 * 570 * It's possible for a display that was previously invalid to become 571 * valid again if a display with the same id is reconnected. 572 * 573 * @return True if the display is still valid. 574 */ isValid()575 public boolean isValid() { 576 synchronized (mLock) { 577 updateDisplayInfoLocked(); 578 return mIsValid; 579 } 580 } 581 582 /** 583 * Gets a full copy of the display information. 584 * 585 * @param outDisplayInfo The object to receive the copy of the display information. 586 * @return True if the display is still valid. 587 * @hide 588 */ 589 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) getDisplayInfo(DisplayInfo outDisplayInfo)590 public boolean getDisplayInfo(DisplayInfo outDisplayInfo) { 591 synchronized (mLock) { 592 updateDisplayInfoLocked(); 593 outDisplayInfo.copyFrom(mDisplayInfo); 594 return mIsValid; 595 } 596 } 597 598 /** 599 * Gets the display's layer stack. 600 * 601 * Each display has its own independent layer stack upon which surfaces 602 * are placed to be managed by surface flinger. 603 * 604 * @return The display's layer stack number. 605 * @hide 606 */ getLayerStack()607 public int getLayerStack() { 608 synchronized (mLock) { 609 updateDisplayInfoLocked(); 610 return mDisplayInfo.layerStack; 611 } 612 } 613 614 /** 615 * Returns a combination of flags that describe the capabilities of the display. 616 * 617 * @return The display flags. 618 * 619 * @see #FLAG_SUPPORTS_PROTECTED_BUFFERS 620 * @see #FLAG_SECURE 621 * @see #FLAG_PRIVATE 622 * @see #FLAG_ROUND 623 */ getFlags()624 public int getFlags() { 625 return mFlags; 626 } 627 628 /** 629 * Gets the display type. 630 * 631 * @return The display type. 632 * 633 * @see #TYPE_UNKNOWN 634 * @see #TYPE_INTERNAL 635 * @see #TYPE_EXTERNAL 636 * @see #TYPE_WIFI 637 * @see #TYPE_OVERLAY 638 * @see #TYPE_VIRTUAL 639 * @hide 640 */ 641 @UnsupportedAppUsage 642 @TestApi getType()643 public int getType() { 644 return mType; 645 } 646 647 /** 648 * Gets the display address, or null if none. 649 * Interpretation varies by display type. 650 * 651 * @return The display address. 652 * @hide 653 */ getAddress()654 public DisplayAddress getAddress() { 655 synchronized (mLock) { 656 updateDisplayInfoLocked(); 657 return mDisplayInfo.address; 658 } 659 } 660 661 /** 662 * Gets the UID of the application that owns this display, or zero if it is 663 * owned by the system. 664 * <p> 665 * If the display is private, then only the owner can use it. 666 * </p> 667 * 668 * @hide 669 */ getOwnerUid()670 public int getOwnerUid() { 671 return mOwnerUid; 672 } 673 674 /** 675 * Gets the package name of the application that owns this display, or null if it is 676 * owned by the system. 677 * <p> 678 * If the display is private, then only the owner can use it. 679 * </p> 680 * 681 * @hide 682 */ 683 @UnsupportedAppUsage getOwnerPackageName()684 public String getOwnerPackageName() { 685 return mOwnerPackageName; 686 } 687 688 /** 689 * Gets the compatibility info used by this display instance. 690 * 691 * @return The display adjustments holder, or null if none is required. 692 * @hide 693 */ 694 @UnsupportedAppUsage getDisplayAdjustments()695 public DisplayAdjustments getDisplayAdjustments() { 696 if (mResources != null) { 697 final DisplayAdjustments currentAdjustments = mResources.getDisplayAdjustments(); 698 if (!mDisplayAdjustments.equals(currentAdjustments)) { 699 mDisplayAdjustments = new DisplayAdjustments(currentAdjustments); 700 } 701 } 702 703 return mDisplayAdjustments; 704 } 705 706 /** 707 * Gets the name of the display. 708 * <p> 709 * Note that some displays may be renamed by the user. 710 * </p> 711 * 712 * @return The display's name. 713 */ getName()714 public String getName() { 715 synchronized (mLock) { 716 updateDisplayInfoLocked(); 717 return mDisplayInfo.name; 718 } 719 } 720 721 /** 722 * Gets the default brightness configured for the display. 723 * 724 * @return Default brightness between 0.0-1.0 725 * @hide 726 */ getBrightnessDefault()727 public float getBrightnessDefault() { 728 synchronized (mLock) { 729 updateDisplayInfoLocked(); 730 return mDisplayInfo.brightnessDefault; 731 } 732 } 733 734 /** 735 * @return Brightness information about the display. 736 * @hide 737 */ 738 @RequiresPermission(CONTROL_DISPLAY_BRIGHTNESS) getBrightnessInfo()739 public @Nullable BrightnessInfo getBrightnessInfo() { 740 return mGlobal.getBrightnessInfo(mDisplayId); 741 } 742 743 /** 744 * Gets the size of the display, in pixels. 745 * Value returned by this method does not necessarily represent the actual raw size 746 * (native resolution) of the display. 747 * <p> 748 * 1. The returned size may be adjusted to exclude certain system decor elements 749 * that are always visible. 750 * </p><p> 751 * 2. It may be scaled to provide compatibility with older applications that 752 * were originally designed for smaller displays. 753 * </p><p> 754 * 3. It can be different depending on the WindowManager to which the display belongs. 755 * </p><p> 756 * - If requested from non-Activity context (e.g. Application context via 757 * {@code (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE)}) 758 * it will report the size of the entire display based on current rotation and with subtracted 759 * system decoration areas. 760 * </p><p> 761 * - If requested from activity (either using {@code getWindowManager()} or 762 * {@code (WindowManager) getSystemService(Context.WINDOW_SERVICE)}) resulting size will 763 * correspond to current app window size. In this case it can be smaller than physical size in 764 * multi-window mode. 765 * </p><p> 766 * Typically for the purposes of layout apps should make a request from activity context 767 * to obtain size available for the app content. 768 * </p> 769 * 770 * @param outSize A {@link Point} object to receive the size information. 771 * @deprecated Use {@link WindowManager#getCurrentWindowMetrics()} to obtain an instance of 772 * {@link WindowMetrics} and use {@link WindowMetrics#getBounds()} instead. 773 */ 774 @Deprecated getSize(Point outSize)775 public void getSize(Point outSize) { 776 synchronized (mLock) { 777 updateDisplayInfoLocked(); 778 mDisplayInfo.getAppMetrics(mTempMetrics, getDisplayAdjustments()); 779 outSize.x = mTempMetrics.widthPixels; 780 outSize.y = mTempMetrics.heightPixels; 781 } 782 } 783 784 /** 785 * Gets the size of the display as a rectangle, in pixels. 786 * 787 * @param outSize A {@link Rect} object to receive the size information. 788 * @deprecated Use {@link WindowMetrics#getBounds()} to get the dimensions of the application 789 * window area. 790 */ 791 @Deprecated getRectSize(Rect outSize)792 public void getRectSize(Rect outSize) { 793 synchronized (mLock) { 794 updateDisplayInfoLocked(); 795 mDisplayInfo.getAppMetrics(mTempMetrics, getDisplayAdjustments()); 796 outSize.set(0, 0, mTempMetrics.widthPixels, mTempMetrics.heightPixels); 797 } 798 } 799 800 /** 801 * Return the range of display sizes an application can expect to encounter 802 * under normal operation, as long as there is no physical change in screen 803 * size. This is basically the sizes you will see as the orientation 804 * changes, taking into account whatever screen decoration there is in 805 * each rotation. For example, the status bar is always at the top of the 806 * screen, so it will reduce the height both in landscape and portrait, and 807 * the smallest height returned here will be the smaller of the two. 808 * 809 * This is intended for applications to get an idea of the range of sizes 810 * they will encounter while going through device rotations, to provide a 811 * stable UI through rotation. The sizes here take into account all standard 812 * system decorations that reduce the size actually available to the 813 * application: the status bar, navigation bar, system bar, etc. It does 814 * <em>not</em> take into account more transient elements like an IME 815 * soft keyboard. 816 * 817 * @param outSmallestSize Filled in with the smallest width and height 818 * that the application will encounter, in pixels (not dp units). The x 819 * (width) dimension here directly corresponds to 820 * {@link android.content.res.Configuration#smallestScreenWidthDp 821 * Configuration.smallestScreenWidthDp}, except the value here is in raw 822 * screen pixels rather than dp units. Your application may of course 823 * still get smaller space yet if, for example, a soft keyboard is 824 * being displayed. 825 * @param outLargestSize Filled in with the largest width and height 826 * that the application will encounter, in pixels (not dp units). Your 827 * application may of course still get larger space than this if, 828 * for example, screen decorations like the status bar are being hidden. 829 */ getCurrentSizeRange(Point outSmallestSize, Point outLargestSize)830 public void getCurrentSizeRange(Point outSmallestSize, Point outLargestSize) { 831 synchronized (mLock) { 832 updateDisplayInfoLocked(); 833 outSmallestSize.x = mDisplayInfo.smallestNominalAppWidth; 834 outSmallestSize.y = mDisplayInfo.smallestNominalAppHeight; 835 outLargestSize.x = mDisplayInfo.largestNominalAppWidth; 836 outLargestSize.y = mDisplayInfo.largestNominalAppHeight; 837 } 838 } 839 840 /** 841 * Return the maximum screen size dimension that will happen. This is 842 * mostly for wallpapers. 843 * @hide 844 */ 845 @UnsupportedAppUsage getMaximumSizeDimension()846 public int getMaximumSizeDimension() { 847 synchronized (mLock) { 848 updateDisplayInfoLocked(); 849 return Math.max(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); 850 } 851 } 852 853 /** 854 * @deprecated Use {@link WindowMetrics#getBounds#width()} instead. 855 */ 856 @Deprecated getWidth()857 public int getWidth() { 858 synchronized (mLock) { 859 updateCachedAppSizeIfNeededLocked(); 860 return mCachedAppWidthCompat; 861 } 862 } 863 864 /** 865 * @deprecated Use {@link WindowMetrics#getBounds()#height()} instead. 866 */ 867 @Deprecated getHeight()868 public int getHeight() { 869 synchronized (mLock) { 870 updateCachedAppSizeIfNeededLocked(); 871 return mCachedAppHeightCompat; 872 } 873 } 874 875 /** 876 * Returns the rotation of the screen from its "natural" orientation. 877 * The returned value may be {@link Surface#ROTATION_0 Surface.ROTATION_0} 878 * (no rotation), {@link Surface#ROTATION_90 Surface.ROTATION_90}, 879 * {@link Surface#ROTATION_180 Surface.ROTATION_180}, or 880 * {@link Surface#ROTATION_270 Surface.ROTATION_270}. For 881 * example, if a device has a naturally tall screen, and the user has 882 * turned it on its side to go into a landscape orientation, the value 883 * returned here may be either {@link Surface#ROTATION_90 Surface.ROTATION_90} 884 * or {@link Surface#ROTATION_270 Surface.ROTATION_270} depending on 885 * the direction it was turned. The angle is the rotation of the drawn 886 * graphics on the screen, which is the opposite direction of the physical 887 * rotation of the device. For example, if the device is rotated 90 888 * degrees counter-clockwise, to compensate rendering will be rotated by 889 * 90 degrees clockwise and thus the returned value here will be 890 * {@link Surface#ROTATION_90 Surface.ROTATION_90}. 891 */ 892 @Surface.Rotation getRotation()893 public int getRotation() { 894 synchronized (mLock) { 895 updateDisplayInfoLocked(); 896 return mMayAdjustByFixedRotation 897 ? getDisplayAdjustments().getRotation(mDisplayInfo.rotation) 898 : mDisplayInfo.rotation; 899 } 900 } 901 902 /** 903 * @deprecated use {@link #getRotation} 904 * @return orientation of this display. 905 */ 906 @Deprecated 907 @Surface.Rotation getOrientation()908 public int getOrientation() { 909 return getRotation(); 910 } 911 912 913 /** 914 * Returns the {@link DisplayCutout}, or {@code null} if there is none. 915 * 916 * @see DisplayCutout 917 */ 918 @Nullable getCutout()919 public DisplayCutout getCutout() { 920 synchronized (mLock) { 921 updateDisplayInfoLocked(); 922 return mMayAdjustByFixedRotation 923 ? getDisplayAdjustments().getDisplayCutout(mDisplayInfo.displayCutout) 924 : mDisplayInfo.displayCutout; 925 } 926 } 927 928 /** 929 * Returns the {@link RoundedCorner} of the given position if there is one. 930 * 931 * @param position the position of the rounded corner on the display. 932 * 933 * @return the rounded corner of the given position. Returns {@code null} if there is none. 934 */ 935 @SuppressLint("VisiblySynchronized") 936 @Nullable getRoundedCorner(@oundedCorner.Position int position)937 public RoundedCorner getRoundedCorner(@RoundedCorner.Position int position) { 938 synchronized (mLock) { 939 updateDisplayInfoLocked(); 940 RoundedCorners roundedCorners; 941 if (mMayAdjustByFixedRotation) { 942 roundedCorners = getDisplayAdjustments().adjustRoundedCorner( 943 mDisplayInfo.roundedCorners, 944 mDisplayInfo.rotation, 945 mDisplayInfo.logicalWidth, 946 mDisplayInfo.logicalHeight); 947 } else { 948 roundedCorners = mDisplayInfo.roundedCorners; 949 } 950 return roundedCorners == null ? null : roundedCorners.getRoundedCorner(position); 951 } 952 } 953 954 /** 955 * Gets the pixel format of the display. 956 * @return One of the constants defined in {@link android.graphics.PixelFormat}. 957 * 958 * @deprecated This method is no longer supported. 959 * The result is always {@link PixelFormat#RGBA_8888}. 960 */ 961 @Deprecated getPixelFormat()962 public int getPixelFormat() { 963 return PixelFormat.RGBA_8888; 964 } 965 966 /** 967 * Gets the refresh rate of this display in frames per second. 968 */ getRefreshRate()969 public float getRefreshRate() { 970 synchronized (mLock) { 971 updateDisplayInfoLocked(); 972 return mDisplayInfo.getRefreshRate(); 973 } 974 } 975 976 /** 977 * Get the supported refresh rates of this display in frames per second. 978 * <p> 979 * This method only returns refresh rates for the display's default modes. For more options, use 980 * {@link #getSupportedModes()}. 981 * 982 * @deprecated use {@link #getSupportedModes()} instead 983 */ 984 @Deprecated getSupportedRefreshRates()985 public float[] getSupportedRefreshRates() { 986 synchronized (mLock) { 987 updateDisplayInfoLocked(); 988 return mDisplayInfo.getDefaultRefreshRates(); 989 } 990 } 991 992 /** 993 * Returns the active mode of the display. 994 */ getMode()995 public Mode getMode() { 996 synchronized (mLock) { 997 updateDisplayInfoLocked(); 998 return mDisplayInfo.getMode(); 999 } 1000 } 1001 1002 /** 1003 * Gets the supported modes of this display. 1004 */ getSupportedModes()1005 public Mode[] getSupportedModes() { 1006 synchronized (mLock) { 1007 updateDisplayInfoLocked(); 1008 final Display.Mode[] modes = mDisplayInfo.supportedModes; 1009 return Arrays.copyOf(modes, modes.length); 1010 } 1011 } 1012 1013 /** 1014 * <p> Returns true if the connected display can be switched into a mode with minimal 1015 * post processing. </p> 1016 * 1017 * <p> If the Display sink is connected via HDMI, this method will return true if the 1018 * display supports either Auto Low Latency Mode or Game Content Type. 1019 * 1020 * <p> If the Display sink has an internal connection or uses some other protocol than 1021 * HDMI, this method will return true if the sink can be switched into an 1022 * implementation-defined low latency image processing mode. </p> 1023 * 1024 * <p> The ability to switch to a mode with minimal post processing may be disabled 1025 * by a user setting in the system settings menu. In that case, this method returns 1026 * false. </p> 1027 * 1028 * @see android.view.Window#setPreferMinimalPostProcessing 1029 */ 1030 @SuppressLint("VisiblySynchronized") isMinimalPostProcessingSupported()1031 public boolean isMinimalPostProcessingSupported() { 1032 synchronized (mLock) { 1033 updateDisplayInfoLocked(); 1034 return mDisplayInfo.minimalPostProcessingSupported; 1035 } 1036 } 1037 1038 /** 1039 * Request the display applies a color mode. 1040 * @hide 1041 */ 1042 @RequiresPermission(CONFIGURE_DISPLAY_COLOR_MODE) requestColorMode(int colorMode)1043 public void requestColorMode(int colorMode) { 1044 mGlobal.requestColorMode(mDisplayId, colorMode); 1045 } 1046 1047 /** 1048 * Returns the active color mode of this display 1049 * @hide 1050 */ getColorMode()1051 public int getColorMode() { 1052 synchronized (mLock) { 1053 updateDisplayInfoLocked(); 1054 return mDisplayInfo.colorMode; 1055 } 1056 } 1057 1058 /** 1059 * @hide 1060 * Get current remove mode of the display - what actions should be performed with the display's 1061 * content when it is removed. Default behavior for public displays in this case is to move all 1062 * activities to the primary display and make it focused. For private display - destroy all 1063 * activities. 1064 * 1065 * @see #REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY 1066 * @see #REMOVE_MODE_DESTROY_CONTENT 1067 */ 1068 // TODO (b/114338689): Remove the method and use IWindowManager#getRemoveContentMode getRemoveMode()1069 public int getRemoveMode() { 1070 return mDisplayInfo.removeMode; 1071 } 1072 1073 /** 1074 * Returns the display's HDR capabilities. 1075 * 1076 * @see #isHdr() 1077 */ getHdrCapabilities()1078 public HdrCapabilities getHdrCapabilities() { 1079 synchronized (mLock) { 1080 updateDisplayInfoLocked(); 1081 if (mDisplayInfo.userDisabledHdrTypes.length == 0) { 1082 return mDisplayInfo.hdrCapabilities; 1083 } 1084 1085 if (mDisplayInfo.hdrCapabilities == null) { 1086 return null; 1087 } 1088 1089 ArraySet<Integer> enabledTypesSet = new ArraySet<>(); 1090 for (int supportedType : mDisplayInfo.hdrCapabilities.getSupportedHdrTypes()) { 1091 boolean typeDisabled = false; 1092 for (int userDisabledType : mDisplayInfo.userDisabledHdrTypes) { 1093 if (supportedType == userDisabledType) { 1094 typeDisabled = true; 1095 break; 1096 } 1097 } 1098 if (!typeDisabled) { 1099 enabledTypesSet.add(supportedType); 1100 } 1101 } 1102 1103 int[] enabledTypes = new int[enabledTypesSet.size()]; 1104 int index = 0; 1105 for (int enabledType : enabledTypesSet) { 1106 enabledTypes[index++] = enabledType; 1107 } 1108 return new HdrCapabilities(enabledTypes, 1109 mDisplayInfo.hdrCapabilities.mMaxLuminance, 1110 mDisplayInfo.hdrCapabilities.mMaxAverageLuminance, 1111 mDisplayInfo.hdrCapabilities.mMinLuminance); 1112 } 1113 } 1114 1115 /** 1116 * @hide 1117 * Returns the display's HDR supported types. 1118 * 1119 * @see #isHdr() 1120 * @see HdrCapabilities#getSupportedHdrTypes() 1121 */ 1122 @TestApi 1123 @NonNull getReportedHdrTypes()1124 public int[] getReportedHdrTypes() { 1125 synchronized (mLock) { 1126 updateDisplayInfoLocked(); 1127 if (mDisplayInfo.hdrCapabilities == null) { 1128 return new int[0]; 1129 } 1130 return mDisplayInfo.hdrCapabilities.getSupportedHdrTypes(); 1131 } 1132 } 1133 1134 /** 1135 * Returns whether this display supports any HDR type. 1136 * 1137 * @see #getHdrCapabilities() 1138 * @see HdrCapabilities#getSupportedHdrTypes() 1139 */ isHdr()1140 public boolean isHdr() { 1141 synchronized (mLock) { 1142 updateDisplayInfoLocked(); 1143 HdrCapabilities hdrCapabilities = getHdrCapabilities(); 1144 if (hdrCapabilities == null) { 1145 return false; 1146 } 1147 return !(hdrCapabilities.getSupportedHdrTypes().length == 0); 1148 } 1149 } 1150 1151 /** 1152 * Returns whether this display can be used to display wide color gamut content. 1153 * This does not necessarily mean the device itself can render wide color gamut 1154 * content. To ensure wide color gamut content can be produced, refer to 1155 * {@link Configuration#isScreenWideColorGamut()}. 1156 */ isWideColorGamut()1157 public boolean isWideColorGamut() { 1158 synchronized (mLock) { 1159 updateDisplayInfoLocked(); 1160 return mDisplayInfo.isWideColorGamut(); 1161 } 1162 } 1163 1164 /** 1165 * Returns the preferred wide color space of the Display. 1166 * The returned wide gamut color space is based on hardware capability and 1167 * is preferred by the composition pipeline. 1168 * Returns null if the display doesn't support wide color gamut. 1169 * {@link Display#isWideColorGamut()}. 1170 */ 1171 @Nullable getPreferredWideGamutColorSpace()1172 public ColorSpace getPreferredWideGamutColorSpace() { 1173 synchronized (mLock) { 1174 updateDisplayInfoLocked(); 1175 if (mDisplayInfo.isWideColorGamut()) { 1176 return mGlobal.getPreferredWideGamutColorSpace(); 1177 } 1178 return null; 1179 } 1180 } 1181 1182 /** 1183 * Gets the supported color modes of this device. 1184 * @hide 1185 */ getSupportedColorModes()1186 public int[] getSupportedColorModes() { 1187 synchronized (mLock) { 1188 updateDisplayInfoLocked(); 1189 int[] colorModes = mDisplayInfo.supportedColorModes; 1190 return Arrays.copyOf(colorModes, colorModes.length); 1191 } 1192 } 1193 1194 /** 1195 * Gets the supported wide color gamuts of this device. 1196 * 1197 * @return Supported WCG color spaces. 1198 * @hide 1199 */ 1200 @SuppressLint("VisiblySynchronized") 1201 @NonNull 1202 @TestApi getSupportedWideColorGamut()1203 public @ColorMode ColorSpace[] getSupportedWideColorGamut() { 1204 synchronized (mLock) { 1205 final ColorSpace[] defaultColorSpaces = new ColorSpace[0]; 1206 updateDisplayInfoLocked(); 1207 if (!isWideColorGamut()) { 1208 return defaultColorSpaces; 1209 } 1210 1211 final int[] colorModes = getSupportedColorModes(); 1212 final List<ColorSpace> colorSpaces = new ArrayList<>(); 1213 for (int colorMode : colorModes) { 1214 // Refer to DisplayInfo#isWideColorGamut. 1215 switch (colorMode) { 1216 case COLOR_MODE_DCI_P3: 1217 colorSpaces.add(ColorSpace.get(ColorSpace.Named.DCI_P3)); 1218 break; 1219 case COLOR_MODE_DISPLAY_P3: 1220 colorSpaces.add(ColorSpace.get(ColorSpace.Named.DISPLAY_P3)); 1221 break; 1222 } 1223 } 1224 return colorSpaces.toArray(defaultColorSpaces); 1225 } 1226 } 1227 1228 /** 1229 * Gets the app VSYNC offset, in nanoseconds. This is a positive value indicating 1230 * the phase offset of the VSYNC events provided by Choreographer relative to the 1231 * display refresh. For example, if Choreographer reports that the refresh occurred 1232 * at time N, it actually occurred at (N - appVsyncOffset). 1233 * <p> 1234 * Apps generally do not need to be aware of this. It's only useful for fine-grained 1235 * A/V synchronization. 1236 */ getAppVsyncOffsetNanos()1237 public long getAppVsyncOffsetNanos() { 1238 synchronized (mLock) { 1239 updateDisplayInfoLocked(); 1240 return mDisplayInfo.appVsyncOffsetNanos; 1241 } 1242 } 1243 1244 /** 1245 * This is how far in advance a buffer must be queued for presentation at 1246 * a given time. If you want a buffer to appear on the screen at 1247 * time N, you must submit the buffer before (N - presentationDeadline). 1248 * <p> 1249 * The desired presentation time for GLES rendering may be set with 1250 * {@link android.opengl.EGLExt#eglPresentationTimeANDROID}. For video decoding, use 1251 * {@link android.media.MediaCodec#releaseOutputBuffer(int, long)}. Times are 1252 * expressed in nanoseconds, using the system monotonic clock 1253 * ({@link System#nanoTime}). 1254 */ getPresentationDeadlineNanos()1255 public long getPresentationDeadlineNanos() { 1256 synchronized (mLock) { 1257 updateDisplayInfoLocked(); 1258 return mDisplayInfo.presentationDeadlineNanos; 1259 } 1260 } 1261 1262 /** 1263 * Returns the product-specific information about the display or the directly connected 1264 * device on the display chain. 1265 * For example, if the display is transitively connected, this field may contain product 1266 * information about the intermediate device. 1267 * Returns {@code null} if product information is not available. 1268 */ 1269 @Nullable getDeviceProductInfo()1270 public DeviceProductInfo getDeviceProductInfo() { 1271 synchronized (mLock) { 1272 updateDisplayInfoLocked(); 1273 return mDisplayInfo.deviceProductInfo; 1274 } 1275 } 1276 1277 /** 1278 * Gets display metrics that describe the size and density of this display. 1279 * The size returned by this method does not necessarily represent the 1280 * actual raw size (native resolution) of the display. 1281 * <p> 1282 * 1. The returned size may be adjusted to exclude certain system decor elements 1283 * that are always visible. 1284 * </p><p> 1285 * 2. It may be scaled to provide compatibility with older applications that 1286 * were originally designed for smaller displays. 1287 * </p><p> 1288 * 3. It can be different depending on the WindowManager to which the display belongs. 1289 * </p><p> 1290 * - If requested from non-Activity context (e.g. Application context via 1291 * {@code (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE)}) 1292 * metrics will report the size of the entire display based on current rotation and with 1293 * subtracted system decoration areas. 1294 * </p><p> 1295 * - If requested from activity (either using {@code getWindowManager()} or 1296 * {@code (WindowManager) getSystemService(Context.WINDOW_SERVICE)}) resulting metrics will 1297 * correspond to current app window metrics. In this case the size can be smaller than physical 1298 * size in multi-window mode. 1299 * </p> 1300 * 1301 * @param outMetrics A {@link DisplayMetrics} object to receive the metrics. 1302 * @deprecated Use {@link WindowMetrics#getBounds()} to get the dimensions of the application 1303 * window area, and {@link Configuration#densityDpi} to get the current density. 1304 */ 1305 @Deprecated getMetrics(DisplayMetrics outMetrics)1306 public void getMetrics(DisplayMetrics outMetrics) { 1307 synchronized (mLock) { 1308 updateDisplayInfoLocked(); 1309 mDisplayInfo.getAppMetrics(outMetrics, getDisplayAdjustments()); 1310 } 1311 } 1312 1313 /** 1314 * Gets the size of the largest region of the display accessible to an app in the current system 1315 * state, without subtracting any window decor or applying scaling factors. 1316 * <p> 1317 * The size is adjusted based on the current rotation of the display. 1318 * <p></p> 1319 * The returned size will fall into one of these scenarios: 1320 * <ol> 1321 * <li>The device has no partitions on the display. The returned value is the largest region 1322 * of the display accessible to an app in the current system state, regardless of windowing 1323 * mode.</li> 1324 * <li>The device divides a single display into multiple partitions. An application is 1325 * restricted to a portion of the display. This is common in devices where the display changes 1326 * size, such as foldables or large screens. The returned size will match the portion of 1327 * the display the application is restricted to.</li> 1328 * <li>The window manager is emulating a different display size, using {@code adb shell wm 1329 * size}. The returned size will match the emulated display size.</li> 1330 * </ol> 1331 * </p><p> 1332 * The returned value is <b>unsuitable to use when sizing and placing UI elements</b>, since it 1333 * does not reflect the application window size in any of these scenarios. 1334 * {@link WindowManager#getCurrentWindowMetrics()} is an alternative that returns the size 1335 * of the current application window, even if the window is on a device with a partitioned 1336 * display. This helps prevent UI bugs where UI elements are misaligned or placed beyond the 1337 * bounds of the window. 1338 * <p></p> 1339 * Handling multi-window mode correctly is necessary since applications are not always 1340 * fullscreen. A user on a large screen device, such as a tablet or Chrome OS devices, is more 1341 * likely to use multi-window modes. 1342 * <p></p> 1343 * For example, consider a device with a display partitioned into two halves. The user may have 1344 * a fullscreen application open on the first partition. They may have two applications open in 1345 * split screen (an example of multi-window mode) on the second partition, with each application 1346 * consuming half of the partition. In this case, 1347 * {@link WindowManager#getCurrentWindowMetrics()} reports the fullscreen window is half of the 1348 * screen in size, and each split screen window is a quarter of the screen in size. On the other 1349 * hand, {@link #getRealSize} reports half of the screen size for all windows, since the 1350 * application windows are all restricted to their respective partitions. 1351 * </p> 1352 * 1353 * @param outSize Set to the real size of the display. 1354 * @deprecated Use {@link WindowManager#getCurrentWindowMetrics()} to identify the current size 1355 * of the activity window. UI-related work, such as choosing UI layouts, should rely 1356 * upon {@link WindowMetrics#getBounds()}. 1357 */ 1358 @Deprecated getRealSize(Point outSize)1359 public void getRealSize(Point outSize) { 1360 synchronized (mLock) { 1361 updateDisplayInfoLocked(); 1362 if (shouldReportMaxBounds()) { 1363 final Rect bounds = mResources.getConfiguration() 1364 .windowConfiguration.getMaxBounds(); 1365 outSize.x = bounds.width(); 1366 outSize.y = bounds.height(); 1367 if (DEBUG) { 1368 Log.d(TAG, "getRealSize determined from max bounds: " + outSize); 1369 } 1370 // Skip adjusting by fixed rotation, since if it is necessary, the configuration 1371 // should already reflect the expected rotation. 1372 return; 1373 } 1374 outSize.x = mDisplayInfo.logicalWidth; 1375 outSize.y = mDisplayInfo.logicalHeight; 1376 if (mMayAdjustByFixedRotation) { 1377 getDisplayAdjustments().adjustSize(outSize, mDisplayInfo.rotation); 1378 } 1379 } 1380 } 1381 1382 /** 1383 * Gets the size of the largest region of the display accessible to an app in the current system 1384 * state, without subtracting any window decor or applying scaling factors. 1385 * <p> 1386 * The size is adjusted based on the current rotation of the display. 1387 * <p></p> 1388 * The returned size will fall into one of these scenarios: 1389 * <ol> 1390 * <li>The device has no partitions on the display. The returned value is the largest region 1391 * of the display accessible to an app in the current system state, regardless of windowing 1392 * mode.</li> 1393 * <li>The device divides a single display into multiple partitions. An application is 1394 * restricted to a portion of the display. This is common in devices where the display changes 1395 * size, such as foldables or large screens. The returned size will match the portion of 1396 * the display the application is restricted to.</li> 1397 * <li>The window manager is emulating a different display size, using {@code adb shell wm 1398 * size}. The returned size will match the emulated display size.</li> 1399 * </ol> 1400 * </p><p> 1401 * The returned value is <b>unsuitable to use when sizing and placing UI elements</b>, since it 1402 * does not reflect the application window size in any of these scenarios. 1403 * {@link WindowManager#getCurrentWindowMetrics()} is an alternative that returns the size 1404 * of the current application window, even if the window is on a device with a partitioned 1405 * display. This helps prevent UI bugs where UI elements are misaligned or placed beyond the 1406 * bounds of the window. 1407 * <p></p> 1408 * Handling multi-window mode correctly is necessary since applications are not always 1409 * fullscreen. A user on a large screen device, such as a tablet or Chrome OS devices, is more 1410 * likely to use multi-window modes. 1411 * <p></p> 1412 * For example, consider a device with a display partitioned into two halves. The user may have 1413 * a fullscreen application open on the first partition. They may have two applications open in 1414 * split screen (an example of multi-window mode) on the second partition, with each application 1415 * consuming half of the partition. In this case, 1416 * {@link WindowManager#getCurrentWindowMetrics()} reports the fullscreen window is half of the 1417 * screen in size, and each split screen window is a quarter of the screen in size. On the other 1418 * hand, {@link #getRealMetrics} reports half of the screen size for all windows, since the 1419 * application windows are all restricted to their respective partitions. 1420 * </p> 1421 * 1422 * @param outMetrics A {@link DisplayMetrics} object to receive the metrics. 1423 * @deprecated Use {@link WindowManager#getCurrentWindowMetrics()} to identify the current size 1424 * of the activity window. UI-related work, such as choosing UI layouts, should rely 1425 * upon {@link WindowMetrics#getBounds()}. Use {@link Configuration#densityDpi} to 1426 * get the current density. 1427 */ 1428 @Deprecated getRealMetrics(DisplayMetrics outMetrics)1429 public void getRealMetrics(DisplayMetrics outMetrics) { 1430 synchronized (mLock) { 1431 updateDisplayInfoLocked(); 1432 if (shouldReportMaxBounds()) { 1433 mDisplayInfo.getMaxBoundsMetrics(outMetrics, 1434 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, 1435 mResources.getConfiguration()); 1436 if (DEBUG) { 1437 Log.d(TAG, "getRealMetrics determined from max bounds: " + outMetrics); 1438 } 1439 // Skip adjusting by fixed rotation, since if it is necessary, the configuration 1440 // should already reflect the expected rotation. 1441 return; 1442 } 1443 mDisplayInfo.getLogicalMetrics(outMetrics, 1444 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 1445 if (mMayAdjustByFixedRotation) { 1446 getDisplayAdjustments().adjustMetrics(outMetrics, mDisplayInfo.rotation); 1447 } 1448 } 1449 } 1450 1451 /** 1452 * Determines if {@link WindowConfiguration#getMaxBounds()} should be reported as the 1453 * display dimensions. The max bounds field may be smaller than the logical dimensions 1454 * when apps need to be sandboxed. 1455 * 1456 * Depends upon {@link WindowConfiguration#getMaxBounds()} being set in 1457 * {@link com.android.server.wm.ConfigurationContainer#providesMaxBounds()}. In most cases, this 1458 * value reflects the size of the current DisplayArea. 1459 * @return {@code true} when max bounds should be applied. 1460 */ shouldReportMaxBounds()1461 private boolean shouldReportMaxBounds() { 1462 if (mResources == null) { 1463 return false; 1464 } 1465 final Configuration config = mResources.getConfiguration(); 1466 // TODO(b/179308296) Temporarily exclude Launcher from being given max bounds, by checking 1467 // if the caller is the recents component. 1468 return config != null && !config.windowConfiguration.getMaxBounds().isEmpty() 1469 && !isRecentsComponent(); 1470 } 1471 1472 /** 1473 * Returns {@code true} when the calling package is the recents component. 1474 * TODO(b/179308296) Remove once Launcher addresses issue 1475 */ isRecentsComponent()1476 boolean isRecentsComponent() { 1477 if (mIsRecentsComponent.isPresent()) { 1478 return mIsRecentsComponent.get(); 1479 } 1480 if (mResources == null) { 1481 return false; 1482 } 1483 try { 1484 String recentsComponent = mResources.getString(R.string.config_recentsComponentName); 1485 if (recentsComponent == null) { 1486 return false; 1487 } 1488 String recentsPackage = ComponentName.unflattenFromString(recentsComponent) 1489 .getPackageName(); 1490 mIsRecentsComponent = Optional.of(recentsPackage != null 1491 && recentsPackage.equals(ActivityThread.currentPackageName())); 1492 return mIsRecentsComponent.get(); 1493 } catch (Resources.NotFoundException e) { 1494 return false; 1495 } 1496 } 1497 1498 /** 1499 * Gets the state of the display, such as whether it is on or off. 1500 * 1501 * @return The state of the display: one of {@link #STATE_OFF}, {@link #STATE_ON}, 1502 * {@link #STATE_DOZE}, {@link #STATE_DOZE_SUSPEND}, {@link #STATE_ON_SUSPEND}, or 1503 * {@link #STATE_UNKNOWN}. 1504 */ getState()1505 public int getState() { 1506 synchronized (mLock) { 1507 updateDisplayInfoLocked(); 1508 return mIsValid ? mDisplayInfo.state : STATE_UNKNOWN; 1509 } 1510 } 1511 1512 /** 1513 * Returns true if the specified UID has access to this display. 1514 * @hide 1515 */ 1516 @TestApi hasAccess(int uid)1517 public boolean hasAccess(int uid) { 1518 return hasAccess(uid, mFlags, mOwnerUid, mDisplayId); 1519 } 1520 1521 /** @hide */ hasAccess(int uid, int flags, int ownerUid, int displayId)1522 public static boolean hasAccess(int uid, int flags, int ownerUid, int displayId) { 1523 return (flags & Display.FLAG_PRIVATE) == 0 1524 || uid == ownerUid 1525 || uid == Process.SYSTEM_UID 1526 || uid == 0 1527 // Check if the UID is present on given display. 1528 || DisplayManagerGlobal.getInstance().isUidPresentOnDisplay(uid, displayId); 1529 } 1530 1531 /** 1532 * Returns true if the display is a public presentation display. 1533 * @hide 1534 */ isPublicPresentation()1535 public boolean isPublicPresentation() { 1536 return (mFlags & (Display.FLAG_PRIVATE | Display.FLAG_PRESENTATION)) == 1537 Display.FLAG_PRESENTATION; 1538 } 1539 1540 /** 1541 * @return {@code true} if the display is a trusted display. 1542 * 1543 * @see #FLAG_TRUSTED 1544 * @hide 1545 */ isTrusted()1546 public boolean isTrusted() { 1547 return (mFlags & FLAG_TRUSTED) == FLAG_TRUSTED; 1548 } 1549 updateDisplayInfoLocked()1550 private void updateDisplayInfoLocked() { 1551 // Note: The display manager caches display info objects on our behalf. 1552 DisplayInfo newInfo = mGlobal.getDisplayInfo(mDisplayId); 1553 if (newInfo == null) { 1554 // Preserve the old mDisplayInfo after the display is removed. 1555 if (mIsValid) { 1556 mIsValid = false; 1557 if (DEBUG) { 1558 Log.d(TAG, "Logical display " + mDisplayId + " was removed."); 1559 } 1560 } 1561 } else { 1562 // Use the new display info. (It might be the same object if nothing changed.) 1563 mDisplayInfo = newInfo; 1564 if (!mIsValid) { 1565 mIsValid = true; 1566 if (DEBUG) { 1567 Log.d(TAG, "Logical display " + mDisplayId + " was recreated."); 1568 } 1569 } 1570 } 1571 1572 mMayAdjustByFixedRotation = mResources != null 1573 && mResources.hasOverrideDisplayAdjustments(); 1574 } 1575 updateCachedAppSizeIfNeededLocked()1576 private void updateCachedAppSizeIfNeededLocked() { 1577 long now = SystemClock.uptimeMillis(); 1578 if (now > mLastCachedAppSizeUpdate + CACHED_APP_SIZE_DURATION_MILLIS) { 1579 updateDisplayInfoLocked(); 1580 mDisplayInfo.getAppMetrics(mTempMetrics, getDisplayAdjustments()); 1581 mCachedAppWidthCompat = mTempMetrics.widthPixels; 1582 mCachedAppHeightCompat = mTempMetrics.heightPixels; 1583 mLastCachedAppSizeUpdate = now; 1584 } 1585 } 1586 1587 // For debugging purposes 1588 @Override toString()1589 public String toString() { 1590 synchronized (mLock) { 1591 updateDisplayInfoLocked(); 1592 final DisplayAdjustments adjustments = getDisplayAdjustments(); 1593 mDisplayInfo.getAppMetrics(mTempMetrics, adjustments); 1594 return "Display id " + mDisplayId + ": " + mDisplayInfo 1595 + (mMayAdjustByFixedRotation 1596 ? (", " + adjustments.getFixedRotationAdjustments() + ", ") : ", ") 1597 + mTempMetrics + ", isValid=" + mIsValid; 1598 } 1599 } 1600 1601 /** 1602 * @hide 1603 */ typeToString(int type)1604 public static String typeToString(int type) { 1605 switch (type) { 1606 case TYPE_UNKNOWN: 1607 return "UNKNOWN"; 1608 case TYPE_INTERNAL: 1609 return "INTERNAL"; 1610 case TYPE_EXTERNAL: 1611 return "EXTERNAL"; 1612 case TYPE_WIFI: 1613 return "WIFI"; 1614 case TYPE_OVERLAY: 1615 return "OVERLAY"; 1616 case TYPE_VIRTUAL: 1617 return "VIRTUAL"; 1618 default: 1619 return Integer.toString(type); 1620 } 1621 } 1622 1623 /** 1624 * @hide 1625 */ stateToString(int state)1626 public static String stateToString(int state) { 1627 switch (state) { 1628 case STATE_UNKNOWN: 1629 return "UNKNOWN"; 1630 case STATE_OFF: 1631 return "OFF"; 1632 case STATE_ON: 1633 return "ON"; 1634 case STATE_DOZE: 1635 return "DOZE"; 1636 case STATE_DOZE_SUSPEND: 1637 return "DOZE_SUSPEND"; 1638 case STATE_VR: 1639 return "VR"; 1640 case STATE_ON_SUSPEND: 1641 return "ON_SUSPEND"; 1642 default: 1643 return Integer.toString(state); 1644 } 1645 } 1646 1647 /** 1648 * Returns true if display updates may be suspended while in the specified 1649 * display power state. In SUSPEND states, updates are absolutely forbidden. 1650 * @hide 1651 */ isSuspendedState(int state)1652 public static boolean isSuspendedState(int state) { 1653 return state == STATE_OFF || state == STATE_DOZE_SUSPEND || state == STATE_ON_SUSPEND; 1654 } 1655 1656 /** 1657 * Returns true if the display may be in a reduced operating mode while in the 1658 * specified display power state. 1659 * @hide 1660 */ isDozeState(int state)1661 public static boolean isDozeState(int state) { 1662 return state == STATE_DOZE || state == STATE_DOZE_SUSPEND; 1663 } 1664 1665 /** 1666 * Returns true if the display is in active state such as {@link #STATE_ON} 1667 * or {@link #STATE_VR}. 1668 * @hide 1669 */ isActiveState(int state)1670 public static boolean isActiveState(int state) { 1671 return state == STATE_ON || state == STATE_VR; 1672 } 1673 1674 /** 1675 * Returns true if the display is in an off state such as {@link #STATE_OFF}. 1676 * @hide 1677 */ isOffState(int state)1678 public static boolean isOffState(int state) { 1679 return state == STATE_OFF; 1680 } 1681 1682 /** 1683 * Returns true if the display is in an on state such as {@link #STATE_ON} 1684 * or {@link #STATE_VR} or {@link #STATE_ON_SUSPEND}. 1685 * @hide 1686 */ isOnState(int state)1687 public static boolean isOnState(int state) { 1688 return state == STATE_ON || state == STATE_VR || state == STATE_ON_SUSPEND; 1689 } 1690 1691 /** 1692 * A mode supported by a given display. 1693 * 1694 * @see Display#getSupportedModes() 1695 */ 1696 public static final class Mode implements Parcelable { 1697 /** 1698 * @hide 1699 */ 1700 public static final Mode[] EMPTY_ARRAY = new Mode[0]; 1701 1702 private final int mModeId; 1703 private final int mWidth; 1704 private final int mHeight; 1705 private final float mRefreshRate; 1706 @NonNull 1707 private final float[] mAlternativeRefreshRates; 1708 1709 /** 1710 * @hide 1711 */ 1712 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) Mode(int modeId, int width, int height, float refreshRate)1713 public Mode(int modeId, int width, int height, float refreshRate) { 1714 this(modeId, width, height, refreshRate, new float[0]); 1715 } 1716 1717 /** 1718 * @hide 1719 */ Mode(int modeId, int width, int height, float refreshRate, float[] alternativeRefreshRates)1720 public Mode(int modeId, int width, int height, float refreshRate, 1721 float[] alternativeRefreshRates) { 1722 mModeId = modeId; 1723 mWidth = width; 1724 mHeight = height; 1725 mRefreshRate = refreshRate; 1726 mAlternativeRefreshRates = 1727 Arrays.copyOf(alternativeRefreshRates, alternativeRefreshRates.length); 1728 Arrays.sort(mAlternativeRefreshRates); 1729 } 1730 1731 /** 1732 * Returns this mode's id. 1733 */ getModeId()1734 public int getModeId() { 1735 return mModeId; 1736 } 1737 1738 /** 1739 * Returns the physical width of the display in pixels when configured in this mode's 1740 * resolution. 1741 * <p> 1742 * Note that due to application UI scaling, the number of pixels made available to 1743 * applications when the mode is active (as reported by {@link Display#getWidth()} may 1744 * differ from the mode's actual resolution (as reported by this function). 1745 * <p> 1746 * For example, applications running on a 4K display may have their UI laid out and rendered 1747 * in 1080p and then scaled up. Applications can take advantage of the extra resolution by 1748 * rendering content through a {@link android.view.SurfaceView} using full size buffers. 1749 */ getPhysicalWidth()1750 public int getPhysicalWidth() { 1751 return mWidth; 1752 } 1753 1754 /** 1755 * Returns the physical height of the display in pixels when configured in this mode's 1756 * resolution. 1757 * <p> 1758 * Note that due to application UI scaling, the number of pixels made available to 1759 * applications when the mode is active (as reported by {@link Display#getHeight()} may 1760 * differ from the mode's actual resolution (as reported by this function). 1761 * <p> 1762 * For example, applications running on a 4K display may have their UI laid out and rendered 1763 * in 1080p and then scaled up. Applications can take advantage of the extra resolution by 1764 * rendering content through a {@link android.view.SurfaceView} using full size buffers. 1765 */ getPhysicalHeight()1766 public int getPhysicalHeight() { 1767 return mHeight; 1768 } 1769 1770 /** 1771 * Returns the refresh rate in frames per second. 1772 */ getRefreshRate()1773 public float getRefreshRate() { 1774 return mRefreshRate; 1775 } 1776 1777 /** 1778 * Returns an array of refresh rates which can be switched to seamlessly. 1779 * <p> 1780 * A seamless switch is one without visual interruptions, such as a black screen for 1781 * a second or two. 1782 * <p> 1783 * Presence in this list does not guarantee a switch will occur to the desired 1784 * refresh rate, but rather, if a switch does occur to a refresh rate in this list, 1785 * it is guaranteed to be seamless. 1786 * <p> 1787 * The binary relation "refresh rate X is alternative to Y" is non-reflexive, 1788 * symmetric and transitive. For example the mode 1920x1080 60Hz, will never have an 1789 * alternative refresh rate of 60Hz. If 1920x1080 60Hz has an alternative of 50Hz 1790 * then 1920x1080 50Hz will have alternative refresh rate of 60Hz. If 1920x1080 60Hz 1791 * has an alternative of 50Hz and 1920x1080 50Hz has an alternative of 24Hz, then 1920x1080 1792 * 60Hz will also have an alternative of 24Hz. 1793 * 1794 * @see Surface#setFrameRate 1795 * @see SurfaceControl.Transaction#setFrameRate 1796 */ 1797 @NonNull getAlternativeRefreshRates()1798 public float[] getAlternativeRefreshRates() { 1799 return mAlternativeRefreshRates; 1800 } 1801 1802 /** 1803 * Returns {@code true} if this mode matches the given parameters. 1804 * 1805 * @hide 1806 */ matches(int width, int height, float refreshRate)1807 public boolean matches(int width, int height, float refreshRate) { 1808 return mWidth == width && 1809 mHeight == height && 1810 Float.floatToIntBits(mRefreshRate) == Float.floatToIntBits(refreshRate); 1811 } 1812 1813 /** 1814 * Returns {@code true} if this mode equals to the other mode in all parameters except 1815 * the refresh rate. 1816 * 1817 * @hide 1818 */ equalsExceptRefreshRate(@ullable Display.Mode other)1819 public boolean equalsExceptRefreshRate(@Nullable Display.Mode other) { 1820 return mWidth == other.mWidth && mHeight == other.mHeight; 1821 } 1822 1823 @Override equals(@ullable Object other)1824 public boolean equals(@Nullable Object other) { 1825 if (this == other) { 1826 return true; 1827 } 1828 if (!(other instanceof Mode)) { 1829 return false; 1830 } 1831 Mode that = (Mode) other; 1832 return mModeId == that.mModeId && matches(that.mWidth, that.mHeight, that.mRefreshRate) 1833 && Arrays.equals(mAlternativeRefreshRates, that.mAlternativeRefreshRates); 1834 } 1835 1836 @Override hashCode()1837 public int hashCode() { 1838 int hash = 1; 1839 hash = hash * 17 + mModeId; 1840 hash = hash * 17 + mWidth; 1841 hash = hash * 17 + mHeight; 1842 hash = hash * 17 + Float.floatToIntBits(mRefreshRate); 1843 hash = hash * 17 + Arrays.hashCode(mAlternativeRefreshRates); 1844 return hash; 1845 } 1846 1847 @Override toString()1848 public String toString() { 1849 return new StringBuilder("{") 1850 .append("id=").append(mModeId) 1851 .append(", width=").append(mWidth) 1852 .append(", height=").append(mHeight) 1853 .append(", fps=").append(mRefreshRate) 1854 .append(", alternativeRefreshRates=") 1855 .append(Arrays.toString(mAlternativeRefreshRates)) 1856 .append("}") 1857 .toString(); 1858 } 1859 1860 @Override describeContents()1861 public int describeContents() { 1862 return 0; 1863 } 1864 Mode(Parcel in)1865 private Mode(Parcel in) { 1866 this(in.readInt(), in.readInt(), in.readInt(), in.readFloat(), in.createFloatArray()); 1867 } 1868 1869 @Override writeToParcel(Parcel out, int parcelableFlags)1870 public void writeToParcel(Parcel out, int parcelableFlags) { 1871 out.writeInt(mModeId); 1872 out.writeInt(mWidth); 1873 out.writeInt(mHeight); 1874 out.writeFloat(mRefreshRate); 1875 out.writeFloatArray(mAlternativeRefreshRates); 1876 } 1877 1878 @SuppressWarnings("hiding") 1879 public static final @android.annotation.NonNull Parcelable.Creator<Mode> CREATOR 1880 = new Parcelable.Creator<Mode>() { 1881 @Override 1882 public Mode createFromParcel(Parcel in) { 1883 return new Mode(in); 1884 } 1885 1886 @Override 1887 public Mode[] newArray(int size) { 1888 return new Mode[size]; 1889 } 1890 }; 1891 } 1892 1893 /** 1894 * Encapsulates the HDR capabilities of a given display. 1895 * For example, what HDR types it supports and details about the desired luminance data. 1896 * <p>You can get an instance for a given {@link Display} object with 1897 * {@link Display#getHdrCapabilities getHdrCapabilities()}. 1898 */ 1899 public static final class HdrCapabilities implements Parcelable { 1900 /** 1901 * Invalid luminance value. 1902 */ 1903 public static final float INVALID_LUMINANCE = -1; 1904 /** 1905 * Dolby Vision high dynamic range (HDR) display. 1906 */ 1907 public static final int HDR_TYPE_DOLBY_VISION = 1; 1908 /** 1909 * HDR10 display. 1910 */ 1911 public static final int HDR_TYPE_HDR10 = 2; 1912 /** 1913 * Hybrid Log-Gamma HDR display. 1914 */ 1915 public static final int HDR_TYPE_HLG = 3; 1916 1917 /** 1918 * HDR10+ display. 1919 */ 1920 public static final int HDR_TYPE_HDR10_PLUS = 4; 1921 1922 /** @hide */ 1923 public static final int[] HDR_TYPES = { 1924 HDR_TYPE_DOLBY_VISION, 1925 HDR_TYPE_HDR10, 1926 HDR_TYPE_HLG, 1927 HDR_TYPE_HDR10_PLUS 1928 }; 1929 1930 /** @hide */ 1931 @IntDef(prefix = { "HDR_TYPE_" }, value = { 1932 HDR_TYPE_DOLBY_VISION, 1933 HDR_TYPE_HDR10, 1934 HDR_TYPE_HLG, 1935 HDR_TYPE_HDR10_PLUS, 1936 }) 1937 @Retention(RetentionPolicy.SOURCE) 1938 public @interface HdrType {} 1939 1940 private @HdrType int[] mSupportedHdrTypes = new int[0]; 1941 private float mMaxLuminance = INVALID_LUMINANCE; 1942 private float mMaxAverageLuminance = INVALID_LUMINANCE; 1943 private float mMinLuminance = INVALID_LUMINANCE; 1944 1945 /** 1946 * @hide 1947 */ HdrCapabilities()1948 public HdrCapabilities() { 1949 } 1950 1951 /** 1952 * @hide 1953 */ 1954 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) HdrCapabilities(int[] supportedHdrTypes, float maxLuminance, float maxAverageLuminance, float minLuminance)1955 public HdrCapabilities(int[] supportedHdrTypes, float maxLuminance, 1956 float maxAverageLuminance, float minLuminance) { 1957 mSupportedHdrTypes = supportedHdrTypes; 1958 Arrays.sort(mSupportedHdrTypes); 1959 mMaxLuminance = maxLuminance; 1960 mMaxAverageLuminance = maxAverageLuminance; 1961 mMinLuminance = minLuminance; 1962 } 1963 1964 /** 1965 * Gets the supported HDR types of this display. 1966 * Returns empty array if HDR is not supported by the display. 1967 */ getSupportedHdrTypes()1968 public @HdrType int[] getSupportedHdrTypes() { 1969 return mSupportedHdrTypes; 1970 } 1971 /** 1972 * Returns the desired content max luminance data in cd/m2 for this display. 1973 */ getDesiredMaxLuminance()1974 public float getDesiredMaxLuminance() { 1975 return mMaxLuminance; 1976 } 1977 /** 1978 * Returns the desired content max frame-average luminance data in cd/m2 for this display. 1979 */ getDesiredMaxAverageLuminance()1980 public float getDesiredMaxAverageLuminance() { 1981 return mMaxAverageLuminance; 1982 } 1983 /** 1984 * Returns the desired content min luminance data in cd/m2 for this display. 1985 */ getDesiredMinLuminance()1986 public float getDesiredMinLuminance() { 1987 return mMinLuminance; 1988 } 1989 1990 @Override equals(@ullable Object other)1991 public boolean equals(@Nullable Object other) { 1992 if (this == other) { 1993 return true; 1994 } 1995 1996 if (!(other instanceof HdrCapabilities)) { 1997 return false; 1998 } 1999 HdrCapabilities that = (HdrCapabilities) other; 2000 2001 return Arrays.equals(mSupportedHdrTypes, that.mSupportedHdrTypes) 2002 && mMaxLuminance == that.mMaxLuminance 2003 && mMaxAverageLuminance == that.mMaxAverageLuminance 2004 && mMinLuminance == that.mMinLuminance; 2005 } 2006 2007 @Override hashCode()2008 public int hashCode() { 2009 int hash = 23; 2010 hash = hash * 17 + Arrays.hashCode(mSupportedHdrTypes); 2011 hash = hash * 17 + Float.floatToIntBits(mMaxLuminance); 2012 hash = hash * 17 + Float.floatToIntBits(mMaxAverageLuminance); 2013 hash = hash * 17 + Float.floatToIntBits(mMinLuminance); 2014 return hash; 2015 } 2016 2017 public static final @android.annotation.NonNull Creator<HdrCapabilities> CREATOR = new Creator<HdrCapabilities>() { 2018 @Override 2019 public HdrCapabilities createFromParcel(Parcel source) { 2020 return new HdrCapabilities(source); 2021 } 2022 2023 @Override 2024 public HdrCapabilities[] newArray(int size) { 2025 return new HdrCapabilities[size]; 2026 } 2027 }; 2028 HdrCapabilities(Parcel source)2029 private HdrCapabilities(Parcel source) { 2030 readFromParcel(source); 2031 } 2032 2033 /** 2034 * @hide 2035 */ readFromParcel(Parcel source)2036 public void readFromParcel(Parcel source) { 2037 int types = source.readInt(); 2038 mSupportedHdrTypes = new int[types]; 2039 for (int i = 0; i < types; ++i) { 2040 mSupportedHdrTypes[i] = source.readInt(); 2041 } 2042 mMaxLuminance = source.readFloat(); 2043 mMaxAverageLuminance = source.readFloat(); 2044 mMinLuminance = source.readFloat(); 2045 } 2046 2047 @Override writeToParcel(Parcel dest, int flags)2048 public void writeToParcel(Parcel dest, int flags) { 2049 dest.writeInt(mSupportedHdrTypes.length); 2050 for (int i = 0; i < mSupportedHdrTypes.length; ++i) { 2051 dest.writeInt(mSupportedHdrTypes[i]); 2052 } 2053 dest.writeFloat(mMaxLuminance); 2054 dest.writeFloat(mMaxAverageLuminance); 2055 dest.writeFloat(mMinLuminance); 2056 } 2057 2058 @Override describeContents()2059 public int describeContents() { 2060 return 0; 2061 } 2062 2063 @Override toString()2064 public String toString() { 2065 return "HdrCapabilities{" 2066 + "mSupportedHdrTypes=" + Arrays.toString(mSupportedHdrTypes) 2067 + ", mMaxLuminance=" + mMaxLuminance 2068 + ", mMaxAverageLuminance=" + mMaxAverageLuminance 2069 + ", mMinLuminance=" + mMinLuminance + '}'; 2070 } 2071 } 2072 } 2073