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 android.content.res.CompatibilityInfo;
     20 import android.graphics.PixelFormat;
     21 import android.graphics.Point;
     22 import android.graphics.Rect;
     23 import android.hardware.display.DisplayManagerGlobal;
     24 import android.os.Parcel;
     25 import android.os.Parcelable;
     26 import android.os.Process;
     27 import android.os.SystemClock;
     28 import android.util.DisplayMetrics;
     29 import android.util.Log;
     30 
     31 import java.util.Arrays;
     32 
     33 /**
     34  * Provides information about the size and density of a logical display.
     35  * <p>
     36  * The display area is described in two different ways.
     37  * <ul>
     38  * <li>The application display area specifies the part of the display that may contain
     39  * an application window, excluding the system decorations.  The application display area may
     40  * be smaller than the real display area because the system subtracts the space needed
     41  * for decor elements such as the status bar.  Use the following methods to query the
     42  * application display area: {@link #getSize}, {@link #getRectSize} and {@link #getMetrics}.</li>
     43  * <li>The real display area specifies the part of the display that contains content
     44  * including the system decorations.  Even so, the real display area may be smaller than the
     45  * physical size of the display if the window manager is emulating a smaller display
     46  * using (adb shell am display-size).  Use the following methods to query the
     47  * real display area: {@link #getRealSize}, {@link #getRealMetrics}.</li>
     48  * </ul>
     49  * </p><p>
     50  * A logical display does not necessarily represent a particular physical display device
     51  * such as the built-in screen or an external monitor.  The contents of a logical
     52  * display may be presented on one or more physical displays according to the devices
     53  * that are currently attached and whether mirroring has been enabled.
     54  * </p>
     55  */
     56 public final class Display {
     57     private static final String TAG = "Display";
     58     private static final boolean DEBUG = false;
     59 
     60     private final DisplayManagerGlobal mGlobal;
     61     private final int mDisplayId;
     62     private final int mLayerStack;
     63     private final int mFlags;
     64     private final int mType;
     65     private final String mAddress;
     66     private final int mOwnerUid;
     67     private final String mOwnerPackageName;
     68     private final DisplayAdjustments mDisplayAdjustments;
     69 
     70     private DisplayInfo mDisplayInfo; // never null
     71     private boolean mIsValid;
     72 
     73     // Temporary display metrics structure used for compatibility mode.
     74     private final DisplayMetrics mTempMetrics = new DisplayMetrics();
     75 
     76     // We cache the app width and height properties briefly between calls
     77     // to getHeight() and getWidth() to ensure that applications perceive
     78     // consistent results when the size changes (most of the time).
     79     // Applications should now be using getSize() instead.
     80     private static final int CACHED_APP_SIZE_DURATION_MILLIS = 20;
     81     private long mLastCachedAppSizeUpdate;
     82     private int mCachedAppWidthCompat;
     83     private int mCachedAppHeightCompat;
     84 
     85     /**
     86      * The default Display id, which is the id of the built-in primary display
     87      * assuming there is one.
     88      */
     89     public static final int DEFAULT_DISPLAY = 0;
     90 
     91     /**
     92      * Invalid display id.
     93      */
     94     public static final int INVALID_DISPLAY = -1;
     95 
     96     /**
     97      * Display flag: Indicates that the display supports compositing content
     98      * that is stored in protected graphics buffers.
     99      * <p>
    100      * If this flag is set then the display device supports compositing protected buffers.
    101      * </p><p>
    102      * If this flag is not set then the display device may not support compositing
    103      * protected buffers; the user may see a blank region on the screen instead of
    104      * the protected content.
    105      * </p><p>
    106      * Secure (DRM) video decoders may allocate protected graphics buffers to request that
    107      * a hardware-protected path be provided between the video decoder and the external
    108      * display sink.  If a hardware-protected path is not available, then content stored
    109      * in protected graphics buffers may not be composited.
    110      * </p><p>
    111      * An application can use the absence of this flag as a hint that it should not use protected
    112      * buffers for this display because the content may not be visible.  For example,
    113      * if the flag is not set then the application may choose not to show content on this
    114      * display, show an informative error message, select an alternate content stream
    115      * or adopt a different strategy for decoding content that does not rely on
    116      * protected buffers.
    117      * </p>
    118      *
    119      * @see #getFlags
    120      */
    121     public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1 << 0;
    122 
    123     /**
    124      * Display flag: Indicates that the display has a secure video output and
    125      * supports compositing secure surfaces.
    126      * <p>
    127      * If this flag is set then the display device has a secure video output
    128      * and is capable of showing secure surfaces.  It may also be capable of
    129      * showing {@link #FLAG_SUPPORTS_PROTECTED_BUFFERS protected buffers}.
    130      * </p><p>
    131      * If this flag is not set then the display device may not have a secure video
    132      * output; the user may see a blank region on the screen instead of
    133      * the contents of secure surfaces or protected buffers.
    134      * </p><p>
    135      * Secure surfaces are used to prevent content rendered into those surfaces
    136      * by applications from appearing in screenshots or from being viewed
    137      * on non-secure displays.  Protected buffers are used by secure video decoders
    138      * for a similar purpose.
    139      * </p><p>
    140      * An application creates a window with a secure surface by specifying the
    141      * {@link WindowManager.LayoutParams#FLAG_SECURE} window flag.
    142      * Likewise, an application creates a {@link SurfaceView} with a secure surface
    143      * by calling {@link SurfaceView#setSecure} before attaching the secure view to
    144      * its containing window.
    145      * </p><p>
    146      * An application can use the absence of this flag as a hint that it should not create
    147      * secure surfaces or protected buffers on this display because the content may
    148      * not be visible.  For example, if the flag is not set then the application may
    149      * choose not to show content on this display, show an informative error message,
    150      * select an alternate content stream or adopt a different strategy for decoding
    151      * content that does not rely on secure surfaces or protected buffers.
    152      * </p>
    153      *
    154      * @see #getFlags
    155      */
    156     public static final int FLAG_SECURE = 1 << 1;
    157 
    158     /**
    159      * Display flag: Indicates that the display is private.  Only the application that
    160      * owns the display can create windows on it.
    161      *
    162      * @see #getFlags
    163      */
    164     public static final int FLAG_PRIVATE = 1 << 2;
    165 
    166     /**
    167      * Display flag: Indicates that the display is a presentation display.
    168      * <p>
    169      * This flag identifies secondary displays that are suitable for
    170      * use as presentation displays such as HDMI or Wireless displays.  Applications
    171      * may automatically project their content to presentation displays to provide
    172      * richer second screen experiences.
    173      * </p>
    174      *
    175      * @see #getFlags
    176      */
    177     public static final int FLAG_PRESENTATION = 1 << 3;
    178 
    179     /**
    180      * Display flag: Indicates that the display has a round shape.
    181      * <p>
    182      * This flag identifies displays that are circular, elliptical or otherwise
    183      * do not permit the user to see all the way to the logical corners of the display.
    184      * </p>
    185      *
    186      * @see #getFlags
    187      */
    188     public static final int FLAG_ROUND = 1 << 4;
    189 
    190     /**
    191      * Display flag: Indicates that the contents of the display should not be scaled
    192      * to fit the physical screen dimensions.  Used for development only to emulate
    193      * devices with smaller physicals screens while preserving density.
    194      *
    195      * @hide
    196      */
    197     public static final int FLAG_SCALING_DISABLED = 1 << 30;
    198 
    199     /**
    200      * Display type: Unknown display type.
    201      * @hide
    202      */
    203     public static final int TYPE_UNKNOWN = 0;
    204 
    205     /**
    206      * Display type: Built-in display.
    207      * @hide
    208      */
    209     public static final int TYPE_BUILT_IN = 1;
    210 
    211     /**
    212      * Display type: HDMI display.
    213      * @hide
    214      */
    215     public static final int TYPE_HDMI = 2;
    216 
    217     /**
    218      * Display type: WiFi display.
    219      * @hide
    220      */
    221     public static final int TYPE_WIFI = 3;
    222 
    223     /**
    224      * Display type: Overlay display.
    225      * @hide
    226      */
    227     public static final int TYPE_OVERLAY = 4;
    228 
    229     /**
    230      * Display type: Virtual display.
    231      * @hide
    232      */
    233     public static final int TYPE_VIRTUAL = 5;
    234 
    235     /**
    236      * Display state: The display state is unknown.
    237      *
    238      * @see #getState
    239      */
    240     public static final int STATE_UNKNOWN = 0;
    241 
    242     /**
    243      * Display state: The display is off.
    244      *
    245      * @see #getState
    246      */
    247     public static final int STATE_OFF = 1;
    248 
    249     /**
    250      * Display state: The display is on.
    251      *
    252      * @see #getState
    253      */
    254     public static final int STATE_ON = 2;
    255 
    256     /**
    257      * Display state: The display is dozing in a low power state; it is still
    258      * on but is optimized for showing system-provided content while the
    259      * device is non-interactive.
    260      *
    261      * @see #getState
    262      * @see android.os.PowerManager#isInteractive
    263      */
    264     public static final int STATE_DOZE = 3;
    265 
    266     /**
    267      * Display state: The display is dozing in a suspended low power state; it is still
    268      * on but is optimized for showing static system-provided content while the device
    269      * is non-interactive.  This mode may be used to conserve even more power by allowing
    270      * the hardware to stop applying frame buffer updates from the graphics subsystem or
    271      * to take over the display and manage it autonomously to implement low power always-on
    272      * display functionality.
    273      *
    274      * @see #getState
    275      * @see android.os.PowerManager#isInteractive
    276      */
    277     public static final int STATE_DOZE_SUSPEND = 4;
    278 
    279     /**
    280      * Internal method to create a display.
    281      * Applications should use {@link android.view.WindowManager#getDefaultDisplay()}
    282      * or {@link android.hardware.display.DisplayManager#getDisplay}
    283      * to get a display object.
    284      *
    285      * @hide
    286      */
    287     public Display(DisplayManagerGlobal global,
    288             int displayId, DisplayInfo displayInfo /*not null*/,
    289             DisplayAdjustments daj) {
    290         mGlobal = global;
    291         mDisplayId = displayId;
    292         mDisplayInfo = displayInfo;
    293         mDisplayAdjustments = new DisplayAdjustments(daj);
    294         mIsValid = true;
    295 
    296         // Cache properties that cannot change as long as the display is valid.
    297         mLayerStack = displayInfo.layerStack;
    298         mFlags = displayInfo.flags;
    299         mType = displayInfo.type;
    300         mAddress = displayInfo.address;
    301         mOwnerUid = displayInfo.ownerUid;
    302         mOwnerPackageName = displayInfo.ownerPackageName;
    303     }
    304 
    305     /**
    306      * Gets the display id.
    307      * <p>
    308      * Each logical display has a unique id.
    309      * The default display has id {@link #DEFAULT_DISPLAY}.
    310      * </p>
    311      */
    312     public int getDisplayId() {
    313         return mDisplayId;
    314     }
    315 
    316     /**
    317      * Returns true if this display is still valid, false if the display has been removed.
    318      *
    319      * If the display is invalid, then the methods of this class will
    320      * continue to report the most recently observed display information.
    321      * However, it is unwise (and rather fruitless) to continue using a
    322      * {@link Display} object after the display's demise.
    323      *
    324      * It's possible for a display that was previously invalid to become
    325      * valid again if a display with the same id is reconnected.
    326      *
    327      * @return True if the display is still valid.
    328      */
    329     public boolean isValid() {
    330         synchronized (this) {
    331             updateDisplayInfoLocked();
    332             return mIsValid;
    333         }
    334     }
    335 
    336     /**
    337      * Gets a full copy of the display information.
    338      *
    339      * @param outDisplayInfo The object to receive the copy of the display information.
    340      * @return True if the display is still valid.
    341      * @hide
    342      */
    343     public boolean getDisplayInfo(DisplayInfo outDisplayInfo) {
    344         synchronized (this) {
    345             updateDisplayInfoLocked();
    346             outDisplayInfo.copyFrom(mDisplayInfo);
    347             return mIsValid;
    348         }
    349     }
    350 
    351     /**
    352      * Gets the display's layer stack.
    353      *
    354      * Each display has its own independent layer stack upon which surfaces
    355      * are placed to be managed by surface flinger.
    356      *
    357      * @return The display's layer stack number.
    358      * @hide
    359      */
    360     public int getLayerStack() {
    361         return mLayerStack;
    362     }
    363 
    364     /**
    365      * Returns a combination of flags that describe the capabilities of the display.
    366      *
    367      * @return The display flags.
    368      *
    369      * @see #FLAG_SUPPORTS_PROTECTED_BUFFERS
    370      * @see #FLAG_SECURE
    371      * @see #FLAG_PRIVATE
    372      */
    373     public int getFlags() {
    374         return mFlags;
    375     }
    376 
    377     /**
    378      * Gets the display type.
    379      *
    380      * @return The display type.
    381      *
    382      * @see #TYPE_UNKNOWN
    383      * @see #TYPE_BUILT_IN
    384      * @see #TYPE_HDMI
    385      * @see #TYPE_WIFI
    386      * @see #TYPE_OVERLAY
    387      * @see #TYPE_VIRTUAL
    388      * @hide
    389      */
    390     public int getType() {
    391         return mType;
    392     }
    393 
    394     /**
    395      * Gets the display address, or null if none.
    396      * Interpretation varies by display type.
    397      *
    398      * @return The display address.
    399      * @hide
    400      */
    401     public String getAddress() {
    402         return mAddress;
    403     }
    404 
    405     /**
    406      * Gets the UID of the application that owns this display, or zero if it is
    407      * owned by the system.
    408      * <p>
    409      * If the display is private, then only the owner can use it.
    410      * </p>
    411      *
    412      * @hide
    413      */
    414     public int getOwnerUid() {
    415         return mOwnerUid;
    416     }
    417 
    418     /**
    419      * Gets the package name of the application that owns this display, or null if it is
    420      * owned by the system.
    421      * <p>
    422      * If the display is private, then only the owner can use it.
    423      * </p>
    424      *
    425      * @hide
    426      */
    427     public String getOwnerPackageName() {
    428         return mOwnerPackageName;
    429     }
    430 
    431     /**
    432      * Gets the compatibility info used by this display instance.
    433      *
    434      * @return The display adjustments holder, or null if none is required.
    435      * @hide
    436      */
    437     public DisplayAdjustments getDisplayAdjustments() {
    438         return mDisplayAdjustments;
    439     }
    440 
    441     /**
    442      * Gets the name of the display.
    443      * <p>
    444      * Note that some displays may be renamed by the user.
    445      * </p>
    446      *
    447      * @return The display's name.
    448      */
    449     public String getName() {
    450         synchronized (this) {
    451             updateDisplayInfoLocked();
    452             return mDisplayInfo.name;
    453         }
    454     }
    455 
    456     /**
    457      * Gets the size of the display, in pixels.
    458      * <p>
    459      * Note that this value should <em>not</em> be used for computing layouts,
    460      * since a device will typically have screen decoration (such as a status bar)
    461      * along the edges of the display that reduce the amount of application
    462      * space available from the size returned here.  Layouts should instead use
    463      * the window size.
    464      * </p><p>
    465      * The size is adjusted based on the current rotation of the display.
    466      * </p><p>
    467      * The size returned by this method does not necessarily represent the
    468      * actual raw size (native resolution) of the display.  The returned size may
    469      * be adjusted to exclude certain system decoration elements that are always visible.
    470      * It may also be scaled to provide compatibility with older applications that
    471      * were originally designed for smaller displays.
    472      * </p>
    473      *
    474      * @param outSize A {@link Point} object to receive the size information.
    475      */
    476     public void getSize(Point outSize) {
    477         synchronized (this) {
    478             updateDisplayInfoLocked();
    479             mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments);
    480             outSize.x = mTempMetrics.widthPixels;
    481             outSize.y = mTempMetrics.heightPixels;
    482         }
    483     }
    484 
    485     /**
    486      * Gets the size of the display as a rectangle, in pixels.
    487      *
    488      * @param outSize A {@link Rect} object to receive the size information.
    489      * @see #getSize(Point)
    490      */
    491     public void getRectSize(Rect outSize) {
    492         synchronized (this) {
    493             updateDisplayInfoLocked();
    494             mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments);
    495             outSize.set(0, 0, mTempMetrics.widthPixels, mTempMetrics.heightPixels);
    496         }
    497     }
    498 
    499     /**
    500      * Return the range of display sizes an application can expect to encounter
    501      * under normal operation, as long as there is no physical change in screen
    502      * size.  This is basically the sizes you will see as the orientation
    503      * changes, taking into account whatever screen decoration there is in
    504      * each rotation.  For example, the status bar is always at the top of the
    505      * screen, so it will reduce the height both in landscape and portrait, and
    506      * the smallest height returned here will be the smaller of the two.
    507      *
    508      * This is intended for applications to get an idea of the range of sizes
    509      * they will encounter while going through device rotations, to provide a
    510      * stable UI through rotation.  The sizes here take into account all standard
    511      * system decorations that reduce the size actually available to the
    512      * application: the status bar, navigation bar, system bar, etc.  It does
    513      * <em>not</em> take into account more transient elements like an IME
    514      * soft keyboard.
    515      *
    516      * @param outSmallestSize Filled in with the smallest width and height
    517      * that the application will encounter, in pixels (not dp units).  The x
    518      * (width) dimension here directly corresponds to
    519      * {@link android.content.res.Configuration#smallestScreenWidthDp
    520      * Configuration.smallestScreenWidthDp}, except the value here is in raw
    521      * screen pixels rather than dp units.  Your application may of course
    522      * still get smaller space yet if, for example, a soft keyboard is
    523      * being displayed.
    524      * @param outLargestSize Filled in with the largest width and height
    525      * that the application will encounter, in pixels (not dp units).  Your
    526      * application may of course still get larger space than this if,
    527      * for example, screen decorations like the status bar are being hidden.
    528      */
    529     public void getCurrentSizeRange(Point outSmallestSize, Point outLargestSize) {
    530         synchronized (this) {
    531             updateDisplayInfoLocked();
    532             outSmallestSize.x = mDisplayInfo.smallestNominalAppWidth;
    533             outSmallestSize.y = mDisplayInfo.smallestNominalAppHeight;
    534             outLargestSize.x = mDisplayInfo.largestNominalAppWidth;
    535             outLargestSize.y = mDisplayInfo.largestNominalAppHeight;
    536         }
    537     }
    538 
    539     /**
    540      * Return the maximum screen size dimension that will happen.  This is
    541      * mostly for wallpapers.
    542      * @hide
    543      */
    544     public int getMaximumSizeDimension() {
    545         synchronized (this) {
    546             updateDisplayInfoLocked();
    547             return Math.max(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
    548         }
    549     }
    550 
    551     /**
    552      * @deprecated Use {@link #getSize(Point)} instead.
    553      */
    554     @Deprecated
    555     public int getWidth() {
    556         synchronized (this) {
    557             updateCachedAppSizeIfNeededLocked();
    558             return mCachedAppWidthCompat;
    559         }
    560     }
    561 
    562     /**
    563      * @deprecated Use {@link #getSize(Point)} instead.
    564      */
    565     @Deprecated
    566     public int getHeight() {
    567         synchronized (this) {
    568             updateCachedAppSizeIfNeededLocked();
    569             return mCachedAppHeightCompat;
    570         }
    571     }
    572 
    573     /**
    574      * @hide
    575      * Return a rectangle defining the insets of the overscan region of the display.
    576      * Each field of the rectangle is the number of pixels the overscan area extends
    577      * into the display on that side.
    578      */
    579     public void getOverscanInsets(Rect outRect) {
    580         synchronized (this) {
    581             updateDisplayInfoLocked();
    582             outRect.set(mDisplayInfo.overscanLeft, mDisplayInfo.overscanTop,
    583                     mDisplayInfo.overscanRight, mDisplayInfo.overscanBottom);
    584         }
    585     }
    586 
    587     /**
    588      * Returns the rotation of the screen from its "natural" orientation.
    589      * The returned value may be {@link Surface#ROTATION_0 Surface.ROTATION_0}
    590      * (no rotation), {@link Surface#ROTATION_90 Surface.ROTATION_90},
    591      * {@link Surface#ROTATION_180 Surface.ROTATION_180}, or
    592      * {@link Surface#ROTATION_270 Surface.ROTATION_270}.  For
    593      * example, if a device has a naturally tall screen, and the user has
    594      * turned it on its side to go into a landscape orientation, the value
    595      * returned here may be either {@link Surface#ROTATION_90 Surface.ROTATION_90}
    596      * or {@link Surface#ROTATION_270 Surface.ROTATION_270} depending on
    597      * the direction it was turned.  The angle is the rotation of the drawn
    598      * graphics on the screen, which is the opposite direction of the physical
    599      * rotation of the device.  For example, if the device is rotated 90
    600      * degrees counter-clockwise, to compensate rendering will be rotated by
    601      * 90 degrees clockwise and thus the returned value here will be
    602      * {@link Surface#ROTATION_90 Surface.ROTATION_90}.
    603      */
    604     @Surface.Rotation
    605     public int getRotation() {
    606         synchronized (this) {
    607             updateDisplayInfoLocked();
    608             return mDisplayInfo.rotation;
    609         }
    610     }
    611 
    612     /**
    613      * @deprecated use {@link #getRotation}
    614      * @return orientation of this display.
    615      */
    616     @Deprecated
    617     @Surface.Rotation
    618     public int getOrientation() {
    619         return getRotation();
    620     }
    621 
    622     /**
    623      * Gets the pixel format of the display.
    624      * @return One of the constants defined in {@link android.graphics.PixelFormat}.
    625      *
    626      * @deprecated This method is no longer supported.
    627      * The result is always {@link PixelFormat#RGBA_8888}.
    628      */
    629     @Deprecated
    630     public int getPixelFormat() {
    631         return PixelFormat.RGBA_8888;
    632     }
    633 
    634     /**
    635      * Gets the refresh rate of this display in frames per second.
    636      */
    637     public float getRefreshRate() {
    638         synchronized (this) {
    639             updateDisplayInfoLocked();
    640             return mDisplayInfo.getMode().getRefreshRate();
    641         }
    642     }
    643 
    644     /**
    645      * Get the supported refresh rates of this display in frames per second.
    646      * <p>
    647      * This method only returns refresh rates for the display's default modes. For more options, use
    648      * {@link #getSupportedModes()}.
    649      *
    650      * @deprecated use {@link #getSupportedModes()} instead
    651      */
    652     @Deprecated
    653     public float[] getSupportedRefreshRates() {
    654         synchronized (this) {
    655             updateDisplayInfoLocked();
    656             return mDisplayInfo.getDefaultRefreshRates();
    657         }
    658     }
    659 
    660     /**
    661      * Returns the active mode of the display.
    662      */
    663     public Mode getMode() {
    664         synchronized (this) {
    665             updateDisplayInfoLocked();
    666             return mDisplayInfo.getMode();
    667         }
    668     }
    669 
    670     /**
    671      * Gets the supported modes of this display.
    672      */
    673     public Mode[] getSupportedModes() {
    674         synchronized (this) {
    675             updateDisplayInfoLocked();
    676             final Display.Mode[] modes = mDisplayInfo.supportedModes;
    677             return Arrays.copyOf(modes, modes.length);
    678         }
    679     }
    680 
    681     /**
    682      * Gets the app VSYNC offset, in nanoseconds.  This is a positive value indicating
    683      * the phase offset of the VSYNC events provided by Choreographer relative to the
    684      * display refresh.  For example, if Choreographer reports that the refresh occurred
    685      * at time N, it actually occurred at (N - appVsyncOffset).
    686      * <p>
    687      * Apps generally do not need to be aware of this.  It's only useful for fine-grained
    688      * A/V synchronization.
    689      */
    690     public long getAppVsyncOffsetNanos() {
    691         synchronized (this) {
    692             updateDisplayInfoLocked();
    693             return mDisplayInfo.appVsyncOffsetNanos;
    694         }
    695     }
    696 
    697     /**
    698      * This is how far in advance a buffer must be queued for presentation at
    699      * a given time.  If you want a buffer to appear on the screen at
    700      * time N, you must submit the buffer before (N - presentationDeadline).
    701      * <p>
    702      * The desired presentation time for GLES rendering may be set with
    703      * {@link android.opengl.EGLExt#eglPresentationTimeANDROID}.  For video decoding, use
    704      * {@link android.media.MediaCodec#releaseOutputBuffer(int, long)}.  Times are
    705      * expressed in nanoseconds, using the system monotonic clock
    706      * ({@link System#nanoTime}).
    707      */
    708     public long getPresentationDeadlineNanos() {
    709         synchronized (this) {
    710             updateDisplayInfoLocked();
    711             return mDisplayInfo.presentationDeadlineNanos;
    712         }
    713     }
    714 
    715     /**
    716      * Gets display metrics that describe the size and density of this display.
    717      * <p>
    718      * The size is adjusted based on the current rotation of the display.
    719      * </p><p>
    720      * The size returned by this method does not necessarily represent the
    721      * actual raw size (native resolution) of the display.  The returned size may
    722      * be adjusted to exclude certain system decor elements that are always visible.
    723      * It may also be scaled to provide compatibility with older applications that
    724      * were originally designed for smaller displays.
    725      * </p>
    726      *
    727      * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
    728      */
    729     public void getMetrics(DisplayMetrics outMetrics) {
    730         synchronized (this) {
    731             updateDisplayInfoLocked();
    732             mDisplayInfo.getAppMetrics(outMetrics, mDisplayAdjustments);
    733         }
    734     }
    735 
    736     /**
    737      * Gets the real size of the display without subtracting any window decor or
    738      * applying any compatibility scale factors.
    739      * <p>
    740      * The size is adjusted based on the current rotation of the display.
    741      * </p><p>
    742      * The real size may be smaller than the physical size of the screen when the
    743      * window manager is emulating a smaller display (using adb shell am display-size).
    744      * </p>
    745      *
    746      * @param outSize Set to the real size of the display.
    747      */
    748     public void getRealSize(Point outSize) {
    749         synchronized (this) {
    750             updateDisplayInfoLocked();
    751             outSize.x = mDisplayInfo.logicalWidth;
    752             outSize.y = mDisplayInfo.logicalHeight;
    753         }
    754     }
    755 
    756     /**
    757      * Gets display metrics based on the real size of this display.
    758      * <p>
    759      * The size is adjusted based on the current rotation of the display.
    760      * </p><p>
    761      * The real size may be smaller than the physical size of the screen when the
    762      * window manager is emulating a smaller display (using adb shell am display-size).
    763      * </p>
    764      *
    765      * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
    766      */
    767     public void getRealMetrics(DisplayMetrics outMetrics) {
    768         synchronized (this) {
    769             updateDisplayInfoLocked();
    770             mDisplayInfo.getLogicalMetrics(outMetrics,
    771                     CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO,
    772                     mDisplayAdjustments.getConfiguration());
    773         }
    774     }
    775 
    776     /**
    777      * Gets the state of the display, such as whether it is on or off.
    778      *
    779      * @return The state of the display: one of {@link #STATE_OFF}, {@link #STATE_ON},
    780      * {@link #STATE_DOZE}, {@link #STATE_DOZE_SUSPEND}, or {@link #STATE_UNKNOWN}.
    781      */
    782     public int getState() {
    783         synchronized (this) {
    784             updateDisplayInfoLocked();
    785             return mIsValid ? mDisplayInfo.state : STATE_UNKNOWN;
    786         }
    787     }
    788 
    789     /**
    790      * Returns true if the specified UID has access to this display.
    791      * @hide
    792      */
    793     public boolean hasAccess(int uid) {
    794         return Display.hasAccess(uid, mFlags, mOwnerUid);
    795     }
    796 
    797     /** @hide */
    798     public static boolean hasAccess(int uid, int flags, int ownerUid) {
    799         return (flags & Display.FLAG_PRIVATE) == 0
    800                 || uid == ownerUid
    801                 || uid == Process.SYSTEM_UID
    802                 || uid == 0;
    803     }
    804 
    805     /**
    806      * Returns true if the display is a public presentation display.
    807      * @hide
    808      */
    809     public boolean isPublicPresentation() {
    810         return (mFlags & (Display.FLAG_PRIVATE | Display.FLAG_PRESENTATION)) ==
    811                 Display.FLAG_PRESENTATION;
    812     }
    813 
    814     private void updateDisplayInfoLocked() {
    815         // Note: The display manager caches display info objects on our behalf.
    816         DisplayInfo newInfo = mGlobal.getDisplayInfo(mDisplayId);
    817         if (newInfo == null) {
    818             // Preserve the old mDisplayInfo after the display is removed.
    819             if (mIsValid) {
    820                 mIsValid = false;
    821                 if (DEBUG) {
    822                     Log.d(TAG, "Logical display " + mDisplayId + " was removed.");
    823                 }
    824             }
    825         } else {
    826             // Use the new display info.  (It might be the same object if nothing changed.)
    827             mDisplayInfo = newInfo;
    828             if (!mIsValid) {
    829                 mIsValid = true;
    830                 if (DEBUG) {
    831                     Log.d(TAG, "Logical display " + mDisplayId + " was recreated.");
    832                 }
    833             }
    834         }
    835     }
    836 
    837     private void updateCachedAppSizeIfNeededLocked() {
    838         long now = SystemClock.uptimeMillis();
    839         if (now > mLastCachedAppSizeUpdate + CACHED_APP_SIZE_DURATION_MILLIS) {
    840             updateDisplayInfoLocked();
    841             mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments);
    842             mCachedAppWidthCompat = mTempMetrics.widthPixels;
    843             mCachedAppHeightCompat = mTempMetrics.heightPixels;
    844             mLastCachedAppSizeUpdate = now;
    845         }
    846     }
    847 
    848     // For debugging purposes
    849     @Override
    850     public String toString() {
    851         synchronized (this) {
    852             updateDisplayInfoLocked();
    853             mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments);
    854             return "Display id " + mDisplayId + ": " + mDisplayInfo
    855                     + ", " + mTempMetrics + ", isValid=" + mIsValid;
    856         }
    857     }
    858 
    859     /**
    860      * @hide
    861      */
    862     public static String typeToString(int type) {
    863         switch (type) {
    864             case TYPE_UNKNOWN:
    865                 return "UNKNOWN";
    866             case TYPE_BUILT_IN:
    867                 return "BUILT_IN";
    868             case TYPE_HDMI:
    869                 return "HDMI";
    870             case TYPE_WIFI:
    871                 return "WIFI";
    872             case TYPE_OVERLAY:
    873                 return "OVERLAY";
    874             case TYPE_VIRTUAL:
    875                 return "VIRTUAL";
    876             default:
    877                 return Integer.toString(type);
    878         }
    879     }
    880 
    881     /**
    882      * @hide
    883      */
    884     public static String stateToString(int state) {
    885         switch (state) {
    886             case STATE_UNKNOWN:
    887                 return "UNKNOWN";
    888             case STATE_OFF:
    889                 return "OFF";
    890             case STATE_ON:
    891                 return "ON";
    892             case STATE_DOZE:
    893                 return "DOZE";
    894             case STATE_DOZE_SUSPEND:
    895                 return "DOZE_SUSPEND";
    896             default:
    897                 return Integer.toString(state);
    898         }
    899     }
    900 
    901     /**
    902      * Returns true if display updates may be suspended while in the specified
    903      * display power state.
    904      * @hide
    905      */
    906     public static boolean isSuspendedState(int state) {
    907         return state == STATE_OFF || state == STATE_DOZE_SUSPEND;
    908     }
    909 
    910     /**
    911      * A mode supported by a given display.
    912      *
    913      * @see Display#getSupportedModes()
    914      */
    915     public static final class Mode implements Parcelable {
    916         /**
    917          * @hide
    918          */
    919         public static final Mode[] EMPTY_ARRAY = new Mode[0];
    920 
    921         private final int mModeId;
    922         private final int mWidth;
    923         private final int mHeight;
    924         private final float mRefreshRate;
    925 
    926         /**
    927          * @hide
    928          */
    929         public Mode(int modeId, int width, int height, float refreshRate) {
    930             mModeId = modeId;
    931             mWidth = width;
    932             mHeight = height;
    933             mRefreshRate = refreshRate;
    934         }
    935 
    936         /**
    937          * Returns this mode's id.
    938          */
    939         public int getModeId() {
    940             return mModeId;
    941         }
    942 
    943         /**
    944          * Returns the physical width of the display in pixels when configured in this mode's
    945          * resolution.
    946          * <p>
    947          * Note that due to application UI scaling, the number of pixels made available to
    948          * applications when the mode is active (as reported by {@link Display#getWidth()} may
    949          * differ from the mode's actual resolution (as reported by this function).
    950          * <p>
    951          * For example, applications running on a 4K display may have their UI laid out and rendered
    952          * in 1080p and then scaled up. Applications can take advantage of the extra resolution by
    953          * rendering content through a {@link android.view.SurfaceView} using full size buffers.
    954          */
    955         public int getPhysicalWidth() {
    956             return mWidth;
    957         }
    958 
    959         /**
    960          * Returns the physical height of the display in pixels when configured in this mode's
    961          * resolution.
    962          * <p>
    963          * Note that due to application UI scaling, the number of pixels made available to
    964          * applications when the mode is active (as reported by {@link Display#getHeight()} may
    965          * differ from the mode's actual resolution (as reported by this function).
    966          * <p>
    967          * For example, applications running on a 4K display may have their UI laid out and rendered
    968          * in 1080p and then scaled up. Applications can take advantage of the extra resolution by
    969          * rendering content through a {@link android.view.SurfaceView} using full size buffers.
    970          */
    971         public int getPhysicalHeight() {
    972             return mHeight;
    973         }
    974 
    975         /**
    976          * Returns the refresh rate in frames per second.
    977          */
    978         public float getRefreshRate() {
    979             return mRefreshRate;
    980         }
    981 
    982         /**
    983          * Returns {@code true} if this mode matches the given parameters.
    984          *
    985          * @hide
    986          */
    987         public boolean matches(int width, int height, float refreshRate) {
    988             return mWidth == width &&
    989                     mHeight == height &&
    990                     Float.floatToIntBits(mRefreshRate) == Float.floatToIntBits(refreshRate);
    991         }
    992 
    993         @Override
    994         public boolean equals(Object other) {
    995             if (this == other) {
    996                 return true;
    997             }
    998             if (!(other instanceof Mode)) {
    999                 return false;
   1000             }
   1001             Mode that = (Mode) other;
   1002             return mModeId == that.mModeId && matches(that.mWidth, that.mHeight, that.mRefreshRate);
   1003         }
   1004 
   1005         @Override
   1006         public int hashCode() {
   1007             int hash = 1;
   1008             hash = hash * 17 + mModeId;
   1009             hash = hash * 17 + mWidth;
   1010             hash = hash * 17 + mHeight;
   1011             hash = hash * 17 + Float.floatToIntBits(mRefreshRate);
   1012             return hash;
   1013         }
   1014 
   1015         @Override
   1016         public String toString() {
   1017             return new StringBuilder("{")
   1018                     .append("id=").append(mModeId)
   1019                     .append(", width=").append(mWidth)
   1020                     .append(", height=").append(mHeight)
   1021                     .append(", fps=").append(mRefreshRate)
   1022                     .append("}")
   1023                     .toString();
   1024         }
   1025 
   1026         @Override
   1027         public int describeContents() {
   1028             return 0;
   1029         }
   1030 
   1031         private Mode(Parcel in) {
   1032             this(in.readInt(), in.readInt(), in.readInt(), in.readFloat());
   1033         }
   1034 
   1035         @Override
   1036         public void writeToParcel(Parcel out, int parcelableFlags) {
   1037             out.writeInt(mModeId);
   1038             out.writeInt(mWidth);
   1039             out.writeInt(mHeight);
   1040             out.writeFloat(mRefreshRate);
   1041         }
   1042 
   1043         @SuppressWarnings("hiding")
   1044         public static final Parcelable.Creator<Mode> CREATOR
   1045                 = new Parcelable.Creator<Mode>() {
   1046             @Override
   1047             public Mode createFromParcel(Parcel in) {
   1048                 return new Mode(in);
   1049             }
   1050 
   1051             @Override
   1052             public Mode[] newArray(int size) {
   1053                 return new Mode[size];
   1054             }
   1055         };
   1056     }
   1057 }
   1058