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