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 
21 import android.annotation.IntDef;
22 import android.annotation.RequiresPermission;
23 import android.content.res.CompatibilityInfo;
24 import android.content.res.Resources;
25 import android.graphics.PixelFormat;
26 import android.graphics.Point;
27 import android.graphics.Rect;
28 import android.hardware.display.DisplayManagerGlobal;
29 import android.os.Parcel;
30 import android.os.Parcelable;
31 import android.os.Process;
32 import android.os.SystemClock;
33 import android.util.DisplayMetrics;
34 import android.util.Log;
35 
36 import java.lang.annotation.Retention;
37 import java.lang.annotation.RetentionPolicy;
38 import java.util.Arrays;
39 
40 /**
41  * Provides information about the size and density of a logical display.
42  * <p>
43  * The display area is described in two different ways.
44  * <ul>
45  * <li>The application display area specifies the part of the display that may contain
46  * an application window, excluding the system decorations.  The application display area may
47  * be smaller than the real display area because the system subtracts the space needed
48  * for decor elements such as the status bar.  Use the following methods to query the
49  * application display area: {@link #getSize}, {@link #getRectSize} and {@link #getMetrics}.</li>
50  * <li>The real display area specifies the part of the display that contains content
51  * including the system decorations.  Even so, the real display area may be smaller than the
52  * physical size of the display if the window manager is emulating a smaller display
53  * using (adb shell wm size).  Use the following methods to query the
54  * real display area: {@link #getRealSize}, {@link #getRealMetrics}.</li>
55  * </ul>
56  * </p><p>
57  * A logical display does not necessarily represent a particular physical display device
58  * such as the built-in screen or an external monitor.  The contents of a logical
59  * display may be presented on one or more physical displays according to the devices
60  * that are currently attached and whether mirroring has been enabled.
61  * </p>
62  */
63 public final class Display {
64     private static final String TAG = "Display";
65     private static final boolean DEBUG = false;
66 
67     private final DisplayManagerGlobal mGlobal;
68     private final int mDisplayId;
69     private final int mLayerStack;
70     private final int mFlags;
71     private final int mType;
72     private final String mAddress;
73     private final int mOwnerUid;
74     private final String mOwnerPackageName;
75     private final Resources mResources;
76     private DisplayAdjustments mDisplayAdjustments;
77 
78     private DisplayInfo mDisplayInfo; // never null
79     private boolean mIsValid;
80 
81     // Temporary display metrics structure used for compatibility mode.
82     private final DisplayMetrics mTempMetrics = new DisplayMetrics();
83 
84     // We cache the app width and height properties briefly between calls
85     // to getHeight() and getWidth() to ensure that applications perceive
86     // consistent results when the size changes (most of the time).
87     // Applications should now be using getSize() instead.
88     private static final int CACHED_APP_SIZE_DURATION_MILLIS = 20;
89     private long mLastCachedAppSizeUpdate;
90     private int mCachedAppWidthCompat;
91     private int mCachedAppHeightCompat;
92 
93     /**
94      * The default Display id, which is the id of the built-in primary display
95      * assuming there is one.
96      */
97     public static final int DEFAULT_DISPLAY = 0;
98 
99     /**
100      * Invalid display id.
101      */
102     public static final int INVALID_DISPLAY = -1;
103 
104     /**
105      * Display flag: Indicates that the display supports compositing content
106      * that is stored in protected graphics buffers.
107      * <p>
108      * If this flag is set then the display device supports compositing protected buffers.
109      * </p><p>
110      * If this flag is not set then the display device may not support compositing
111      * protected buffers; the user may see a blank region on the screen instead of
112      * the protected content.
113      * </p><p>
114      * Secure (DRM) video decoders may allocate protected graphics buffers to request that
115      * a hardware-protected path be provided between the video decoder and the external
116      * display sink.  If a hardware-protected path is not available, then content stored
117      * in protected graphics buffers may not be composited.
118      * </p><p>
119      * An application can use the absence of this flag as a hint that it should not use protected
120      * buffers for this display because the content may not be visible.  For example,
121      * if the flag is not set then the application may choose not to show content on this
122      * display, show an informative error message, select an alternate content stream
123      * or adopt a different strategy for decoding content that does not rely on
124      * protected buffers.
125      * </p>
126      *
127      * @see #getFlags
128      */
129     public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1 << 0;
130 
131     /**
132      * Display flag: Indicates that the display has a secure video output and
133      * supports compositing secure surfaces.
134      * <p>
135      * If this flag is set then the display device has a secure video output
136      * and is capable of showing secure surfaces.  It may also be capable of
137      * showing {@link #FLAG_SUPPORTS_PROTECTED_BUFFERS protected buffers}.
138      * </p><p>
139      * If this flag is not set then the display device may not have a secure video
140      * output; the user may see a blank region on the screen instead of
141      * the contents of secure surfaces or protected buffers.
142      * </p><p>
143      * Secure surfaces are used to prevent content rendered into those surfaces
144      * by applications from appearing in screenshots or from being viewed
145      * on non-secure displays.  Protected buffers are used by secure video decoders
146      * for a similar purpose.
147      * </p><p>
148      * An application creates a window with a secure surface by specifying the
149      * {@link WindowManager.LayoutParams#FLAG_SECURE} window flag.
150      * Likewise, an application creates a {@link SurfaceView} with a secure surface
151      * by calling {@link SurfaceView#setSecure} before attaching the secure view to
152      * its containing window.
153      * </p><p>
154      * An application can use the absence of this flag as a hint that it should not create
155      * secure surfaces or protected buffers on this display because the content may
156      * not be visible.  For example, if the flag is not set then the application may
157      * choose not to show content on this display, show an informative error message,
158      * select an alternate content stream or adopt a different strategy for decoding
159      * content that does not rely on secure surfaces or protected buffers.
160      * </p>
161      *
162      * @see #getFlags
163      */
164     public static final int FLAG_SECURE = 1 << 1;
165 
166     /**
167      * Display flag: Indicates that the display is private.  Only the application that
168      * owns the display and apps that are already on the display can create windows on it.
169      *
170      * @see #getFlags
171      */
172     public static final int FLAG_PRIVATE = 1 << 2;
173 
174     /**
175      * Display flag: Indicates that the display is a presentation display.
176      * <p>
177      * This flag identifies secondary displays that are suitable for
178      * use as presentation displays such as HDMI or Wireless displays.  Applications
179      * may automatically project their content to presentation displays to provide
180      * richer second screen experiences.
181      * </p>
182      *
183      * @see #getFlags
184      */
185     public static final int FLAG_PRESENTATION = 1 << 3;
186 
187     /**
188      * Display flag: Indicates that the display has a round shape.
189      * <p>
190      * This flag identifies displays that are circular, elliptical or otherwise
191      * do not permit the user to see all the way to the logical corners of the display.
192      * </p>
193      *
194      * @see #getFlags
195      */
196     public static final int FLAG_ROUND = 1 << 4;
197 
198     /**
199      * Display flag: Indicates that the display can show its content when non-secure keyguard is
200      * shown.
201      * <p>
202      * This flag identifies secondary displays that won't show keyguard if it can be dismissed
203      * without entering credentials. Display content will be shown even if other displays are
204      * locked.
205      * </p>
206      *
207      * @see #getFlags
208      * @hide
209      */
210     public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5;
211 
212     /**
213      * Display flag: Indicates that the contents of the display should not be scaled
214      * to fit the physical screen dimensions.  Used for development only to emulate
215      * devices with smaller physicals screens while preserving density.
216      *
217      * @hide
218      */
219     public static final int FLAG_SCALING_DISABLED = 1 << 30;
220 
221     /**
222      * Display type: Unknown display type.
223      * @hide
224      */
225     public static final int TYPE_UNKNOWN = 0;
226 
227     /**
228      * Display type: Built-in display.
229      * @hide
230      */
231     public static final int TYPE_BUILT_IN = 1;
232 
233     /**
234      * Display type: HDMI display.
235      * @hide
236      */
237     public static final int TYPE_HDMI = 2;
238 
239     /**
240      * Display type: WiFi display.
241      * @hide
242      */
243     public static final int TYPE_WIFI = 3;
244 
245     /**
246      * Display type: Overlay display.
247      * @hide
248      */
249     public static final int TYPE_OVERLAY = 4;
250 
251     /**
252      * Display type: Virtual display.
253      * @hide
254      */
255     public static final int TYPE_VIRTUAL = 5;
256 
257     /**
258      * Display state: The display state is unknown.
259      *
260      * @see #getState
261      */
262     public static final int STATE_UNKNOWN = 0;
263 
264     /**
265      * Display state: The display is off.
266      *
267      * @see #getState
268      */
269     public static final int STATE_OFF = 1;
270 
271     /**
272      * Display state: The display is on.
273      *
274      * @see #getState
275      */
276     public static final int STATE_ON = 2;
277 
278     /**
279      * Display state: The display is dozing in a low power state; it is still
280      * on but is optimized for showing system-provided content while the
281      * device is non-interactive.
282      *
283      * @see #getState
284      * @see android.os.PowerManager#isInteractive
285      */
286     public static final int STATE_DOZE = 3;
287 
288     /**
289      * Display state: The display is dozing in a suspended low power state; it is still
290      * on but is optimized for showing static system-provided content while the device
291      * is non-interactive.  This mode may be used to conserve even more power by allowing
292      * the hardware to stop applying frame buffer updates from the graphics subsystem or
293      * to take over the display and manage it autonomously to implement low power always-on
294      * display functionality.
295      *
296      * @see #getState
297      * @see android.os.PowerManager#isInteractive
298      */
299     public static final int STATE_DOZE_SUSPEND = 4;
300 
301     /**
302      * Display state: The display is on and optimized for VR mode.
303      *
304      * @see #getState
305      * @see android.os.PowerManager#isInteractive
306      */
307     public static final int STATE_VR = 5;
308 
309     /* The color mode constants defined below must be kept in sync with the ones in
310      * system/core/include/system/graphics-base.h */
311 
312     /**
313      * Display color mode: The current color mode is unknown or invalid.
314      * @hide
315      */
316     public static final int COLOR_MODE_INVALID = -1;
317 
318     /**
319      * Display color mode: The default or native gamut of the display.
320      * @hide
321      */
322     public static final int COLOR_MODE_DEFAULT = 0;
323 
324     /** @hide */
325     public static final int COLOR_MODE_BT601_625 = 1;
326     /** @hide */
327     public static final int COLOR_MODE_BT601_625_UNADJUSTED = 2;
328     /** @hide */
329     public static final int COLOR_MODE_BT601_525 = 3;
330     /** @hide */
331     public static final int COLOR_MODE_BT601_525_UNADJUSTED = 4;
332     /** @hide */
333     public static final int COLOR_MODE_BT709 = 5;
334     /** @hide */
335     public static final int COLOR_MODE_DCI_P3 = 6;
336     /** @hide */
337     public static final int COLOR_MODE_SRGB = 7;
338     /** @hide */
339     public static final int COLOR_MODE_ADOBE_RGB = 8;
340     /** @hide */
341     public static final int COLOR_MODE_DISPLAY_P3 = 9;
342 
343     /**
344      * Indicates that when display is removed, all its activities will be moved to the primary
345      * display and the topmost activity should become focused.
346      *
347      * @hide
348      */
349     public static final int REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY = 0;
350     /**
351      * Indicates that when display is removed, all its stacks and tasks will be removed, all
352      * activities will be destroyed according to the usual lifecycle.
353      *
354      * @hide
355      */
356     public static final int REMOVE_MODE_DESTROY_CONTENT = 1;
357 
358     /**
359      * Internal method to create a display.
360      * The display created with this method will have a static {@link DisplayAdjustments} applied.
361      * Applications should use {@link android.view.WindowManager#getDefaultDisplay()}
362      * or {@link android.hardware.display.DisplayManager#getDisplay}
363      * to get a display object.
364      *
365      * @hide
366      */
Display(DisplayManagerGlobal global, int displayId, DisplayInfo displayInfo, DisplayAdjustments daj)367     public Display(DisplayManagerGlobal global, int displayId, /*@NotNull*/ DisplayInfo displayInfo,
368             DisplayAdjustments daj) {
369         this(global, displayId, displayInfo, daj, null /*res*/);
370     }
371 
372     /**
373      * Internal method to create a display.
374      * The display created with this method will be adjusted based on the adjustments in the
375      * supplied {@link Resources}.
376      *
377      * @hide
378      */
Display(DisplayManagerGlobal global, int displayId, DisplayInfo displayInfo, Resources res)379     public Display(DisplayManagerGlobal global, int displayId, /*@NotNull*/ DisplayInfo displayInfo,
380             Resources res) {
381         this(global, displayId, displayInfo, null /*daj*/, res);
382     }
383 
Display(DisplayManagerGlobal global, int displayId, DisplayInfo displayInfo, DisplayAdjustments daj, Resources res)384     private Display(DisplayManagerGlobal global, int displayId,
385             /*@NotNull*/ DisplayInfo displayInfo, DisplayAdjustments daj, Resources res) {
386         mGlobal = global;
387         mDisplayId = displayId;
388         mDisplayInfo = displayInfo;
389         mResources = res;
390         mDisplayAdjustments = mResources != null
391             ? new DisplayAdjustments(mResources.getConfiguration())
392             : daj != null ? new DisplayAdjustments(daj) : null;
393         mIsValid = true;
394 
395         // Cache properties that cannot change as long as the display is valid.
396         mLayerStack = displayInfo.layerStack;
397         mFlags = displayInfo.flags;
398         mType = displayInfo.type;
399         mAddress = displayInfo.address;
400         mOwnerUid = displayInfo.ownerUid;
401         mOwnerPackageName = displayInfo.ownerPackageName;
402     }
403 
404     /**
405      * Gets the display id.
406      * <p>
407      * Each logical display has a unique id.
408      * The default display has id {@link #DEFAULT_DISPLAY}.
409      * </p>
410      */
getDisplayId()411     public int getDisplayId() {
412         return mDisplayId;
413     }
414 
415     /**
416      * Returns true if this display is still valid, false if the display has been removed.
417      *
418      * If the display is invalid, then the methods of this class will
419      * continue to report the most recently observed display information.
420      * However, it is unwise (and rather fruitless) to continue using a
421      * {@link Display} object after the display's demise.
422      *
423      * It's possible for a display that was previously invalid to become
424      * valid again if a display with the same id is reconnected.
425      *
426      * @return True if the display is still valid.
427      */
isValid()428     public boolean isValid() {
429         synchronized (this) {
430             updateDisplayInfoLocked();
431             return mIsValid;
432         }
433     }
434 
435     /**
436      * Gets a full copy of the display information.
437      *
438      * @param outDisplayInfo The object to receive the copy of the display information.
439      * @return True if the display is still valid.
440      * @hide
441      */
getDisplayInfo(DisplayInfo outDisplayInfo)442     public boolean getDisplayInfo(DisplayInfo outDisplayInfo) {
443         synchronized (this) {
444             updateDisplayInfoLocked();
445             outDisplayInfo.copyFrom(mDisplayInfo);
446             return mIsValid;
447         }
448     }
449 
450     /**
451      * Gets the display's layer stack.
452      *
453      * Each display has its own independent layer stack upon which surfaces
454      * are placed to be managed by surface flinger.
455      *
456      * @return The display's layer stack number.
457      * @hide
458      */
getLayerStack()459     public int getLayerStack() {
460         return mLayerStack;
461     }
462 
463     /**
464      * Returns a combination of flags that describe the capabilities of the display.
465      *
466      * @return The display flags.
467      *
468      * @see #FLAG_SUPPORTS_PROTECTED_BUFFERS
469      * @see #FLAG_SECURE
470      * @see #FLAG_PRIVATE
471      */
getFlags()472     public int getFlags() {
473         return mFlags;
474     }
475 
476     /**
477      * Gets the display type.
478      *
479      * @return The display type.
480      *
481      * @see #TYPE_UNKNOWN
482      * @see #TYPE_BUILT_IN
483      * @see #TYPE_HDMI
484      * @see #TYPE_WIFI
485      * @see #TYPE_OVERLAY
486      * @see #TYPE_VIRTUAL
487      * @hide
488      */
getType()489     public int getType() {
490         return mType;
491     }
492 
493     /**
494      * Gets the display address, or null if none.
495      * Interpretation varies by display type.
496      *
497      * @return The display address.
498      * @hide
499      */
getAddress()500     public String getAddress() {
501         return mAddress;
502     }
503 
504     /**
505      * Gets the UID of the application that owns this display, or zero if it is
506      * owned by the system.
507      * <p>
508      * If the display is private, then only the owner can use it.
509      * </p>
510      *
511      * @hide
512      */
getOwnerUid()513     public int getOwnerUid() {
514         return mOwnerUid;
515     }
516 
517     /**
518      * Gets the package name of the application that owns this display, or null if it is
519      * owned by the system.
520      * <p>
521      * If the display is private, then only the owner can use it.
522      * </p>
523      *
524      * @hide
525      */
getOwnerPackageName()526     public String getOwnerPackageName() {
527         return mOwnerPackageName;
528     }
529 
530     /**
531      * Gets the compatibility info used by this display instance.
532      *
533      * @return The display adjustments holder, or null if none is required.
534      * @hide
535      */
getDisplayAdjustments()536     public DisplayAdjustments getDisplayAdjustments() {
537         if (mResources != null) {
538             final DisplayAdjustments currentAdjustements = mResources.getDisplayAdjustments();
539             if (!mDisplayAdjustments.equals(currentAdjustements)) {
540                 mDisplayAdjustments = new DisplayAdjustments(currentAdjustements);
541             }
542         }
543 
544         return mDisplayAdjustments;
545     }
546 
547     /**
548      * Gets the name of the display.
549      * <p>
550      * Note that some displays may be renamed by the user.
551      * </p>
552      *
553      * @return The display's name.
554      */
getName()555     public String getName() {
556         synchronized (this) {
557             updateDisplayInfoLocked();
558             return mDisplayInfo.name;
559         }
560     }
561 
562     /**
563      * Gets the size of the display, in pixels.
564      * Value returned by this method does not necessarily represent the actual raw size
565      * (native resolution) of the display.
566      * <p>
567      * 1. The returned size may be adjusted to exclude certain system decor elements
568      * that are always visible.
569      * </p><p>
570      * 2. It may be scaled to provide compatibility with older applications that
571      * were originally designed for smaller displays.
572      * </p><p>
573      * 3. It can be different depending on the WindowManager to which the display belongs.
574      * </p><p>
575      * - If requested from non-Activity context (e.g. Application context via
576      * {@code (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE)})
577      * it will report the size of the entire display based on current rotation and with subtracted
578      * system decoration areas.
579      * </p><p>
580      * - If requested from activity (either using {@code getWindowManager()} or
581      * {@code (WindowManager) getSystemService(Context.WINDOW_SERVICE)}) resulting size will
582      * correspond to current app window size. In this case it can be smaller than physical size in
583      * multi-window mode.
584      * </p><p>
585      * Typically for the purposes of layout apps should make a request from activity context
586      * to obtain size available for the app content.
587      * </p>
588      *
589      * @param outSize A {@link Point} object to receive the size information.
590      */
getSize(Point outSize)591     public void getSize(Point outSize) {
592         synchronized (this) {
593             updateDisplayInfoLocked();
594             mDisplayInfo.getAppMetrics(mTempMetrics, getDisplayAdjustments());
595             outSize.x = mTempMetrics.widthPixels;
596             outSize.y = mTempMetrics.heightPixels;
597         }
598     }
599 
600     /**
601      * Gets the size of the display as a rectangle, in pixels.
602      *
603      * @param outSize A {@link Rect} object to receive the size information.
604      * @see #getSize(Point)
605      */
getRectSize(Rect outSize)606     public void getRectSize(Rect outSize) {
607         synchronized (this) {
608             updateDisplayInfoLocked();
609             mDisplayInfo.getAppMetrics(mTempMetrics, getDisplayAdjustments());
610             outSize.set(0, 0, mTempMetrics.widthPixels, mTempMetrics.heightPixels);
611         }
612     }
613 
614     /**
615      * Return the range of display sizes an application can expect to encounter
616      * under normal operation, as long as there is no physical change in screen
617      * size.  This is basically the sizes you will see as the orientation
618      * changes, taking into account whatever screen decoration there is in
619      * each rotation.  For example, the status bar is always at the top of the
620      * screen, so it will reduce the height both in landscape and portrait, and
621      * the smallest height returned here will be the smaller of the two.
622      *
623      * This is intended for applications to get an idea of the range of sizes
624      * they will encounter while going through device rotations, to provide a
625      * stable UI through rotation.  The sizes here take into account all standard
626      * system decorations that reduce the size actually available to the
627      * application: the status bar, navigation bar, system bar, etc.  It does
628      * <em>not</em> take into account more transient elements like an IME
629      * soft keyboard.
630      *
631      * @param outSmallestSize Filled in with the smallest width and height
632      * that the application will encounter, in pixels (not dp units).  The x
633      * (width) dimension here directly corresponds to
634      * {@link android.content.res.Configuration#smallestScreenWidthDp
635      * Configuration.smallestScreenWidthDp}, except the value here is in raw
636      * screen pixels rather than dp units.  Your application may of course
637      * still get smaller space yet if, for example, a soft keyboard is
638      * being displayed.
639      * @param outLargestSize Filled in with the largest width and height
640      * that the application will encounter, in pixels (not dp units).  Your
641      * application may of course still get larger space than this if,
642      * for example, screen decorations like the status bar are being hidden.
643      */
getCurrentSizeRange(Point outSmallestSize, Point outLargestSize)644     public void getCurrentSizeRange(Point outSmallestSize, Point outLargestSize) {
645         synchronized (this) {
646             updateDisplayInfoLocked();
647             outSmallestSize.x = mDisplayInfo.smallestNominalAppWidth;
648             outSmallestSize.y = mDisplayInfo.smallestNominalAppHeight;
649             outLargestSize.x = mDisplayInfo.largestNominalAppWidth;
650             outLargestSize.y = mDisplayInfo.largestNominalAppHeight;
651         }
652     }
653 
654     /**
655      * Return the maximum screen size dimension that will happen.  This is
656      * mostly for wallpapers.
657      * @hide
658      */
getMaximumSizeDimension()659     public int getMaximumSizeDimension() {
660         synchronized (this) {
661             updateDisplayInfoLocked();
662             return Math.max(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
663         }
664     }
665 
666     /**
667      * @deprecated Use {@link #getSize(Point)} instead.
668      */
669     @Deprecated
getWidth()670     public int getWidth() {
671         synchronized (this) {
672             updateCachedAppSizeIfNeededLocked();
673             return mCachedAppWidthCompat;
674         }
675     }
676 
677     /**
678      * @deprecated Use {@link #getSize(Point)} instead.
679      */
680     @Deprecated
getHeight()681     public int getHeight() {
682         synchronized (this) {
683             updateCachedAppSizeIfNeededLocked();
684             return mCachedAppHeightCompat;
685         }
686     }
687 
688     /**
689      * @hide
690      * Return a rectangle defining the insets of the overscan region of the display.
691      * Each field of the rectangle is the number of pixels the overscan area extends
692      * into the display on that side.
693      */
getOverscanInsets(Rect outRect)694     public void getOverscanInsets(Rect outRect) {
695         synchronized (this) {
696             updateDisplayInfoLocked();
697             outRect.set(mDisplayInfo.overscanLeft, mDisplayInfo.overscanTop,
698                     mDisplayInfo.overscanRight, mDisplayInfo.overscanBottom);
699         }
700     }
701 
702     /**
703      * Returns the rotation of the screen from its "natural" orientation.
704      * The returned value may be {@link Surface#ROTATION_0 Surface.ROTATION_0}
705      * (no rotation), {@link Surface#ROTATION_90 Surface.ROTATION_90},
706      * {@link Surface#ROTATION_180 Surface.ROTATION_180}, or
707      * {@link Surface#ROTATION_270 Surface.ROTATION_270}.  For
708      * example, if a device has a naturally tall screen, and the user has
709      * turned it on its side to go into a landscape orientation, the value
710      * returned here may be either {@link Surface#ROTATION_90 Surface.ROTATION_90}
711      * or {@link Surface#ROTATION_270 Surface.ROTATION_270} depending on
712      * the direction it was turned.  The angle is the rotation of the drawn
713      * graphics on the screen, which is the opposite direction of the physical
714      * rotation of the device.  For example, if the device is rotated 90
715      * degrees counter-clockwise, to compensate rendering will be rotated by
716      * 90 degrees clockwise and thus the returned value here will be
717      * {@link Surface#ROTATION_90 Surface.ROTATION_90}.
718      */
719     @Surface.Rotation
getRotation()720     public int getRotation() {
721         synchronized (this) {
722             updateDisplayInfoLocked();
723             return mDisplayInfo.rotation;
724         }
725     }
726 
727     /**
728      * @deprecated use {@link #getRotation}
729      * @return orientation of this display.
730      */
731     @Deprecated
732     @Surface.Rotation
getOrientation()733     public int getOrientation() {
734         return getRotation();
735     }
736 
737     /**
738      * Gets the pixel format of the display.
739      * @return One of the constants defined in {@link android.graphics.PixelFormat}.
740      *
741      * @deprecated This method is no longer supported.
742      * The result is always {@link PixelFormat#RGBA_8888}.
743      */
744     @Deprecated
getPixelFormat()745     public int getPixelFormat() {
746         return PixelFormat.RGBA_8888;
747     }
748 
749     /**
750      * Gets the refresh rate of this display in frames per second.
751      */
getRefreshRate()752     public float getRefreshRate() {
753         synchronized (this) {
754             updateDisplayInfoLocked();
755             return mDisplayInfo.getMode().getRefreshRate();
756         }
757     }
758 
759     /**
760      * Get the supported refresh rates of this display in frames per second.
761      * <p>
762      * This method only returns refresh rates for the display's default modes. For more options, use
763      * {@link #getSupportedModes()}.
764      *
765      * @deprecated use {@link #getSupportedModes()} instead
766      */
767     @Deprecated
getSupportedRefreshRates()768     public float[] getSupportedRefreshRates() {
769         synchronized (this) {
770             updateDisplayInfoLocked();
771             return mDisplayInfo.getDefaultRefreshRates();
772         }
773     }
774 
775     /**
776      * Returns the active mode of the display.
777      */
getMode()778     public Mode getMode() {
779         synchronized (this) {
780             updateDisplayInfoLocked();
781             return mDisplayInfo.getMode();
782         }
783     }
784 
785     /**
786      * Gets the supported modes of this display.
787      */
getSupportedModes()788     public Mode[] getSupportedModes() {
789         synchronized (this) {
790             updateDisplayInfoLocked();
791             final Display.Mode[] modes = mDisplayInfo.supportedModes;
792             return Arrays.copyOf(modes, modes.length);
793         }
794     }
795 
796     /**
797      * Request the display applies a color mode.
798      * @hide
799      */
800     @RequiresPermission(CONFIGURE_DISPLAY_COLOR_MODE)
requestColorMode(int colorMode)801     public void requestColorMode(int colorMode) {
802         mGlobal.requestColorMode(mDisplayId, colorMode);
803     }
804 
805     /**
806      * Returns the active color mode of this display
807      * @hide
808      */
getColorMode()809     public int getColorMode() {
810         synchronized (this) {
811             updateDisplayInfoLocked();
812             return mDisplayInfo.colorMode;
813         }
814     }
815 
816     /**
817      * @hide
818      * Get current remove mode of the display - what actions should be performed with the display's
819      * content when it is removed. Default behavior for public displays in this case is to move all
820      * activities to the primary display and make it focused. For private display - destroy all
821      * activities.
822      *
823      * @see #REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY
824      * @see #REMOVE_MODE_DESTROY_CONTENT
825      */
getRemoveMode()826     public int getRemoveMode() {
827         return mDisplayInfo.removeMode;
828     }
829 
830     /**
831      * Returns the display's HDR capabilities.
832      *
833      * @see #isHdr()
834      */
getHdrCapabilities()835     public HdrCapabilities getHdrCapabilities() {
836         synchronized (this) {
837             updateDisplayInfoLocked();
838             return mDisplayInfo.hdrCapabilities;
839         }
840     }
841 
842     /**
843      * Returns whether this display supports any HDR type.
844      *
845      * @see #getHdrCapabilities()
846      * @see HdrCapabilities#getSupportedHdrTypes()
847      */
isHdr()848     public boolean isHdr() {
849         synchronized (this) {
850             updateDisplayInfoLocked();
851             return mDisplayInfo.isHdr();
852         }
853     }
854 
855     /**
856      * Returns whether this display can be used to display wide color gamut content.
857      */
isWideColorGamut()858     public boolean isWideColorGamut() {
859         synchronized (this) {
860             updateDisplayInfoLocked();
861             return mDisplayInfo.isWideColorGamut();
862         }
863     }
864 
865     /**
866      * Gets the supported color modes of this device.
867      * @hide
868      */
getSupportedColorModes()869     public int[] getSupportedColorModes() {
870         synchronized (this) {
871             updateDisplayInfoLocked();
872             int[] colorModes = mDisplayInfo.supportedColorModes;
873             return Arrays.copyOf(colorModes, colorModes.length);
874         }
875     }
876 
877     /**
878      * Gets the app VSYNC offset, in nanoseconds.  This is a positive value indicating
879      * the phase offset of the VSYNC events provided by Choreographer relative to the
880      * display refresh.  For example, if Choreographer reports that the refresh occurred
881      * at time N, it actually occurred at (N - appVsyncOffset).
882      * <p>
883      * Apps generally do not need to be aware of this.  It's only useful for fine-grained
884      * A/V synchronization.
885      */
getAppVsyncOffsetNanos()886     public long getAppVsyncOffsetNanos() {
887         synchronized (this) {
888             updateDisplayInfoLocked();
889             return mDisplayInfo.appVsyncOffsetNanos;
890         }
891     }
892 
893     /**
894      * This is how far in advance a buffer must be queued for presentation at
895      * a given time.  If you want a buffer to appear on the screen at
896      * time N, you must submit the buffer before (N - presentationDeadline).
897      * <p>
898      * The desired presentation time for GLES rendering may be set with
899      * {@link android.opengl.EGLExt#eglPresentationTimeANDROID}.  For video decoding, use
900      * {@link android.media.MediaCodec#releaseOutputBuffer(int, long)}.  Times are
901      * expressed in nanoseconds, using the system monotonic clock
902      * ({@link System#nanoTime}).
903      */
getPresentationDeadlineNanos()904     public long getPresentationDeadlineNanos() {
905         synchronized (this) {
906             updateDisplayInfoLocked();
907             return mDisplayInfo.presentationDeadlineNanos;
908         }
909     }
910 
911     /**
912      * Gets display metrics that describe the size and density of this display.
913      * The size returned by this method does not necessarily represent the
914      * actual raw size (native resolution) of the display.
915      * <p>
916      * 1. The returned size may be adjusted to exclude certain system decor elements
917      * that are always visible.
918      * </p><p>
919      * 2. It may be scaled to provide compatibility with older applications that
920      * were originally designed for smaller displays.
921      * </p><p>
922      * 3. It can be different depending on the WindowManager to which the display belongs.
923      * </p><p>
924      * - If requested from non-Activity context (e.g. Application context via
925      * {@code (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE)})
926      * metrics will report the size of the entire display based on current rotation and with
927      * subtracted system decoration areas.
928      * </p><p>
929      * - If requested from activity (either using {@code getWindowManager()} or
930      * {@code (WindowManager) getSystemService(Context.WINDOW_SERVICE)}) resulting metrics will
931      * correspond to current app window metrics. In this case the size can be smaller than physical
932      * size in multi-window mode.
933      * </p>
934      *
935      * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
936      */
getMetrics(DisplayMetrics outMetrics)937     public void getMetrics(DisplayMetrics outMetrics) {
938         synchronized (this) {
939             updateDisplayInfoLocked();
940             mDisplayInfo.getAppMetrics(outMetrics, getDisplayAdjustments());
941         }
942     }
943 
944     /**
945      * Gets the real size of the display without subtracting any window decor or
946      * applying any compatibility scale factors.
947      * <p>
948      * The size is adjusted based on the current rotation of the display.
949      * </p><p>
950      * The real size may be smaller than the physical size of the screen when the
951      * window manager is emulating a smaller display (using adb shell wm size).
952      * </p>
953      *
954      * @param outSize Set to the real size of the display.
955      */
getRealSize(Point outSize)956     public void getRealSize(Point outSize) {
957         synchronized (this) {
958             updateDisplayInfoLocked();
959             outSize.x = mDisplayInfo.logicalWidth;
960             outSize.y = mDisplayInfo.logicalHeight;
961         }
962     }
963 
964     /**
965      * Gets display metrics based on the real size of this display.
966      * <p>
967      * The size is adjusted based on the current rotation of the display.
968      * </p><p>
969      * The real size may be smaller than the physical size of the screen when the
970      * window manager is emulating a smaller display (using adb shell wm size).
971      * </p>
972      *
973      * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
974      */
getRealMetrics(DisplayMetrics outMetrics)975     public void getRealMetrics(DisplayMetrics outMetrics) {
976         synchronized (this) {
977             updateDisplayInfoLocked();
978             mDisplayInfo.getLogicalMetrics(outMetrics,
979                     CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
980         }
981     }
982 
983     /**
984      * Gets the state of the display, such as whether it is on or off.
985      *
986      * @return The state of the display: one of {@link #STATE_OFF}, {@link #STATE_ON},
987      * {@link #STATE_DOZE}, {@link #STATE_DOZE_SUSPEND}, or
988      * {@link #STATE_UNKNOWN}.
989      */
getState()990     public int getState() {
991         synchronized (this) {
992             updateDisplayInfoLocked();
993             return mIsValid ? mDisplayInfo.state : STATE_UNKNOWN;
994         }
995     }
996 
997     /**
998      * Returns true if the specified UID has access to this display.
999      * @hide
1000      */
hasAccess(int uid)1001     public boolean hasAccess(int uid) {
1002         return Display.hasAccess(uid, mFlags, mOwnerUid);
1003     }
1004 
1005     /** @hide */
hasAccess(int uid, int flags, int ownerUid)1006     public static boolean hasAccess(int uid, int flags, int ownerUid) {
1007         return (flags & Display.FLAG_PRIVATE) == 0
1008                 || uid == ownerUid
1009                 || uid == Process.SYSTEM_UID
1010                 || uid == 0;
1011     }
1012 
1013     /**
1014      * Returns true if the display is a public presentation display.
1015      * @hide
1016      */
isPublicPresentation()1017     public boolean isPublicPresentation() {
1018         return (mFlags & (Display.FLAG_PRIVATE | Display.FLAG_PRESENTATION)) ==
1019                 Display.FLAG_PRESENTATION;
1020     }
1021 
updateDisplayInfoLocked()1022     private void updateDisplayInfoLocked() {
1023         // Note: The display manager caches display info objects on our behalf.
1024         DisplayInfo newInfo = mGlobal.getDisplayInfo(mDisplayId);
1025         if (newInfo == null) {
1026             // Preserve the old mDisplayInfo after the display is removed.
1027             if (mIsValid) {
1028                 mIsValid = false;
1029                 if (DEBUG) {
1030                     Log.d(TAG, "Logical display " + mDisplayId + " was removed.");
1031                 }
1032             }
1033         } else {
1034             // Use the new display info.  (It might be the same object if nothing changed.)
1035             mDisplayInfo = newInfo;
1036             if (!mIsValid) {
1037                 mIsValid = true;
1038                 if (DEBUG) {
1039                     Log.d(TAG, "Logical display " + mDisplayId + " was recreated.");
1040                 }
1041             }
1042         }
1043     }
1044 
updateCachedAppSizeIfNeededLocked()1045     private void updateCachedAppSizeIfNeededLocked() {
1046         long now = SystemClock.uptimeMillis();
1047         if (now > mLastCachedAppSizeUpdate + CACHED_APP_SIZE_DURATION_MILLIS) {
1048             updateDisplayInfoLocked();
1049             mDisplayInfo.getAppMetrics(mTempMetrics, getDisplayAdjustments());
1050             mCachedAppWidthCompat = mTempMetrics.widthPixels;
1051             mCachedAppHeightCompat = mTempMetrics.heightPixels;
1052             mLastCachedAppSizeUpdate = now;
1053         }
1054     }
1055 
1056     // For debugging purposes
1057     @Override
toString()1058     public String toString() {
1059         synchronized (this) {
1060             updateDisplayInfoLocked();
1061             mDisplayInfo.getAppMetrics(mTempMetrics, getDisplayAdjustments());
1062             return "Display id " + mDisplayId + ": " + mDisplayInfo
1063                     + ", " + mTempMetrics + ", isValid=" + mIsValid;
1064         }
1065     }
1066 
1067     /**
1068      * @hide
1069      */
typeToString(int type)1070     public static String typeToString(int type) {
1071         switch (type) {
1072             case TYPE_UNKNOWN:
1073                 return "UNKNOWN";
1074             case TYPE_BUILT_IN:
1075                 return "BUILT_IN";
1076             case TYPE_HDMI:
1077                 return "HDMI";
1078             case TYPE_WIFI:
1079                 return "WIFI";
1080             case TYPE_OVERLAY:
1081                 return "OVERLAY";
1082             case TYPE_VIRTUAL:
1083                 return "VIRTUAL";
1084             default:
1085                 return Integer.toString(type);
1086         }
1087     }
1088 
1089     /**
1090      * @hide
1091      */
stateToString(int state)1092     public static String stateToString(int state) {
1093         switch (state) {
1094             case STATE_UNKNOWN:
1095                 return "UNKNOWN";
1096             case STATE_OFF:
1097                 return "OFF";
1098             case STATE_ON:
1099                 return "ON";
1100             case STATE_DOZE:
1101                 return "DOZE";
1102             case STATE_DOZE_SUSPEND:
1103                 return "DOZE_SUSPEND";
1104             case STATE_VR:
1105                 return "VR";
1106             default:
1107                 return Integer.toString(state);
1108         }
1109     }
1110 
1111     /**
1112      * Returns true if display updates may be suspended while in the specified
1113      * display power state.
1114      * @hide
1115      */
isSuspendedState(int state)1116     public static boolean isSuspendedState(int state) {
1117         return state == STATE_OFF || state == STATE_DOZE_SUSPEND;
1118     }
1119 
1120     /**
1121      * A mode supported by a given display.
1122      *
1123      * @see Display#getSupportedModes()
1124      */
1125     public static final class Mode implements Parcelable {
1126         /**
1127          * @hide
1128          */
1129         public static final Mode[] EMPTY_ARRAY = new Mode[0];
1130 
1131         private final int mModeId;
1132         private final int mWidth;
1133         private final int mHeight;
1134         private final float mRefreshRate;
1135 
1136         /**
1137          * @hide
1138          */
Mode(int modeId, int width, int height, float refreshRate)1139         public Mode(int modeId, int width, int height, float refreshRate) {
1140             mModeId = modeId;
1141             mWidth = width;
1142             mHeight = height;
1143             mRefreshRate = refreshRate;
1144         }
1145 
1146         /**
1147          * Returns this mode's id.
1148          */
getModeId()1149         public int getModeId() {
1150             return mModeId;
1151         }
1152 
1153         /**
1154          * Returns the physical width of the display in pixels when configured in this mode's
1155          * resolution.
1156          * <p>
1157          * Note that due to application UI scaling, the number of pixels made available to
1158          * applications when the mode is active (as reported by {@link Display#getWidth()} may
1159          * differ from the mode's actual resolution (as reported by this function).
1160          * <p>
1161          * For example, applications running on a 4K display may have their UI laid out and rendered
1162          * in 1080p and then scaled up. Applications can take advantage of the extra resolution by
1163          * rendering content through a {@link android.view.SurfaceView} using full size buffers.
1164          */
getPhysicalWidth()1165         public int getPhysicalWidth() {
1166             return mWidth;
1167         }
1168 
1169         /**
1170          * Returns the physical height of the display in pixels when configured in this mode's
1171          * resolution.
1172          * <p>
1173          * Note that due to application UI scaling, the number of pixels made available to
1174          * applications when the mode is active (as reported by {@link Display#getHeight()} may
1175          * differ from the mode's actual resolution (as reported by this function).
1176          * <p>
1177          * For example, applications running on a 4K display may have their UI laid out and rendered
1178          * in 1080p and then scaled up. Applications can take advantage of the extra resolution by
1179          * rendering content through a {@link android.view.SurfaceView} using full size buffers.
1180          */
getPhysicalHeight()1181         public int getPhysicalHeight() {
1182             return mHeight;
1183         }
1184 
1185         /**
1186          * Returns the refresh rate in frames per second.
1187          */
getRefreshRate()1188         public float getRefreshRate() {
1189             return mRefreshRate;
1190         }
1191 
1192         /**
1193          * Returns {@code true} if this mode matches the given parameters.
1194          *
1195          * @hide
1196          */
matches(int width, int height, float refreshRate)1197         public boolean matches(int width, int height, float refreshRate) {
1198             return mWidth == width &&
1199                     mHeight == height &&
1200                     Float.floatToIntBits(mRefreshRate) == Float.floatToIntBits(refreshRate);
1201         }
1202 
1203         @Override
equals(Object other)1204         public boolean equals(Object other) {
1205             if (this == other) {
1206                 return true;
1207             }
1208             if (!(other instanceof Mode)) {
1209                 return false;
1210             }
1211             Mode that = (Mode) other;
1212             return mModeId == that.mModeId && matches(that.mWidth, that.mHeight, that.mRefreshRate);
1213         }
1214 
1215         @Override
hashCode()1216         public int hashCode() {
1217             int hash = 1;
1218             hash = hash * 17 + mModeId;
1219             hash = hash * 17 + mWidth;
1220             hash = hash * 17 + mHeight;
1221             hash = hash * 17 + Float.floatToIntBits(mRefreshRate);
1222             return hash;
1223         }
1224 
1225         @Override
toString()1226         public String toString() {
1227             return new StringBuilder("{")
1228                     .append("id=").append(mModeId)
1229                     .append(", width=").append(mWidth)
1230                     .append(", height=").append(mHeight)
1231                     .append(", fps=").append(mRefreshRate)
1232                     .append("}")
1233                     .toString();
1234         }
1235 
1236         @Override
describeContents()1237         public int describeContents() {
1238             return 0;
1239         }
1240 
Mode(Parcel in)1241         private Mode(Parcel in) {
1242             this(in.readInt(), in.readInt(), in.readInt(), in.readFloat());
1243         }
1244 
1245         @Override
writeToParcel(Parcel out, int parcelableFlags)1246         public void writeToParcel(Parcel out, int parcelableFlags) {
1247             out.writeInt(mModeId);
1248             out.writeInt(mWidth);
1249             out.writeInt(mHeight);
1250             out.writeFloat(mRefreshRate);
1251         }
1252 
1253         @SuppressWarnings("hiding")
1254         public static final Parcelable.Creator<Mode> CREATOR
1255                 = new Parcelable.Creator<Mode>() {
1256             @Override
1257             public Mode createFromParcel(Parcel in) {
1258                 return new Mode(in);
1259             }
1260 
1261             @Override
1262             public Mode[] newArray(int size) {
1263                 return new Mode[size];
1264             }
1265         };
1266     }
1267 
1268     /**
1269      * Encapsulates the HDR capabilities of a given display.
1270      * For example, what HDR types it supports and details about the desired luminance data.
1271      * <p>You can get an instance for a given {@link Display} object with
1272      * {@link Display#getHdrCapabilities getHdrCapabilities()}.
1273      */
1274     public static final class HdrCapabilities implements Parcelable {
1275         /**
1276          * Invalid luminance value.
1277          */
1278         public static final float INVALID_LUMINANCE = -1;
1279         /**
1280          * Dolby Vision high dynamic range (HDR) display.
1281          */
1282         public static final int HDR_TYPE_DOLBY_VISION = 1;
1283         /**
1284          * HDR10 display.
1285          */
1286         public static final int HDR_TYPE_HDR10 = 2;
1287         /**
1288          * Hybrid Log-Gamma HDR display.
1289          */
1290         public static final int HDR_TYPE_HLG = 3;
1291 
1292         /** @hide */
1293         @IntDef({
1294             HDR_TYPE_DOLBY_VISION,
1295             HDR_TYPE_HDR10,
1296             HDR_TYPE_HLG,
1297         })
1298         @Retention(RetentionPolicy.SOURCE)
1299         public @interface HdrType {}
1300 
1301         private @HdrType int[] mSupportedHdrTypes = new int[0];
1302         private float mMaxLuminance = INVALID_LUMINANCE;
1303         private float mMaxAverageLuminance = INVALID_LUMINANCE;
1304         private float mMinLuminance = INVALID_LUMINANCE;
1305 
1306         /**
1307          * @hide
1308          */
HdrCapabilities()1309         public HdrCapabilities() {
1310         }
1311 
1312         /**
1313          * @hide
1314          */
HdrCapabilities(int[] supportedHdrTypes, float maxLuminance, float maxAverageLuminance, float minLuminance)1315         public HdrCapabilities(int[] supportedHdrTypes, float maxLuminance,
1316                 float maxAverageLuminance, float minLuminance) {
1317             mSupportedHdrTypes = supportedHdrTypes;
1318             mMaxLuminance = maxLuminance;
1319             mMaxAverageLuminance = maxAverageLuminance;
1320             mMinLuminance = minLuminance;
1321         }
1322 
1323         /**
1324          * Gets the supported HDR types of this display.
1325          * Returns empty array if HDR is not supported by the display.
1326          */
getSupportedHdrTypes()1327         public @HdrType int[] getSupportedHdrTypes() {
1328             return mSupportedHdrTypes;
1329         }
1330         /**
1331          * Returns the desired content max luminance data in cd/m2 for this display.
1332          */
getDesiredMaxLuminance()1333         public float getDesiredMaxLuminance() {
1334             return mMaxLuminance;
1335         }
1336         /**
1337          * Returns the desired content max frame-average luminance data in cd/m2 for this display.
1338          */
getDesiredMaxAverageLuminance()1339         public float getDesiredMaxAverageLuminance() {
1340             return mMaxAverageLuminance;
1341         }
1342         /**
1343          * Returns the desired content min luminance data in cd/m2 for this display.
1344          */
getDesiredMinLuminance()1345         public float getDesiredMinLuminance() {
1346             return mMinLuminance;
1347         }
1348 
1349         @Override
equals(Object other)1350         public boolean equals(Object other) {
1351             if (this == other) {
1352                 return true;
1353             }
1354 
1355             if (!(other instanceof HdrCapabilities)) {
1356                 return false;
1357             }
1358             HdrCapabilities that = (HdrCapabilities) other;
1359 
1360             return Arrays.equals(mSupportedHdrTypes, that.mSupportedHdrTypes)
1361                 && mMaxLuminance == that.mMaxLuminance
1362                 && mMaxAverageLuminance == that.mMaxAverageLuminance
1363                 && mMinLuminance == that.mMinLuminance;
1364         }
1365 
1366         @Override
hashCode()1367         public int hashCode() {
1368             int hash = 23;
1369             hash = hash * 17 + Arrays.hashCode(mSupportedHdrTypes);
1370             hash = hash * 17 + Float.floatToIntBits(mMaxLuminance);
1371             hash = hash * 17 + Float.floatToIntBits(mMaxAverageLuminance);
1372             hash = hash * 17 + Float.floatToIntBits(mMinLuminance);
1373             return hash;
1374         }
1375 
1376         public static final Creator<HdrCapabilities> CREATOR = new Creator<HdrCapabilities>() {
1377             @Override
1378             public HdrCapabilities createFromParcel(Parcel source) {
1379                 return new HdrCapabilities(source);
1380             }
1381 
1382             @Override
1383             public HdrCapabilities[] newArray(int size) {
1384                 return new HdrCapabilities[size];
1385             }
1386         };
1387 
HdrCapabilities(Parcel source)1388         private HdrCapabilities(Parcel source) {
1389             readFromParcel(source);
1390         }
1391 
1392         /**
1393          * @hide
1394          */
readFromParcel(Parcel source)1395         public void readFromParcel(Parcel source) {
1396             int types = source.readInt();
1397             mSupportedHdrTypes = new int[types];
1398             for (int i = 0; i < types; ++i) {
1399                 mSupportedHdrTypes[i] = source.readInt();
1400             }
1401             mMaxLuminance = source.readFloat();
1402             mMaxAverageLuminance = source.readFloat();
1403             mMinLuminance = source.readFloat();
1404         }
1405 
1406         @Override
writeToParcel(Parcel dest, int flags)1407         public void writeToParcel(Parcel dest, int flags) {
1408             dest.writeInt(mSupportedHdrTypes.length);
1409             for (int i = 0; i < mSupportedHdrTypes.length; ++i) {
1410                 dest.writeInt(mSupportedHdrTypes[i]);
1411             }
1412             dest.writeFloat(mMaxLuminance);
1413             dest.writeFloat(mMaxAverageLuminance);
1414             dest.writeFloat(mMinLuminance);
1415         }
1416 
1417         @Override
describeContents()1418         public int describeContents() {
1419             return 0;
1420         }
1421     }
1422 }
1423