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.graphics.PixelFormat;
     20 import android.graphics.Point;
     21 import android.graphics.Rect;
     22 import android.hardware.display.DisplayManagerGlobal;
     23 import android.os.SystemClock;
     24 import android.util.DisplayMetrics;
     25 import android.util.Log;
     26 
     27 /**
     28  * Provides information about the size and density of a logical display.
     29  * <p>
     30  * The display area is described in two different ways.
     31  * <ul>
     32  * <li>The application display area specifies the part of the display that may contain
     33  * an application window, excluding the system decorations.  The application display area may
     34  * be smaller than the real display area because the system subtracts the space needed
     35  * for decor elements such as the status bar.  Use the following methods to query the
     36  * application display area: {@link #getSize}, {@link #getRectSize} and {@link #getMetrics}.</li>
     37  * <li>The real display area specifies the part of the display that contains content
     38  * including the system decorations.  Even so, the real display area may be smaller than the
     39  * physical size of the display if the window manager is emulating a smaller display
     40  * using (adb shell am display-size).  Use the following methods to query the
     41  * real display area: {@link #getRealSize}, {@link #getRealMetrics}.</li>
     42  * </ul>
     43  * </p><p>
     44  * A logical display does not necessarily represent a particular physical display device
     45  * such as the built-in screen or an external monitor.  The contents of a logical
     46  * display may be presented on one or more physical displays according to the devices
     47  * that are currently attached and whether mirroring has been enabled.
     48  * </p>
     49  */
     50 public final class Display {
     51     private static final String TAG = "Display";
     52     private static final boolean DEBUG = false;
     53 
     54     private final DisplayManagerGlobal mGlobal;
     55     private final int mDisplayId;
     56     private final int mLayerStack;
     57     private final int mFlags;
     58     private final int mType;
     59     private final String mAddress;
     60     private final CompatibilityInfoHolder mCompatibilityInfo;
     61 
     62     private DisplayInfo mDisplayInfo; // never null
     63     private boolean mIsValid;
     64 
     65     // Temporary display metrics structure used for compatibility mode.
     66     private final DisplayMetrics mTempMetrics = new DisplayMetrics();
     67 
     68     // We cache the app width and height properties briefly between calls
     69     // to getHeight() and getWidth() to ensure that applications perceive
     70     // consistent results when the size changes (most of the time).
     71     // Applications should now be using getSize() instead.
     72     private static final int CACHED_APP_SIZE_DURATION_MILLIS = 20;
     73     private long mLastCachedAppSizeUpdate;
     74     private int mCachedAppWidthCompat;
     75     private int mCachedAppHeightCompat;
     76 
     77     /**
     78      * The default Display id, which is the id of the built-in primary display
     79      * assuming there is one.
     80      */
     81     public static final int DEFAULT_DISPLAY = 0;
     82 
     83     /**
     84      * Display flag: Indicates that the display supports compositing content
     85      * that is stored in protected graphics buffers.
     86      * <p>
     87      * If this flag is set then the display device supports compositing protected buffers.
     88      * </p><p>
     89      * If this flag is not set then the display device may not support compositing
     90      * protected buffers; the user may see a blank region on the screen instead of
     91      * the protected content.
     92      * </p><p>
     93      * Secure (DRM) video decoders may allocate protected graphics buffers to request that
     94      * a hardware-protected path be provided between the video decoder and the external
     95      * display sink.  If a hardware-protected path is not available, then content stored
     96      * in protected graphics buffers may not be composited.
     97      * </p><p>
     98      * An application can use the absence of this flag as a hint that it should not use protected
     99      * buffers for this display because the content may not be visible.  For example,
    100      * if the flag is not set then the application may choose not to show content on this
    101      * display, show an informative error message, select an alternate content stream
    102      * or adopt a different strategy for decoding content that does not rely on
    103      * protected buffers.
    104      * </p>
    105      *
    106      * @see #getFlags
    107      */
    108     public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1 << 0;
    109 
    110     /**
    111      * Display flag: Indicates that the display has a secure video output and
    112      * supports compositing secure surfaces.
    113      * <p>
    114      * If this flag is set then the display device has a secure video output
    115      * and is capable of showing secure surfaces.  It may also be capable of
    116      * showing {@link #FLAG_SUPPORTS_PROTECTED_BUFFERS protected buffers}.
    117      * </p><p>
    118      * If this flag is not set then the display device may not have a secure video
    119      * output; the user may see a blank region on the screen instead of
    120      * the contents of secure surfaces or protected buffers.
    121      * </p><p>
    122      * Secure surfaces are used to prevent content rendered into those surfaces
    123      * by applications from appearing in screenshots or from being viewed
    124      * on non-secure displays.  Protected buffers are used by secure video decoders
    125      * for a similar purpose.
    126      * </p><p>
    127      * An application creates a window with a secure surface by specifying the
    128      * {@link WindowManager.LayoutParams#FLAG_SECURE} window flag.
    129      * Likewise, an application creates a {@link SurfaceView} with a secure surface
    130      * by calling {@link SurfaceView#setSecure} before attaching the secure view to
    131      * its containing window.
    132      * </p><p>
    133      * An application can use the absence of this flag as a hint that it should not create
    134      * secure surfaces or protected buffers on this display because the content may
    135      * not be visible.  For example, if the flag is not set then the application may
    136      * choose not to show content on this display, show an informative error message,
    137      * select an alternate content stream or adopt a different strategy for decoding
    138      * content that does not rely on secure surfaces or protected buffers.
    139      * </p>
    140      *
    141      * @see #getFlags
    142      */
    143     public static final int FLAG_SECURE = 1 << 1;
    144 
    145     /**
    146      * Display type: Unknown display type.
    147      * @hide
    148      */
    149     public static final int TYPE_UNKNOWN = 0;
    150 
    151     /**
    152      * Display type: Built-in display.
    153      * @hide
    154      */
    155     public static final int TYPE_BUILT_IN = 1;
    156 
    157     /**
    158      * Display type: HDMI display.
    159      * @hide
    160      */
    161     public static final int TYPE_HDMI = 2;
    162 
    163     /**
    164      * Display type: WiFi display.
    165      * @hide
    166      */
    167     public static final int TYPE_WIFI = 3;
    168 
    169     /**
    170      * Display type: Overlay display.
    171      * @hide
    172      */
    173     public static final int TYPE_OVERLAY = 4;
    174 
    175     /**
    176      * Internal method to create a display.
    177      * Applications should use {@link android.view.WindowManager#getDefaultDisplay()}
    178      * or {@link android.hardware.display.DisplayManager#getDisplay}
    179      * to get a display object.
    180      *
    181      * @hide
    182      */
    183     public Display(DisplayManagerGlobal global,
    184             int displayId, DisplayInfo displayInfo /*not null*/,
    185             CompatibilityInfoHolder compatibilityInfo) {
    186         mGlobal = global;
    187         mDisplayId = displayId;
    188         mDisplayInfo = displayInfo;
    189         mCompatibilityInfo = compatibilityInfo;
    190         mIsValid = true;
    191 
    192         // Cache properties that cannot change as long as the display is valid.
    193         mLayerStack = displayInfo.layerStack;
    194         mFlags = displayInfo.flags;
    195         mType = displayInfo.type;
    196         mAddress = displayInfo.address;
    197     }
    198 
    199     /**
    200      * Gets the display id.
    201      * <p>
    202      * Each logical display has a unique id.
    203      * The default display has id {@link #DEFAULT_DISPLAY}.
    204      * </p>
    205      */
    206     public int getDisplayId() {
    207         return mDisplayId;
    208     }
    209 
    210     /**
    211      * Returns true if this display is still valid, false if the display has been removed.
    212      *
    213      * If the display is invalid, then the methods of this class will
    214      * continue to report the most recently observed display information.
    215      * However, it is unwise (and rather fruitless) to continue using a
    216      * {@link Display} object after the display's demise.
    217      *
    218      * It's possible for a display that was previously invalid to become
    219      * valid again if a display with the same id is reconnected.
    220      *
    221      * @return True if the display is still valid.
    222      */
    223     public boolean isValid() {
    224         synchronized (this) {
    225             updateDisplayInfoLocked();
    226             return mIsValid;
    227         }
    228     }
    229 
    230     /**
    231      * Gets a full copy of the display information.
    232      *
    233      * @param outDisplayInfo The object to receive the copy of the display information.
    234      * @return True if the display is still valid.
    235      * @hide
    236      */
    237     public boolean getDisplayInfo(DisplayInfo outDisplayInfo) {
    238         synchronized (this) {
    239             updateDisplayInfoLocked();
    240             outDisplayInfo.copyFrom(mDisplayInfo);
    241             return mIsValid;
    242         }
    243     }
    244 
    245     /**
    246      * Gets the display's layer stack.
    247      *
    248      * Each display has its own independent layer stack upon which surfaces
    249      * are placed to be managed by surface flinger.
    250      *
    251      * @return The display's layer stack number.
    252      * @hide
    253      */
    254     public int getLayerStack() {
    255         return mLayerStack;
    256     }
    257 
    258     /**
    259      * Returns a combination of flags that describe the capabilities of the display.
    260      *
    261      * @return The display flags.
    262      *
    263      * @see #FLAG_SUPPORTS_PROTECTED_BUFFERS
    264      * @see #FLAG_SECURE
    265      */
    266     public int getFlags() {
    267         return mFlags;
    268     }
    269 
    270     /**
    271      * Gets the display type.
    272      *
    273      * @return The display type.
    274      *
    275      * @see #TYPE_UNKNOWN
    276      * @see #TYPE_BUILT_IN
    277      * @see #TYPE_HDMI
    278      * @see #TYPE_WIFI
    279      * @see #TYPE_OVERLAY
    280      * @hide
    281      */
    282     public int getType() {
    283         return mType;
    284     }
    285 
    286     /**
    287      * Gets the display address, or null if none.
    288      * Interpretation varies by display type.
    289      *
    290      * @return The display address.
    291      * @hide
    292      */
    293     public String getAddress() {
    294         return mAddress;
    295     }
    296 
    297     /**
    298      * Gets the compatibility info used by this display instance.
    299      *
    300      * @return The compatibility info holder, or null if none is required.
    301      * @hide
    302      */
    303     public CompatibilityInfoHolder getCompatibilityInfo() {
    304         return mCompatibilityInfo;
    305     }
    306 
    307     /**
    308      * Gets the name of the display.
    309      * <p>
    310      * Note that some displays may be renamed by the user.
    311      * </p>
    312      *
    313      * @return The display's name.
    314      */
    315     public String getName() {
    316         synchronized (this) {
    317             updateDisplayInfoLocked();
    318             return mDisplayInfo.name;
    319         }
    320     }
    321 
    322     /**
    323      * Gets the size of the display, in pixels.
    324      * <p>
    325      * Note that this value should <em>not</em> be used for computing layouts,
    326      * since a device will typically have screen decoration (such as a status bar)
    327      * along the edges of the display that reduce the amount of application
    328      * space available from the size returned here.  Layouts should instead use
    329      * the window size.
    330      * </p><p>
    331      * The size is adjusted based on the current rotation of the display.
    332      * </p><p>
    333      * The size returned by this method does not necessarily represent the
    334      * actual raw size (native resolution) of the display.  The returned size may
    335      * be adjusted to exclude certain system decoration elements that are always visible.
    336      * It may also be scaled to provide compatibility with older applications that
    337      * were originally designed for smaller displays.
    338      * </p>
    339      *
    340      * @param outSize A {@link Point} object to receive the size information.
    341      */
    342     public void getSize(Point outSize) {
    343         synchronized (this) {
    344             updateDisplayInfoLocked();
    345             mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
    346             outSize.x = mTempMetrics.widthPixels;
    347             outSize.y = mTempMetrics.heightPixels;
    348         }
    349     }
    350 
    351     /**
    352      * Gets the size of the display as a rectangle, in pixels.
    353      *
    354      * @param outSize A {@link Rect} object to receive the size information.
    355      * @see #getSize(Point)
    356      */
    357     public void getRectSize(Rect outSize) {
    358         synchronized (this) {
    359             updateDisplayInfoLocked();
    360             mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
    361             outSize.set(0, 0, mTempMetrics.widthPixels, mTempMetrics.heightPixels);
    362         }
    363     }
    364 
    365     /**
    366      * Return the range of display sizes an application can expect to encounter
    367      * under normal operation, as long as there is no physical change in screen
    368      * size.  This is basically the sizes you will see as the orientation
    369      * changes, taking into account whatever screen decoration there is in
    370      * each rotation.  For example, the status bar is always at the top of the
    371      * screen, so it will reduce the height both in landscape and portrait, and
    372      * the smallest height returned here will be the smaller of the two.
    373      *
    374      * This is intended for applications to get an idea of the range of sizes
    375      * they will encounter while going through device rotations, to provide a
    376      * stable UI through rotation.  The sizes here take into account all standard
    377      * system decorations that reduce the size actually available to the
    378      * application: the status bar, navigation bar, system bar, etc.  It does
    379      * <em>not</em> take into account more transient elements like an IME
    380      * soft keyboard.
    381      *
    382      * @param outSmallestSize Filled in with the smallest width and height
    383      * that the application will encounter, in pixels (not dp units).  The x
    384      * (width) dimension here directly corresponds to
    385      * {@link android.content.res.Configuration#smallestScreenWidthDp
    386      * Configuration.smallestScreenWidthDp}, except the value here is in raw
    387      * screen pixels rather than dp units.  Your application may of course
    388      * still get smaller space yet if, for example, a soft keyboard is
    389      * being displayed.
    390      * @param outLargestSize Filled in with the largest width and height
    391      * that the application will encounter, in pixels (not dp units).  Your
    392      * application may of course still get larger space than this if,
    393      * for example, screen decorations like the status bar are being hidden.
    394      */
    395     public void getCurrentSizeRange(Point outSmallestSize, Point outLargestSize) {
    396         synchronized (this) {
    397             updateDisplayInfoLocked();
    398             outSmallestSize.x = mDisplayInfo.smallestNominalAppWidth;
    399             outSmallestSize.y = mDisplayInfo.smallestNominalAppHeight;
    400             outLargestSize.x = mDisplayInfo.largestNominalAppWidth;
    401             outLargestSize.y = mDisplayInfo.largestNominalAppHeight;
    402         }
    403     }
    404 
    405     /**
    406      * Return the maximum screen size dimension that will happen.  This is
    407      * mostly for wallpapers.
    408      * @hide
    409      */
    410     public int getMaximumSizeDimension() {
    411         synchronized (this) {
    412             updateDisplayInfoLocked();
    413             return Math.max(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
    414         }
    415     }
    416 
    417     /**
    418      * @deprecated Use {@link #getSize(Point)} instead.
    419      */
    420     @Deprecated
    421     public int getWidth() {
    422         synchronized (this) {
    423             updateCachedAppSizeIfNeededLocked();
    424             return mCachedAppWidthCompat;
    425         }
    426     }
    427 
    428     /**
    429      * @deprecated Use {@link #getSize(Point)} instead.
    430      */
    431     @Deprecated
    432     public int getHeight() {
    433         synchronized (this) {
    434             updateCachedAppSizeIfNeededLocked();
    435             return mCachedAppHeightCompat;
    436         }
    437     }
    438 
    439     /**
    440      * @hide
    441      * Return a rectangle defining the insets of the overscan region of the display.
    442      * Each field of the rectangle is the number of pixels the overscan area extends
    443      * into the display on that side.
    444      */
    445     public void getOverscanInsets(Rect outRect) {
    446         synchronized (this) {
    447             updateDisplayInfoLocked();
    448             outRect.set(mDisplayInfo.overscanLeft, mDisplayInfo.overscanTop,
    449                     mDisplayInfo.overscanRight, mDisplayInfo.overscanBottom);
    450         }
    451     }
    452 
    453     /**
    454      * Returns the rotation of the screen from its "natural" orientation.
    455      * The returned value may be {@link Surface#ROTATION_0 Surface.ROTATION_0}
    456      * (no rotation), {@link Surface#ROTATION_90 Surface.ROTATION_90},
    457      * {@link Surface#ROTATION_180 Surface.ROTATION_180}, or
    458      * {@link Surface#ROTATION_270 Surface.ROTATION_270}.  For
    459      * example, if a device has a naturally tall screen, and the user has
    460      * turned it on its side to go into a landscape orientation, the value
    461      * returned here may be either {@link Surface#ROTATION_90 Surface.ROTATION_90}
    462      * or {@link Surface#ROTATION_270 Surface.ROTATION_270} depending on
    463      * the direction it was turned.  The angle is the rotation of the drawn
    464      * graphics on the screen, which is the opposite direction of the physical
    465      * rotation of the device.  For example, if the device is rotated 90
    466      * degrees counter-clockwise, to compensate rendering will be rotated by
    467      * 90 degrees clockwise and thus the returned value here will be
    468      * {@link Surface#ROTATION_90 Surface.ROTATION_90}.
    469      */
    470     public int getRotation() {
    471         synchronized (this) {
    472             updateDisplayInfoLocked();
    473             return mDisplayInfo.rotation;
    474         }
    475     }
    476 
    477     /**
    478      * @deprecated use {@link #getRotation}
    479      * @return orientation of this display.
    480      */
    481     @Deprecated
    482     public int getOrientation() {
    483         return getRotation();
    484     }
    485 
    486     /**
    487      * Gets the pixel format of the display.
    488      * @return One of the constants defined in {@link android.graphics.PixelFormat}.
    489      *
    490      * @deprecated This method is no longer supported.
    491      * The result is always {@link PixelFormat#RGBA_8888}.
    492      */
    493     @Deprecated
    494     public int getPixelFormat() {
    495         return PixelFormat.RGBA_8888;
    496     }
    497 
    498     /**
    499      * Gets the refresh rate of this display in frames per second.
    500      */
    501     public float getRefreshRate() {
    502         synchronized (this) {
    503             updateDisplayInfoLocked();
    504             return mDisplayInfo.refreshRate;
    505         }
    506     }
    507 
    508     /**
    509      * Gets display metrics that describe the size and density of this display.
    510      * <p>
    511      * The size is adjusted based on the current rotation of the display.
    512      * </p><p>
    513      * The size returned by this method does not necessarily represent the
    514      * actual raw size (native resolution) of the display.  The returned size may
    515      * be adjusted to exclude certain system decor elements that are always visible.
    516      * It may also be scaled to provide compatibility with older applications that
    517      * were originally designed for smaller displays.
    518      * </p>
    519      *
    520      * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
    521      */
    522     public void getMetrics(DisplayMetrics outMetrics) {
    523         synchronized (this) {
    524             updateDisplayInfoLocked();
    525             mDisplayInfo.getAppMetrics(outMetrics, mCompatibilityInfo);
    526         }
    527     }
    528 
    529     /**
    530      * Gets the real size of the display without subtracting any window decor or
    531      * applying any compatibility scale factors.
    532      * <p>
    533      * The size is adjusted based on the current rotation of the display.
    534      * </p><p>
    535      * The real size may be smaller than the physical size of the screen when the
    536      * window manager is emulating a smaller display (using adb shell am display-size).
    537      * </p>
    538      *
    539      * @param outSize Set to the real size of the display.
    540      */
    541     public void getRealSize(Point outSize) {
    542         synchronized (this) {
    543             updateDisplayInfoLocked();
    544             outSize.x = mDisplayInfo.logicalWidth;
    545             outSize.y = mDisplayInfo.logicalHeight;
    546         }
    547     }
    548 
    549     /**
    550      * Gets display metrics based on the real size of this display.
    551      * <p>
    552      * The size is adjusted based on the current rotation of the display.
    553      * </p><p>
    554      * The real size may be smaller than the physical size of the screen when the
    555      * window manager is emulating a smaller display (using adb shell am display-size).
    556      * </p>
    557      *
    558      * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
    559      */
    560     public void getRealMetrics(DisplayMetrics outMetrics) {
    561         synchronized (this) {
    562             updateDisplayInfoLocked();
    563             mDisplayInfo.getLogicalMetrics(outMetrics, null);
    564         }
    565     }
    566 
    567     private void updateDisplayInfoLocked() {
    568         // Note: The display manager caches display info objects on our behalf.
    569         DisplayInfo newInfo = mGlobal.getDisplayInfo(mDisplayId);
    570         if (newInfo == null) {
    571             // Preserve the old mDisplayInfo after the display is removed.
    572             if (mIsValid) {
    573                 mIsValid = false;
    574                 if (DEBUG) {
    575                     Log.d(TAG, "Logical display " + mDisplayId + " was removed.");
    576                 }
    577             }
    578         } else {
    579             // Use the new display info.  (It might be the same object if nothing changed.)
    580             mDisplayInfo = newInfo;
    581             if (!mIsValid) {
    582                 mIsValid = true;
    583                 if (DEBUG) {
    584                     Log.d(TAG, "Logical display " + mDisplayId + " was recreated.");
    585                 }
    586             }
    587         }
    588     }
    589 
    590     private void updateCachedAppSizeIfNeededLocked() {
    591         long now = SystemClock.uptimeMillis();
    592         if (now > mLastCachedAppSizeUpdate + CACHED_APP_SIZE_DURATION_MILLIS) {
    593             updateDisplayInfoLocked();
    594             mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
    595             mCachedAppWidthCompat = mTempMetrics.widthPixels;
    596             mCachedAppHeightCompat = mTempMetrics.heightPixels;
    597             mLastCachedAppSizeUpdate = now;
    598         }
    599     }
    600 
    601     // For debugging purposes
    602     @Override
    603     public String toString() {
    604         synchronized (this) {
    605             updateDisplayInfoLocked();
    606             mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
    607             return "Display id " + mDisplayId + ": " + mDisplayInfo
    608                     + ", " + mTempMetrics + ", isValid=" + mIsValid;
    609         }
    610     }
    611 
    612     /**
    613      * @hide
    614      */
    615     public static String typeToString(int type) {
    616         switch (type) {
    617             case TYPE_UNKNOWN:
    618                 return "UNKNOWN";
    619             case TYPE_BUILT_IN:
    620                 return "BUILT_IN";
    621             case TYPE_HDMI:
    622                 return "HDMI";
    623             case TYPE_WIFI:
    624                 return "WIFI";
    625             case TYPE_OVERLAY:
    626                 return "OVERLAY";
    627             default:
    628                 return Integer.toString(type);
    629         }
    630     }
    631 }
    632 
    633