1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.hardware.display; 18 19 import static android.Manifest.permission.MANAGE_DISPLAYS; 20 import static android.view.Display.DEFAULT_DISPLAY; 21 import static android.view.Display.HdrCapabilities.HdrType; 22 import static android.view.Display.INVALID_DISPLAY; 23 24 import static com.android.server.display.feature.flags.Flags.FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS; 25 26 import android.Manifest; 27 import android.annotation.CallbackExecutor; 28 import android.annotation.FlaggedApi; 29 import android.annotation.FloatRange; 30 import android.annotation.IntDef; 31 import android.annotation.IntRange; 32 import android.annotation.LongDef; 33 import android.annotation.NonNull; 34 import android.annotation.Nullable; 35 import android.annotation.RequiresPermission; 36 import android.annotation.SuppressLint; 37 import android.annotation.SystemApi; 38 import android.annotation.SystemService; 39 import android.annotation.TestApi; 40 import android.app.ActivityThread; 41 import android.app.KeyguardManager; 42 import android.compat.annotation.UnsupportedAppUsage; 43 import android.content.Context; 44 import android.content.pm.IPackageManager; 45 import android.content.res.Resources; 46 import android.graphics.Point; 47 import android.media.projection.MediaProjection; 48 import android.os.Build; 49 import android.os.Handler; 50 import android.os.HandlerExecutor; 51 import android.os.Looper; 52 import android.os.Process; 53 import android.os.RemoteException; 54 import android.os.ServiceManager; 55 import android.os.UserManager; 56 import android.util.Log; 57 import android.util.Pair; 58 import android.util.Slog; 59 import android.util.SparseArray; 60 import android.view.Display; 61 import android.view.Surface; 62 63 import com.android.internal.R; 64 import com.android.internal.annotations.GuardedBy; 65 import com.android.server.display.feature.flags.Flags; 66 67 import java.lang.annotation.Retention; 68 import java.lang.annotation.RetentionPolicy; 69 import java.lang.ref.WeakReference; 70 import java.util.ArrayList; 71 import java.util.List; 72 import java.util.Objects; 73 import java.util.concurrent.Executor; 74 import java.util.function.Consumer; 75 import java.util.function.Predicate; 76 77 78 /** 79 * Manages the properties of attached displays. 80 */ 81 @SystemService(Context.DISPLAY_SERVICE) 82 public final class DisplayManager { 83 private static final String TAG = "DisplayManager"; 84 85 // To enable these logs, run: 86 // 'adb shell setprop persist.log.tag.DisplayManager DEBUG && adb reboot' 87 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG) 88 || Log.isLoggable("DisplayManager_All", Log.DEBUG); 89 private static final boolean ENABLE_VIRTUAL_DISPLAY_REFRESH_RATE = true; 90 91 /** 92 * The hdr output control feature flag, the value should be read via 93 * {@link android.provider.DeviceConfig#getBoolean(String, String, boolean)} with 94 * {@link android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER} as the namespace. 95 * @hide 96 */ 97 @TestApi 98 public static final String HDR_OUTPUT_CONTROL_FLAG = "enable_hdr_output_control"; 99 100 private final Context mContext; 101 private final DisplayManagerGlobal mGlobal; 102 103 private final Object mLock = new Object(); 104 @GuardedBy("mLock") 105 private final WeakDisplayCache mDisplayCache = new WeakDisplayCache(); 106 107 private int mDisplayIdToMirror = INVALID_DISPLAY; 108 private AmbientDisplayConfiguration mAmbientDisplayConfiguration; 109 110 /** 111 * Broadcast receiver that indicates when the Wifi display status changes. 112 * <p> 113 * The status is provided as a {@link WifiDisplayStatus} object in the 114 * {@link #EXTRA_WIFI_DISPLAY_STATUS} extra. 115 * </p><p> 116 * This broadcast is only sent to registered receivers and can only be sent by the system. 117 * </p> 118 * @hide 119 */ 120 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 121 public static final String ACTION_WIFI_DISPLAY_STATUS_CHANGED = 122 "android.hardware.display.action.WIFI_DISPLAY_STATUS_CHANGED"; 123 124 /** 125 * Contains a {@link WifiDisplayStatus} object. 126 * @hide 127 */ 128 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 129 public static final String EXTRA_WIFI_DISPLAY_STATUS = 130 "android.hardware.display.extra.WIFI_DISPLAY_STATUS"; 131 132 /** 133 * Display category: Presentation displays. 134 * <p> 135 * This category can be used to identify secondary displays that are suitable for 136 * use as presentation displays such as external or wireless displays. Applications 137 * may automatically project their content to presentation displays to provide 138 * richer second screen experiences. 139 * </p> 140 * 141 * @see android.app.Presentation 142 * @see Display#FLAG_PRESENTATION 143 * @see #getDisplays(String) 144 */ 145 public static final String DISPLAY_CATEGORY_PRESENTATION = 146 "android.hardware.display.category.PRESENTATION"; 147 148 /** 149 * Display category: Built in displays. 150 * 151 * <p> 152 * This category can be used to identify displays that are built into the device. The 153 * displays that are returned may be inactive or disabled at the current moment. The 154 * returned displays are useful in identifying the various sizes of built-in displays. The 155 * id from {@link Display#getDisplayId()} is not guaranteed to be stable and may change 156 * when the display becomes active. 157 * </p> 158 * @see #getDisplays(String) 159 */ 160 @FlaggedApi(com.android.server.display.feature.flags.Flags.FLAG_DISPLAY_CATEGORY_BUILT_IN) 161 public static final String DISPLAY_CATEGORY_BUILT_IN_DISPLAYS = 162 "android.hardware.display.category.BUILT_IN_DISPLAYS"; 163 164 /** 165 * Display category: Rear displays. 166 * <p> 167 * This category can be used to identify complementary internal displays that are facing away 168 * from the user. 169 * Certain applications may present to this display. 170 * Similar to presentation displays. 171 * </p> 172 * 173 * @see android.app.Presentation 174 * @see Display#FLAG_PRESENTATION 175 * @see #getDisplays(String) 176 * @hide 177 */ 178 @TestApi 179 public static final String DISPLAY_CATEGORY_REAR = 180 "android.hardware.display.category.REAR"; 181 182 /** 183 * Display category: All displays, including disabled displays. 184 * <p> 185 * This returns all displays, including currently disabled and inaccessible displays. 186 * 187 * @see #getDisplays(String) 188 * @hide 189 */ 190 @TestApi 191 @SuppressLint("UnflaggedApi") 192 public static final String DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED = 193 "android.hardware.display.category.ALL_INCLUDING_DISABLED"; 194 195 /** @hide **/ 196 @IntDef(prefix = "VIRTUAL_DISPLAY_FLAG_", flag = true, value = { 197 VIRTUAL_DISPLAY_FLAG_PUBLIC, 198 VIRTUAL_DISPLAY_FLAG_PRESENTATION, 199 VIRTUAL_DISPLAY_FLAG_SECURE, 200 VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY, 201 VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, 202 VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD, 203 VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH, 204 VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT, 205 VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL, 206 VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS, 207 VIRTUAL_DISPLAY_FLAG_TRUSTED, 208 VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP, 209 VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED, 210 VIRTUAL_DISPLAY_FLAG_TOUCH_FEEDBACK_DISABLED, 211 VIRTUAL_DISPLAY_FLAG_OWN_FOCUS, 212 VIRTUAL_DISPLAY_FLAG_STEAL_TOP_FOCUS_DISABLED, 213 }) 214 @Retention(RetentionPolicy.SOURCE) 215 public @interface VirtualDisplayFlag {} 216 217 /** 218 * Virtual display flag: Create a public display. 219 * 220 * <h3>Public virtual displays</h3> 221 * <p> 222 * When this flag is set, the virtual display is public. 223 * </p><p> 224 * A public virtual display behaves just like most any other display that is connected 225 * to the system such as an external or wireless display. Applications can open 226 * windows on the display and the system may mirror the contents of other displays 227 * onto it. 228 * </p><p> 229 * Creating a public virtual display that isn't restricted to own-content only implicitly 230 * creates an auto-mirroring display. See {@link #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR} for 231 * restrictions on who is allowed to create an auto-mirroring display. 232 * </p> 233 * 234 * <h3>Private virtual displays</h3> 235 * <p> 236 * When this flag is not set, the virtual display is private as defined by the 237 * {@link Display#FLAG_PRIVATE} display flag. 238 * </p> 239 * 240 * <p> 241 * A private virtual display belongs to the application that created it. Only the a owner of a 242 * private virtual display and the apps that are already on that display are allowed to place 243 * windows upon it. The private virtual display also does not participate in display mirroring: 244 * it will neither receive mirrored content from another display nor allow its own content to be 245 * mirrored elsewhere. More precisely, the only processes that are allowed to enumerate or 246 * interact with the private display are those that have the same UID as the application that 247 * originally created the private virtual display or as the activities that are already on that 248 * display. 249 * </p> 250 * 251 * @see #createVirtualDisplay 252 * @see #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY 253 * @see #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR 254 */ 255 public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1 << 0; 256 257 /** 258 * Virtual display flag: Create a presentation display. 259 * 260 * <h3>Presentation virtual displays</h3> 261 * <p> 262 * When this flag is set, the virtual display is registered as a presentation 263 * display in the {@link #DISPLAY_CATEGORY_PRESENTATION presentation display category}. 264 * Applications may automatically project their content to presentation displays 265 * to provide richer second screen experiences. 266 * </p> 267 * 268 * <h3>Non-presentation virtual displays</h3> 269 * <p> 270 * When this flag is not set, the virtual display is not registered as a presentation 271 * display. Applications can still project their content on the display but they 272 * will typically not do so automatically. This option is appropriate for 273 * more special-purpose displays. 274 * </p> 275 * 276 * @see android.app.Presentation 277 * @see #createVirtualDisplay 278 * @see #DISPLAY_CATEGORY_PRESENTATION 279 * @see Display#FLAG_PRESENTATION 280 */ 281 public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 1 << 1; 282 283 /** 284 * Virtual display flag: Create a secure display. 285 * 286 * <h3>Secure virtual displays</h3> 287 * <p> 288 * When this flag is set, the virtual display is considered secure as defined 289 * by the {@link Display#FLAG_SECURE} display flag. The caller promises to take 290 * reasonable measures, such as over-the-air encryption, to prevent the contents 291 * of the display from being intercepted or recorded on a persistent medium. 292 * </p><p> 293 * Creating a secure virtual display requires the CAPTURE_SECURE_VIDEO_OUTPUT permission. 294 * This permission is reserved for use by system components and is not available to 295 * third-party applications. 296 * </p> 297 * 298 * <h3>Non-secure virtual displays</h3> 299 * <p> 300 * When this flag is not set, the virtual display is considered unsecure. 301 * The content of secure windows will be blanked if shown on this display. 302 * </p> 303 * 304 * @see Display#FLAG_SECURE 305 * @see #createVirtualDisplay 306 */ 307 public static final int VIRTUAL_DISPLAY_FLAG_SECURE = 1 << 2; 308 309 /** 310 * Virtual display flag: Only show this display's own content; do not mirror 311 * the content of another display. 312 * 313 * <p> 314 * This flag is used in conjunction with {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}. 315 * Ordinarily public virtual displays will automatically mirror the content of the 316 * default display if they have no windows of their own. When this flag is 317 * specified, the virtual display will only ever show its own content and 318 * will be blanked instead if it has no windows. 319 * </p> 320 * 321 * <p> 322 * This flag is mutually exclusive with {@link #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}. If both 323 * flags are specified then the own-content only behavior will be applied. 324 * </p> 325 * 326 * <p> 327 * This behavior of this flag is implied whenever neither {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC} 328 * nor {@link #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR} have been set. This flag is only required to 329 * override the default behavior when creating a public display. 330 * </p> 331 * 332 * @see #createVirtualDisplay 333 */ 334 public static final int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = 1 << 3; 335 336 337 /** 338 * Virtual display flag: Allows content to be mirrored on private displays when no content is 339 * being shown. 340 * 341 * <p> 342 * This flag is mutually exclusive with {@link #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY}. 343 * If both flags are specified then the own-content only behavior will be applied. 344 * </p> 345 * 346 * <p> 347 * The behavior of this flag is implied whenever {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC} is set 348 * and {@link #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY} has not been set. This flag is only 349 * required to override the default behavior when creating a private display. 350 * </p> 351 * 352 * <p> 353 * Creating an auto-mirroing virtual display requires the CAPTURE_VIDEO_OUTPUT 354 * or CAPTURE_SECURE_VIDEO_OUTPUT permission. 355 * These permissions are reserved for use by system components and are not available to 356 * third-party applications. 357 * 358 * Alternatively, an appropriate {@link MediaProjection} may be used to create an 359 * auto-mirroring virtual display. 360 * </p> 361 * 362 * @see #createVirtualDisplay 363 */ 364 public static final int VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR = 1 << 4; 365 366 /** 367 * Virtual display flag: Allows content to be displayed on private virtual displays when 368 * keyguard is shown but is insecure. 369 * 370 * <p> 371 * This might be used in a case when the content of a virtual display is captured and sent to an 372 * external hardware display that is not visible to the system directly. This flag will allow 373 * the continued display of content while other displays will be covered by a keyguard which 374 * doesn't require providing credentials to unlock. This means that there is either no password 375 * or other authentication method set, or the device is in a trusted state - 376 * {@link android.service.trust.TrustAgentService} has available and active trust agent. 377 * </p><p> 378 * This flag can only be applied to private displays as defined by the 379 * {@link Display#FLAG_PRIVATE} display flag. It is mutually exclusive with 380 * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}. If both flags are specified then this flag's behavior 381 * will not be applied. 382 * </p> 383 * 384 * @see #createVirtualDisplay 385 * @see KeyguardManager#isDeviceSecure() 386 * @see KeyguardManager#isDeviceLocked() 387 * @hide 388 */ 389 // TODO (b/114338689): Remove the flag and use IWindowManager#shouldShowWithInsecureKeyguard 390 // TODO: Update name and documentation and un-hide the flag. Don't change the value before that. 391 public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5; 392 393 /** 394 * Virtual display flag: Specifies that the virtual display can be associated with a 395 * touchpad device that matches its uniqueId. 396 * 397 * @see #createVirtualDisplay 398 * @hide 399 */ 400 @SuppressLint("UnflaggedApi") // @TestApi without associated feature. 401 @TestApi 402 public static final int VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH = 1 << 6; 403 404 /** 405 * Virtual display flag: Indicates that the orientation of this display device is coupled to 406 * the orientation of its associated logical display. 407 * <p> 408 * The flag should not be set when the physical display is mounted in a fixed orientation 409 * such as on a desk. Without this flag, display manager will apply a coordinate transformation 410 * such as a scale and translation to letterbox or pillarbox format under the assumption that 411 * the physical orientation of the display is invariant. With this flag set, the content will 412 * rotate to fill in the space of the display, as it does on the internal device display. 413 * </p> 414 * 415 * @see #createVirtualDisplay 416 * @hide 417 */ 418 @SystemApi 419 public static final int VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT = 1 << 7; 420 421 /** 422 * Virtual display flag: Indicates that the contents will be destroyed once 423 * the display is removed. 424 * 425 * Public virtual displays without this flag will move their content to main display 426 * stack once they're removed. Private virtual displays will always destroy their 427 * content on removal even without this flag. 428 * 429 * @see #createVirtualDisplay 430 * @hide 431 */ 432 // TODO (b/114338689): Remove the flag and use WindowManager#REMOVE_CONTENT_MODE_DESTROY 433 public static final int VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL = 1 << 8; 434 435 /** 436 * Virtual display flag: Indicates that the display supports and should always show system 437 * decorations. Virtual displays without this flag shouldn't show home, navigation bar or 438 * wallpaper. 439 * <p>This flag doesn't work without {@link #VIRTUAL_DISPLAY_FLAG_TRUSTED}</p> 440 * 441 * @see #createVirtualDisplay 442 * @see #VIRTUAL_DISPLAY_FLAG_TRUSTED 443 * @hide 444 */ 445 @TestApi 446 public static final int VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 9; 447 448 /** 449 * Virtual display flags: Indicates that the display is trusted to show system decorations and 450 * receive inputs without users' touch. 451 * 452 * @see #createVirtualDisplay 453 * @see #VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS 454 * @hide 455 */ 456 @SystemApi 457 public static final int VIRTUAL_DISPLAY_FLAG_TRUSTED = 1 << 10; 458 459 /** 460 * Virtual display flags: Indicates that the display should not be a part of the default 461 * DisplayGroup and instead be part of a new DisplayGroup. 462 * 463 * @see #createVirtualDisplay 464 * @hide 465 */ 466 public static final int VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP = 1 << 11; 467 468 /** 469 * Virtual display flags: Indicates that the virtual display should always be unlocked and not 470 * have keyguard displayed on it. Only valid for virtual displays that aren't in the default 471 * display group. 472 * 473 * @see #createVirtualDisplay 474 * @see #VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP 475 * @hide 476 */ 477 public static final int VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED = 1 << 12; 478 479 /** 480 * Virtual display flags: Indicates that the display should not play sound effects or perform 481 * haptic feedback when the user touches the screen. 482 * 483 * @see #createVirtualDisplay 484 * @hide 485 */ 486 public static final int VIRTUAL_DISPLAY_FLAG_TOUCH_FEEDBACK_DISABLED = 1 << 13; 487 488 /** 489 * Virtual display flags: Indicates that the display maintains its own focus and touch mode. 490 * 491 * This flag is similar to {@link com.android.internal.R.bool.config_perDisplayFocusEnabled} in 492 * behavior, but only applies to the specific display instead of system-wide to all displays. 493 * 494 * Note: The display must be trusted in order to have its own focus. 495 * 496 * @see #createVirtualDisplay 497 * @see #VIRTUAL_DISPLAY_FLAG_TRUSTED 498 * @hide 499 */ 500 @TestApi 501 public static final int VIRTUAL_DISPLAY_FLAG_OWN_FOCUS = 1 << 14; 502 503 /** 504 * Virtual display flags: Indicates that the display should not be a part of the default 505 * DisplayGroup and instead be part of a DisplayGroup associated with its virtual device. 506 * 507 * @see #createVirtualDisplay 508 * @hide 509 */ 510 public static final int VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP = 1 << 15; 511 512 513 /** 514 * Virtual display flags: Indicates that the display should not become the top focused display 515 * by stealing the top focus from another display. 516 * 517 * @see Display#FLAG_STEAL_TOP_FOCUS_DISABLED 518 * @see #createVirtualDisplay 519 * @see #VIRTUAL_DISPLAY_FLAG_OWN_FOCUS 520 * @hide 521 */ 522 @SystemApi 523 public static final int VIRTUAL_DISPLAY_FLAG_STEAL_TOP_FOCUS_DISABLED = 1 << 16; 524 525 /** @hide */ 526 @IntDef(prefix = {"MATCH_CONTENT_FRAMERATE_"}, value = { 527 MATCH_CONTENT_FRAMERATE_UNKNOWN, 528 MATCH_CONTENT_FRAMERATE_NEVER, 529 MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY, 530 MATCH_CONTENT_FRAMERATE_ALWAYS, 531 }) 532 @Retention(RetentionPolicy.SOURCE) 533 public @interface MatchContentFrameRateType {} 534 535 /** 536 * Match content frame rate user preference is unknown. 537 */ 538 public static final int MATCH_CONTENT_FRAMERATE_UNKNOWN = -1; 539 540 /** 541 * No mode switching is allowed. 542 */ 543 public static final int MATCH_CONTENT_FRAMERATE_NEVER = 0; 544 545 /** 546 * Only refresh rate switches without visual interruptions are allowed. 547 */ 548 public static final int MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY = 1; 549 550 /** 551 * Refresh rate switches between all refresh rates are allowed even if they have visual 552 * interruptions for the user. 553 */ 554 public static final int MATCH_CONTENT_FRAMERATE_ALWAYS = 2; 555 556 /** @hide */ 557 @IntDef(prefix = {"SWITCHING_TYPE_"}, value = { 558 SWITCHING_TYPE_NONE, 559 SWITCHING_TYPE_WITHIN_GROUPS, 560 SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS, 561 SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY, 562 }) 563 @Retention(RetentionPolicy.SOURCE) 564 public @interface SwitchingType {} 565 566 /** 567 * No display mode switching will happen. 568 * @hide 569 */ 570 @TestApi 571 public static final int SWITCHING_TYPE_NONE = 0; 572 573 /** 574 * Allow only refresh rate switching between modes in the same configuration group. This way 575 * only switches without visual interruptions for the user will be allowed. 576 * @hide 577 */ 578 @TestApi 579 public static final int SWITCHING_TYPE_WITHIN_GROUPS = 1; 580 581 /** 582 * Allow refresh rate switching between all refresh rates even if the switch with have visual 583 * interruptions for the user. 584 * @hide 585 */ 586 @TestApi 587 public static final int SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS = 2; 588 589 /** 590 * Allow render frame rate switches, but not physical modes. 591 * @hide 592 */ 593 @TestApi 594 public static final int SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY = 3; 595 596 /** 597 * @hide 598 */ 599 @LongDef(flag = true, prefix = {"EVENT_TYPE_"}, value = { 600 EVENT_TYPE_DISPLAY_ADDED, 601 EVENT_TYPE_DISPLAY_CHANGED, 602 EVENT_TYPE_DISPLAY_REMOVED, 603 EVENT_TYPE_DISPLAY_REFRESH_RATE, 604 EVENT_TYPE_DISPLAY_STATE 605 }) 606 @Retention(RetentionPolicy.SOURCE) 607 public @interface EventType {} 608 609 /** 610 * @hide 611 */ 612 @LongDef(flag = true, prefix = {"PRIVATE_EVENT_TYPE_"}, value = { 613 PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS, 614 PRIVATE_EVENT_TYPE_HDR_SDR_RATIO_CHANGED, 615 PRIVATE_EVENT_TYPE_DISPLAY_CONNECTION_CHANGED, 616 PRIVATE_EVENT_TYPE_DISPLAY_COMMITTED_STATE_CHANGED 617 }) 618 @Retention(RetentionPolicy.SOURCE) 619 public @interface PrivateEventType {} 620 621 /** 622 * Event type for when a new display is added. This notification is sent 623 * through the {@link DisplayListener#onDisplayAdded} callback method 624 * 625 * @see #registerDisplayListener(DisplayListener, Handler, long) 626 * 627 */ 628 @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS) 629 public static final long EVENT_TYPE_DISPLAY_ADDED = 1L << 0; 630 631 /** 632 * Event type for when a display is removed. This notification is sent 633 * through the {@link DisplayListener#onDisplayRemoved} callback method 634 * 635 * @see #registerDisplayListener(DisplayListener, Handler, long) 636 * 637 */ 638 @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS) 639 public static final long EVENT_TYPE_DISPLAY_REMOVED = 1L << 1; 640 641 /** 642 * Event type for when a display is changed. {@link DisplayListener#onDisplayChanged} callback 643 * is triggered whenever the properties of a {@link android.view.Display}, such as size, 644 * state, density are modified. 645 * 646 * This event is not triggered for refresh rate changes as they can change very often. 647 * To monitor refresh rate changes, subscribe to {@link EVENT_TYPE_DISPLAY_REFRESH_RATE}. 648 * 649 * @see #registerDisplayListener(DisplayListener, Handler, long) 650 * 651 */ 652 @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS) 653 public static final long EVENT_TYPE_DISPLAY_CHANGED = 1L << 2; 654 655 /** 656 * Event type for when a display's refresh rate changes. 657 * {@link DisplayListener#onDisplayChanged} callback is triggered whenever the refresh rate 658 * of the display changes. New refresh rate values can be retrieved via 659 * {@link Display#getRefreshRate()}. 660 * 661 * @see #registerDisplayListener(DisplayListener, Handler, long) 662 */ 663 @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS) 664 public static final long EVENT_TYPE_DISPLAY_REFRESH_RATE = 1L << 3; 665 666 /** 667 * Event type for when a display state changes. 668 * {@link DisplayListener#onDisplayChanged} callback is triggered whenever the state 669 * of the display changes. New state values can be retrieved via 670 * {@link Display#getState()}. 671 * 672 * @see #registerDisplayListener(DisplayListener, Handler, long) 673 */ 674 @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS) 675 public static final long EVENT_TYPE_DISPLAY_STATE = 1L << 4; 676 677 /** 678 * Event type to register for a display's brightness changes. This notification is sent 679 * through the {@link DisplayListener#onDisplayChanged} callback method. New brightness 680 * values can be retrieved via {@link android.view.Display#getBrightnessInfo()}. 681 * 682 * @see #registerDisplayListener(DisplayListener, Handler, long, long) 683 * 684 * @hide 685 */ 686 public static final long PRIVATE_EVENT_TYPE_DISPLAY_BRIGHTNESS = 1L << 0; 687 688 /** 689 * Event type to register for a display's hdr/sdr ratio changes. This notification is sent 690 * through the {@link DisplayListener#onDisplayChanged} callback method. New hdr/sdr 691 * values can be retrieved via {@link Display#getHdrSdrRatio()}. 692 * 693 * Requires that {@link Display#isHdrSdrRatioAvailable()} is true. 694 * 695 * @see #registerDisplayListener(DisplayListener, Handler, long, long) 696 * 697 * @hide 698 */ 699 public static final long PRIVATE_EVENT_TYPE_HDR_SDR_RATIO_CHANGED = 1L << 1; 700 701 /** 702 * Event type to register for a display's connection changed. 703 * 704 * @see #registerDisplayListener(DisplayListener, Handler, long, long) 705 * @hide 706 */ 707 public static final long PRIVATE_EVENT_TYPE_DISPLAY_CONNECTION_CHANGED = 1L << 2; 708 709 /** 710 * Event type to register for a display's committed state changes. 711 * 712 * @see #registerDisplayListener(DisplayListener, Handler, long, long) 713 * @hide 714 */ 715 public static final long PRIVATE_EVENT_TYPE_DISPLAY_COMMITTED_STATE_CHANGED = 1L << 3; 716 717 718 /** @hide */ DisplayManager(Context context)719 public DisplayManager(Context context) { 720 mContext = context; 721 mGlobal = DisplayManagerGlobal.getInstance(); 722 } 723 724 /** 725 * Gets information about a logical display. 726 * 727 * The display metrics may be adjusted to provide compatibility 728 * for legacy applications. 729 * 730 * @param displayId The logical display id. 731 * @return The display object, or null if there is no valid display with the given id. 732 */ getDisplay(int displayId)733 public Display getDisplay(int displayId) { 734 return getOrCreateDisplay(displayId, false /*assumeValid*/); 735 } 736 737 /** 738 * Gets all currently valid logical displays. 739 * 740 * @return An array containing all displays. 741 */ getDisplays()742 public Display[] getDisplays() { 743 return getDisplays(null); 744 } 745 746 /** 747 * Gets all currently valid logical displays of the specified category. 748 * <p> 749 * When there are multiple displays in a category the returned displays are sorted 750 * of preference. For example, if the requested category is 751 * {@link #DISPLAY_CATEGORY_PRESENTATION} and there are multiple presentation displays 752 * then the displays are sorted so that the first display in the returned array 753 * is the most preferred presentation display. The application may simply 754 * use the first display or allow the user to choose. 755 * </p> 756 * 757 * @param category The requested display category or null to return all displays. 758 * @return An array containing all displays sorted by order of preference. 759 * 760 * @see #DISPLAY_CATEGORY_PRESENTATION 761 */ getDisplays(String category)762 public Display[] getDisplays(String category) { 763 boolean includeDisabled = shouldIncludeDisabledDisplays(category); 764 final int[] displayIds = mGlobal.getDisplayIds(includeDisabled); 765 if (Flags.displayCategoryBuiltIn() 766 && DISPLAY_CATEGORY_BUILT_IN_DISPLAYS.equals(category)) { 767 Display[] value = getDisplays(displayIds, DisplayManager::isBuiltInDisplay); 768 return value; 769 } else if (DISPLAY_CATEGORY_PRESENTATION.equals(category)) { 770 return getDisplays(displayIds, DisplayManager::isPresentationDisplay); 771 } else if (DISPLAY_CATEGORY_REAR.equals(category)) { 772 return getDisplays(displayIds, DisplayManager::isRearDisplay); 773 } else if (category == null || DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED.equals(category)) { 774 return getDisplays(displayIds, Objects::nonNull); 775 } 776 return new Display[0]; 777 } 778 shouldIncludeDisabledDisplays(@ullable String category)779 private boolean shouldIncludeDisabledDisplays(@Nullable String category) { 780 if (DISPLAY_CATEGORY_BUILT_IN_DISPLAYS.equals(category)) { 781 return true; 782 } 783 if (DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED.equals(category)) { 784 return true; 785 } 786 return false; 787 } 788 getDisplays(int[] displayIds, Predicate<Display> predicate)789 private Display[] getDisplays(int[] displayIds, Predicate<Display> predicate) { 790 ArrayList<Display> tmpDisplays = new ArrayList<>(); 791 for (int displayId : displayIds) { 792 Display display = getOrCreateDisplay(displayId, /*assumeValid=*/true); 793 if (predicate.test(display)) { 794 tmpDisplays.add(display); 795 } 796 } 797 return tmpDisplays.toArray(new Display[tmpDisplays.size()]); 798 } 799 isBuiltInDisplay(@ullable Display display)800 private static boolean isBuiltInDisplay(@Nullable Display display) { 801 if (display == null) { 802 return false; 803 } 804 return display.getType() == Display.TYPE_INTERNAL; 805 } 806 isPresentationDisplay(@ullable Display display)807 private static boolean isPresentationDisplay(@Nullable Display display) { 808 if (display == null || (display.getDisplayId() == DEFAULT_DISPLAY) 809 || (display.getFlags() & Display.FLAG_PRESENTATION) == 0) { 810 return false; 811 } 812 switch (display.getType()) { 813 case Display.TYPE_INTERNAL: 814 case Display.TYPE_EXTERNAL: 815 case Display.TYPE_WIFI: 816 case Display.TYPE_OVERLAY: 817 case Display.TYPE_VIRTUAL: 818 return true; 819 default: 820 return false; 821 } 822 } 823 isRearDisplay(@ullable Display display)824 private static boolean isRearDisplay(@Nullable Display display) { 825 return display != null && display.getDisplayId() != DEFAULT_DISPLAY 826 && display.getType() == Display.TYPE_INTERNAL 827 && (display.getFlags() & Display.FLAG_REAR) != 0; 828 } 829 getOrCreateDisplay(int displayId, boolean assumeValid)830 private Display getOrCreateDisplay(int displayId, boolean assumeValid) { 831 Display display; 832 synchronized (mLock) { 833 display = mDisplayCache.get(displayId); 834 if (display == null) { 835 // TODO: We cannot currently provide any override configurations for metrics on 836 // displays other than the display the context is associated with. 837 final Resources resources = mContext.getDisplayId() == displayId 838 ? mContext.getResources() : null; 839 840 display = mGlobal.getCompatibleDisplay(displayId, resources); 841 if (display != null) { 842 mDisplayCache.put(display); 843 } 844 } else if (!assumeValid && !display.isValid()) { 845 display = null; 846 } 847 } 848 return display; 849 } 850 851 /** 852 * Registers a display listener to receive notifications about when 853 * displays are added, removed or changed. 854 * 855 * Because of the high frequency at which the refresh rate can change, clients will be 856 * registered for refresh rate change callbacks only when they request for refresh rate 857 * data({@link Display#getRefreshRate()}. Or alternately, you can consider using 858 * {@link #registerDisplayListener(Executor, long, DisplayListener)} and explicitly subscribe to 859 * {@link #EVENT_TYPE_DISPLAY_REFRESH_RATE} event 860 * 861 * We encourage to use {@link #registerDisplayListener(Executor, long, DisplayListener)} 862 * instead to subscribe for explicit events of interest 863 * 864 * @param listener The listener to register. 865 * @param handler The handler on which the listener should be invoked, or null 866 * if the listener should be invoked on the calling thread's looper. 867 * 868 * @see #unregisterDisplayListener 869 */ registerDisplayListener(DisplayListener listener, Handler handler)870 public void registerDisplayListener(DisplayListener listener, Handler handler) { 871 registerDisplayListener(listener, handler, EVENT_TYPE_DISPLAY_ADDED 872 | EVENT_TYPE_DISPLAY_CHANGED 873 | EVENT_TYPE_DISPLAY_REMOVED, 0, 874 ActivityThread.currentPackageName(), /* isEventFilterExplicit */ false); 875 } 876 877 /** 878 * Registers a display listener to receive notifications about given display event types. 879 * 880 * @param listener The listener to register. 881 * @param handler The handler on which the listener should be invoked, or null 882 * if the listener should be invoked on the calling thread's looper. 883 * @param eventFilter A bitmask of the event types for which this listener is subscribed. 884 * 885 * @see #registerDisplayListener(DisplayListener, Handler) 886 * @see #unregisterDisplayListener 887 * 888 * @hide 889 */ registerDisplayListener(@onNull DisplayListener listener, @Nullable Handler handler, @EventType long eventFilter)890 public void registerDisplayListener(@NonNull DisplayListener listener, 891 @Nullable Handler handler, @EventType long eventFilter) { 892 registerDisplayListener(listener, handler, eventFilter, 0, 893 ActivityThread.currentPackageName(), /* isEventFilterExplicit */ true); 894 } 895 896 /** 897 * Registers a display listener to receive notifications about given display event types. 898 * 899 * @param listener The listener to register. 900 * @param executor Executor for the thread that will be receiving the callbacks. Cannot be null. 901 * @param eventFilter A bitmask of the event types for which this listener is subscribed. 902 * 903 * @see #registerDisplayListener(DisplayListener, Handler) 904 * @see #unregisterDisplayListener 905 * 906 */ 907 @FlaggedApi(FLAG_DISPLAY_LISTENER_PERFORMANCE_IMPROVEMENTS) registerDisplayListener(@onNull Executor executor, @EventType long eventFilter, @NonNull DisplayListener listener)908 public void registerDisplayListener(@NonNull Executor executor, @EventType long eventFilter, 909 @NonNull DisplayListener listener) { 910 registerDisplayListener(listener, executor, eventFilter, 0, 911 ActivityThread.currentPackageName(), /* isEventFilterExplicit */ true); 912 } 913 914 /** 915 * Registers a display listener to receive notifications about given display event types. 916 * 917 * @param listener The listener to register. 918 * @param handler The handler on which the listener should be invoked, or null 919 * if the listener should be invoked on the calling thread's looper. 920 * @param eventFilter A bitmask of the event types for which this listener is subscribed. 921 * @param privateEventFilter A bitmask of the private event types for which this listener 922 * is subscribed. 923 * 924 * @see #registerDisplayListener(DisplayListener, Handler) 925 * @see #unregisterDisplayListener 926 * 927 * @hide 928 */ registerDisplayListener(@onNull DisplayListener listener, @Nullable Handler handler, @EventType long eventFilter, @PrivateEventType long privateEventFilter)929 public void registerDisplayListener(@NonNull DisplayListener listener, 930 @Nullable Handler handler, @EventType long eventFilter, 931 @PrivateEventType long privateEventFilter) { 932 registerDisplayListener(listener, handler, eventFilter, privateEventFilter, 933 ActivityThread.currentPackageName(), /* isEventFilterExplicit */ true); 934 } 935 936 /** 937 * Registers a display listener to receive notifications about given display event types. 938 * 939 * @param listener The listener to register. 940 * @param handler The handler on which the listener should be invoked, or null 941 * if the listener should be invoked on the calling thread's looper. 942 * @param eventFilter A bitmask of the event types for which this listener is subscribed. 943 * @param privateEventFilter A bitmask of the private event types for which this listener 944 * is subscribed. 945 * @param isEventFilterExplicit Indicates if the client explicitly supplied the display events 946 * to be subscribed to. 947 * 948 */ registerDisplayListener(@onNull DisplayListener listener, @Nullable Handler handler, @EventType long eventFilter, @PrivateEventType long privateEventFilter, String packageName, boolean isEventFilterExplicit)949 private void registerDisplayListener(@NonNull DisplayListener listener, 950 @Nullable Handler handler, @EventType long eventFilter, 951 @PrivateEventType long privateEventFilter, String packageName, 952 boolean isEventFilterExplicit) { 953 mGlobal.registerDisplayListener(listener, handler, 954 mGlobal.mapFiltersToInternalEventFlag(eventFilter, privateEventFilter), 955 packageName, /* isEventFilterExplicit */ isEventFilterExplicit); 956 } 957 registerDisplayListener(@onNull DisplayListener listener, Executor executor, @EventType long eventFilter, @PrivateEventType long privateEventFilter, String packageName, boolean isEventFilterExplicit)958 private void registerDisplayListener(@NonNull DisplayListener listener, 959 Executor executor, @EventType long eventFilter, 960 @PrivateEventType long privateEventFilter, String packageName, 961 boolean isEventFilterExplicit) { 962 mGlobal.registerDisplayListener(listener, executor, 963 mGlobal.mapFiltersToInternalEventFlag(eventFilter, privateEventFilter), 964 packageName, /* isEventFilterExplicit */ isEventFilterExplicit); 965 } 966 967 /** 968 * Unregisters a display listener. 969 * 970 * @param listener The listener to unregister. 971 * 972 * @see #registerDisplayListener 973 */ unregisterDisplayListener(DisplayListener listener)974 public void unregisterDisplayListener(DisplayListener listener) { 975 mGlobal.unregisterDisplayListener(listener); 976 } 977 978 /** 979 * Starts scanning for available Wifi displays. 980 * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast. 981 * <p> 982 * Calls to this method nest and must be matched by an equal number of calls to 983 * {@link #stopWifiDisplayScan()}. 984 * </p><p> 985 * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. 986 * </p> 987 * 988 * @hide 989 */ 990 @UnsupportedAppUsage startWifiDisplayScan()991 public void startWifiDisplayScan() { 992 mGlobal.startWifiDisplayScan(); 993 } 994 995 /** 996 * Stops scanning for available Wifi displays. 997 * <p> 998 * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. 999 * </p> 1000 * 1001 * @hide 1002 */ 1003 @UnsupportedAppUsage stopWifiDisplayScan()1004 public void stopWifiDisplayScan() { 1005 mGlobal.stopWifiDisplayScan(); 1006 } 1007 1008 /** 1009 * Connects to a Wifi display. 1010 * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast. 1011 * <p> 1012 * Automatically remembers the display after a successful connection, if not 1013 * already remembered. 1014 * </p><p> 1015 * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. 1016 * </p> 1017 * 1018 * @param deviceAddress The MAC address of the device to which we should connect. 1019 * @hide 1020 */ 1021 @UnsupportedAppUsage connectWifiDisplay(String deviceAddress)1022 public void connectWifiDisplay(String deviceAddress) { 1023 mGlobal.connectWifiDisplay(deviceAddress); 1024 } 1025 1026 /** @hide */ 1027 @UnsupportedAppUsage pauseWifiDisplay()1028 public void pauseWifiDisplay() { 1029 mGlobal.pauseWifiDisplay(); 1030 } 1031 1032 /** @hide */ 1033 @UnsupportedAppUsage resumeWifiDisplay()1034 public void resumeWifiDisplay() { 1035 mGlobal.resumeWifiDisplay(); 1036 } 1037 1038 /** 1039 * Disconnects from the current Wifi display. 1040 * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast. 1041 * @hide 1042 */ 1043 @UnsupportedAppUsage disconnectWifiDisplay()1044 public void disconnectWifiDisplay() { 1045 mGlobal.disconnectWifiDisplay(); 1046 } 1047 1048 /** 1049 * Renames a Wifi display. 1050 * <p> 1051 * The display must already be remembered for this call to succeed. In other words, 1052 * we must already have successfully connected to the display at least once and then 1053 * not forgotten it. 1054 * </p><p> 1055 * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. 1056 * </p> 1057 * 1058 * @param deviceAddress The MAC address of the device to rename. 1059 * @param alias The alias name by which to remember the device, or null 1060 * or empty if no alias should be used. 1061 * @hide 1062 */ 1063 @UnsupportedAppUsage renameWifiDisplay(String deviceAddress, String alias)1064 public void renameWifiDisplay(String deviceAddress, String alias) { 1065 mGlobal.renameWifiDisplay(deviceAddress, alias); 1066 } 1067 1068 /** 1069 * Forgets a previously remembered Wifi display. 1070 * <p> 1071 * Automatically disconnects from the display if currently connected to it. 1072 * </p><p> 1073 * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. 1074 * </p> 1075 * 1076 * @param deviceAddress The MAC address of the device to forget. 1077 * @hide 1078 */ 1079 @UnsupportedAppUsage forgetWifiDisplay(String deviceAddress)1080 public void forgetWifiDisplay(String deviceAddress) { 1081 mGlobal.forgetWifiDisplay(deviceAddress); 1082 } 1083 1084 /** 1085 * Gets the current Wifi display status. 1086 * Watch for changes in the status by registering a broadcast receiver for 1087 * {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED}. 1088 * 1089 * @return The current Wifi display status. 1090 * @hide 1091 */ 1092 @UnsupportedAppUsage getWifiDisplayStatus()1093 public WifiDisplayStatus getWifiDisplayStatus() { 1094 return mGlobal.getWifiDisplayStatus(); 1095 } 1096 1097 /** 1098 * Enable a connected display that is currently disabled. 1099 * @hide 1100 */ 1101 @RequiresPermission("android.permission.MANAGE_DISPLAYS") enableConnectedDisplay(int displayId)1102 public void enableConnectedDisplay(int displayId) { 1103 mGlobal.enableConnectedDisplay(displayId); 1104 } 1105 1106 1107 /** 1108 * Disable a connected display that is currently enabled. 1109 * @hide 1110 */ 1111 @RequiresPermission("android.permission.MANAGE_DISPLAYS") disableConnectedDisplay(int displayId)1112 public void disableConnectedDisplay(int displayId) { 1113 mGlobal.disableConnectedDisplay(displayId); 1114 } 1115 1116 /** 1117 * Set the level of color saturation to apply to the display. 1118 * @param level The amount of saturation to apply, between 0 and 1 inclusive. 1119 * 0 produces a grayscale image, 1 is normal. 1120 * 1121 * @hide 1122 * @deprecated use {@link ColorDisplayManager#setSaturationLevel(int)} instead. The level passed 1123 * as a parameter here will be rounded to the nearest hundredth. 1124 */ 1125 @SystemApi 1126 @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_SATURATION) setSaturationLevel(float level)1127 public void setSaturationLevel(float level) { 1128 if (level < 0f || level > 1f) { 1129 throw new IllegalArgumentException("Saturation level must be between 0 and 1"); 1130 } 1131 final ColorDisplayManager cdm = mContext.getSystemService(ColorDisplayManager.class); 1132 cdm.setSaturationLevel(Math.round(level * 100f)); 1133 } 1134 1135 /** 1136 * Sets the HDR types that have been disabled by user. 1137 * @param userDisabledTypes the HDR types to disable. 1138 * @hide 1139 */ 1140 @TestApi 1141 @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) setUserDisabledHdrTypes(@onNull @drType int[] userDisabledTypes)1142 public void setUserDisabledHdrTypes(@NonNull @HdrType int[] userDisabledTypes) { 1143 mGlobal.setUserDisabledHdrTypes(userDisabledTypes); 1144 } 1145 1146 /** 1147 * Sets whether or not the user disabled HDR types are returned from 1148 * {@link Display#getHdrCapabilities}. 1149 * 1150 * @param areUserDisabledHdrTypesAllowed If true, the user-disabled types 1151 * are ignored and returned, if the display supports them. If false, the 1152 * user-disabled types are taken into consideration and are never returned, 1153 * even if the display supports them. 1154 * @hide 1155 */ 1156 @TestApi 1157 @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) setAreUserDisabledHdrTypesAllowed(boolean areUserDisabledHdrTypesAllowed)1158 public void setAreUserDisabledHdrTypesAllowed(boolean areUserDisabledHdrTypesAllowed) { 1159 mGlobal.setAreUserDisabledHdrTypesAllowed(areUserDisabledHdrTypesAllowed); 1160 } 1161 1162 /** 1163 * Returns whether or not the user-disabled HDR types are returned from 1164 * {@link Display#getHdrCapabilities}. 1165 * 1166 * @hide 1167 */ 1168 @TestApi areUserDisabledHdrTypesAllowed()1169 public boolean areUserDisabledHdrTypesAllowed() { 1170 return mGlobal.areUserDisabledHdrTypesAllowed(); 1171 } 1172 1173 /** 1174 * Returns the HDR formats disabled by the user. 1175 * 1176 * @hide 1177 */ 1178 @TestApi getUserDisabledHdrTypes()1179 public @NonNull int[] getUserDisabledHdrTypes() { 1180 return mGlobal.getUserDisabledHdrTypes(); 1181 } 1182 1183 /** 1184 * Resets the behavior that automatically registers clients for refresh rate change callbacks 1185 * when they register via {@link #registerDisplayListener(DisplayListener, Handler)} 1186 * 1187 * <p>By default, clients are not registered for refresh rate change callbacks via 1188 * {@link #registerDisplayListener(DisplayListener, Handler)}. However, calling 1189 * {@link Display#getRefreshRate()} triggers automatic registration for existing and future 1190 * {@link DisplayListener} instances. This method reverts this behavior, preventing new 1191 * clients from being automatically registered for refresh rate change callbacks. Note that the 1192 * existing ones will continue to stay registered 1193 * 1194 * <p>In essence, this method returns the system to its initial state, where explicit calls to 1195 * {{@link Display#getRefreshRate()} are required to receive refresh rate change notifications. 1196 * 1197 * @hide 1198 */ 1199 @FlaggedApi(Flags.FLAG_DELAY_IMPLICIT_RR_REGISTRATION_UNTIL_RR_ACCESSED) 1200 @TestApi resetImplicitRefreshRateCallbackStatus()1201 public void resetImplicitRefreshRateCallbackStatus() { 1202 mGlobal.resetImplicitRefreshRateCallbackStatus(); 1203 } 1204 1205 /** 1206 * Overrides HDR modes for a display device. 1207 * 1208 * @hide 1209 */ 1210 @RequiresPermission(Manifest.permission.ACCESS_SURFACE_FLINGER) 1211 @TestApi overrideHdrTypes(int displayId, @NonNull int[] modes)1212 public void overrideHdrTypes(int displayId, @NonNull int[] modes) { 1213 mGlobal.overrideHdrTypes(displayId, modes); 1214 } 1215 1216 /** 1217 * Creates a virtual display. 1218 * 1219 * @see #createVirtualDisplay(String, int, int, int, Surface, int, 1220 * VirtualDisplay.Callback, Handler) 1221 */ createVirtualDisplay(@onNull String name, @IntRange(from = 1) int width, @IntRange(from = 1) int height, @IntRange(from = 1) int densityDpi, @Nullable Surface surface, @VirtualDisplayFlag int flags)1222 public VirtualDisplay createVirtualDisplay(@NonNull String name, 1223 @IntRange(from = 1) int width, 1224 @IntRange(from = 1) int height, 1225 @IntRange(from = 1) int densityDpi, 1226 @Nullable Surface surface, 1227 @VirtualDisplayFlag int flags) { 1228 return createVirtualDisplay(name, width, height, densityDpi, surface, flags, null, null); 1229 } 1230 1231 /** 1232 * Creates a virtual display. 1233 * <p> 1234 * The content of a virtual display is rendered to a {@link Surface} provided 1235 * by the application. 1236 * </p><p> 1237 * The virtual display should be {@link VirtualDisplay#release released} 1238 * when no longer needed. Because a virtual display renders to a surface 1239 * provided by the application, it will be released automatically when the 1240 * process terminates and all remaining windows on it will be forcibly removed. 1241 * </p><p> 1242 * The behavior of the virtual display depends on the flags that are provided 1243 * to this method. By default, virtual displays are created to be private, 1244 * non-presentation and unsecure. Permissions may be required to use certain flags. 1245 * </p><p> 1246 * As of {@link android.os.Build.VERSION_CODES#KITKAT_WATCH}, the surface may 1247 * be attached or detached dynamically using {@link VirtualDisplay#setSurface}. 1248 * Previously, the surface had to be non-null when {@link #createVirtualDisplay} 1249 * was called and could not be changed for the lifetime of the display. 1250 * </p><p> 1251 * Detaching the surface that backs a virtual display has a similar effect to 1252 * turning off the screen. 1253 * </p> 1254 * 1255 * @param name The name of the virtual display, must be non-empty. 1256 * @param width The width of the virtual display in pixels, must be greater than 0. 1257 * @param height The height of the virtual display in pixels, must be greater than 0. 1258 * @param densityDpi The density of the virtual display in dpi, must be greater than 0. 1259 * @param surface The surface to which the content of the virtual display should 1260 * be rendered, or null if there is none initially. 1261 * @param flags A combination of virtual display flags: 1262 * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}, {@link #VIRTUAL_DISPLAY_FLAG_PRESENTATION}, 1263 * {@link #VIRTUAL_DISPLAY_FLAG_SECURE}, {@link #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY}, 1264 * or {@link #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}. 1265 * @param callback Callback to call when the state of the {@link VirtualDisplay} changes 1266 * @param handler The handler on which the listener should be invoked, or null 1267 * if the listener should be invoked on the calling thread's looper. 1268 * @return The newly created virtual display, or null if the application could 1269 * not create the virtual display. 1270 * 1271 * @throws SecurityException if the caller does not have permission to create 1272 * a virtual display with the specified flags. 1273 */ createVirtualDisplay(@onNull String name, @IntRange(from = 1) int width, @IntRange(from = 1) int height, @IntRange(from = 1) int densityDpi, @Nullable Surface surface, @VirtualDisplayFlag int flags, @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler)1274 public VirtualDisplay createVirtualDisplay(@NonNull String name, 1275 @IntRange(from = 1) int width, 1276 @IntRange(from = 1) int height, 1277 @IntRange(from = 1) int densityDpi, 1278 @Nullable Surface surface, 1279 @VirtualDisplayFlag int flags, 1280 @Nullable VirtualDisplay.Callback callback, 1281 @Nullable Handler handler) { 1282 final VirtualDisplayConfig.Builder builder = 1283 new VirtualDisplayConfig.Builder(name, width, height, densityDpi); 1284 builder.setFlags(flags); 1285 if (surface != null) { 1286 builder.setSurface(surface); 1287 } 1288 builder.setDisplayIdToMirror(getDisplayIdToMirror()); 1289 return createVirtualDisplay(builder.build(), handler, callback); 1290 } 1291 1292 /** 1293 * Creates a virtual display. 1294 * 1295 * @see #createVirtualDisplay(VirtualDisplayConfig, Handler, VirtualDisplay.Callback) 1296 */ 1297 @Nullable createVirtualDisplay(@onNull VirtualDisplayConfig config)1298 public VirtualDisplay createVirtualDisplay(@NonNull VirtualDisplayConfig config) { 1299 return createVirtualDisplay(config, /*handler=*/null, /*callback=*/null); 1300 } 1301 1302 /** 1303 * Creates a virtual display. 1304 * <p> 1305 * The content of a virtual display is rendered to a {@link Surface} provided 1306 * by the application. 1307 * </p><p> 1308 * The virtual display should be {@link VirtualDisplay#release released} 1309 * when no longer needed. Because a virtual display renders to a surface 1310 * provided by the application, it will be released automatically when the 1311 * process terminates and all remaining windows on it will be forcibly removed. 1312 * </p><p> 1313 * The behavior of the virtual display depends on the flags that are provided 1314 * to this method. By default, virtual displays are created to be private, 1315 * non-presentation and unsecure. Permissions may be required to use certain flags. 1316 * </p><p> 1317 * As of {@link android.os.Build.VERSION_CODES#KITKAT_WATCH}, the surface may 1318 * be attached or detached dynamically using {@link VirtualDisplay#setSurface}. 1319 * Previously, the surface had to be non-null when {@link #createVirtualDisplay} 1320 * was called and could not be changed for the lifetime of the display. 1321 * </p><p> 1322 * Detaching the surface that backs a virtual display has a similar effect to 1323 * turning off the screen. 1324 * </p> 1325 * 1326 * @param config The configuration of the virtual display, must be non-null. 1327 * @param handler The handler on which the listener should be invoked, or null 1328 * if the listener should be invoked on the calling thread's looper. 1329 * @param callback Callback to call when the state of the {@link VirtualDisplay} changes 1330 * @return The newly created virtual display, or null if the application could 1331 * not create the virtual display. 1332 * 1333 * @throws SecurityException if the caller does not have permission to create 1334 * a virtual display with flags specified in the configuration. 1335 */ 1336 @Nullable createVirtualDisplay( @onNull VirtualDisplayConfig config, @Nullable Handler handler, @Nullable VirtualDisplay.Callback callback)1337 public VirtualDisplay createVirtualDisplay( 1338 @NonNull VirtualDisplayConfig config, 1339 @Nullable Handler handler, 1340 @Nullable VirtualDisplay.Callback callback) { 1341 return createVirtualDisplay(null /* projection */, config, callback, handler); 1342 } 1343 1344 // TODO : Remove this hidden API after remove all callers. (Refer to MultiDisplayService) 1345 /** @hide */ createVirtualDisplay( @ullable MediaProjection projection, @NonNull String name, @IntRange(from = 1) int width, @IntRange(from = 1) int height, @IntRange(from = 1) int densityDpi, @Nullable Surface surface, @VirtualDisplayFlag int flags, @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler, @Nullable String uniqueId)1346 public VirtualDisplay createVirtualDisplay( 1347 @Nullable MediaProjection projection, 1348 @NonNull String name, 1349 @IntRange(from = 1) int width, 1350 @IntRange(from = 1) int height, 1351 @IntRange(from = 1) int densityDpi, 1352 @Nullable Surface surface, 1353 @VirtualDisplayFlag int flags, 1354 @Nullable VirtualDisplay.Callback callback, 1355 @Nullable Handler handler, 1356 @Nullable String uniqueId) { 1357 final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width, 1358 height, densityDpi); 1359 builder.setFlags(flags); 1360 if (uniqueId != null) { 1361 builder.setUniqueId(uniqueId); 1362 } 1363 if (surface != null) { 1364 builder.setSurface(surface); 1365 } 1366 builder.setDisplayIdToMirror(getDisplayIdToMirror()); 1367 return createVirtualDisplay(projection, builder.build(), callback, handler); 1368 } 1369 1370 /** @hide */ createVirtualDisplay(@ullable MediaProjection projection, @NonNull VirtualDisplayConfig virtualDisplayConfig, @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler)1371 public VirtualDisplay createVirtualDisplay(@Nullable MediaProjection projection, 1372 @NonNull VirtualDisplayConfig virtualDisplayConfig, 1373 @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) { 1374 Executor executor = null; 1375 // If callback is null, the executor will not be used. Avoid creating the handler and the 1376 // handler executor. 1377 if (callback != null) { 1378 executor = new HandlerExecutor( 1379 Handler.createAsync(handler != null ? handler.getLooper() : Looper.myLooper())); 1380 } 1381 return mGlobal.createVirtualDisplay(mContext, projection, virtualDisplayConfig, callback, 1382 executor); 1383 } 1384 1385 /** 1386 * Gets the stable device display size, in pixels. 1387 * 1388 * This should really only be used for things like server-side filtering of available 1389 * applications. Most applications don't need the level of stability guaranteed by this and 1390 * should instead query either the size of the display they're currently running on or the 1391 * size of the default display. 1392 * @hide 1393 */ 1394 @SystemApi getStableDisplaySize()1395 public Point getStableDisplaySize() { 1396 return mGlobal.getStableDisplaySize(); 1397 } 1398 1399 /** 1400 * Fetch {@link BrightnessChangeEvent}s. 1401 * @hide until we make it a system api. 1402 */ 1403 @SystemApi 1404 @RequiresPermission(Manifest.permission.BRIGHTNESS_SLIDER_USAGE) getBrightnessEvents()1405 public List<BrightnessChangeEvent> getBrightnessEvents() { 1406 return mGlobal.getBrightnessEvents(mContext.getOpPackageName()); 1407 } 1408 1409 /** 1410 * Fetch {@link AmbientBrightnessDayStats}s. 1411 * 1412 * @hide until we make it a system api 1413 */ 1414 @SystemApi 1415 @RequiresPermission(Manifest.permission.ACCESS_AMBIENT_LIGHT_STATS) getAmbientBrightnessStats()1416 public List<AmbientBrightnessDayStats> getAmbientBrightnessStats() { 1417 return mGlobal.getAmbientBrightnessStats(); 1418 } 1419 1420 /** 1421 * Sets the global display brightness configuration. 1422 * 1423 * @hide 1424 */ 1425 @SystemApi 1426 @RequiresPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) setBrightnessConfiguration(BrightnessConfiguration c)1427 public void setBrightnessConfiguration(BrightnessConfiguration c) { 1428 setBrightnessConfigurationForUser(c, mContext.getUserId(), mContext.getPackageName()); 1429 } 1430 1431 /** 1432 * Sets the brightness configuration for the specified display. 1433 * If the specified display doesn't exist, then this will return and do nothing. 1434 * 1435 * @hide 1436 */ 1437 @SystemApi 1438 @RequiresPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) setBrightnessConfigurationForDisplay(@onNull BrightnessConfiguration c, @NonNull String uniqueId)1439 public void setBrightnessConfigurationForDisplay(@NonNull BrightnessConfiguration c, 1440 @NonNull String uniqueId) { 1441 mGlobal.setBrightnessConfigurationForDisplay(c, uniqueId, mContext.getUserId(), 1442 mContext.getPackageName()); 1443 } 1444 1445 /** 1446 * Gets the brightness configuration for the specified display and default user. 1447 * Returns the default configuration if unset or display is invalid. 1448 * 1449 * @hide 1450 */ 1451 @Nullable 1452 @SystemApi 1453 @RequiresPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) getBrightnessConfigurationForDisplay( @onNull String uniqueId)1454 public BrightnessConfiguration getBrightnessConfigurationForDisplay( 1455 @NonNull String uniqueId) { 1456 return mGlobal.getBrightnessConfigurationForDisplay(uniqueId, mContext.getUserId()); 1457 } 1458 1459 /** 1460 * Sets the global display brightness configuration for a specific user. 1461 * 1462 * Note this requires the INTERACT_ACROSS_USERS permission if setting the configuration for a 1463 * user other than the one you're currently running as. 1464 * 1465 * @hide 1466 */ setBrightnessConfigurationForUser(BrightnessConfiguration c, int userId, String packageName)1467 public void setBrightnessConfigurationForUser(BrightnessConfiguration c, int userId, 1468 String packageName) { 1469 mGlobal.setBrightnessConfigurationForUser(c, userId, packageName); 1470 } 1471 1472 /** 1473 * Gets the global display brightness configuration or the default curve if one hasn't been set. 1474 * 1475 * @hide 1476 */ 1477 @SystemApi 1478 @RequiresPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) getBrightnessConfiguration()1479 public BrightnessConfiguration getBrightnessConfiguration() { 1480 return getBrightnessConfigurationForUser(mContext.getUserId()); 1481 } 1482 1483 /** 1484 * Gets the global display brightness configuration or the default curve if one hasn't been set 1485 * for a specific user. 1486 * 1487 * Note this requires the INTERACT_ACROSS_USERS permission if getting the configuration for a 1488 * user other than the one you're currently running as. 1489 * 1490 * @hide 1491 */ getBrightnessConfigurationForUser(int userId)1492 public BrightnessConfiguration getBrightnessConfigurationForUser(int userId) { 1493 return mGlobal.getBrightnessConfigurationForUser(userId); 1494 } 1495 1496 /** 1497 * Gets the default global display brightness configuration or null one hasn't 1498 * been configured. 1499 * 1500 * @hide 1501 */ 1502 @SystemApi 1503 @RequiresPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) 1504 @Nullable getDefaultBrightnessConfiguration()1505 public BrightnessConfiguration getDefaultBrightnessConfiguration() { 1506 return mGlobal.getDefaultBrightnessConfiguration(); 1507 } 1508 1509 1510 /** 1511 * Gets the last requested minimal post processing setting for the display with displayId. 1512 * 1513 * @hide 1514 */ 1515 @TestApi isMinimalPostProcessingRequested(int displayId)1516 public boolean isMinimalPostProcessingRequested(int displayId) { 1517 return mGlobal.isMinimalPostProcessingRequested(displayId); 1518 } 1519 1520 /** 1521 * Temporarily sets the brightness of the display. 1522 * <p> 1523 * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} permission. 1524 * </p> 1525 * 1526 * @param brightness The brightness value from 0.0f to 1.0f. 1527 * 1528 * @hide Requires signature permission. 1529 */ setTemporaryBrightness(int displayId, float brightness)1530 public void setTemporaryBrightness(int displayId, float brightness) { 1531 mGlobal.setTemporaryBrightness(displayId, brightness); 1532 } 1533 1534 1535 /** 1536 * Sets the brightness of the specified display. 1537 * <p> 1538 * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} 1539 * permission. 1540 * </p> 1541 * 1542 * @param displayId the logical display id 1543 * @param brightness The brightness value from 0.0f to 1.0f. 1544 * 1545 * @hide 1546 */ 1547 @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS) setBrightness(int displayId, @FloatRange(from = 0f, to = 1f) float brightness)1548 public void setBrightness(int displayId, @FloatRange(from = 0f, to = 1f) float brightness) { 1549 mGlobal.setBrightness(displayId, brightness); 1550 } 1551 1552 1553 /** 1554 * Gets the brightness of the specified display. 1555 * <p> 1556 * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} 1557 * permission. 1558 * </p> 1559 * 1560 * @param displayId The display of which brightness value to get from. 1561 * 1562 * @hide 1563 */ 1564 @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS) 1565 @FloatRange(from = 0f, to = 1f) getBrightness(int displayId)1566 public float getBrightness(int displayId) { 1567 return mGlobal.getBrightness(displayId); 1568 } 1569 1570 1571 /** 1572 * Temporarily sets the auto brightness adjustment factor. 1573 * <p> 1574 * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} permission. 1575 * </p> 1576 * 1577 * @param adjustment The adjustment factor from -1.0 to 1.0. 1578 * 1579 * @hide Requires signature permission. 1580 */ setTemporaryAutoBrightnessAdjustment(float adjustment)1581 public void setTemporaryAutoBrightnessAdjustment(float adjustment) { 1582 mGlobal.setTemporaryAutoBrightnessAdjustment(adjustment); 1583 } 1584 1585 /** 1586 * Returns the minimum brightness curve, which guarantess that any brightness curve that dips 1587 * below it is rejected by the system. 1588 * This prevent auto-brightness from setting the screen so dark as to prevent the user from 1589 * resetting or disabling it, and maps lux to the absolute minimum nits that are still readable 1590 * in that ambient brightness. 1591 * 1592 * @return The minimum brightness curve (as lux values and their corresponding nits values). 1593 * 1594 * @hide 1595 */ 1596 @SystemApi getMinimumBrightnessCurve()1597 public Pair<float[], float[]> getMinimumBrightnessCurve() { 1598 return mGlobal.getMinimumBrightnessCurve(); 1599 } 1600 1601 /** 1602 * Sets the global default {@link Display.Mode}. The display mode includes preference for 1603 * resolution and refresh rate. The mode change is applied globally, i.e. to all the connected 1604 * displays. If the mode specified is not supported by a connected display, then no mode change 1605 * occurs for that display. 1606 * 1607 * @param mode The {@link Display.Mode} to set, which can include resolution and/or 1608 * refresh-rate. It is created using {@link Display.Mode.Builder}. 1609 *` 1610 * @hide 1611 */ 1612 @TestApi 1613 @RequiresPermission(Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE) setGlobalUserPreferredDisplayMode(@onNull Display.Mode mode)1614 public void setGlobalUserPreferredDisplayMode(@NonNull Display.Mode mode) { 1615 // Create a new object containing default values for the unused fields like mode ID and 1616 // alternative refresh rates. 1617 Display.Mode preferredMode = new Display.Mode(mode.getPhysicalWidth(), 1618 mode.getPhysicalHeight(), mode.getRefreshRate()); 1619 mGlobal.setUserPreferredDisplayMode(Display.INVALID_DISPLAY, preferredMode); 1620 } 1621 1622 /** 1623 * Removes the global user preferred display mode. 1624 * User preferred display mode is cleared for all the connected displays. 1625 * 1626 * @hide 1627 */ 1628 @TestApi 1629 @RequiresPermission(Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE) clearGlobalUserPreferredDisplayMode()1630 public void clearGlobalUserPreferredDisplayMode() { 1631 mGlobal.setUserPreferredDisplayMode(Display.INVALID_DISPLAY, null); 1632 } 1633 1634 /** 1635 * Returns the global user preferred display mode. 1636 * If no user preferred mode has been set, or it has been cleared, this method returns null. 1637 * 1638 * @hide 1639 */ 1640 @TestApi 1641 @Nullable getGlobalUserPreferredDisplayMode()1642 public Display.Mode getGlobalUserPreferredDisplayMode() { 1643 return mGlobal.getUserPreferredDisplayMode(Display.INVALID_DISPLAY); 1644 } 1645 1646 /** 1647 * Sets the HDR conversion mode for the device. 1648 * 1649 * @param hdrConversionMode The {@link HdrConversionMode} to set. 1650 * Note, {@code HdrConversionMode.preferredHdrOutputType} is only applicable when 1651 * {@code HdrConversionMode.conversionMode} is {@link HdrConversionMode#HDR_CONVERSION_FORCE}. 1652 * If {@code HdrConversionMode.preferredHdrOutputType} is not set in case when 1653 * {@code HdrConversionMode.conversionMode} is {@link HdrConversionMode#HDR_CONVERSION_FORCE}, 1654 * it means that preferred output type is SDR. 1655 * 1656 * @throws IllegalArgumentException if hdrConversionMode.preferredHdrOutputType is set but 1657 * hdrConversionMode.conversionMode is not {@link HdrConversionMode#HDR_CONVERSION_FORCE}. 1658 * 1659 * @see #getHdrConversionMode 1660 * @see #getHdrConversionModeSetting 1661 * @see #getSupportedHdrOutputTypes 1662 * @hide 1663 */ 1664 @TestApi 1665 @RequiresPermission(Manifest.permission.MODIFY_HDR_CONVERSION_MODE) setHdrConversionMode(@onNull HdrConversionMode hdrConversionMode)1666 public void setHdrConversionMode(@NonNull HdrConversionMode hdrConversionMode) { 1667 mGlobal.setHdrConversionMode(hdrConversionMode); 1668 } 1669 1670 /** 1671 * Returns the {@link HdrConversionMode} of the device, which is set by the user. 1672 * 1673 * When {@link HdrConversionMode#getConversionMode} is 1674 * {@link HdrConversionMode#HDR_CONVERSION_SYSTEM}, the 1675 * {@link HdrConversionMode#getPreferredHdrOutputType} depicts the systemPreferredHdrOutputType. 1676 * The HDR conversion mode chosen by user which considers the app override is returned. Apps can 1677 * override HDR conversion using 1678 * {@link android.view.WindowManager.LayoutParams#setHdrConversionEnabled(boolean)}. 1679 */ 1680 @NonNull getHdrConversionMode()1681 public HdrConversionMode getHdrConversionMode() { 1682 return mGlobal.getHdrConversionMode(); 1683 } 1684 1685 /** 1686 * Returns the {@link HdrConversionMode} of the device, which is set by the user. 1687 1688 * The HDR conversion mode chosen by user is returned irrespective of whether HDR conversion 1689 * is disabled by an app. 1690 * 1691 * @see #setHdrConversionMode 1692 * @see #getSupportedHdrOutputTypes 1693 * @see #getHdrConversionMode 1694 * @hide 1695 */ 1696 @TestApi 1697 @NonNull getHdrConversionModeSetting()1698 public HdrConversionMode getHdrConversionModeSetting() { 1699 return mGlobal.getHdrConversionModeSetting(); 1700 } 1701 1702 /** 1703 * Returns the HDR output types supported by the device. 1704 * 1705 * @see #getHdrConversionMode 1706 * @see #setHdrConversionMode 1707 * @hide 1708 */ 1709 @TestApi 1710 @NonNull getSupportedHdrOutputTypes()1711 public @HdrType int[] getSupportedHdrOutputTypes() { 1712 return mGlobal.getSupportedHdrOutputTypes(); 1713 } 1714 1715 /** 1716 * When enabled the app requested mode is always selected regardless of user settings and 1717 * policies for low brightness, low battery, etc. 1718 * 1719 * @hide 1720 */ 1721 @TestApi 1722 @RequiresPermission(Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) setShouldAlwaysRespectAppRequestedMode(boolean enabled)1723 public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) { 1724 mGlobal.setShouldAlwaysRespectAppRequestedMode(enabled); 1725 } 1726 1727 /** 1728 * Returns whether we are running in a mode which always selects the app requested display mode 1729 * and ignores user settings and policies for low brightness, low battery etc. 1730 * 1731 * @hide 1732 */ 1733 @TestApi 1734 @RequiresPermission(Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) shouldAlwaysRespectAppRequestedMode()1735 public boolean shouldAlwaysRespectAppRequestedMode() { 1736 return mGlobal.shouldAlwaysRespectAppRequestedMode(); 1737 } 1738 1739 /** 1740 * Returns whether this device supports Always On Display. 1741 * 1742 * @hide 1743 */ 1744 @SystemApi 1745 @FlaggedApi(Flags.FLAG_IS_ALWAYS_ON_AVAILABLE_API) isAlwaysOnDisplayCurrentlyAvailable()1746 public boolean isAlwaysOnDisplayCurrentlyAvailable() { 1747 return getAmbientDisplayConfiguration().alwaysOnAvailableForUser(mContext.getUserId()); 1748 } 1749 1750 /** 1751 * Returns whether device supports seamless refresh rate switching. 1752 * 1753 * Match content frame rate setting has three options: seamless, non-seamless and never. 1754 * The seamless option does nothing if the device does not support seamless refresh rate 1755 * switching. This API is used in such a case to hide the seamless option. 1756 * 1757 * @see DisplayManager#setRefreshRateSwitchingType 1758 * @see DisplayManager#getMatchContentFrameRateUserPreference 1759 * @hide 1760 */ supportsSeamlessRefreshRateSwitching()1761 public boolean supportsSeamlessRefreshRateSwitching() { 1762 return mContext.getResources().getBoolean( 1763 R.bool.config_supportsSeamlessRefreshRateSwitching); 1764 } 1765 1766 /** 1767 * Sets the refresh rate switching type. 1768 * This matches {@link android.provider.Settings.Secure.MATCH_CONTENT_FRAME_RATE} 1769 * 1770 * @hide 1771 */ 1772 @TestApi 1773 @RequiresPermission(Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE) setRefreshRateSwitchingType(@witchingType int newValue)1774 public void setRefreshRateSwitchingType(@SwitchingType int newValue) { 1775 mGlobal.setRefreshRateSwitchingType(newValue); 1776 } 1777 1778 /** 1779 * Returns the user preference for "Match content frame rate". 1780 * <p> 1781 * Never: Even if the app requests it, the device will never try to match its output to the 1782 * original frame rate of the content. 1783 * </p><p> 1784 * Seamless: If the app requests it, the device will match its output to the original frame 1785 * rate of the content, ONLY if the display can transition seamlessly. 1786 * </p><p> 1787 * Always: If the app requests it, the device will match its output to the original 1788 * frame rate of the content. This may cause the screen to go blank for a 1789 * second when exiting or entering a video playback. 1790 * </p> 1791 */ getMatchContentFrameRateUserPreference()1792 @MatchContentFrameRateType public int getMatchContentFrameRateUserPreference() { 1793 return toMatchContentFrameRateSetting(mGlobal.getRefreshRateSwitchingType()); 1794 } 1795 1796 @MatchContentFrameRateType toMatchContentFrameRateSetting(@witchingType int switchingType)1797 private int toMatchContentFrameRateSetting(@SwitchingType int switchingType) { 1798 switch (switchingType) { 1799 case SWITCHING_TYPE_NONE: 1800 return MATCH_CONTENT_FRAMERATE_NEVER; 1801 case SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY: 1802 case SWITCHING_TYPE_WITHIN_GROUPS: 1803 return MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY; 1804 case SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS: 1805 return MATCH_CONTENT_FRAMERATE_ALWAYS; 1806 default: 1807 Slog.e(TAG, switchingType + " is not a valid value of switching type."); 1808 return MATCH_CONTENT_FRAMERATE_UNKNOWN; 1809 } 1810 } 1811 getAmbientDisplayConfiguration()1812 private AmbientDisplayConfiguration getAmbientDisplayConfiguration() { 1813 synchronized (this) { 1814 if (mAmbientDisplayConfiguration == null) { 1815 mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext); 1816 } 1817 } 1818 return mAmbientDisplayConfiguration; 1819 } 1820 1821 /** 1822 * Creates a VirtualDisplay that will mirror the content of displayIdToMirror 1823 * @param name The name for the virtual display 1824 * @param width The initial width for the virtual display 1825 * @param height The initial height for the virtual display 1826 * @param displayIdToMirror The displayId that will be mirrored into the virtual display. 1827 * @return VirtualDisplay that can be used to update properties. 1828 * 1829 * @hide 1830 */ 1831 @RequiresPermission(Manifest.permission.CAPTURE_VIDEO_OUTPUT) 1832 @Nullable 1833 @SystemApi createVirtualDisplay(@onNull String name, int width, int height, int displayIdToMirror, @Nullable Surface surface)1834 public static VirtualDisplay createVirtualDisplay(@NonNull String name, int width, int height, 1835 int displayIdToMirror, @Nullable Surface surface) { 1836 IDisplayManager sDm = IDisplayManager.Stub.asInterface( 1837 ServiceManager.getService(Context.DISPLAY_SERVICE)); 1838 IPackageManager sPackageManager = IPackageManager.Stub.asInterface( 1839 ServiceManager.getService("package")); 1840 1841 // Density doesn't matter since this virtual display is only used for mirroring. 1842 VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width, 1843 height, 1 /* densityDpi */) 1844 .setFlags(VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) 1845 .setDisplayIdToMirror(displayIdToMirror); 1846 if (surface != null) { 1847 builder.setSurface(surface); 1848 } 1849 VirtualDisplayConfig virtualDisplayConfig = builder.build(); 1850 1851 String[] packages; 1852 try { 1853 packages = sPackageManager.getPackagesForUid(Process.myUid()); 1854 } catch (RemoteException ex) { 1855 throw ex.rethrowFromSystemServer(); 1856 } 1857 1858 // Just use the first one since it just needs to match the package when looking it up by 1859 // calling UID in system server. 1860 // The call may come from a rooted device, in that case the requesting uid will be root so 1861 // it will not have any package name 1862 String packageName = packages == null ? null : packages[0]; 1863 DisplayManagerGlobal.VirtualDisplayCallback 1864 callbackWrapper = new DisplayManagerGlobal.VirtualDisplayCallback(null, null); 1865 int displayId; 1866 try { 1867 displayId = sDm.createVirtualDisplay(virtualDisplayConfig, callbackWrapper, null, 1868 packageName); 1869 } catch (RemoteException ex) { 1870 throw ex.rethrowFromSystemServer(); 1871 } 1872 return DisplayManagerGlobal.getInstance().createVirtualDisplayWrapper(virtualDisplayConfig, 1873 callbackWrapper, displayId); 1874 } 1875 1876 /** 1877 * Allows internal application to restrict display modes to specified modeIds 1878 * 1879 * @param displayId display that restrictions will be applied to 1880 * @param modeIds allowed mode ids 1881 * 1882 * @hide 1883 */ 1884 @RequiresPermission("android.permission.RESTRICT_DISPLAY_MODES") requestDisplayModes(int displayId, @Nullable int[] modeIds)1885 public void requestDisplayModes(int displayId, @Nullable int[] modeIds) { 1886 if (modeIds != null && modeIds.length == 0) { 1887 throw new IllegalArgumentException("requestDisplayModes: modesIds can't be empty"); 1888 } 1889 mGlobal.requestDisplayModes(displayId, modeIds); 1890 } 1891 1892 /** 1893 * Gets the mapping between the doze brightness sensor values and brightness values. The doze 1894 * brightness sensor is a light sensor used to determine the brightness while the device is 1895 * dozing. Light sensor values are typically integers in the rage of 0-4. The returned values 1896 * are between {@link PowerManager#BRIGHTNESS_MIN} and {@link PowerManager#BRIGHTNESS_MAX}, or 1897 * -1 meaning that the current brightness should be kept. 1898 * <p> 1899 * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} 1900 * permission. 1901 * </p> 1902 * 1903 * @param displayId The ID of the display 1904 * 1905 * @hide 1906 */ 1907 @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS) 1908 @Nullable getDozeBrightnessSensorValueToBrightness(int displayId)1909 public float[] getDozeBrightnessSensorValueToBrightness(int displayId) { 1910 return mGlobal.getDozeBrightnessSensorValueToBrightness(displayId); 1911 } 1912 1913 /** 1914 * Gets the default doze brightness. 1915 * The returned values are between {@link PowerManager#BRIGHTNESS_MIN} and 1916 * {@link PowerManager#BRIGHTNESS_MAX}. 1917 * <p> 1918 * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} 1919 * permission. 1920 * </p> 1921 * 1922 * @param displayId The ID of the display 1923 * 1924 * @hide 1925 */ 1926 @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS) 1927 @FloatRange(from = 0f, to = 1f) getDefaultDozeBrightness(int displayId)1928 public float getDefaultDozeBrightness(int displayId) { 1929 return mGlobal.getDefaultDozeBrightness(displayId); 1930 } 1931 getDisplayIdToMirror()1932 private int getDisplayIdToMirror() { 1933 if (mDisplayIdToMirror == INVALID_DISPLAY) { 1934 final UserManager userManager = mContext.getSystemService(UserManager.class); 1935 mDisplayIdToMirror = userManager.isVisibleBackgroundUsersSupported() 1936 ? userManager.getMainDisplayIdAssignedToUser() 1937 : DEFAULT_DISPLAY; 1938 } 1939 return mDisplayIdToMirror; 1940 } 1941 1942 /** 1943 * @return The current display topology that represents the relative positions of extended 1944 * displays. 1945 * 1946 * @hide 1947 */ 1948 @RequiresPermission(MANAGE_DISPLAYS) 1949 @Nullable 1950 @TestApi 1951 @FlaggedApi(Flags.FLAG_DISPLAY_TOPOLOGY) getDisplayTopology()1952 public DisplayTopology getDisplayTopology() { 1953 return mGlobal.getDisplayTopology(); 1954 } 1955 1956 /** 1957 * Set the relative positions between extended displays (display topology). 1958 * @param topology The display topology to be set 1959 * 1960 * @hide 1961 */ 1962 @RequiresPermission(MANAGE_DISPLAYS) setDisplayTopology(DisplayTopology topology)1963 public void setDisplayTopology(DisplayTopology topology) { 1964 mGlobal.setDisplayTopology(topology); 1965 } 1966 1967 /** 1968 * Register a listener to receive display topology updates. 1969 * @param executor The executor specifying the thread on which the callbacks will be invoked 1970 * @param listener The listener 1971 * 1972 * @hide 1973 */ 1974 @RequiresPermission(MANAGE_DISPLAYS) registerTopologyListener(@onNull @allbackExecutor Executor executor, @NonNull Consumer<DisplayTopology> listener)1975 public void registerTopologyListener(@NonNull @CallbackExecutor Executor executor, 1976 @NonNull Consumer<DisplayTopology> listener) { 1977 mGlobal.registerTopologyListener(executor, listener, ActivityThread.currentPackageName()); 1978 } 1979 1980 /** 1981 * Unregister a display topology listener. 1982 * @param listener The listener to unregister 1983 * 1984 * @hide 1985 */ 1986 @RequiresPermission(MANAGE_DISPLAYS) unregisterTopologyListener(@onNull Consumer<DisplayTopology> listener)1987 public void unregisterTopologyListener(@NonNull Consumer<DisplayTopology> listener) { 1988 mGlobal.unregisterTopologyListener(listener); 1989 } 1990 1991 /** 1992 * Listens for changes in available display devices. 1993 */ 1994 public interface DisplayListener { 1995 /** 1996 * Called whenever a logical display has been added to the system. 1997 * Use {@link DisplayManager#getDisplay} to get more information about 1998 * the display. 1999 * 2000 * @param displayId The id of the logical display that was added. 2001 */ onDisplayAdded(int displayId)2002 void onDisplayAdded(int displayId); 2003 2004 /** 2005 * Called whenever a logical display has been removed from the system. 2006 * 2007 * @param displayId The id of the logical display that was removed. 2008 */ onDisplayRemoved(int displayId)2009 void onDisplayRemoved(int displayId); 2010 2011 /** 2012 * Called whenever the properties of a logical {@link android.view.Display}, 2013 * such as size and density, have changed. 2014 * 2015 * @param displayId The id of the logical display that changed. 2016 */ onDisplayChanged(int displayId)2017 void onDisplayChanged(int displayId); 2018 2019 /** 2020 * Called when a display is connected, but not necessarily used. 2021 * 2022 * A display is always connected before being added. 2023 * @hide 2024 */ onDisplayConnected(int displayId)2025 default void onDisplayConnected(int displayId) { } 2026 2027 /** 2028 * Called when a display is disconnected. 2029 * 2030 * If a display was added, a display is only disconnected after it has been removed. Note, 2031 * however, that the display may have been disconnected by the time the removed event is 2032 * received by the listener. 2033 * @hide 2034 */ onDisplayDisconnected(int displayId)2035 default void onDisplayDisconnected(int displayId) { } 2036 } 2037 2038 /** 2039 * Interface for accessing keys belonging to {@link 2040 * android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER}. 2041 * @hide 2042 */ 2043 public interface DeviceConfig { 2044 2045 /** 2046 * Key for refresh rate in the low zone defined by thresholds. 2047 * 2048 * Note that the name and value don't match because they were added before we had a high 2049 * zone to consider. 2050 * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER 2051 * @see android.R.integer#config_defaultZoneBehavior 2052 */ 2053 String KEY_REFRESH_RATE_IN_LOW_ZONE = "refresh_rate_in_zone"; 2054 2055 /** 2056 * Key for accessing the low display brightness thresholds for the configured refresh 2057 * rate zone. 2058 * The value will be a pair of comma separated integers representing the minimum and maximum 2059 * thresholds of the zone, respectively, in display backlight units (i.e. [0, 255]). 2060 * 2061 * Note that the name and value don't match because they were added before we had a high 2062 * zone to consider. 2063 * 2064 * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER 2065 * @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate 2066 * @hide 2067 */ 2068 String KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS = 2069 "peak_refresh_rate_brightness_thresholds"; 2070 2071 /** 2072 * Key for accessing the low ambient brightness thresholds for the configured refresh 2073 * rate zone. The value will be a pair of comma separated integers representing the minimum 2074 * and maximum thresholds of the zone, respectively, in lux. 2075 * 2076 * Note that the name and value don't match because they were added before we had a high 2077 * zone to consider. 2078 * 2079 * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER 2080 * @see android.R.array#config_ambientThresholdsOfPeakRefreshRate 2081 * @hide 2082 */ 2083 String KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS = 2084 "peak_refresh_rate_ambient_thresholds"; 2085 /** 2086 * Key for refresh rate in the high zone defined by thresholds. 2087 * 2088 * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER 2089 * @see android.R.integer#config_fixedRefreshRateInHighZone 2090 */ 2091 String KEY_REFRESH_RATE_IN_HIGH_ZONE = "refresh_rate_in_high_zone"; 2092 2093 /** 2094 * Key for accessing the display brightness thresholds for the configured refresh rate zone. 2095 * The value will be a pair of comma separated integers representing the minimum and maximum 2096 * thresholds of the zone, respectively, in display backlight units (i.e. [0, 255]). 2097 * 2098 * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER 2099 * @see android.R.array#config_brightnessHighThresholdsOfFixedRefreshRate 2100 * @hide 2101 */ 2102 String KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS = 2103 "fixed_refresh_rate_high_display_brightness_thresholds"; 2104 2105 /** 2106 * Key for accessing the ambient brightness thresholds for the configured refresh rate zone. 2107 * The value will be a pair of comma separated integers representing the minimum and maximum 2108 * thresholds of the zone, respectively, in lux. 2109 * 2110 * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER 2111 * @see android.R.array#config_ambientHighThresholdsOfFixedRefreshRate 2112 * @hide 2113 */ 2114 String KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS = 2115 "fixed_refresh_rate_high_ambient_brightness_thresholds"; 2116 2117 /** 2118 * Key for refresh rate when the device is in high brightness mode for sunlight visility. 2119 * 2120 * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER 2121 * @see android.R.integer#config_defaultRefreshRateInHbmSunlight 2122 */ 2123 String KEY_REFRESH_RATE_IN_HBM_SUNLIGHT = "refresh_rate_in_hbm_sunlight"; 2124 2125 /** 2126 * Key for refresh rate when the device is in high brightness mode for HDR. 2127 * 2128 * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER 2129 * @see android.R.integer#config_defaultRefreshRateInHbmHdr 2130 */ 2131 String KEY_REFRESH_RATE_IN_HBM_HDR = "refresh_rate_in_hbm_hdr"; 2132 2133 /** 2134 * Key for default peak refresh rate 2135 * 2136 * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER 2137 * @see android.R.integer#config_defaultPeakRefreshRate 2138 * @hide 2139 */ 2140 String KEY_PEAK_REFRESH_RATE_DEFAULT = "peak_refresh_rate_default"; 2141 2142 // TODO(b/162536543): rename it once it is proved not harmful for users. 2143 /** 2144 * Key for controlling which packages are explicitly blocked from running at refresh rates 2145 * higher than 60hz. An app may be added to this list if they exhibit performance issues at 2146 * higher refresh rates. 2147 * 2148 * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER 2149 * @see android.R.array#config_highRefreshRateBlacklist 2150 * @hide 2151 */ 2152 String KEY_HIGH_REFRESH_RATE_BLACKLIST = "high_refresh_rate_blacklist"; 2153 2154 /** 2155 * Key for the brightness throttling data as a String formatted: 2156 * <displayId>,<no of throttling levels>,[<severity as string>,<brightness cap>] 2157 * [,<throttlingId>]? 2158 * Where [<severity as string>,<brightness cap>] is repeated for each throttling level. 2159 * The entirety is repeated for each display and throttling id, separated by a semicolon. 2160 * For example: 2161 * 123,1,critical,0.8;456,2,moderate,0.9,critical,0.7 2162 * 123,1,critical,0.8,default;123,1,moderate,0.6,id_2;456,2,moderate,0.9,critical,0.7 2163 */ 2164 String KEY_BRIGHTNESS_THROTTLING_DATA = "brightness_throttling_data"; 2165 2166 /** 2167 * Key for the power throttling data as a String formatted, from the display 2168 * device config. 2169 */ 2170 String KEY_POWER_THROTTLING_DATA = "power_throttling_data"; 2171 2172 /** 2173 * Key for normal brightness mode controller feature flag. 2174 * It enables NormalBrightnessModeController. 2175 * Read value via {@link android.provider.DeviceConfig#getBoolean(String, String, boolean)} 2176 * with {@link android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER} as the namespace. 2177 * @hide 2178 */ 2179 String KEY_USE_NORMAL_BRIGHTNESS_MODE_CONTROLLER = "use_normal_brightness_mode_controller"; 2180 2181 /** 2182 * Key for disabling screen wake locks while apps are in cached state. 2183 * Read value via {@link android.provider.DeviceConfig#getBoolean(String, String, boolean)} 2184 * with {@link android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER} as the namespace. 2185 * @hide 2186 */ 2187 String KEY_DISABLE_SCREEN_WAKE_LOCKS_WHILE_CACHED = 2188 "disable_screen_wake_locks_while_cached"; 2189 } 2190 2191 /** 2192 * Helper class to maintain cache of weak references to Display instances. 2193 * 2194 * Note this class is not thread-safe, so external synchronization is needed if accessed 2195 * concurrently. 2196 */ 2197 private static final class WeakDisplayCache { 2198 private final SparseArray<WeakReference<Display>> mDisplayCache = new SparseArray<>(); 2199 2200 /** 2201 * Return cached {@link Display} instance for the provided display id. 2202 * 2203 * @param displayId - display id of the requested {@link Display} instance. 2204 * @return cached {@link Display} instance or null 2205 */ get(int displayId)2206 Display get(int displayId) { 2207 WeakReference<Display> wrDisplay = mDisplayCache.get(displayId); 2208 if (wrDisplay == null) { 2209 return null; 2210 } 2211 return wrDisplay.get(); 2212 } 2213 2214 /** 2215 * Insert new {@link Display} instance in the cache. This replaced the previously cached 2216 * {@link Display} instance, if there's already one with the same display id. 2217 * 2218 * @param display - Display instance to cache. 2219 */ put(Display display)2220 void put(Display display) { 2221 removeStaleEntries(); 2222 mDisplayCache.put(display.getDisplayId(), new WeakReference<>(display)); 2223 } 2224 2225 /** 2226 * Evict gc-ed entries from the cache. 2227 */ removeStaleEntries()2228 private void removeStaleEntries() { 2229 ArrayList<Integer> staleEntriesIndices = new ArrayList(); 2230 for (int i = 0; i < mDisplayCache.size(); i++) { 2231 if (mDisplayCache.valueAt(i).get() == null) { 2232 staleEntriesIndices.add(i); 2233 } 2234 } 2235 2236 for (int i = 0; i < staleEntriesIndices.size(); i++) { 2237 // removeAt call to SparseArray doesn't compact the underlying array 2238 // so the indices stay valid even after removal. 2239 mDisplayCache.removeAt(staleEntriesIndices.get(i)); 2240 } 2241 } 2242 } 2243 } 2244