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