• 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      * Returns the rotation of the screen from its "natural" orientation.
441      * The returned value may be {@link Surface#ROTATION_0 Surface.ROTATION_0}
442      * (no rotation), {@link Surface#ROTATION_90 Surface.ROTATION_90},
443      * {@link Surface#ROTATION_180 Surface.ROTATION_180}, or
444      * {@link Surface#ROTATION_270 Surface.ROTATION_270}.  For
445      * example, if a device has a naturally tall screen, and the user has
446      * turned it on its side to go into a landscape orientation, the value
447      * returned here may be either {@link Surface#ROTATION_90 Surface.ROTATION_90}
448      * or {@link Surface#ROTATION_270 Surface.ROTATION_270} depending on
449      * the direction it was turned.  The angle is the rotation of the drawn
450      * graphics on the screen, which is the opposite direction of the physical
451      * rotation of the device.  For example, if the device is rotated 90
452      * degrees counter-clockwise, to compensate rendering will be rotated by
453      * 90 degrees clockwise and thus the returned value here will be
454      * {@link Surface#ROTATION_90 Surface.ROTATION_90}.
455      */
getRotation()456     public int getRotation() {
457         synchronized (this) {
458             updateDisplayInfoLocked();
459             return mDisplayInfo.rotation;
460         }
461     }
462 
463     /**
464      * @deprecated use {@link #getRotation}
465      * @return orientation of this display.
466      */
467     @Deprecated
getOrientation()468     public int getOrientation() {
469         return getRotation();
470     }
471 
472     /**
473      * Gets the pixel format of the display.
474      * @return One of the constants defined in {@link android.graphics.PixelFormat}.
475      *
476      * @deprecated This method is no longer supported.
477      * The result is always {@link PixelFormat#RGBA_8888}.
478      */
479     @Deprecated
getPixelFormat()480     public int getPixelFormat() {
481         return PixelFormat.RGBA_8888;
482     }
483 
484     /**
485      * Gets the refresh rate of this display in frames per second.
486      */
getRefreshRate()487     public float getRefreshRate() {
488         synchronized (this) {
489             updateDisplayInfoLocked();
490             return mDisplayInfo.refreshRate;
491         }
492     }
493 
494     /**
495      * Gets display metrics that describe the size and density of this display.
496      * <p>
497      * The size is adjusted based on the current rotation of the display.
498      * </p><p>
499      * The size returned by this method does not necessarily represent the
500      * actual raw size (native resolution) of the display.  The returned size may
501      * be adjusted to exclude certain system decor elements that are always visible.
502      * It may also be scaled to provide compatibility with older applications that
503      * were originally designed for smaller displays.
504      * </p>
505      *
506      * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
507      */
getMetrics(DisplayMetrics outMetrics)508     public void getMetrics(DisplayMetrics outMetrics) {
509         synchronized (this) {
510             updateDisplayInfoLocked();
511             mDisplayInfo.getAppMetrics(outMetrics, mCompatibilityInfo);
512         }
513     }
514 
515     /**
516      * Gets the real size of the display without subtracting any window decor or
517      * applying any compatibility scale factors.
518      * <p>
519      * The size is adjusted based on the current rotation of the display.
520      * </p><p>
521      * The real size may be smaller than the physical size of the screen when the
522      * window manager is emulating a smaller display (using adb shell am display-size).
523      * </p>
524      *
525      * @param outSize Set to the real size of the display.
526      */
getRealSize(Point outSize)527     public void getRealSize(Point outSize) {
528         synchronized (this) {
529             updateDisplayInfoLocked();
530             outSize.x = mDisplayInfo.logicalWidth;
531             outSize.y = mDisplayInfo.logicalHeight;
532         }
533     }
534 
535     /**
536      * Gets display metrics based on the real size of this display.
537      * <p>
538      * The size is adjusted based on the current rotation of the display.
539      * </p><p>
540      * The real size may be smaller than the physical size of the screen when the
541      * window manager is emulating a smaller display (using adb shell am display-size).
542      * </p>
543      *
544      * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
545      */
getRealMetrics(DisplayMetrics outMetrics)546     public void getRealMetrics(DisplayMetrics outMetrics) {
547         synchronized (this) {
548             updateDisplayInfoLocked();
549             mDisplayInfo.getLogicalMetrics(outMetrics, null);
550         }
551     }
552 
updateDisplayInfoLocked()553     private void updateDisplayInfoLocked() {
554         // Note: The display manager caches display info objects on our behalf.
555         DisplayInfo newInfo = mGlobal.getDisplayInfo(mDisplayId);
556         if (newInfo == null) {
557             // Preserve the old mDisplayInfo after the display is removed.
558             if (mIsValid) {
559                 mIsValid = false;
560                 if (DEBUG) {
561                     Log.d(TAG, "Logical display " + mDisplayId + " was removed.");
562                 }
563             }
564         } else {
565             // Use the new display info.  (It might be the same object if nothing changed.)
566             mDisplayInfo = newInfo;
567             if (!mIsValid) {
568                 mIsValid = true;
569                 if (DEBUG) {
570                     Log.d(TAG, "Logical display " + mDisplayId + " was recreated.");
571                 }
572             }
573         }
574     }
575 
updateCachedAppSizeIfNeededLocked()576     private void updateCachedAppSizeIfNeededLocked() {
577         long now = SystemClock.uptimeMillis();
578         if (now > mLastCachedAppSizeUpdate + CACHED_APP_SIZE_DURATION_MILLIS) {
579             updateDisplayInfoLocked();
580             mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
581             mCachedAppWidthCompat = mTempMetrics.widthPixels;
582             mCachedAppHeightCompat = mTempMetrics.heightPixels;
583             mLastCachedAppSizeUpdate = now;
584         }
585     }
586 
587     // For debugging purposes
588     @Override
toString()589     public String toString() {
590         synchronized (this) {
591             updateDisplayInfoLocked();
592             mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
593             return "Display id " + mDisplayId + ": " + mDisplayInfo
594                     + ", " + mTempMetrics + ", isValid=" + mIsValid;
595         }
596     }
597 
598     /**
599      * @hide
600      */
typeToString(int type)601     public static String typeToString(int type) {
602         switch (type) {
603             case TYPE_UNKNOWN:
604                 return "UNKNOWN";
605             case TYPE_BUILT_IN:
606                 return "BUILT_IN";
607             case TYPE_HDMI:
608                 return "HDMI";
609             case TYPE_WIFI:
610                 return "WIFI";
611             case TYPE_OVERLAY:
612                 return "OVERLAY";
613             default:
614                 return Integer.toString(type);
615         }
616     }
617 }
618 
619