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 import static android.hardware.flags.Flags.FLAG_OVERLAYPROPERTIES_CLASS_API; 22 23 import android.Manifest; 24 import android.annotation.FlaggedApi; 25 import android.annotation.IntDef; 26 import android.annotation.NonNull; 27 import android.annotation.Nullable; 28 import android.annotation.RequiresPermission; 29 import android.annotation.SuppressLint; 30 import android.annotation.TestApi; 31 import android.app.ActivityThread; 32 import android.app.KeyguardManager; 33 import android.app.WindowConfiguration; 34 import android.compat.annotation.UnsupportedAppUsage; 35 import android.content.res.CompatibilityInfo; 36 import android.content.res.Configuration; 37 import android.content.res.Resources; 38 import android.graphics.ColorSpace; 39 import android.graphics.PixelFormat; 40 import android.graphics.Point; 41 import android.graphics.Rect; 42 import android.hardware.OverlayProperties; 43 import android.hardware.display.BrightnessInfo; 44 import android.hardware.display.DeviceProductInfo; 45 import android.hardware.display.DisplayManager; 46 import android.hardware.display.DisplayManagerGlobal; 47 import android.hardware.graphics.common.DisplayDecorationSupport; 48 import android.os.Build; 49 import android.os.Parcel; 50 import android.os.Parcelable; 51 import android.os.Process; 52 import android.os.SystemClock; 53 import android.util.ArraySet; 54 import android.util.DisplayMetrics; 55 import android.util.Log; 56 57 import java.lang.annotation.Retention; 58 import java.lang.annotation.RetentionPolicy; 59 import java.util.ArrayList; 60 import java.util.Arrays; 61 import java.util.List; 62 import java.util.concurrent.Executor; 63 import java.util.function.Consumer; 64 65 /** 66 * Provides information about the size and density of a logical display. 67 * <p> 68 * The display area is described in two different ways. 69 * <ul> 70 * <li>The application display area specifies the part of the display that may contain 71 * an application window, excluding the system decorations. The application display area may 72 * be smaller than the real display area because the system subtracts the space needed 73 * for decor elements such as the status bar. Use {@link WindowMetrics#getBounds()} to query the 74 * application window bounds.</li> 75 * <li>The real display area specifies the part of the display that is accessible to an application 76 * in the current system state. The real display area may be smaller than the physical size of the 77 * display in a few scenarios. Use {@link WindowManager#getCurrentWindowMetrics()} to identify the 78 * current size of the activity window. UI-related work, such as choosing UI layouts, should rely 79 * upon {@link WindowMetrics#getBounds()}. See {@link #getRealSize} / {@link #getRealMetrics} for 80 * details.</li> 81 * </ul> 82 * </p><p> 83 * A logical display does not necessarily represent a particular physical display device 84 * such as the internal display or an external display. The contents of a logical 85 * display may be presented on one or more physical displays according to the devices 86 * that are currently attached and whether mirroring has been enabled. 87 * </p> 88 */ 89 @android.ravenwood.annotation.RavenwoodKeepPartialClass 90 public final class Display { 91 private static final String TAG = "Display"; 92 private static final boolean DEBUG = false; 93 94 private final Object mLock = new Object(); 95 private final DisplayManagerGlobal mGlobal; 96 private final int mDisplayId; 97 private final int mFlags; 98 private final int mType; 99 private final int mOwnerUid; 100 private final String mOwnerPackageName; 101 private final Resources mResources; 102 private DisplayAdjustments mDisplayAdjustments; 103 104 @UnsupportedAppUsage 105 private DisplayInfo mDisplayInfo; // never null 106 private boolean mIsValid; 107 108 // Temporary display metrics structure used for compatibility mode. 109 private final DisplayMetrics mTempMetrics = new DisplayMetrics(); 110 111 // We cache the app width and height properties briefly between calls 112 // to getHeight() and getWidth() to ensure that applications perceive 113 // consistent results when the size changes (most of the time). 114 // Applications should now be using WindowMetrics instead. 115 private static final int CACHED_APP_SIZE_DURATION_MILLIS = 20; 116 private long mLastCachedAppSizeUpdate; 117 private int mCachedAppWidthCompat; 118 private int mCachedAppHeightCompat; 119 120 private ArrayList<HdrSdrRatioListenerWrapper> mHdrSdrRatioListeners = new ArrayList<>(); 121 122 /** 123 * The default Display id, which is the id of the primary display assuming there is one. 124 */ 125 public static final int DEFAULT_DISPLAY = 0; 126 127 /** 128 * Invalid display id. 129 */ 130 public static final int INVALID_DISPLAY = -1; 131 132 /** 133 * Invalid resolution width. 134 * @hide 135 */ 136 public static final int INVALID_DISPLAY_WIDTH = -1; 137 138 /** 139 * Invalid resolution height. 140 * @hide 141 */ 142 public static final int INVALID_DISPLAY_HEIGHT = -1; 143 144 /** 145 * Invalid refresh rate. 146 * @hide 147 */ 148 public static final float INVALID_DISPLAY_REFRESH_RATE = 0.0f; 149 150 /** 151 * The default display group id, which is the display group id of the primary display assuming 152 * there is one. 153 * @hide 154 */ 155 public static final int DEFAULT_DISPLAY_GROUP = 0; 156 157 /** 158 * Invalid display group id. 159 * @hide 160 */ 161 public static final int INVALID_DISPLAY_GROUP = -1; 162 163 /** 164 * Display flag: Indicates that the display supports compositing content 165 * that is stored in protected graphics buffers. 166 * <p> 167 * If this flag is set then the display device supports compositing protected buffers. 168 * </p><p> 169 * If this flag is not set then the display device may not support compositing 170 * protected buffers; the user may see a blank region on the screen instead of 171 * the protected content. 172 * </p><p> 173 * Secure (DRM) video decoders may allocate protected graphics buffers to request that 174 * a hardware-protected path be provided between the video decoder and the external 175 * display sink. If a hardware-protected path is not available, then content stored 176 * in protected graphics buffers may not be composited. 177 * </p><p> 178 * An application can use the absence of this flag as a hint that it should not use protected 179 * buffers for this display because the content may not be visible. For example, 180 * if the flag is not set then the application may choose not to show content on this 181 * display, show an informative error message, select an alternate content stream 182 * or adopt a different strategy for decoding content that does not rely on 183 * protected buffers. 184 * </p> 185 * 186 * @see #getFlags 187 */ 188 public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1 << 0; 189 190 /** 191 * Display flag: Indicates that the display has a secure video output and 192 * supports compositing secure surfaces. 193 * <p> 194 * If this flag is set then the display device has a secure video output 195 * and is capable of showing secure surfaces. It may also be capable of 196 * showing {@link #FLAG_SUPPORTS_PROTECTED_BUFFERS protected buffers}. 197 * </p><p> 198 * If this flag is not set then the display device may not have a secure video 199 * output; the user may see a blank region on the screen instead of 200 * the contents of secure surfaces or protected buffers. 201 * </p><p> 202 * Secure surfaces are used to prevent content rendered into those surfaces 203 * by applications from appearing in screenshots or from being viewed 204 * on non-secure displays. Protected buffers are used by secure video decoders 205 * for a similar purpose. 206 * </p><p> 207 * An application creates a window with a secure surface by specifying the 208 * {@link WindowManager.LayoutParams#FLAG_SECURE} window flag. 209 * Likewise, an application creates a {@link SurfaceView} with a secure surface 210 * by calling {@link SurfaceView#setSecure} before attaching the secure view to 211 * its containing window. 212 * </p><p> 213 * An application can use the absence of this flag as a hint that it should not create 214 * secure surfaces or protected buffers on this display because the content may 215 * not be visible. For example, if the flag is not set then the application may 216 * choose not to show content on this display, show an informative error message, 217 * select an alternate content stream or adopt a different strategy for decoding 218 * content that does not rely on secure surfaces or protected buffers. 219 * </p> 220 * 221 * @see #getFlags 222 */ 223 public static final int FLAG_SECURE = 1 << 1; 224 225 /** 226 * Display flag: Indicates that the display is private. Only the application that 227 * owns the display and apps that are already on the display can create windows on it. 228 * 229 * @see #getFlags 230 */ 231 public static final int FLAG_PRIVATE = 1 << 2; 232 233 /** 234 * Display flag: Indicates that the display is a presentation display. 235 * <p> 236 * This flag identifies secondary displays that are suitable for 237 * use as presentation displays such as external or wireless displays. Applications 238 * may automatically project their content to presentation displays to provide 239 * richer second screen experiences. 240 * </p> 241 * 242 * @see #getFlags 243 */ 244 public static final int FLAG_PRESENTATION = 1 << 3; 245 246 /** 247 * Display flag: Indicates that the display has a round shape. 248 * <p> 249 * This flag identifies displays that are circular, elliptical or otherwise 250 * do not permit the user to see all the way to the logical corners of the display. 251 * </p> 252 * 253 * @see #getFlags 254 */ 255 public static final int FLAG_ROUND = 1 << 4; 256 257 /** 258 * Display flag: Indicates that the display can show its content when non-secure keyguard is 259 * shown. 260 * <p> 261 * This flag identifies secondary displays that will continue showing content if keyguard can be 262 * dismissed without entering credentials. 263 * </p><p> 264 * An example of usage is a virtual display which content is displayed on external hardware 265 * display that is not visible to the system directly. 266 * </p> 267 * 268 * @see DisplayManager#VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD 269 * @see KeyguardManager#isDeviceSecure() 270 * @see KeyguardManager#isDeviceLocked() 271 * @see #getFlags 272 * @hide 273 */ 274 // TODO (b/114338689): Remove the flag and use IWindowManager#shouldShowWithInsecureKeyguard 275 public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5; 276 277 /** 278 * Display flag: Indicates that the display should show system decorations. 279 * <p> 280 * This flag identifies secondary displays that should show system decorations, such as 281 * navigation bar, home activity or wallpaper. 282 * </p> 283 * <p>Note that this flag doesn't work without {@link #FLAG_TRUSTED}</p> 284 * 285 * @see #getFlags() 286 * @hide 287 */ 288 public static final int FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 6; 289 290 /** 291 * Flag: The display is trusted to show system decorations and receive inputs without users' 292 * touch. 293 * @see #FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS 294 * 295 * @see #getFlags() 296 * @hide 297 */ 298 @TestApi 299 public static final int FLAG_TRUSTED = 1 << 7; 300 301 /** 302 * Flag: Indicates that the display should not be a part of the default DisplayGroup and 303 * instead be part of a new DisplayGroup. 304 * 305 * @hide 306 * @see #getFlags() 307 */ 308 public static final int FLAG_OWN_DISPLAY_GROUP = 1 << 8; 309 310 /** 311 * Flag: Indicates that the display should always be unlocked. Only valid on virtual displays 312 * that aren't in the default display group. 313 * 314 * @hide 315 * @see #getFlags() 316 */ 317 public static final int FLAG_ALWAYS_UNLOCKED = 1 << 9; 318 319 /** 320 * Flag: Indicates that the display should not play sound effects or perform haptic feedback 321 * when the user touches the screen. 322 * 323 * @hide 324 * @see #getFlags() 325 */ 326 public static final int FLAG_TOUCH_FEEDBACK_DISABLED = 1 << 10; 327 328 /** 329 * Flag: Indicates that the display maintains its own focus and touch mode. 330 * 331 * This flag is similar to {@link com.android.internal.R.bool.config_perDisplayFocusEnabled} in 332 * behavior, but only applies to the specific display instead of system-wide to all displays. 333 * 334 * Note: The display must be trusted in order to have its own focus. 335 * 336 * @see #FLAG_TRUSTED 337 * @hide 338 */ 339 public static final int FLAG_OWN_FOCUS = 1 << 11; 340 341 /** 342 * Flag: Indicates that the display should not become the top focused display by stealing the 343 * top focus from another display. 344 * 345 * <p>The result is that only targeted input events (displayId of input event matches the 346 * displayId of the display) can reach this display. A display with this flag set can still 347 * become the top focused display, if the system consists of only one display or if all 348 * displays have this flag set. In both cases the default display becomes the top focused 349 * display. 350 * 351 * <p>Note: A display only has a focused window if either 352 * - the display is the top focused display or 353 * - the display manages its own focus (via {@link #FLAG_OWN_FOCUS}) 354 * - or all the displays manage their own focus (via {@code config_perDisplayFocusEnabled} flag) 355 * If a display has no focused window, no input event is dispatched to it. Therefore this 356 * flag is only useful together with {@link #FLAG_OWN_FOCUS} and will be 357 * ignored if it is not set. 358 * 359 * <p>Note: The framework only supports IME on the top focused display (b/262520411). Therefore, 360 * Enabling this flag on a display implicitly disables showing any IME. This is not intended 361 * behavior but cannot be fixed until b/262520411 is implemented. If you need IME on display do 362 * not set this flag. 363 * 364 * @hide 365 * @see #getFlags() 366 */ 367 public static final int FLAG_STEAL_TOP_FOCUS_DISABLED = 1 << 12; 368 369 /** 370 * Display flag: Indicates that the display is a rear display. 371 * <p> 372 * This flag identifies complementary displays that are facing away from the user. 373 * </p> 374 * 375 * @hide 376 * @see #getFlags() 377 */ 378 public static final int FLAG_REAR = 1 << 13; 379 380 /** 381 * Display flag: Indicates that the orientation of this display is not fixed and is coupled to 382 * the orientation of its content. 383 * 384 * @hide 385 */ 386 public static final int FLAG_ROTATES_WITH_CONTENT = 1 << 14; 387 388 /** 389 * Display flag: Indicates that the contents of the display should not be scaled 390 * to fit the physical screen dimensions. Used for development only to emulate 391 * devices with smaller physicals screens while preserving density. 392 * 393 * @hide 394 */ 395 public static final int FLAG_SCALING_DISABLED = 1 << 30; 396 397 /** 398 * Display type: Unknown display type. 399 * @hide 400 */ 401 @UnsupportedAppUsage 402 @TestApi 403 public static final int TYPE_UNKNOWN = 0; 404 405 /** 406 * Display type: Physical display connected through an internal port. 407 * @hide 408 */ 409 @TestApi 410 public static final int TYPE_INTERNAL = 1; 411 412 /** 413 * Display type: Physical display connected through an external port. 414 * @hide 415 */ 416 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 417 @TestApi 418 public static final int TYPE_EXTERNAL = 2; 419 420 /** 421 * Display type: WiFi display. 422 * @hide 423 */ 424 @UnsupportedAppUsage 425 @TestApi 426 public static final int TYPE_WIFI = 3; 427 428 /** 429 * Display type: Overlay display. 430 * @hide 431 */ 432 @TestApi 433 public static final int TYPE_OVERLAY = 4; 434 435 /** 436 * Display type: Virtual display. 437 * @hide 438 */ 439 @UnsupportedAppUsage 440 @TestApi 441 public static final int TYPE_VIRTUAL = 5; 442 443 /** 444 * Display state: The display state is unknown. 445 * 446 * @see #getState 447 */ 448 public static final int STATE_UNKNOWN = ViewProtoEnums.DISPLAY_STATE_UNKNOWN; // 0 449 450 /** 451 * Display state: The display is off. 452 * 453 * @see #getState 454 */ 455 public static final int STATE_OFF = ViewProtoEnums.DISPLAY_STATE_OFF; // 1 456 457 /** 458 * Display state: The display is on. 459 * 460 * @see #getState 461 */ 462 public static final int STATE_ON = ViewProtoEnums.DISPLAY_STATE_ON; // 2 463 464 /** 465 * Display state: The display is dozing in a low power state; it is still 466 * on but is optimized for showing system-provided content while the 467 * device is non-interactive. 468 * 469 * @see #getState 470 * @see android.os.PowerManager#isInteractive 471 */ 472 public static final int STATE_DOZE = ViewProtoEnums.DISPLAY_STATE_DOZE; // 3 473 474 /** 475 * Display state: The display is dozing in a suspended low power state; it is still 476 * on but the CPU is not updating it. This may be used in one of two ways: to show 477 * static system-provided content while the device is non-interactive, or to allow 478 * a "Sidekick" compute resource to update the display. For this reason, the 479 * CPU must not control the display in this mode. 480 * 481 * @see #getState 482 * @see android.os.PowerManager#isInteractive 483 */ 484 public static final int STATE_DOZE_SUSPEND = ViewProtoEnums.DISPLAY_STATE_DOZE_SUSPEND; // 4 485 486 /** 487 * Display state: The display is on and optimized for VR mode. 488 * 489 * @see #getState 490 * @see android.os.PowerManager#isInteractive 491 */ 492 public static final int STATE_VR = ViewProtoEnums.DISPLAY_STATE_VR; // 5 493 494 /** 495 * Display state: The display is in a suspended full power state; it is still 496 * on but the CPU is not updating it. This may be used in one of two ways: to show 497 * static system-provided content while the device is non-interactive, or to allow 498 * a "Sidekick" compute resource to update the display. For this reason, the 499 * CPU must not control the display in this mode. 500 * 501 * @see #getState 502 * @see android.os.PowerManager#isInteractive 503 */ 504 public static final int STATE_ON_SUSPEND = ViewProtoEnums.DISPLAY_STATE_ON_SUSPEND; // 6 505 506 /** 507 * The cause of the display state change is unknown. 508 * 509 * @hide 510 */ 511 public static final int STATE_REASON_UNKNOWN = ViewProtoEnums.DISPLAY_STATE_REASON_UNKNOWN; 512 513 /** 514 * The default power and display policy caused the display state. 515 * 516 * @hide 517 */ 518 public static final int STATE_REASON_DEFAULT_POLICY = 519 ViewProtoEnums.DISPLAY_STATE_REASON_DEFAULT_POLICY; 520 521 /** 522 * The display state was changed due to acquiring a draw wake lock. 523 * 524 * @hide 525 */ 526 public static final int STATE_REASON_DRAW_WAKE_LOCK = 527 ViewProtoEnums.DISPLAY_STATE_REASON_DRAW_WAKE_LOCK; 528 529 /** 530 * The display state was changed due to display offloading. 531 * 532 * @hide 533 */ 534 public static final int STATE_REASON_OFFLOAD = ViewProtoEnums.DISPLAY_STATE_REASON_OFFLOAD; 535 536 /** 537 * The display state was changed due to a tilt event. 538 * 539 * @hide 540 */ 541 public static final int STATE_REASON_TILT = ViewProtoEnums.DISPLAY_STATE_REASON_TILT; 542 543 /** 544 * The display state was changed due to the dream manager. 545 * 546 * @hide 547 */ 548 public static final int STATE_REASON_DREAM_MANAGER = 549 ViewProtoEnums.DISPLAY_STATE_REASON_DREAM_MANAGER; 550 551 /** 552 * The display state was changed due to a {@link KeyEvent}. 553 * 554 * @hide 555 */ 556 public static final int STATE_REASON_KEY = ViewProtoEnums.DISPLAY_STATE_REASON_KEY; 557 558 /** 559 * The display state was changed due to a {@link MotionEvent}. 560 * 561 * @hide 562 */ 563 public static final int STATE_REASON_MOTION = ViewProtoEnums.DISPLAY_STATE_REASON_MOTION; 564 565 /** @hide */ 566 @IntDef(prefix = {"STATE_REASON_"}, value = { 567 STATE_REASON_UNKNOWN, 568 STATE_REASON_DEFAULT_POLICY, 569 STATE_REASON_DRAW_WAKE_LOCK, 570 STATE_REASON_OFFLOAD, 571 STATE_REASON_TILT, 572 STATE_REASON_DREAM_MANAGER, 573 STATE_REASON_KEY, 574 STATE_REASON_MOTION, 575 }) 576 @Retention(RetentionPolicy.SOURCE) 577 public @interface StateReason {} 578 579 /* The color mode constants defined below must be kept in sync with the ones in 580 * system/core/include/system/graphics-base.h */ 581 582 /** 583 * Display color mode: The current color mode is unknown or invalid. 584 * @hide 585 */ 586 public static final int COLOR_MODE_INVALID = -1; 587 588 /** 589 * Display color mode: The default or native gamut of the display. 590 * @hide 591 */ 592 public static final int COLOR_MODE_DEFAULT = 0; 593 594 /** @hide */ 595 public static final int COLOR_MODE_BT601_625 = 1; 596 /** @hide */ 597 public static final int COLOR_MODE_BT601_625_UNADJUSTED = 2; 598 /** @hide */ 599 public static final int COLOR_MODE_BT601_525 = 3; 600 /** @hide */ 601 public static final int COLOR_MODE_BT601_525_UNADJUSTED = 4; 602 /** @hide */ 603 public static final int COLOR_MODE_BT709 = 5; 604 /** @hide */ 605 public static final int COLOR_MODE_DCI_P3 = 6; 606 /** @hide */ 607 public static final int COLOR_MODE_SRGB = 7; 608 /** @hide */ 609 public static final int COLOR_MODE_ADOBE_RGB = 8; 610 /** @hide */ 611 public static final int COLOR_MODE_DISPLAY_P3 = 9; 612 613 /** @hide **/ 614 @IntDef(prefix = {"COLOR_MODE_"}, value = { 615 COLOR_MODE_INVALID, 616 COLOR_MODE_DEFAULT, 617 COLOR_MODE_BT601_625, 618 COLOR_MODE_BT601_625_UNADJUSTED, 619 COLOR_MODE_BT601_525, 620 COLOR_MODE_BT601_525_UNADJUSTED, 621 COLOR_MODE_BT709, 622 COLOR_MODE_DCI_P3, 623 COLOR_MODE_SRGB, 624 COLOR_MODE_ADOBE_RGB, 625 COLOR_MODE_DISPLAY_P3 626 }) 627 @Retention(RetentionPolicy.SOURCE) 628 public @interface ColorMode {} 629 630 /** 631 * Indicates that when display is removed, all its activities will be moved to the primary 632 * display and the topmost activity should become focused. 633 * 634 * @hide 635 */ 636 // TODO (b/114338689): Remove the flag and use WindowManager#REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY 637 public static final int REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY = 0; 638 /** 639 * Indicates that when display is removed, all its stacks and tasks will be removed, all 640 * activities will be destroyed according to the usual lifecycle. 641 * 642 * @hide 643 */ 644 // TODO (b/114338689): Remove the flag and use WindowManager#REMOVE_CONTENT_MODE_DESTROY 645 public static final int REMOVE_MODE_DESTROY_CONTENT = 1; 646 647 /** @hide */ 648 public static final int DISPLAY_MODE_ID_FOR_FRAME_RATE_OVERRIDE = 0xFF; 649 650 /** 651 * Internal method to create a display. 652 * The display created with this method will have a static {@link DisplayAdjustments} applied. 653 * Applications should use {@link android.content.Context#getDisplay} with 654 * {@link android.app.Activity} or a context associated with a {@link Display} via 655 * {@link android.content.Context#createDisplayContext(Display)} 656 * to get a display object associated with a {@link android.app.Context}, or 657 * {@link android.hardware.display.DisplayManager#getDisplay} to get a display object by id. 658 * 659 * @see android.content.Context#getDisplay() 660 * @see android.content.Context#createDisplayContext(Display) 661 * @hide 662 */ Display(DisplayManagerGlobal global, int displayId, DisplayInfo displayInfo, DisplayAdjustments daj)663 public Display(DisplayManagerGlobal global, int displayId, /*@NotNull*/ DisplayInfo displayInfo, 664 DisplayAdjustments daj) { 665 this(global, displayId, displayInfo, daj, null /*res*/); 666 } 667 668 /** 669 * Internal method to create a display. 670 * The display created with this method will be adjusted based on the adjustments in the 671 * supplied {@link Resources}. 672 * 673 * @hide 674 */ Display(DisplayManagerGlobal global, int displayId, DisplayInfo displayInfo, Resources res)675 public Display(DisplayManagerGlobal global, int displayId, /*@NotNull*/ DisplayInfo displayInfo, 676 Resources res) { 677 this(global, displayId, displayInfo, null /*daj*/, res); 678 } 679 Display(DisplayManagerGlobal global, int displayId, DisplayInfo displayInfo, DisplayAdjustments daj, Resources res)680 private Display(DisplayManagerGlobal global, int displayId, 681 /*@NotNull*/ DisplayInfo displayInfo, DisplayAdjustments daj, Resources res) { 682 mGlobal = global; 683 mDisplayId = displayId; 684 mDisplayInfo = displayInfo; 685 mResources = res; 686 mDisplayAdjustments = mResources != null 687 ? new DisplayAdjustments(mResources.getConfiguration()) 688 : daj != null ? new DisplayAdjustments(daj) : new DisplayAdjustments(); 689 mIsValid = true; 690 691 // Cache properties that cannot change as long as the display is valid. 692 mFlags = displayInfo.flags; 693 mType = displayInfo.type; 694 mOwnerUid = displayInfo.ownerUid; 695 mOwnerPackageName = displayInfo.ownerPackageName; 696 } 697 698 /** 699 * Gets the display id. 700 * <p> 701 * Each logical display has a unique id. 702 * The default display has id {@link #DEFAULT_DISPLAY}. 703 * </p> 704 */ getDisplayId()705 public int getDisplayId() { 706 return mDisplayId; 707 } 708 709 /** 710 * Gets the display unique id. 711 * <p> 712 * Unique id is different from display id because physical displays have stable unique id across 713 * reboots. 714 * 715 * @see com.android.service.display.DisplayDevice#hasStableUniqueId(). 716 * @hide 717 */ 718 @TestApi getUniqueId()719 public @Nullable String getUniqueId() { 720 return mDisplayInfo.uniqueId; 721 } 722 723 /** 724 * Returns true if this display is still valid, false if the display has been removed. 725 * 726 * If the display is invalid, then the methods of this class will 727 * continue to report the most recently observed display information. 728 * However, it is unwise (and rather fruitless) to continue using a 729 * {@link Display} object after the display's demise. 730 * 731 * It's possible for a display that was previously invalid to become 732 * valid again if a display with the same id is reconnected. 733 * 734 * @return True if the display is still valid. 735 */ isValid()736 public boolean isValid() { 737 synchronized (mLock) { 738 updateDisplayInfoLocked(); 739 return mIsValid; 740 } 741 } 742 743 /** 744 * Gets a full copy of the display information. 745 * 746 * @param outDisplayInfo The object to receive the copy of the display information. 747 * @return True if the display is still valid. 748 * @hide 749 */ 750 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) getDisplayInfo(DisplayInfo outDisplayInfo)751 public boolean getDisplayInfo(DisplayInfo outDisplayInfo) { 752 synchronized (mLock) { 753 updateDisplayInfoLocked(); 754 outDisplayInfo.copyFrom(mDisplayInfo); 755 return mIsValid; 756 } 757 } 758 759 /** 760 * Gets the display's layer stack. 761 * 762 * Each display has its own independent layer stack upon which surfaces 763 * are placed to be managed by surface flinger. 764 * 765 * @return The display's layer stack number. 766 * @hide 767 */ getLayerStack()768 public int getLayerStack() { 769 synchronized (mLock) { 770 updateDisplayInfoLocked(); 771 return mDisplayInfo.layerStack; 772 } 773 } 774 775 /** 776 * Returns a combination of flags that describe the capabilities of the display. 777 * 778 * @return The display flags. 779 * 780 * @see #FLAG_SUPPORTS_PROTECTED_BUFFERS 781 * @see #FLAG_SECURE 782 * @see #FLAG_PRIVATE 783 * @see #FLAG_ROUND 784 */ getFlags()785 public int getFlags() { 786 return mFlags; 787 } 788 789 /** 790 * Gets the display type. 791 * 792 * @return The display type. 793 * 794 * @see #TYPE_UNKNOWN 795 * @see #TYPE_INTERNAL 796 * @see #TYPE_EXTERNAL 797 * @see #TYPE_WIFI 798 * @see #TYPE_OVERLAY 799 * @see #TYPE_VIRTUAL 800 * @hide 801 */ 802 @UnsupportedAppUsage 803 @TestApi getType()804 public int getType() { 805 return mType; 806 } 807 808 /** 809 * Gets the display address, or null if none. 810 * Interpretation varies by display type. 811 * 812 * @return The display address. 813 * @hide 814 */ getAddress()815 public DisplayAddress getAddress() { 816 synchronized (mLock) { 817 updateDisplayInfoLocked(); 818 return mDisplayInfo.address; 819 } 820 } 821 822 /** 823 * Gets the UID of the application that owns this display, or zero if it is 824 * owned by the system. 825 * <p> 826 * If the display is private, then only the owner can use it. 827 * </p> 828 * 829 * @hide 830 */ getOwnerUid()831 public int getOwnerUid() { 832 return mOwnerUid; 833 } 834 835 /** 836 * Gets the package name of the application that owns this display, or null if it is 837 * owned by the system. 838 * <p> 839 * If the display is private, then only the owner can use it. 840 * </p> 841 * 842 * @hide 843 */ 844 @UnsupportedAppUsage getOwnerPackageName()845 public String getOwnerPackageName() { 846 return mOwnerPackageName; 847 } 848 849 /** 850 * Gets the compatibility info used by this display instance. 851 * 852 * @return The display adjustments holder, or null if none is required. 853 * @hide 854 */ 855 @UnsupportedAppUsage getDisplayAdjustments()856 public DisplayAdjustments getDisplayAdjustments() { 857 if (mResources != null) { 858 final DisplayAdjustments currentAdjustments = mResources.getDisplayAdjustments(); 859 if (!mDisplayAdjustments.equals(currentAdjustments)) { 860 mDisplayAdjustments = new DisplayAdjustments(currentAdjustments); 861 } 862 } 863 864 return mDisplayAdjustments; 865 } 866 867 /** 868 * Gets the name of the display. 869 * <p> 870 * Note that some displays may be renamed by the user. 871 * </p> 872 * 873 * @return The display's name. 874 */ getName()875 public String getName() { 876 synchronized (mLock) { 877 updateDisplayInfoLocked(); 878 return mDisplayInfo.name; 879 } 880 } 881 882 /** 883 * Gets the default brightness configured for the display. 884 * 885 * @return Default brightness between 0.0-1.0 886 * @hide 887 */ getBrightnessDefault()888 public float getBrightnessDefault() { 889 synchronized (mLock) { 890 updateDisplayInfoLocked(); 891 return mDisplayInfo.brightnessDefault; 892 } 893 } 894 895 /** 896 * @return Brightness information about the display. 897 * @hide 898 */ 899 @RequiresPermission(CONTROL_DISPLAY_BRIGHTNESS) getBrightnessInfo()900 public @Nullable BrightnessInfo getBrightnessInfo() { 901 return mGlobal.getBrightnessInfo(mDisplayId); 902 } 903 904 /** 905 * Gets the size of the display in pixels. 906 * 907 * <p>The return value does not necessarily represent the actual size (native resolution) of the 908 * display. The returned size might be adjusted to exclude certain system decor elements that 909 * are always visible, or the size might be scaled to provide compatibility with older 910 * applications that were originally designed for smaller displays. 911 * 912 * <p>The returned size can also be different depending on the WindowManager bound to the 913 * display: 914 * <ul> 915 * <li>If size is requested from an activity (either using a WindowManager accessed by 916 * {@code getWindowManager()} or {@code getSystemService(Context.WINDOW_SERVICE)}), the 917 * size of the current app window is returned. As a result, in multi-window mode, the 918 * returned size can be smaller than the size of the device screen. 919 * The returned window size can vary depending on API level: 920 * <ul> 921 * <li>API level 35 and above, the window size will be returned. 922 * <li>API level 34 and below, the window size minus system decoration areas and 923 * display cutout is returned. 924 * </ul> 925 * <li>If size is requested from a non-activity context (for example, the application 926 * context, where the WindowManager is accessed by 927 * {@code getApplicationContext().getSystemService(Context.WINDOW_SERVICE)}), the 928 * returned size can vary depending on API level: 929 * <ul> 930 * <li>API level 29 and below — The size of the entire display (based on 931 * current rotation) minus system decoration areas is returned. 932 * <li>API level 30 and above — The size of the top running activity in the 933 * current process is returned, system decoration areas exclusion follows the 934 * behavior defined above, based on the caller's API level. If the current 935 * process has no running activities, the size of the device default display, 936 * including system decoration areas, is returned. 937 * </ul> 938 * </ul> 939 * 940 * <p>For layout purposes, apps should make a request from an activity context to obtain the 941 * size of the display area available for app content. 942 * 943 * @param outSize A {@link Point} object which receives the display size information. 944 * 945 * @deprecated Use {@link WindowMetrics} instead. Obtain a {@code WindowMetrics} instance by 946 * calling {@link WindowManager#getCurrentWindowMetrics()}, then call 947 * {@link WindowMetrics#getBounds()} to get the dimensions of the application window. 948 */ 949 @Deprecated getSize(Point outSize)950 public void getSize(Point outSize) { 951 synchronized (mLock) { 952 updateDisplayInfoLocked(); 953 mDisplayInfo.getAppMetrics(mTempMetrics, getDisplayAdjustments()); 954 outSize.x = mTempMetrics.widthPixels; 955 outSize.y = mTempMetrics.heightPixels; 956 } 957 } 958 959 /** 960 * Gets the size of the display as a rectangle, in pixels. 961 * 962 * @param outSize A {@link Rect} object to receive the size information. 963 * 964 * @deprecated Use {@link WindowMetrics#getBounds()} to get the dimensions of the application 965 * window. 966 */ 967 @Deprecated getRectSize(Rect outSize)968 public void getRectSize(Rect outSize) { 969 synchronized (mLock) { 970 updateDisplayInfoLocked(); 971 mDisplayInfo.getAppMetrics(mTempMetrics, getDisplayAdjustments()); 972 outSize.set(0, 0, mTempMetrics.widthPixels, mTempMetrics.heightPixels); 973 } 974 } 975 976 /** 977 * Return the range of display sizes an application can expect to encounter 978 * under normal operation, as long as there is no physical change in screen 979 * size. This is basically the sizes you will see as the orientation 980 * changes, taking into account whatever screen decoration there is in 981 * each rotation. For example, the status bar is always at the top of the 982 * screen, so it will reduce the height both in landscape and portrait, and 983 * the smallest height returned here will be the smaller of the two. 984 * 985 * This is intended for applications to get an idea of the range of sizes 986 * they will encounter while going through device rotations, to provide a 987 * stable UI through rotation. The sizes here take into account all standard 988 * system decorations that reduce the size actually available to the 989 * application: the status bar, navigation bar, system bar, etc. It does 990 * <em>not</em> take into account more transient elements like an IME 991 * soft keyboard. 992 * 993 * @param outSmallestSize Filled in with the smallest width and height 994 * that the application will encounter, in pixels (not dp units). The x 995 * (width) dimension here directly corresponds to 996 * {@link android.content.res.Configuration#smallestScreenWidthDp 997 * Configuration.smallestScreenWidthDp}, except the value here is in raw 998 * screen pixels rather than dp units. Your application may of course 999 * still get smaller space yet if, for example, a soft keyboard is 1000 * being displayed. 1001 * @param outLargestSize Filled in with the largest width and height 1002 * that the application will encounter, in pixels (not dp units). Your 1003 * application may of course still get larger space than this if, 1004 * for example, screen decorations like the status bar are being hidden. 1005 */ getCurrentSizeRange(Point outSmallestSize, Point outLargestSize)1006 public void getCurrentSizeRange(Point outSmallestSize, Point outLargestSize) { 1007 synchronized (mLock) { 1008 updateDisplayInfoLocked(); 1009 outSmallestSize.x = mDisplayInfo.smallestNominalAppWidth; 1010 outSmallestSize.y = mDisplayInfo.smallestNominalAppHeight; 1011 outLargestSize.x = mDisplayInfo.largestNominalAppWidth; 1012 outLargestSize.y = mDisplayInfo.largestNominalAppHeight; 1013 } 1014 } 1015 1016 /** 1017 * Return the maximum screen size dimension that will happen. This is 1018 * mostly for wallpapers. 1019 * @hide 1020 */ 1021 @UnsupportedAppUsage getMaximumSizeDimension()1022 public int getMaximumSizeDimension() { 1023 synchronized (mLock) { 1024 updateDisplayInfoLocked(); 1025 return Math.max(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); 1026 } 1027 } 1028 1029 /** 1030 * @deprecated Use {@link WindowMetrics#getBounds#width()} instead. 1031 */ 1032 @Deprecated getWidth()1033 public int getWidth() { 1034 synchronized (mLock) { 1035 updateCachedAppSizeIfNeededLocked(); 1036 return mCachedAppWidthCompat; 1037 } 1038 } 1039 1040 /** 1041 * @deprecated Use {@link WindowMetrics#getBounds()#height()} instead. 1042 */ 1043 @Deprecated getHeight()1044 public int getHeight() { 1045 synchronized (mLock) { 1046 updateCachedAppSizeIfNeededLocked(); 1047 return mCachedAppHeightCompat; 1048 } 1049 } 1050 1051 /** 1052 * Returns the rotation of the screen from its "natural" orientation. 1053 * The returned value may be {@link Surface#ROTATION_0 Surface.ROTATION_0} 1054 * (no rotation), {@link Surface#ROTATION_90 Surface.ROTATION_90}, 1055 * {@link Surface#ROTATION_180 Surface.ROTATION_180}, or 1056 * {@link Surface#ROTATION_270 Surface.ROTATION_270}. For 1057 * example, if a device has a naturally tall screen, and the user has 1058 * turned it on its side to go into a landscape orientation, the value 1059 * returned here may be either {@link Surface#ROTATION_90 Surface.ROTATION_90} 1060 * or {@link Surface#ROTATION_270 Surface.ROTATION_270} depending on 1061 * the direction it was turned. The angle is the rotation of the drawn 1062 * graphics on the screen, which is the opposite direction of the physical 1063 * rotation of the device. For example, if the device is rotated 90 1064 * degrees counter-clockwise, to compensate rendering will be rotated by 1065 * 90 degrees clockwise and thus the returned value here will be 1066 * {@link Surface#ROTATION_90 Surface.ROTATION_90}. 1067 * 1068 * This rotation value will match the results of {@link #getMetrics}: this means that the 1069 * rotation value will correspond to the activity if accessed through the activity. 1070 */ 1071 @Surface.Rotation getRotation()1072 public int getRotation() { 1073 synchronized (mLock) { 1074 updateDisplayInfoLocked(); 1075 return getLocalRotation(); 1076 } 1077 } 1078 1079 /** 1080 * Returns the install orientation of the display. 1081 * @hide 1082 */ 1083 @Surface.Rotation getInstallOrientation()1084 public int getInstallOrientation() { 1085 synchronized (mLock) { 1086 updateDisplayInfoLocked(); 1087 return mDisplayInfo.installOrientation; 1088 } 1089 } 1090 1091 /** 1092 * @deprecated use {@link #getRotation} 1093 * @return orientation of this display. 1094 */ 1095 @Deprecated 1096 @Surface.Rotation getOrientation()1097 public int getOrientation() { 1098 return getRotation(); 1099 } 1100 1101 1102 /** 1103 * Returns the {@link DisplayCutout}, or {@code null} if there is none. 1104 * 1105 * @see DisplayCutout 1106 */ 1107 @Nullable getCutout()1108 public DisplayCutout getCutout() { 1109 synchronized (mLock) { 1110 updateDisplayInfoLocked(); 1111 if (mResources == null) return mDisplayInfo.displayCutout; 1112 final DisplayCutout localCutout = mDisplayInfo.displayCutout; 1113 if (localCutout == null) return null; 1114 int rotation = getLocalRotation(); 1115 if (rotation != mDisplayInfo.rotation) { 1116 return localCutout.getRotated(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight, 1117 mDisplayInfo.rotation, rotation); 1118 } 1119 return localCutout; 1120 } 1121 } 1122 1123 /** 1124 * Returns the {@link RoundedCorner} of the given position if there is one. 1125 * 1126 * @param position the position of the rounded corner on the display. 1127 * 1128 * @return the rounded corner of the given position. Returns {@code null} if there is none. 1129 */ 1130 @SuppressLint("VisiblySynchronized") 1131 @Nullable getRoundedCorner(@oundedCorner.Position int position)1132 public RoundedCorner getRoundedCorner(@RoundedCorner.Position int position) { 1133 synchronized (mLock) { 1134 updateDisplayInfoLocked(); 1135 final RoundedCorners roundedCorners = mDisplayInfo.roundedCorners; 1136 final @Surface.Rotation int rotation = getLocalRotation(); 1137 if (roundedCorners != null && rotation != mDisplayInfo.rotation) { 1138 roundedCorners.rotate(rotation, 1139 mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); 1140 } 1141 return roundedCorners == null ? null : roundedCorners.getRoundedCorner(position); 1142 } 1143 } 1144 1145 /** 1146 * Returns the {@link DisplayShape} which is based on display coordinates. 1147 * 1148 * To get the {@link DisplayShape} based on the window frame, use 1149 * {@link WindowInsets#getDisplayShape()} instead. 1150 * 1151 * @see DisplayShape 1152 */ 1153 @SuppressLint("VisiblySynchronized") 1154 @NonNull getShape()1155 public DisplayShape getShape() { 1156 synchronized (mLock) { 1157 updateDisplayInfoLocked(); 1158 final DisplayShape displayShape = mDisplayInfo.displayShape; 1159 final @Surface.Rotation int rotation = getLocalRotation(); 1160 if (displayShape != null && rotation != mDisplayInfo.rotation) { 1161 return displayShape.setRotation(rotation); 1162 } 1163 return displayShape; 1164 } 1165 } 1166 1167 /** 1168 * Gets the pixel format of the display. 1169 * @return One of the constants defined in {@link android.graphics.PixelFormat}. 1170 * 1171 * @deprecated This method is no longer supported. 1172 * The result is always {@link PixelFormat#RGBA_8888}. 1173 */ 1174 @Deprecated getPixelFormat()1175 public int getPixelFormat() { 1176 return PixelFormat.RGBA_8888; 1177 } 1178 1179 /** 1180 * Gets the refresh rate of this display in frames per second. 1181 */ getRefreshRate()1182 public float getRefreshRate() { 1183 synchronized (mLock) { 1184 updateDisplayInfoLocked(); 1185 return mDisplayInfo.getRefreshRate(); 1186 } 1187 } 1188 1189 /** 1190 * Get the supported refresh rates of this display in frames per second. 1191 * <p> 1192 * This method only returns refresh rates for the display's default modes. For more options, use 1193 * {@link #getSupportedModes()}. 1194 * 1195 * @deprecated use {@link #getSupportedModes()} instead 1196 */ 1197 @Deprecated getSupportedRefreshRates()1198 public float[] getSupportedRefreshRates() { 1199 synchronized (mLock) { 1200 updateDisplayInfoLocked(); 1201 return mDisplayInfo.getDefaultRefreshRates(); 1202 } 1203 } 1204 1205 /** 1206 * Returns the active mode of the display. 1207 */ getMode()1208 public Mode getMode() { 1209 synchronized (mLock) { 1210 updateDisplayInfoLocked(); 1211 return mDisplayInfo.getMode(); 1212 } 1213 } 1214 1215 /** 1216 * Returns the default mode of the display. 1217 * @hide 1218 */ 1219 @TestApi getDefaultMode()1220 public @NonNull Mode getDefaultMode() { 1221 synchronized (mLock) { 1222 updateDisplayInfoLocked(); 1223 return mDisplayInfo.getDefaultMode(); 1224 } 1225 } 1226 1227 /** 1228 * Gets the supported modes of this display, might include synthetic modes 1229 */ getSupportedModes()1230 public Mode[] getSupportedModes() { 1231 synchronized (mLock) { 1232 updateDisplayInfoLocked(); 1233 final Display.Mode[] modes = mDisplayInfo.appsSupportedModes; 1234 return Arrays.copyOf(modes, modes.length); 1235 } 1236 } 1237 1238 /** 1239 * Gets system supported modes of this display, 1240 * @hide 1241 */ 1242 @SuppressLint("ArrayReturn") getSystemSupportedModes()1243 public @NonNull Mode[] getSystemSupportedModes() { 1244 synchronized (mLock) { 1245 updateDisplayInfoLocked(); 1246 final Display.Mode[] modes = mDisplayInfo.supportedModes; 1247 return Arrays.copyOf(modes, modes.length); 1248 } 1249 } 1250 1251 /** 1252 * <p> Returns true if the connected display can be switched into a mode with minimal 1253 * post processing. </p> 1254 * 1255 * <p> If the Display sink is connected via HDMI, this method will return true if the 1256 * display supports either Auto Low Latency Mode or Game Content Type. 1257 * 1258 * <p> If the Display sink has an internal connection or uses some other protocol than 1259 * HDMI, this method will return true if the sink can be switched into an 1260 * implementation-defined low latency image processing mode. </p> 1261 * 1262 * <p> The ability to switch to a mode with minimal post processing may be disabled 1263 * by a user setting in the system settings menu. In that case, this method returns 1264 * false. </p> 1265 * 1266 * @see android.view.Window#setPreferMinimalPostProcessing 1267 */ 1268 @SuppressLint("VisiblySynchronized") isMinimalPostProcessingSupported()1269 public boolean isMinimalPostProcessingSupported() { 1270 synchronized (mLock) { 1271 updateDisplayInfoLocked(); 1272 return mDisplayInfo.minimalPostProcessingSupported; 1273 } 1274 } 1275 1276 /** 1277 * Request the display applies a color mode. 1278 * @hide 1279 */ 1280 @RequiresPermission(CONFIGURE_DISPLAY_COLOR_MODE) requestColorMode(int colorMode)1281 public void requestColorMode(int colorMode) { 1282 mGlobal.requestColorMode(mDisplayId, colorMode); 1283 } 1284 1285 /** 1286 * Returns the active color mode of this display 1287 * @hide 1288 */ getColorMode()1289 public int getColorMode() { 1290 synchronized (mLock) { 1291 updateDisplayInfoLocked(); 1292 return mDisplayInfo.colorMode; 1293 } 1294 } 1295 1296 /** 1297 * @hide 1298 * Get current remove mode of the display - what actions should be performed with the display's 1299 * content when it is removed. Default behavior for public displays in this case is to move all 1300 * activities to the primary display and make it focused. For private display - destroy all 1301 * activities. 1302 * 1303 * @see #REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY 1304 * @see #REMOVE_MODE_DESTROY_CONTENT 1305 */ 1306 // TODO (b/114338689): Remove the method and use IWindowManager#getRemoveContentMode 1307 @SuppressLint("UnflaggedApi") // @TestApi without associated feature. 1308 @TestApi getRemoveMode()1309 public int getRemoveMode() { 1310 return mDisplayInfo.removeMode; 1311 } 1312 1313 /** 1314 * Returns the system's preferred display mode. This mode will be used when the user has not 1315 * specified a display-mode preference. This returns null if the boot display mode feature is 1316 * not supported by system. 1317 * 1318 * @hide 1319 */ 1320 @TestApi 1321 @Nullable getSystemPreferredDisplayMode()1322 public Display.Mode getSystemPreferredDisplayMode() { 1323 return mGlobal.getSystemPreferredDisplayMode(getDisplayId()); 1324 } 1325 1326 /** 1327 * Returns the current display mode's HDR capabilities. 1328 * 1329 * @see #isHdr() 1330 */ getHdrCapabilities()1331 public HdrCapabilities getHdrCapabilities() { 1332 synchronized (mLock) { 1333 updateDisplayInfoLocked(); 1334 if (mDisplayInfo.hdrCapabilities == null) { 1335 return null; 1336 } 1337 int[] supportedHdrTypes; 1338 if (mDisplayInfo.userDisabledHdrTypes.length == 0) { 1339 int[] modeSupportedHdrTypes = getMode().getSupportedHdrTypes(); 1340 supportedHdrTypes = Arrays.copyOf(modeSupportedHdrTypes, 1341 modeSupportedHdrTypes.length); 1342 } else { 1343 ArraySet<Integer> enabledTypesSet = new ArraySet<>(); 1344 for (int supportedType : getMode().getSupportedHdrTypes()) { 1345 if (!contains(mDisplayInfo.userDisabledHdrTypes, supportedType)) { 1346 enabledTypesSet.add(supportedType); 1347 } 1348 } 1349 1350 supportedHdrTypes = new int[enabledTypesSet.size()]; 1351 int index = 0; 1352 for (int enabledType : enabledTypesSet) { 1353 supportedHdrTypes[index++] = enabledType; 1354 } 1355 } 1356 return new HdrCapabilities(supportedHdrTypes, 1357 mDisplayInfo.hdrCapabilities.mMaxLuminance, 1358 mDisplayInfo.hdrCapabilities.mMaxAverageLuminance, 1359 mDisplayInfo.hdrCapabilities.mMinLuminance); 1360 } 1361 } 1362 contains(int[] disabledHdrTypes, int hdrType)1363 private boolean contains(int[] disabledHdrTypes, int hdrType) { 1364 for (Integer disabledHdrFormat : disabledHdrTypes) { 1365 if (disabledHdrFormat == hdrType) { 1366 return true; 1367 } 1368 } 1369 return false; 1370 } 1371 1372 /** 1373 * @hide 1374 * Returns the current mode's supported HDR types. 1375 * 1376 * @see #isHdr() 1377 * @see Mode#getSupportedHdrTypes() 1378 */ 1379 @TestApi 1380 @NonNull getReportedHdrTypes()1381 public int[] getReportedHdrTypes() { 1382 synchronized (mLock) { 1383 updateDisplayInfoLocked(); 1384 return mDisplayInfo.getMode().getSupportedHdrTypes(); 1385 } 1386 } 1387 1388 /** 1389 * Returns whether this display supports any HDR type. 1390 * 1391 * @see #getHdrCapabilities() 1392 * @see HdrCapabilities#getSupportedHdrTypes() 1393 */ isHdr()1394 public boolean isHdr() { 1395 synchronized (mLock) { 1396 updateDisplayInfoLocked(); 1397 HdrCapabilities hdrCapabilities = getHdrCapabilities(); 1398 if (hdrCapabilities == null) { 1399 return false; 1400 } 1401 return !(hdrCapabilities.getSupportedHdrTypes().length == 0); 1402 } 1403 } 1404 1405 /** 1406 * @return Whether the display supports reporting an hdr/sdr ratio. If this is false, 1407 * {@link #getHdrSdrRatio()} will always be 1.0f 1408 */ isHdrSdrRatioAvailable()1409 public boolean isHdrSdrRatioAvailable() { 1410 synchronized (mLock) { 1411 updateDisplayInfoLocked(); 1412 return !Float.isNaN(mDisplayInfo.hdrSdrRatio); 1413 } 1414 } 1415 1416 /** 1417 * @return The current hdr/sdr ratio expressed as the ratio of targetHdrPeakBrightnessInNits / 1418 * targetSdrWhitePointInNits. If {@link #isHdrSdrRatioAvailable()} is false, this 1419 * always returns 1.0f. 1420 */ getHdrSdrRatio()1421 public float getHdrSdrRatio() { 1422 synchronized (mLock) { 1423 updateDisplayInfoLocked(); 1424 return Float.isNaN(mDisplayInfo.hdrSdrRatio) 1425 ? 1.0f : mDisplayInfo.hdrSdrRatio; 1426 } 1427 } 1428 findHdrSdrRatioListenerLocked(Consumer<Display> listener)1429 private int findHdrSdrRatioListenerLocked(Consumer<Display> listener) { 1430 for (int i = 0; i < mHdrSdrRatioListeners.size(); i++) { 1431 final HdrSdrRatioListenerWrapper wrapper = mHdrSdrRatioListeners.get(i); 1432 if (wrapper.mListener == listener) { 1433 return i; 1434 } 1435 } 1436 return -1; 1437 } 1438 1439 /** 1440 * Registers a listener that will be invoked whenever the display's hdr/sdr ratio has changed. 1441 * After receiving the callback on the specified Executor, call {@link #getHdrSdrRatio()} to 1442 * get the updated value. 1443 * If {@link #isHdrSdrRatioAvailable()} is false, then an IllegalStateException will be thrown 1444 * 1445 * @see #unregisterHdrSdrRatioChangedListener(Consumer) 1446 * @param executor The executor to invoke the listener on 1447 * @param listener The listener to invoke when the HDR/SDR ratio changes 1448 * @throws IllegalStateException if {@link #isHdrSdrRatioAvailable()} is false 1449 */ registerHdrSdrRatioChangedListener(@onNull Executor executor, @NonNull Consumer<Display> listener)1450 public void registerHdrSdrRatioChangedListener(@NonNull Executor executor, 1451 @NonNull Consumer<Display> listener) { 1452 if (!isHdrSdrRatioAvailable()) { 1453 throw new IllegalStateException("HDR/SDR ratio changed not available"); 1454 } 1455 HdrSdrRatioListenerWrapper toRegister = null; 1456 synchronized (mLock) { 1457 if (findHdrSdrRatioListenerLocked(listener) == -1) { 1458 toRegister = new HdrSdrRatioListenerWrapper(listener); 1459 mHdrSdrRatioListeners.add(toRegister); 1460 } // else already listening, don't do anything 1461 } 1462 if (toRegister != null) { 1463 // Although we only care about the HDR/SDR ratio changing, that can also come in the 1464 // form of the larger DISPLAY_CHANGED event 1465 mGlobal.registerDisplayListener(toRegister, executor, 1466 DisplayManager.EVENT_FLAG_HDR_SDR_RATIO_CHANGED 1467 | DisplayManagerGlobal.EVENT_DISPLAY_CHANGED, 1468 ActivityThread.currentPackageName()); 1469 } 1470 1471 } 1472 1473 /** 1474 * @param listener The previously 1475 * {@link #registerHdrSdrRatioChangedListener(Executor, Consumer) registered} 1476 * hdr/sdr ratio listener to remove. 1477 * 1478 * @see #registerHdrSdrRatioChangedListener(Executor, Consumer) 1479 */ unregisterHdrSdrRatioChangedListener(@onNull Consumer<Display> listener)1480 public void unregisterHdrSdrRatioChangedListener(@NonNull Consumer<Display> listener) { 1481 HdrSdrRatioListenerWrapper toRemove = null; 1482 synchronized (mLock) { 1483 int index = findHdrSdrRatioListenerLocked(listener); 1484 if (index != -1) { 1485 toRemove = mHdrSdrRatioListeners.remove(index); 1486 } 1487 } 1488 if (toRemove != null) { 1489 mGlobal.unregisterDisplayListener(toRemove); 1490 } 1491 } 1492 1493 /** 1494 * Sets the default {@link Display.Mode} to use for the display. The display mode includes 1495 * preference for resolution and refresh rate. 1496 * If the mode specified is not supported by the display, then no mode change occurs. 1497 * 1498 * @param mode The {@link Display.Mode} to set, which can include resolution and/or 1499 * refresh-rate. It is created using {@link Display.Mode.Builder}. 1500 *` 1501 * @hide 1502 */ 1503 @TestApi 1504 @RequiresPermission(Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE) setUserPreferredDisplayMode(@onNull Display.Mode mode)1505 public void setUserPreferredDisplayMode(@NonNull Display.Mode mode) { 1506 // Create a new object containing default values for the unused fields like mode ID and 1507 // alternative refresh rates. 1508 Display.Mode preferredMode = new Display.Mode(mode.getPhysicalWidth(), 1509 mode.getPhysicalHeight(), mode.getRefreshRate()); 1510 mGlobal.setUserPreferredDisplayMode(mDisplayId, preferredMode); 1511 } 1512 1513 /** 1514 * Removes the display's user preferred display mode. 1515 * 1516 * @hide 1517 */ 1518 @TestApi 1519 @RequiresPermission(Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE) clearUserPreferredDisplayMode()1520 public void clearUserPreferredDisplayMode() { 1521 mGlobal.setUserPreferredDisplayMode(mDisplayId, null); 1522 } 1523 1524 /** 1525 * Returns the display's user preferred display mode. 1526 * 1527 * @hide 1528 */ 1529 @TestApi 1530 @Nullable getUserPreferredDisplayMode()1531 public Display.Mode getUserPreferredDisplayMode() { 1532 return mGlobal.getUserPreferredDisplayMode(mDisplayId); 1533 } 1534 1535 1536 /** 1537 * Returns whether this display can be used to display wide color gamut content. 1538 * This does not necessarily mean the device itself can render wide color gamut 1539 * content. To ensure wide color gamut content can be produced, refer to 1540 * {@link Configuration#isScreenWideColorGamut()}. 1541 */ isWideColorGamut()1542 public boolean isWideColorGamut() { 1543 synchronized (mLock) { 1544 updateDisplayInfoLocked(); 1545 return mDisplayInfo.isWideColorGamut(); 1546 } 1547 } 1548 1549 /** 1550 * Returns the preferred wide color space of the Display. 1551 * The returned wide gamut color space is based on hardware capability and 1552 * is preferred by the composition pipeline. 1553 * Returns null if the display doesn't support wide color gamut. 1554 * {@link Display#isWideColorGamut()}. 1555 */ 1556 @Nullable getPreferredWideGamutColorSpace()1557 public ColorSpace getPreferredWideGamutColorSpace() { 1558 synchronized (mLock) { 1559 updateDisplayInfoLocked(); 1560 if (mDisplayInfo.isWideColorGamut()) { 1561 return mGlobal.getPreferredWideGamutColorSpace(); 1562 } 1563 return null; 1564 } 1565 } 1566 1567 /** 1568 * Returns the {@link OverlayProperties} of the display. 1569 */ 1570 @FlaggedApi(FLAG_OVERLAYPROPERTIES_CLASS_API) 1571 @NonNull getOverlaySupport()1572 public OverlayProperties getOverlaySupport() { 1573 synchronized (mLock) { 1574 updateDisplayInfoLocked(); 1575 if (mDisplayInfo.type == TYPE_INTERNAL 1576 || mDisplayInfo.type == TYPE_EXTERNAL) { 1577 return mGlobal.getOverlaySupport(); 1578 } 1579 return OverlayProperties.getDefault(); 1580 } 1581 } 1582 1583 /** 1584 * Gets the supported color modes of this device. 1585 * @hide 1586 */ getSupportedColorModes()1587 public int[] getSupportedColorModes() { 1588 synchronized (mLock) { 1589 updateDisplayInfoLocked(); 1590 int[] colorModes = mDisplayInfo.supportedColorModes; 1591 return Arrays.copyOf(colorModes, colorModes.length); 1592 } 1593 } 1594 1595 /** 1596 * Gets the supported wide color gamuts of this device. 1597 * 1598 * @return Supported WCG color spaces. 1599 * @hide 1600 */ 1601 @SuppressLint("VisiblySynchronized") 1602 @NonNull 1603 @TestApi getSupportedWideColorGamut()1604 public @ColorMode ColorSpace[] getSupportedWideColorGamut() { 1605 synchronized (mLock) { 1606 final ColorSpace[] defaultColorSpaces = new ColorSpace[0]; 1607 updateDisplayInfoLocked(); 1608 if (!isWideColorGamut()) { 1609 return defaultColorSpaces; 1610 } 1611 1612 final int[] colorModes = getSupportedColorModes(); 1613 final List<ColorSpace> colorSpaces = new ArrayList<>(); 1614 for (int colorMode : colorModes) { 1615 // Refer to DisplayInfo#isWideColorGamut. 1616 switch (colorMode) { 1617 case COLOR_MODE_DCI_P3: 1618 colorSpaces.add(ColorSpace.get(ColorSpace.Named.DCI_P3)); 1619 break; 1620 case COLOR_MODE_DISPLAY_P3: 1621 colorSpaces.add(ColorSpace.get(ColorSpace.Named.DISPLAY_P3)); 1622 break; 1623 } 1624 } 1625 return colorSpaces.toArray(defaultColorSpaces); 1626 } 1627 } 1628 1629 /** 1630 * Gets the app VSYNC offset, in nanoseconds. This is a positive value indicating 1631 * the phase offset of the VSYNC events provided by Choreographer relative to the 1632 * display refresh. For example, if Choreographer reports that the refresh occurred 1633 * at time N, it actually occurred at (N - appVsyncOffset). 1634 * <p> 1635 * Apps generally do not need to be aware of this. It's only useful for fine-grained 1636 * A/V synchronization. 1637 */ getAppVsyncOffsetNanos()1638 public long getAppVsyncOffsetNanos() { 1639 synchronized (mLock) { 1640 updateDisplayInfoLocked(); 1641 return mDisplayInfo.appVsyncOffsetNanos; 1642 } 1643 } 1644 1645 /** 1646 * This is how far in advance a buffer must be queued for presentation at 1647 * a given time. If you want a buffer to appear on the screen at 1648 * time N, you must submit the buffer before (N - presentationDeadline). 1649 * <p> 1650 * The desired presentation time for GLES rendering may be set with 1651 * {@link android.opengl.EGLExt#eglPresentationTimeANDROID}. For video decoding, use 1652 * {@link android.media.MediaCodec#releaseOutputBuffer(int, long)}. Times are 1653 * expressed in nanoseconds, using the system monotonic clock 1654 * ({@link System#nanoTime}). 1655 */ getPresentationDeadlineNanos()1656 public long getPresentationDeadlineNanos() { 1657 synchronized (mLock) { 1658 updateDisplayInfoLocked(); 1659 return mDisplayInfo.presentationDeadlineNanos; 1660 } 1661 } 1662 1663 /** 1664 * Returns the product-specific information about the display or the directly connected 1665 * device on the display chain. 1666 * For example, if the display is transitively connected, this field may contain product 1667 * information about the intermediate device. 1668 * Returns {@code null} if product information is not available. 1669 */ 1670 @Nullable getDeviceProductInfo()1671 public DeviceProductInfo getDeviceProductInfo() { 1672 synchronized (mLock) { 1673 updateDisplayInfoLocked(); 1674 return mDisplayInfo.deviceProductInfo; 1675 } 1676 } 1677 1678 /** 1679 * Gets the size and density of this display. 1680 * 1681 * <p>The size returned does not necessarily represent the actual size (native resolution) of 1682 * the display. The returned size might be adjusted to exclude certain system decor elements 1683 * that are always visible, or the size might be scaled to provide compatibility with older 1684 * applications that were originally designed for smaller displays. 1685 * 1686 * <p>The returned size can also be different depending on the WindowManager associated with the 1687 * display: 1688 * <ul> 1689 * <li>If metrics are requested from an activity (either using a WindowManager accessed by 1690 * {@code getWindowManager()} or {@code getSystemService(Context.WINDOW_SERVICE)}), the 1691 * returned metrics provide the size of the current app window. As a result, in 1692 * multi-window mode, the returned size can be smaller than the size of the device 1693 * screen. 1694 * <li>If metrics are requested from a non-activity context (for example, the application 1695 * context, where the WindowManager is accessed by 1696 * {@code getApplicationContext().getSystemService(Context.WINDOW_SERVICE)}), the 1697 * returned size can vary depending on API level: 1698 * <ul> 1699 * <li>API level 29 and below — The returned metrics provide the size of the 1700 * entire display (based on current rotation) minus system decoration areas. 1701 * <li>API level 30 and above — The returned metrics provide the size of the 1702 * top running activity in the current process. If the current process has no 1703 * running activities, the metrics provide the size of the default display of 1704 * the device, including system decoration areas. 1705 * </ul> 1706 * </ul> 1707 * 1708 * @param outMetrics A {@link DisplayMetrics} object which receives the display metrics. 1709 * 1710 * @deprecated Use {@link WindowMetrics#getBounds()} to get the dimensions of the application 1711 * window. Use {@link WindowMetrics#getDensity()} to get the density of the application 1712 * window. 1713 */ 1714 @Deprecated getMetrics(DisplayMetrics outMetrics)1715 public void getMetrics(DisplayMetrics outMetrics) { 1716 synchronized (mLock) { 1717 updateDisplayInfoLocked(); 1718 mDisplayInfo.getAppMetrics(outMetrics, getDisplayAdjustments()); 1719 } 1720 } 1721 1722 /** 1723 * Gets the size of the largest region of the display accessible to an app in the current system 1724 * state, without subtracting any window decor or applying scaling factors. 1725 * <p> 1726 * The size is adjusted based on the current rotation of the display. 1727 * <p></p> 1728 * The returned size will fall into one of these scenarios: 1729 * <ol> 1730 * <li>The device has no partitions on the display. The returned value is the largest region 1731 * of the display accessible to an app in the current system state, regardless of windowing 1732 * mode.</li> 1733 * <li>The device divides a single display into multiple partitions. An application is 1734 * restricted to a portion of the display. This is common in devices where the display changes 1735 * size, such as foldables or large screens. The returned size will match the portion of 1736 * the display the application is restricted to.</li> 1737 * <li>The window manager is emulating a different display size, using {@code adb shell wm 1738 * size}. The returned size will match the emulated display size.</li> 1739 * </ol> 1740 * </p><p> 1741 * The returned value is <b>unsuitable to use when sizing and placing UI elements</b>, since it 1742 * does not reflect the application window size in any of these scenarios. 1743 * {@link WindowManager#getCurrentWindowMetrics()} is an alternative that returns the size 1744 * of the current application window, even if the window is on a device with a partitioned 1745 * display. This helps prevent UI bugs where UI elements are misaligned or placed beyond the 1746 * bounds of the window. 1747 * <p></p> 1748 * Handling multi-window mode correctly is necessary since applications are not always 1749 * fullscreen. A user on a large screen device, such as a tablet or ChromeOS devices, is more 1750 * likely to use multi-window modes. 1751 * <p></p> 1752 * For example, consider a device with a display partitioned into two halves. The user may have 1753 * a fullscreen application open on the first partition. They may have two applications open in 1754 * split screen (an example of multi-window mode) on the second partition, with each application 1755 * consuming half of the partition. In this case, 1756 * {@link WindowManager#getCurrentWindowMetrics()} reports the fullscreen window is half of the 1757 * screen in size, and each split screen window is a quarter of the screen in size. On the other 1758 * hand, {@link #getRealSize} reports half of the screen size for all windows, since the 1759 * application windows are all restricted to their respective partitions. 1760 * </p> 1761 * 1762 * @param outSize Set to the real size of the display. 1763 * @deprecated Use {@link WindowManager#getCurrentWindowMetrics()} to identify the current size 1764 * of the activity window. UI-related work, such as choosing UI layouts, should rely 1765 * upon {@link WindowMetrics#getBounds()}. 1766 */ 1767 @Deprecated getRealSize(Point outSize)1768 public void getRealSize(Point outSize) { 1769 synchronized (mLock) { 1770 updateDisplayInfoLocked(); 1771 if (shouldReportMaxBounds()) { 1772 final Rect bounds = mResources.getConfiguration() 1773 .windowConfiguration.getMaxBounds(); 1774 outSize.x = bounds.width(); 1775 outSize.y = bounds.height(); 1776 if (DEBUG) { 1777 Log.d(TAG, "getRealSize determined from max bounds: " + outSize); 1778 } 1779 // Skip adjusting by fixed rotation, since if it is necessary, the configuration 1780 // should already reflect the expected rotation. 1781 return; 1782 } 1783 outSize.x = mDisplayInfo.logicalWidth; 1784 outSize.y = mDisplayInfo.logicalHeight; 1785 final @Surface.Rotation int rotation = getLocalRotation(); 1786 if (rotation != mDisplayInfo.rotation) { 1787 adjustSize(outSize, mDisplayInfo.rotation, rotation); 1788 } 1789 } 1790 } 1791 1792 /** 1793 * Gets the size of the largest region of the display accessible to an app in the current system 1794 * state, without subtracting any window decor or applying scaling factors. 1795 * <p> 1796 * The size is adjusted based on the current rotation of the display. 1797 * <p></p> 1798 * The returned size will fall into one of these scenarios: 1799 * <ol> 1800 * <li>The device has no partitions on the display. The returned value is the largest region 1801 * of the display accessible to an app in the current system state, regardless of windowing 1802 * mode.</li> 1803 * <li>The device divides a single display into multiple partitions. An application is 1804 * restricted to a portion of the display. This is common in devices where the display changes 1805 * size, such as foldables or large screens. The returned size will match the portion of 1806 * the display the application is restricted to.</li> 1807 * <li>The window manager is emulating a different display size, using {@code adb shell wm 1808 * size}. The returned size will match the emulated display size.</li> 1809 * </ol> 1810 * </p><p> 1811 * The returned value is <b>unsuitable to use when sizing and placing UI elements</b>, since it 1812 * does not reflect the application window size in any of these scenarios. 1813 * {@link WindowManager#getCurrentWindowMetrics()} is an alternative that returns the size 1814 * of the current application window, even if the window is on a device with a partitioned 1815 * display. This helps prevent UI bugs where UI elements are misaligned or placed beyond the 1816 * bounds of the window. 1817 * <p></p> 1818 * Handling multi-window mode correctly is necessary since applications are not always 1819 * fullscreen. A user on a large screen device, such as a tablet or ChromeOS devices, is more 1820 * likely to use multi-window modes. 1821 * <p></p> 1822 * For example, consider a device with a display partitioned into two halves. The user may have 1823 * a fullscreen application open on the first partition. They may have two applications open in 1824 * split screen (an example of multi-window mode) on the second partition, with each application 1825 * consuming half of the partition. In this case, 1826 * {@link WindowManager#getCurrentWindowMetrics()} reports the fullscreen window is half of the 1827 * screen in size, and each split screen window is a quarter of the screen in size. On the other 1828 * hand, {@link #getRealMetrics} reports half of the screen size for all windows, since the 1829 * application windows are all restricted to their respective partitions. 1830 * </p> 1831 * 1832 * @param outMetrics A {@link DisplayMetrics} object to receive the metrics. 1833 * @deprecated Use {@link WindowManager#getCurrentWindowMetrics()} to identify the current size 1834 * of the activity window. UI-related work, such as choosing UI layouts, should rely 1835 * upon {@link WindowMetrics#getBounds()}. Use {@link Configuration#densityDpi} to 1836 * get the current density. 1837 */ 1838 @Deprecated getRealMetrics(DisplayMetrics outMetrics)1839 public void getRealMetrics(DisplayMetrics outMetrics) { 1840 synchronized (mLock) { 1841 updateDisplayInfoLocked(); 1842 if (shouldReportMaxBounds()) { 1843 mDisplayInfo.getMaxBoundsMetrics(outMetrics, 1844 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, 1845 mResources.getConfiguration()); 1846 if (DEBUG) { 1847 Log.d(TAG, "getRealMetrics determined from max bounds: " + outMetrics); 1848 } 1849 // Skip adjusting by fixed rotation, since if it is necessary, the configuration 1850 // should already reflect the expected rotation. 1851 return; 1852 } 1853 mDisplayInfo.getLogicalMetrics(outMetrics, 1854 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 1855 final @Surface.Rotation int rotation = getLocalRotation(); 1856 if (rotation != mDisplayInfo.rotation) { 1857 adjustMetrics(outMetrics, mDisplayInfo.rotation, rotation); 1858 } 1859 } 1860 } 1861 1862 /** 1863 * Determines if {@link WindowConfiguration#getMaxBounds()} should be reported as the 1864 * display dimensions. The max bounds field may be smaller than the logical dimensions 1865 * when apps need to be sandboxed. 1866 * 1867 * Depends upon {@link WindowConfiguration#getMaxBounds()} being set in 1868 * {@link com.android.server.wm.ConfigurationContainer#providesMaxBounds()}. In most cases, this 1869 * value reflects the size of the current DisplayArea. 1870 * @return {@code true} when max bounds should be applied. 1871 */ shouldReportMaxBounds()1872 private boolean shouldReportMaxBounds() { 1873 if (mResources == null) { 1874 return false; 1875 } 1876 final Configuration config = mResources.getConfiguration(); 1877 return config != null && !config.windowConfiguration.getMaxBounds().isEmpty(); 1878 } 1879 1880 /** 1881 * Gets the state of the display, such as whether it is on or off. 1882 * 1883 * @return The state of the display: one of {@link #STATE_OFF}, {@link #STATE_ON}, 1884 * {@link #STATE_DOZE}, {@link #STATE_DOZE_SUSPEND}, {@link #STATE_ON_SUSPEND}, or 1885 * {@link #STATE_UNKNOWN}. 1886 */ getState()1887 public int getState() { 1888 synchronized (mLock) { 1889 updateDisplayInfoLocked(); 1890 return mIsValid ? mDisplayInfo.state : STATE_UNKNOWN; 1891 } 1892 } 1893 1894 /** 1895 * Returns the committed state of the display. 1896 * 1897 * @return The latest committed display state, such as {@link #STATE_ON}. The display state 1898 * {@link Display#getState()} is set as committed only after power state changes finish. 1899 * 1900 * @hide 1901 */ getCommittedState()1902 public int getCommittedState() { 1903 synchronized (mLock) { 1904 updateDisplayInfoLocked(); 1905 return mIsValid ? mDisplayInfo.committedState : STATE_UNKNOWN; 1906 } 1907 } 1908 1909 /** 1910 * Returns true if the specified UID has access to this display. 1911 * @hide 1912 */ 1913 @TestApi hasAccess(int uid)1914 public boolean hasAccess(int uid) { 1915 return hasAccess(uid, mFlags, mOwnerUid, mDisplayId); 1916 } 1917 1918 /** @hide */ hasAccess(int uid, int flags, int ownerUid, int displayId)1919 public static boolean hasAccess(int uid, int flags, int ownerUid, int displayId) { 1920 return (flags & Display.FLAG_PRIVATE) == 0 1921 || uid == ownerUid 1922 || uid == Process.SYSTEM_UID 1923 || uid == 0 1924 // Check if the UID is present on given display. 1925 || DisplayManagerGlobal.getInstance().isUidPresentOnDisplay(uid, displayId); 1926 } 1927 1928 /** 1929 * Returns true if the display is a public presentation display. 1930 * @hide 1931 */ isPublicPresentation()1932 public boolean isPublicPresentation() { 1933 return (mFlags & (Display.FLAG_PRIVATE | Display.FLAG_PRESENTATION)) == 1934 Display.FLAG_PRESENTATION; 1935 } 1936 1937 /** 1938 * @return {@code true} if the display is a trusted display. 1939 * 1940 * @see #FLAG_TRUSTED 1941 * @hide 1942 */ isTrusted()1943 public boolean isTrusted() { 1944 return (mFlags & FLAG_TRUSTED) == FLAG_TRUSTED; 1945 } 1946 1947 /** 1948 * @return {@code true} if the display can steal the top focus from another display. 1949 * 1950 * @see #FLAG_STEAL_TOP_FOCUS_DISABLED 1951 * @hide 1952 */ canStealTopFocus()1953 public boolean canStealTopFocus() { 1954 return (mFlags & FLAG_STEAL_TOP_FOCUS_DISABLED) == 0; 1955 } 1956 updateDisplayInfoLocked()1957 private void updateDisplayInfoLocked() { 1958 // Note: The display manager caches display info objects on our behalf. 1959 DisplayInfo newInfo = mGlobal.getDisplayInfo(mDisplayId); 1960 if (newInfo == null) { 1961 // Preserve the old mDisplayInfo after the display is removed. 1962 if (mIsValid) { 1963 mIsValid = false; 1964 if (DEBUG) { 1965 Log.d(TAG, "Logical display " + mDisplayId + " was removed."); 1966 } 1967 } 1968 } else { 1969 // Use the new display info. (It might be the same object if nothing changed.) 1970 mDisplayInfo = newInfo; 1971 if (!mIsValid) { 1972 mIsValid = true; 1973 if (DEBUG) { 1974 Log.d(TAG, "Logical display " + mDisplayId + " was recreated."); 1975 } 1976 } 1977 } 1978 } 1979 updateCachedAppSizeIfNeededLocked()1980 private void updateCachedAppSizeIfNeededLocked() { 1981 long now = SystemClock.uptimeMillis(); 1982 if (now > mLastCachedAppSizeUpdate + CACHED_APP_SIZE_DURATION_MILLIS) { 1983 updateDisplayInfoLocked(); 1984 mDisplayInfo.getAppMetrics(mTempMetrics, getDisplayAdjustments()); 1985 mCachedAppWidthCompat = mTempMetrics.widthPixels; 1986 mCachedAppHeightCompat = mTempMetrics.heightPixels; 1987 mLastCachedAppSizeUpdate = now; 1988 } 1989 } 1990 1991 /** Returns {@code false} if the width and height of display should swap. */ noFlip(@urface.Rotation int realRotation, @Surface.Rotation int localRotation)1992 private static boolean noFlip(@Surface.Rotation int realRotation, 1993 @Surface.Rotation int localRotation) { 1994 // Check if the delta is rotated by 90 degrees. 1995 return (realRotation - localRotation + 4) % 2 == 0; 1996 } 1997 1998 /** 1999 * Adjusts the given size by a rotation offset if necessary. 2000 * @hide 2001 */ adjustSize(@onNull Point size, @Surface.Rotation int realRotation, @Surface.Rotation int localRotation)2002 private void adjustSize(@NonNull Point size, @Surface.Rotation int realRotation, 2003 @Surface.Rotation int localRotation) { 2004 if (noFlip(realRotation, localRotation)) return; 2005 final int w = size.x; 2006 size.x = size.y; 2007 size.y = w; 2008 } 2009 2010 /** 2011 * Adjusts the given metrics by a rotation offset if necessary. 2012 * @hide 2013 */ adjustMetrics(@onNull DisplayMetrics metrics, @Surface.Rotation int realRotation, @Surface.Rotation int localRotation)2014 private void adjustMetrics(@NonNull DisplayMetrics metrics, 2015 @Surface.Rotation int realRotation, @Surface.Rotation int localRotation) { 2016 if (noFlip(realRotation, localRotation)) return; 2017 int w = metrics.widthPixels; 2018 metrics.widthPixels = metrics.heightPixels; 2019 metrics.heightPixels = w; 2020 2021 w = metrics.noncompatWidthPixels; 2022 metrics.noncompatWidthPixels = metrics.noncompatHeightPixels; 2023 metrics.noncompatHeightPixels = w; 2024 } 2025 getLocalRotation()2026 private @Surface.Rotation int getLocalRotation() { 2027 if (mResources == null) return mDisplayInfo.rotation; 2028 final @Surface.Rotation int localRotation = 2029 mResources.getConfiguration().windowConfiguration.getDisplayRotation(); 2030 if (localRotation != WindowConfiguration.ROTATION_UNDEFINED) return localRotation; 2031 return mDisplayInfo.rotation; 2032 } 2033 2034 // For debugging purposes 2035 @Override toString()2036 public String toString() { 2037 synchronized (mLock) { 2038 updateDisplayInfoLocked(); 2039 final DisplayAdjustments adjustments = getDisplayAdjustments(); 2040 mDisplayInfo.getAppMetrics(mTempMetrics, adjustments); 2041 return "Display id " + mDisplayId + ": " + mDisplayInfo + ", " 2042 + mTempMetrics + ", isValid=" + mIsValid; 2043 } 2044 } 2045 2046 /** 2047 * @hide 2048 */ typeToString(int type)2049 public static String typeToString(int type) { 2050 switch (type) { 2051 case TYPE_UNKNOWN: 2052 return "UNKNOWN"; 2053 case TYPE_INTERNAL: 2054 return "INTERNAL"; 2055 case TYPE_EXTERNAL: 2056 return "EXTERNAL"; 2057 case TYPE_WIFI: 2058 return "WIFI"; 2059 case TYPE_OVERLAY: 2060 return "OVERLAY"; 2061 case TYPE_VIRTUAL: 2062 return "VIRTUAL"; 2063 default: 2064 return Integer.toString(type); 2065 } 2066 } 2067 2068 /** 2069 * @hide 2070 */ stateToString(int state)2071 public static String stateToString(int state) { 2072 switch (state) { 2073 case STATE_UNKNOWN: 2074 return "UNKNOWN"; 2075 case STATE_OFF: 2076 return "OFF"; 2077 case STATE_ON: 2078 return "ON"; 2079 case STATE_DOZE: 2080 return "DOZE"; 2081 case STATE_DOZE_SUSPEND: 2082 return "DOZE_SUSPEND"; 2083 case STATE_VR: 2084 return "VR"; 2085 case STATE_ON_SUSPEND: 2086 return "ON_SUSPEND"; 2087 default: 2088 return Integer.toString(state); 2089 } 2090 } 2091 2092 /** @hide */ stateReasonToString(@tateReason int reason)2093 public static String stateReasonToString(@StateReason int reason) { 2094 switch (reason) { 2095 case STATE_REASON_UNKNOWN: 2096 return "UNKNOWN"; 2097 case STATE_REASON_DEFAULT_POLICY: 2098 return "DEFAULT_POLICY"; 2099 case STATE_REASON_DRAW_WAKE_LOCK: 2100 return "DRAW_WAKE_LOCK"; 2101 case STATE_REASON_OFFLOAD: 2102 return "OFFLOAD"; 2103 case STATE_REASON_TILT: 2104 return "TILT"; 2105 case STATE_REASON_DREAM_MANAGER: 2106 return "DREAM_MANAGER"; 2107 case STATE_REASON_KEY: 2108 return "KEY"; 2109 case STATE_REASON_MOTION: 2110 return "MOTION"; 2111 default: 2112 return Integer.toString(reason); 2113 } 2114 } 2115 2116 /** 2117 * Returns true if display updates may be suspended while in the specified 2118 * display power state. In SUSPEND states, updates are absolutely forbidden. 2119 * @hide 2120 */ 2121 @android.ravenwood.annotation.RavenwoodKeep isSuspendedState(int state)2122 public static boolean isSuspendedState(int state) { 2123 return state == STATE_OFF || state == STATE_DOZE_SUSPEND || state == STATE_ON_SUSPEND; 2124 } 2125 2126 /** 2127 * Returns true if the display may be in a reduced operating mode while in the 2128 * specified display power state. 2129 * @hide 2130 */ 2131 @android.ravenwood.annotation.RavenwoodKeep isDozeState(int state)2132 public static boolean isDozeState(int state) { 2133 return state == STATE_DOZE || state == STATE_DOZE_SUSPEND; 2134 } 2135 2136 /** 2137 * Returns true if the display is in active state such as {@link #STATE_ON} 2138 * or {@link #STATE_VR}. 2139 * @hide 2140 */ 2141 @android.ravenwood.annotation.RavenwoodKeep isActiveState(int state)2142 public static boolean isActiveState(int state) { 2143 return state == STATE_ON || state == STATE_VR; 2144 } 2145 2146 /** 2147 * Returns true if the display is in an off state such as {@link #STATE_OFF}. 2148 * @hide 2149 */ 2150 @android.ravenwood.annotation.RavenwoodKeep isOffState(int state)2151 public static boolean isOffState(int state) { 2152 return state == STATE_OFF; 2153 } 2154 2155 /** 2156 * Returns true if the display is in an on state such as {@link #STATE_ON} 2157 * or {@link #STATE_VR} or {@link #STATE_ON_SUSPEND}. 2158 * @hide 2159 */ 2160 @android.ravenwood.annotation.RavenwoodKeep isOnState(int state)2161 public static boolean isOnState(int state) { 2162 return state == STATE_ON || state == STATE_VR || state == STATE_ON_SUSPEND; 2163 } 2164 2165 /** 2166 * Returns true if the specified width is valid. 2167 * @hide 2168 */ isWidthValid(int width)2169 public static boolean isWidthValid(int width) { 2170 return width > 0; 2171 } 2172 2173 /** 2174 * Returns true if the specified height is valid. 2175 * @hide 2176 */ isHeightValid(int height)2177 public static boolean isHeightValid(int height) { 2178 return height > 0; 2179 } 2180 2181 /** 2182 * Returns true if the specified refresh-rate is valid. 2183 * @hide 2184 */ isRefreshRateValid(float refreshRate)2185 public static boolean isRefreshRateValid(float refreshRate) { 2186 return refreshRate > 0.0f; 2187 } 2188 2189 /** 2190 * Returns whether/how the specified display supports DISPLAY_DECORATION. 2191 * 2192 * Composition.DISPLAY_DECORATION is a special layer type which is used to 2193 * render the screen decorations (i.e. antialiased rounded corners and 2194 * cutouts) while taking advantage of specific hardware. 2195 * 2196 * @hide 2197 */ getDisplayDecorationSupport()2198 public DisplayDecorationSupport getDisplayDecorationSupport() { 2199 return mGlobal.getDisplayDecorationSupport(mDisplayId); 2200 } 2201 2202 /** 2203 * A mode supported by a given display. 2204 * 2205 * @see Display#getSupportedModes() 2206 */ 2207 @android.ravenwood.annotation.RavenwoodKeepWholeClass 2208 public static final class Mode implements Parcelable { 2209 /** 2210 * @hide 2211 */ 2212 public static final Mode[] EMPTY_ARRAY = new Mode[0]; 2213 2214 /** 2215 * @hide 2216 */ 2217 public static final int INVALID_MODE_ID = -1; 2218 2219 private final int mModeId; 2220 private final int mWidth; 2221 private final int mHeight; 2222 private final float mPeakRefreshRate; 2223 private final float mVsyncRate; 2224 @NonNull 2225 private final float[] mAlternativeRefreshRates; 2226 @NonNull 2227 @HdrCapabilities.HdrType 2228 private final int[] mSupportedHdrTypes; 2229 private final boolean mIsSynthetic; 2230 2231 /** 2232 * @hide 2233 */ 2234 @TestApi Mode(int width, int height, float refreshRate)2235 public Mode(int width, int height, float refreshRate) { 2236 this(INVALID_MODE_ID, width, height, refreshRate, refreshRate, new float[0], 2237 new int[0]); 2238 } 2239 2240 /** 2241 * @hide 2242 */ 2243 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) Mode(int modeId, int width, int height, float refreshRate)2244 public Mode(int modeId, int width, int height, float refreshRate) { 2245 this(modeId, width, height, refreshRate, refreshRate, new float[0], new int[0]); 2246 } 2247 2248 /** 2249 * @hide 2250 */ Mode(int modeId, int width, int height, float refreshRate, float[] alternativeRefreshRates, @HdrCapabilities.HdrType int[] supportedHdrTypes)2251 public Mode(int modeId, int width, int height, float refreshRate, 2252 float[] alternativeRefreshRates, 2253 @HdrCapabilities.HdrType int[] supportedHdrTypes) { 2254 this(modeId, width, height, refreshRate, refreshRate, alternativeRefreshRates, 2255 supportedHdrTypes); 2256 } 2257 2258 /** 2259 * @hide 2260 */ Mode(int modeId, int width, int height, float refreshRate, float vsyncRate, float[] alternativeRefreshRates, @HdrCapabilities.HdrType int[] supportedHdrTypes)2261 public Mode(int modeId, int width, int height, float refreshRate, float vsyncRate, 2262 float[] alternativeRefreshRates, @HdrCapabilities.HdrType int[] supportedHdrTypes) { 2263 this(modeId, width, height, refreshRate, vsyncRate, false, alternativeRefreshRates, 2264 supportedHdrTypes); 2265 } 2266 2267 /** 2268 * @hide 2269 */ Mode(int modeId, int width, int height, float refreshRate, float vsyncRate, boolean isSynthetic, float[] alternativeRefreshRates, @HdrCapabilities.HdrType int[] supportedHdrTypes)2270 public Mode(int modeId, int width, int height, float refreshRate, float vsyncRate, 2271 boolean isSynthetic, float[] alternativeRefreshRates, 2272 @HdrCapabilities.HdrType int[] supportedHdrTypes) { 2273 mModeId = modeId; 2274 mWidth = width; 2275 mHeight = height; 2276 mPeakRefreshRate = refreshRate; 2277 mVsyncRate = vsyncRate; 2278 mIsSynthetic = isSynthetic; 2279 mAlternativeRefreshRates = 2280 Arrays.copyOf(alternativeRefreshRates, alternativeRefreshRates.length); 2281 Arrays.sort(mAlternativeRefreshRates); 2282 mSupportedHdrTypes = Arrays.copyOf(supportedHdrTypes, supportedHdrTypes.length); 2283 Arrays.sort(mSupportedHdrTypes); 2284 } 2285 2286 /** 2287 * Returns this mode's id. 2288 */ getModeId()2289 public int getModeId() { 2290 return mModeId; 2291 } 2292 2293 /** 2294 * Returns the physical width of the display in pixels when configured in this mode's 2295 * resolution. 2296 * <p> 2297 * Note that due to application UI scaling, the number of pixels made available to 2298 * applications when the mode is active (as reported by {@link Display#getWidth()} may 2299 * differ from the mode's actual resolution (as reported by this function). 2300 * <p> 2301 * For example, applications running on a 4K display may have their UI laid out and rendered 2302 * in 1080p and then scaled up. Applications can take advantage of the extra resolution by 2303 * rendering content through a {@link android.view.SurfaceView} using full size buffers. 2304 */ getPhysicalWidth()2305 public int getPhysicalWidth() { 2306 return mWidth; 2307 } 2308 2309 /** 2310 * Returns the physical height of the display in pixels when configured in this mode's 2311 * resolution. 2312 * <p> 2313 * Note that due to application UI scaling, the number of pixels made available to 2314 * applications when the mode is active (as reported by {@link Display#getHeight()} may 2315 * differ from the mode's actual resolution (as reported by this function). 2316 * <p> 2317 * For example, applications running on a 4K display may have their UI laid out and rendered 2318 * in 1080p and then scaled up. Applications can take advantage of the extra resolution by 2319 * rendering content through a {@link android.view.SurfaceView} using full size buffers. 2320 */ getPhysicalHeight()2321 public int getPhysicalHeight() { 2322 return mHeight; 2323 } 2324 2325 /** 2326 * Returns the refresh rate in frames per second. 2327 */ getRefreshRate()2328 public float getRefreshRate() { 2329 return mPeakRefreshRate; 2330 } 2331 2332 /** 2333 * Returns the vsync rate in frames per second. 2334 * The physical vsync rate may be higher than the refresh rate, as the refresh rate may be 2335 * constrained by the system. 2336 * @hide 2337 */ getVsyncRate()2338 public float getVsyncRate() { 2339 return mVsyncRate; 2340 } 2341 2342 /** 2343 * Returns true if mode is synthetic and does not have corresponding 2344 * SurfaceControl.DisplayMode 2345 * @hide 2346 */ isSynthetic()2347 public boolean isSynthetic() { 2348 return mIsSynthetic; 2349 } 2350 2351 /** 2352 * Returns an array of refresh rates which can be switched to seamlessly. 2353 * <p> 2354 * A seamless switch is one without visual interruptions, such as a black screen for 2355 * a second or two. 2356 * <p> 2357 * Presence in this list does not guarantee a switch will occur to the desired 2358 * refresh rate, but rather, if a switch does occur to a refresh rate in this list, 2359 * it is guaranteed to be seamless. 2360 * <p> 2361 * The binary relation "refresh rate X is alternative to Y" is non-reflexive, 2362 * symmetric and transitive. For example the mode 1920x1080 60Hz, will never have an 2363 * alternative refresh rate of 60Hz. If 1920x1080 60Hz has an alternative of 50Hz 2364 * then 1920x1080 50Hz will have alternative refresh rate of 60Hz. If 1920x1080 60Hz 2365 * has an alternative of 50Hz and 1920x1080 50Hz has an alternative of 24Hz, then 1920x1080 2366 * 60Hz will also have an alternative of 24Hz. 2367 * 2368 * @see Surface#setFrameRate 2369 * @see SurfaceControl.Transaction#setFrameRate 2370 */ 2371 @NonNull getAlternativeRefreshRates()2372 public float[] getAlternativeRefreshRates() { 2373 return Arrays.copyOf(mAlternativeRefreshRates, mAlternativeRefreshRates.length); 2374 } 2375 2376 /** 2377 * Returns the supported {@link HdrCapabilities} HDR_TYPE_* for this specific mode 2378 */ 2379 @NonNull 2380 @HdrCapabilities.HdrType getSupportedHdrTypes()2381 public int[] getSupportedHdrTypes() { 2382 return Arrays.copyOf(mSupportedHdrTypes, mSupportedHdrTypes.length); 2383 } 2384 2385 /** 2386 * Returns {@code true} if this mode matches the given parameters. 2387 * 2388 * @hide 2389 */ 2390 @TestApi matches(int width, int height, float refreshRate)2391 public boolean matches(int width, int height, float refreshRate) { 2392 return mWidth == width && 2393 mHeight == height && 2394 Float.floatToIntBits(mPeakRefreshRate) == Float.floatToIntBits(refreshRate); 2395 } 2396 2397 /** 2398 * Returns {@code true} if this mode matches the given parameters, if those parameters are 2399 * valid.<p> 2400 * If resolution (width and height) is valid and refresh-rate is not, the method matches 2401 * only resolution. 2402 * If refresh-rate is valid and resolution (width and height) is not, the method matches 2403 * only refresh-rate.</p> 2404 * 2405 * @hide 2406 */ matchesIfValid(int width, int height, float peakRefreshRate)2407 public boolean matchesIfValid(int width, int height, float peakRefreshRate) { 2408 if (!isWidthValid(width) && !isHeightValid(height) 2409 && !isRefreshRateValid(peakRefreshRate)) { 2410 return false; 2411 } 2412 if (isWidthValid(width) != isHeightValid(height)) { 2413 return false; 2414 } 2415 return (!isWidthValid(width) || mWidth == width) 2416 && (!isHeightValid(height) || mHeight == height) 2417 && (!isRefreshRateValid(peakRefreshRate) 2418 || Float.floatToIntBits(mPeakRefreshRate) 2419 == Float.floatToIntBits(peakRefreshRate)); 2420 } 2421 2422 /** 2423 * Returns {@code true} if this mode equals to the other mode in all parameters except 2424 * the refresh rate. 2425 * 2426 * @hide 2427 */ equalsExceptRefreshRate(@ullable Display.Mode other)2428 public boolean equalsExceptRefreshRate(@Nullable Display.Mode other) { 2429 return mWidth == other.mWidth && mHeight == other.mHeight; 2430 } 2431 2432 /** 2433 * Returns {@code true} if refresh-rate is set for a display mode 2434 * 2435 * @hide 2436 */ isRefreshRateSet()2437 public boolean isRefreshRateSet() { 2438 return mPeakRefreshRate != INVALID_DISPLAY_REFRESH_RATE; 2439 } 2440 2441 /** 2442 * Returns {@code true} if refresh-rate is set for a display mode 2443 * 2444 * @hide 2445 */ isResolutionSet()2446 public boolean isResolutionSet() { 2447 return mWidth != INVALID_DISPLAY_WIDTH && mHeight != INVALID_DISPLAY_HEIGHT; 2448 } 2449 2450 @Override equals(@ullable Object other)2451 public boolean equals(@Nullable Object other) { 2452 if (this == other) { 2453 return true; 2454 } 2455 if (!(other instanceof Mode)) { 2456 return false; 2457 } 2458 Mode that = (Mode) other; 2459 return mModeId == that.mModeId 2460 && matches(that.mWidth, that.mHeight, that.mPeakRefreshRate) 2461 && Arrays.equals(mAlternativeRefreshRates, that.mAlternativeRefreshRates) 2462 && Arrays.equals(mSupportedHdrTypes, that.mSupportedHdrTypes); 2463 } 2464 2465 @Override hashCode()2466 public int hashCode() { 2467 int hash = 1; 2468 hash = hash * 17 + mModeId; 2469 hash = hash * 17 + mWidth; 2470 hash = hash * 17 + mHeight; 2471 hash = hash * 17 + Float.floatToIntBits(mPeakRefreshRate); 2472 hash = hash * 17 + Float.floatToIntBits(mVsyncRate); 2473 hash = hash * 17 + Arrays.hashCode(mAlternativeRefreshRates); 2474 hash = hash * 17 + Arrays.hashCode(mSupportedHdrTypes); 2475 return hash; 2476 } 2477 2478 @Override toString()2479 public String toString() { 2480 return new StringBuilder("{") 2481 .append("id=").append(mModeId) 2482 .append(", width=").append(mWidth) 2483 .append(", height=").append(mHeight) 2484 .append(", fps=").append(mPeakRefreshRate) 2485 .append(", vsync=").append(mVsyncRate) 2486 .append(", synthetic=").append(mIsSynthetic) 2487 .append(", alternativeRefreshRates=") 2488 .append(Arrays.toString(mAlternativeRefreshRates)) 2489 .append(", supportedHdrTypes=") 2490 .append(Arrays.toString(mSupportedHdrTypes)) 2491 .append("}") 2492 .toString(); 2493 } 2494 2495 @Override describeContents()2496 public int describeContents() { 2497 return 0; 2498 } 2499 Mode(Parcel in)2500 private Mode(Parcel in) { 2501 this(in.readInt(), in.readInt(), in.readInt(), in.readFloat(), in.readFloat(), 2502 in.readBoolean(), in.createFloatArray(), in.createIntArray()); 2503 } 2504 2505 @Override writeToParcel(Parcel out, int parcelableFlags)2506 public void writeToParcel(Parcel out, int parcelableFlags) { 2507 out.writeInt(mModeId); 2508 out.writeInt(mWidth); 2509 out.writeInt(mHeight); 2510 out.writeFloat(mPeakRefreshRate); 2511 out.writeFloat(mVsyncRate); 2512 out.writeBoolean(mIsSynthetic); 2513 out.writeFloatArray(mAlternativeRefreshRates); 2514 out.writeIntArray(mSupportedHdrTypes); 2515 } 2516 2517 @SuppressWarnings("hiding") 2518 public static final @android.annotation.NonNull Parcelable.Creator<Mode> CREATOR 2519 = new Parcelable.Creator<Mode>() { 2520 @Override 2521 public Mode createFromParcel(Parcel in) { 2522 return new Mode(in); 2523 } 2524 2525 @Override 2526 public Mode[] newArray(int size) { 2527 return new Mode[size]; 2528 } 2529 }; 2530 2531 /** 2532 * Builder is used to create {@link Display.Mode} objects 2533 * 2534 * @hide 2535 */ 2536 @TestApi 2537 public static final class Builder { 2538 private int mWidth; 2539 private int mHeight; 2540 private float mRefreshRate; 2541 Builder()2542 public Builder() { 2543 mWidth = Display.INVALID_DISPLAY_WIDTH; 2544 mHeight = Display.INVALID_DISPLAY_HEIGHT; 2545 mRefreshRate = Display.INVALID_DISPLAY_REFRESH_RATE; 2546 } 2547 2548 /** 2549 * Sets the resolution (width and height) of a {@link Display.Mode} 2550 * 2551 * @return Instance of {@link Builder} 2552 */ 2553 @NonNull setResolution(int width, int height)2554 public Builder setResolution(int width, int height) { 2555 if (width > 0 && height > 0) { 2556 mWidth = width; 2557 mHeight = height; 2558 } 2559 return this; 2560 } 2561 2562 /** 2563 * Sets the refresh rate of a {@link Display.Mode} 2564 * 2565 * @return Instance of {@link Builder} 2566 */ 2567 @NonNull setRefreshRate(float refreshRate)2568 public Builder setRefreshRate(float refreshRate) { 2569 if (refreshRate > 0.0f) { 2570 mRefreshRate = refreshRate; 2571 } 2572 return this; 2573 } 2574 2575 /** 2576 * Creates the {@link Display.Mode} object. 2577 * 2578 * <p> 2579 * If resolution needs to be set, but refresh-rate doesn't matter, create a mode with 2580 * Builder and call setResolution. 2581 * {@code 2582 * Display.Mode mode = 2583 * new Display.Mode.Builder() 2584 * .setResolution(width, height) 2585 * .build(); 2586 * } 2587 * </p><p> 2588 * If refresh-rate needs to be set, but resolution doesn't matter, create a mode with 2589 * Builder and call setRefreshRate. 2590 * {@code 2591 * Display.Mode mode = 2592 * new Display.Mode.Builder() 2593 * .setRefreshRate(refreshRate) 2594 * .build(); 2595 * } 2596 * </p> 2597 */ 2598 @NonNull build()2599 public Mode build() { 2600 Display.Mode mode = new Mode(mWidth, mHeight, mRefreshRate); 2601 return mode; 2602 } 2603 } 2604 } 2605 2606 /** 2607 * Encapsulates the HDR capabilities of a given display. 2608 * For example, what HDR types it supports and details about the desired luminance data. 2609 * <p>You can get an instance for a given {@link Display} object with 2610 * {@link Display#getHdrCapabilities getHdrCapabilities()}. 2611 */ 2612 @android.ravenwood.annotation.RavenwoodKeepWholeClass 2613 public static final class HdrCapabilities implements Parcelable { 2614 /** 2615 * Invalid luminance value. 2616 */ 2617 public static final float INVALID_LUMINANCE = -1; 2618 /** 2619 * Invalid HDR type value. 2620 */ 2621 public static final int HDR_TYPE_INVALID = -1; 2622 /** 2623 * Dolby Vision high dynamic range (HDR) display. 2624 */ 2625 public static final int HDR_TYPE_DOLBY_VISION = 1; 2626 /** 2627 * HDR10 display. 2628 */ 2629 public static final int HDR_TYPE_HDR10 = 2; 2630 /** 2631 * Hybrid Log-Gamma HDR display. 2632 */ 2633 public static final int HDR_TYPE_HLG = 3; 2634 2635 /** 2636 * HDR10+ display. 2637 */ 2638 public static final int HDR_TYPE_HDR10_PLUS = 4; 2639 2640 /** @hide */ 2641 public static final int[] HDR_TYPES = { 2642 HDR_TYPE_DOLBY_VISION, 2643 HDR_TYPE_HDR10, 2644 HDR_TYPE_HLG, 2645 HDR_TYPE_HDR10_PLUS 2646 }; 2647 2648 /** @hide */ 2649 @IntDef(prefix = { "HDR_TYPE_" }, value = { 2650 HDR_TYPE_INVALID, 2651 HDR_TYPE_DOLBY_VISION, 2652 HDR_TYPE_HDR10, 2653 HDR_TYPE_HLG, 2654 HDR_TYPE_HDR10_PLUS, 2655 }) 2656 @Retention(RetentionPolicy.SOURCE) 2657 public @interface HdrType {} 2658 2659 private @HdrType int[] mSupportedHdrTypes = new int[0]; 2660 private float mMaxLuminance = INVALID_LUMINANCE; 2661 private float mMaxAverageLuminance = INVALID_LUMINANCE; 2662 private float mMinLuminance = INVALID_LUMINANCE; 2663 2664 /** 2665 * @hide 2666 */ HdrCapabilities()2667 public HdrCapabilities() { 2668 } 2669 2670 /** 2671 * @hide 2672 */ 2673 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) HdrCapabilities(int[] supportedHdrTypes, float maxLuminance, float maxAverageLuminance, float minLuminance)2674 public HdrCapabilities(int[] supportedHdrTypes, float maxLuminance, 2675 float maxAverageLuminance, float minLuminance) { 2676 mSupportedHdrTypes = supportedHdrTypes; 2677 Arrays.sort(mSupportedHdrTypes); 2678 mMaxLuminance = maxLuminance; 2679 mMaxAverageLuminance = maxAverageLuminance; 2680 mMinLuminance = minLuminance; 2681 } 2682 2683 /** 2684 * Gets the supported HDR types of this display. 2685 * Returns empty array if HDR is not supported by the display. 2686 * 2687 * @deprecated use {@link Display#getMode()} 2688 * and {@link Mode#getSupportedHdrTypes()} instead 2689 */ 2690 @Deprecated 2691 @HdrType getSupportedHdrTypes()2692 public int[] getSupportedHdrTypes() { 2693 return Arrays.copyOf(mSupportedHdrTypes, mSupportedHdrTypes.length); 2694 } 2695 /** 2696 * Returns the desired content max luminance data in cd/m2 for this display. 2697 */ getDesiredMaxLuminance()2698 public float getDesiredMaxLuminance() { 2699 return mMaxLuminance; 2700 } 2701 /** 2702 * Returns the desired content max frame-average luminance data in cd/m2 for this display. 2703 */ getDesiredMaxAverageLuminance()2704 public float getDesiredMaxAverageLuminance() { 2705 return mMaxAverageLuminance; 2706 } 2707 /** 2708 * Returns the desired content min luminance data in cd/m2 for this display. 2709 */ getDesiredMinLuminance()2710 public float getDesiredMinLuminance() { 2711 return mMinLuminance; 2712 } 2713 2714 @Override equals(@ullable Object other)2715 public boolean equals(@Nullable Object other) { 2716 if (this == other) { 2717 return true; 2718 } 2719 2720 if (!(other instanceof HdrCapabilities)) { 2721 return false; 2722 } 2723 HdrCapabilities that = (HdrCapabilities) other; 2724 2725 return Arrays.equals(mSupportedHdrTypes, that.mSupportedHdrTypes) 2726 && mMaxLuminance == that.mMaxLuminance 2727 && mMaxAverageLuminance == that.mMaxAverageLuminance 2728 && mMinLuminance == that.mMinLuminance; 2729 } 2730 2731 @Override hashCode()2732 public int hashCode() { 2733 int hash = 23; 2734 hash = hash * 17 + Arrays.hashCode(mSupportedHdrTypes); 2735 hash = hash * 17 + Float.floatToIntBits(mMaxLuminance); 2736 hash = hash * 17 + Float.floatToIntBits(mMaxAverageLuminance); 2737 hash = hash * 17 + Float.floatToIntBits(mMinLuminance); 2738 return hash; 2739 } 2740 2741 public static final @android.annotation.NonNull Creator<HdrCapabilities> CREATOR = new Creator<HdrCapabilities>() { 2742 @Override 2743 public HdrCapabilities createFromParcel(Parcel source) { 2744 return new HdrCapabilities(source); 2745 } 2746 2747 @Override 2748 public HdrCapabilities[] newArray(int size) { 2749 return new HdrCapabilities[size]; 2750 } 2751 }; 2752 HdrCapabilities(Parcel source)2753 private HdrCapabilities(Parcel source) { 2754 readFromParcel(source); 2755 } 2756 2757 /** 2758 * @hide 2759 */ readFromParcel(Parcel source)2760 public void readFromParcel(Parcel source) { 2761 int types = source.readInt(); 2762 mSupportedHdrTypes = new int[types]; 2763 for (int i = 0; i < types; ++i) { 2764 mSupportedHdrTypes[i] = source.readInt(); 2765 } 2766 mMaxLuminance = source.readFloat(); 2767 mMaxAverageLuminance = source.readFloat(); 2768 mMinLuminance = source.readFloat(); 2769 } 2770 2771 @Override writeToParcel(Parcel dest, int flags)2772 public void writeToParcel(Parcel dest, int flags) { 2773 dest.writeInt(mSupportedHdrTypes.length); 2774 for (int i = 0; i < mSupportedHdrTypes.length; ++i) { 2775 dest.writeInt(mSupportedHdrTypes[i]); 2776 } 2777 dest.writeFloat(mMaxLuminance); 2778 dest.writeFloat(mMaxAverageLuminance); 2779 dest.writeFloat(mMinLuminance); 2780 } 2781 2782 @Override describeContents()2783 public int describeContents() { 2784 return 0; 2785 } 2786 2787 @Override toString()2788 public String toString() { 2789 return "HdrCapabilities{" 2790 + "mSupportedHdrTypes=" + Arrays.toString(mSupportedHdrTypes) 2791 + ", mMaxLuminance=" + mMaxLuminance 2792 + ", mMaxAverageLuminance=" + mMaxAverageLuminance 2793 + ", mMinLuminance=" + mMinLuminance + '}'; 2794 } 2795 2796 /** 2797 * @hide 2798 */ 2799 @NonNull hdrTypeToString(int hdrType)2800 public static String hdrTypeToString(int hdrType) { 2801 switch (hdrType) { 2802 case HDR_TYPE_DOLBY_VISION: 2803 return "HDR_TYPE_DOLBY_VISION"; 2804 case HDR_TYPE_HDR10: 2805 return "HDR_TYPE_HDR10"; 2806 case HDR_TYPE_HLG: 2807 return "HDR_TYPE_HLG"; 2808 case HDR_TYPE_HDR10_PLUS: 2809 return "HDR_TYPE_HDR10_PLUS"; 2810 default: 2811 return "HDR_TYPE_INVALID"; 2812 } 2813 } 2814 } 2815 2816 private class HdrSdrRatioListenerWrapper implements DisplayManager.DisplayListener { 2817 Consumer<Display> mListener; 2818 float mLastReportedRatio = 1.f; 2819 HdrSdrRatioListenerWrapper(Consumer<Display> listener)2820 private HdrSdrRatioListenerWrapper(Consumer<Display> listener) { 2821 mListener = listener; 2822 } 2823 2824 @Override onDisplayAdded(int displayId)2825 public void onDisplayAdded(int displayId) { 2826 // don't care 2827 } 2828 2829 @Override onDisplayRemoved(int displayId)2830 public void onDisplayRemoved(int displayId) { 2831 // don't care 2832 } 2833 2834 @Override onDisplayChanged(int displayId)2835 public void onDisplayChanged(int displayId) { 2836 if (displayId == getDisplayId()) { 2837 float newRatio = getHdrSdrRatio(); 2838 if (newRatio != mLastReportedRatio) { 2839 mLastReportedRatio = newRatio; 2840 mListener.accept(Display.this); 2841 } 2842 } 2843 } 2844 } 2845 } 2846