• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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