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      */
Display(DisplayManagerGlobal global, int displayId, DisplayInfo displayInfo , DisplayAdjustments daj)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      */
getDisplayId()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      */
isValid()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      */
getDisplayInfo(DisplayInfo outDisplayInfo)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      */
getLayerStack()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      */
getFlags()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      */
getType()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      */
getAddress()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      */
getOwnerUid()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      */
getOwnerPackageName()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      */
getDisplayAdjustments()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      */
getName()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      */
getSize(Point outSize)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      */
getRectSize(Rect outSize)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      */
getCurrentSizeRange(Point outSmallestSize, Point outLargestSize)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      */
getMaximumSizeDimension()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
getWidth()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
getHeight()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      */
getOverscanInsets(Rect outRect)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
getRotation()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
getOrientation()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
getPixelFormat()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      */
getRefreshRate()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
getSupportedRefreshRates()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      */
getMode()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      */
getSupportedModes()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      */
getAppVsyncOffsetNanos()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      */
getPresentationDeadlineNanos()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      */
getMetrics(DisplayMetrics outMetrics)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      */
getRealSize(Point outSize)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      */
getRealMetrics(DisplayMetrics outMetrics)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      */
getState()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      */
hasAccess(int uid)793     public boolean hasAccess(int uid) {
794         return Display.hasAccess(uid, mFlags, mOwnerUid);
795     }
796 
797     /** @hide */
hasAccess(int uid, int flags, int ownerUid)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      */
isPublicPresentation()809     public boolean isPublicPresentation() {
810         return (mFlags & (Display.FLAG_PRIVATE | Display.FLAG_PRESENTATION)) ==
811                 Display.FLAG_PRESENTATION;
812     }
813 
updateDisplayInfoLocked()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 
updateCachedAppSizeIfNeededLocked()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
toString()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      */
typeToString(int type)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      */
stateToString(int state)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      */
isSuspendedState(int state)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          */
Mode(int modeId, int width, int height, float refreshRate)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          */
getModeId()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          */
getPhysicalWidth()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          */
getPhysicalHeight()971         public int getPhysicalHeight() {
972             return mHeight;
973         }
974 
975         /**
976          * Returns the refresh rate in frames per second.
977          */
getRefreshRate()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          */
matches(int width, int height, float refreshRate)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
equals(Object other)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
hashCode()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
toString()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
describeContents()1027         public int describeContents() {
1028             return 0;
1029         }
1030 
Mode(Parcel in)1031         private Mode(Parcel in) {
1032             this(in.readInt(), in.readInt(), in.readInt(), in.readFloat());
1033         }
1034 
1035         @Override
writeToParcel(Parcel out, int parcelableFlags)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