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