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