Home | History | Annotate | Download | only in view
      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      */
    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      */
    379     public Display(DisplayManagerGlobal global, int displayId, /*@NotNull*/ DisplayInfo displayInfo,
    380             Resources res) {
    381         this(global, displayId, displayInfo, null /*daj*/, res);
    382     }
    383 
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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
    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
    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      */
    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
    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
    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
    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      */
    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
    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      */
    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      */
    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)
    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      */
    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      */
    826     public int getRemoveMode() {
    827         return mDisplayInfo.removeMode;
    828     }
    829 
    830     /**
    831      * Returns the display's HDR capabilities.
    832      *
    833      * @see #isHdr()
    834      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
   1001     public boolean hasAccess(int uid) {
   1002         return Display.hasAccess(uid, mFlags, mOwnerUid);
   1003     }
   1004 
   1005     /** @hide */
   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      */
   1017     public boolean isPublicPresentation() {
   1018         return (mFlags & (Display.FLAG_PRIVATE | Display.FLAG_PRESENTATION)) ==
   1019                 Display.FLAG_PRESENTATION;
   1020     }
   1021 
   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 
   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
   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      */
   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      */
   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      */
   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          */
   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          */
   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          */
   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          */
   1181         public int getPhysicalHeight() {
   1182             return mHeight;
   1183         }
   1184 
   1185         /**
   1186          * Returns the refresh rate in frames per second.
   1187          */
   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          */
   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
   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
   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
   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
   1237         public int describeContents() {
   1238             return 0;
   1239         }
   1240 
   1241         private Mode(Parcel in) {
   1242             this(in.readInt(), in.readInt(), in.readInt(), in.readFloat());
   1243         }
   1244 
   1245         @Override
   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          */
   1309         public HdrCapabilities() {
   1310         }
   1311 
   1312         /**
   1313          * @hide
   1314          */
   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          */
   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          */
   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          */
   1339         public float getDesiredMaxAverageLuminance() {
   1340             return mMaxAverageLuminance;
   1341         }
   1342         /**
   1343          * Returns the desired content min luminance data in cd/m2 for this display.
   1344          */
   1345         public float getDesiredMinLuminance() {
   1346             return mMinLuminance;
   1347         }
   1348 
   1349         @Override
   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
   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 
   1388         private HdrCapabilities(Parcel source) {
   1389             readFromParcel(source);
   1390         }
   1391 
   1392         /**
   1393          * @hide
   1394          */
   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
   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
   1418         public int describeContents() {
   1419             return 0;
   1420         }
   1421     }
   1422 }
   1423