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