• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
Display(DisplayManagerGlobal global, int displayId, DisplayInfo displayInfo , CompatibilityInfoHolder compatibilityInfo)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      */
getDisplayId()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      */
isValid()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      */
getDisplayInfo(DisplayInfo outDisplayInfo)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      */
getLayerStack()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      */
getFlags()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      */
getType()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      */
getAddress()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      */
getCompatibilityInfo()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      */
getName()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      */
getSize(Point outSize)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      */
getRectSize(Rect outSize)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      */
getCurrentSizeRange(Point outSmallestSize, Point outLargestSize)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      */
getMaximumSizeDimension()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
getWidth()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
getHeight()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      */
getOverscanInsets(Rect outRect)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      */
getRotation()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
getOrientation()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
getPixelFormat()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      */
getRefreshRate()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      */
getMetrics(DisplayMetrics outMetrics)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      */
getRealSize(Point outSize)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      */
getRealMetrics(DisplayMetrics outMetrics)560     public void getRealMetrics(DisplayMetrics outMetrics) {
561         synchronized (this) {
562             updateDisplayInfoLocked();
563             mDisplayInfo.getLogicalMetrics(outMetrics, null);
564         }
565     }
566 
updateDisplayInfoLocked()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 
updateCachedAppSizeIfNeededLocked()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
toString()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      */
typeToString(int type)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