• 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.content.res.CompatibilityInfo;
20 import android.graphics.Point;
21 import android.graphics.Rect;
22 import android.os.RemoteException;
23 import android.os.ServiceManager;
24 import android.os.SystemClock;
25 import android.util.DisplayMetrics;
26 import android.util.Slog;
27 
28 /**
29  * Provides information about the display size and density.
30  */
31 public class Display {
32     static final String TAG = "Display";
33     static final boolean DEBUG_DISPLAY_SIZE = false;
34 
35     /**
36      * The default Display id.
37      */
38     public static final int DEFAULT_DISPLAY = 0;
39 
40     /**
41      * Use {@link android.view.WindowManager#getDefaultDisplay()
42      * WindowManager.getDefaultDisplay()} to create a Display object.
43      * Display gives you access to some information about a particular display
44      * connected to the device.
45      */
Display(int display, CompatibilityInfoHolder compatInfo)46     Display(int display, CompatibilityInfoHolder compatInfo) {
47         // initalize the statics when this class is first instansiated. This is
48         // done here instead of in the static block because Zygote
49         synchronized (sStaticInit) {
50             if (!sInitialized) {
51                 nativeClassInit();
52                 sInitialized = true;
53             }
54         }
55         mCompatibilityInfo = compatInfo != null ? compatInfo : new CompatibilityInfoHolder();
56         mDisplay = display;
57         init(display);
58     }
59 
60     /**
61      * Returns the index of this display.  This is currently undefined; do
62      * not use.
63      */
getDisplayId()64     public int getDisplayId() {
65         return mDisplay;
66     }
67 
68     /**
69      * Returns the number of displays connected to the device.  This is
70      * currently undefined; do not use.
71      */
getDisplayCount()72     native static int getDisplayCount();
73 
74     /**
75      * Gets the size of the display, in pixels.
76      * <p>
77      * Note that this value should <em>not</em> be used for computing layouts,
78      * since a device will typically have screen decoration (such as a status bar)
79      * along the edges of the display that reduce the amount of application
80      * space available from the size returned here.  Layouts should instead use
81      * the window size.
82      * </p><p>
83      * The size is adjusted based on the current rotation of the display.
84      * </p><p>
85      * The size returned by this method does not necessarily represent the
86      * actual raw size (native resolution) of the display.  The returned size may
87      * be adjusted to exclude certain system decor elements that are always visible.
88      * It may also be scaled to provide compatibility with older applications that
89      * were originally designed for smaller displays.
90      * </p>
91      *
92      * @param outSize A {@link Point} object to receive the size information.
93      */
getSize(Point outSize)94     public void getSize(Point outSize) {
95         getSizeInternal(outSize, true);
96     }
97 
getSizeInternal(Point outSize, boolean doCompat)98     private void getSizeInternal(Point outSize, boolean doCompat) {
99         try {
100             IWindowManager wm = getWindowManager();
101             if (wm != null) {
102                 wm.getDisplaySize(outSize);
103                 CompatibilityInfo ci;
104                 if (doCompat && (ci=mCompatibilityInfo.getIfNeeded()) != null) {
105                     synchronized (mTmpMetrics) {
106                         mTmpMetrics.noncompatWidthPixels = outSize.x;
107                         mTmpMetrics.noncompatHeightPixels = outSize.y;
108                         mTmpMetrics.density = mDensity;
109                         ci.applyToDisplayMetrics(mTmpMetrics);
110                         outSize.x = mTmpMetrics.widthPixels;
111                         outSize.y = mTmpMetrics.heightPixels;
112                     }
113                 }
114             } else {
115                 // This is just for boot-strapping, initializing the
116                 // system process before the window manager is up.
117                 outSize.x = getRawWidth();
118                 outSize.y = getRawHeight();
119             }
120             if (false) {
121                 RuntimeException here = new RuntimeException("here");
122                 here.fillInStackTrace();
123                 Slog.v(TAG, "Returning display size: " + outSize, here);
124             }
125             if (DEBUG_DISPLAY_SIZE && doCompat) Slog.v(
126                     TAG, "Returning display size: " + outSize);
127         } catch (RemoteException e) {
128             Slog.w("Display", "Unable to get display size", e);
129         }
130     }
131 
132     /**
133      * Gets the size of the display as a rectangle, in pixels.
134      *
135      * @param outSize A {@link Rect} object to receive the size information.
136      * @see #getSize(Point)
137      */
getRectSize(Rect outSize)138     public void getRectSize(Rect outSize) {
139         synchronized (mTmpPoint) {
140             getSizeInternal(mTmpPoint, true);
141             outSize.set(0, 0, mTmpPoint.x, mTmpPoint.y);
142         }
143     }
144 
145     /**
146      * Return the maximum screen size dimension that will happen.  This is
147      * mostly for wallpapers.
148      * @hide
149      */
getMaximumSizeDimension()150     public int getMaximumSizeDimension() {
151         try {
152             IWindowManager wm = getWindowManager();
153             return wm.getMaximumSizeDimension();
154         } catch (RemoteException e) {
155             Slog.w("Display", "Unable to get display maximum size dimension", e);
156             return 0;
157         }
158     }
159 
160     /**
161      * @deprecated Use {@link #getSize(Point)} instead.
162      */
163     @Deprecated
getWidth()164     public int getWidth() {
165         synchronized (mTmpPoint) {
166             long now = SystemClock.uptimeMillis();
167             if (now > (mLastGetTime+20)) {
168                 getSizeInternal(mTmpPoint, true);
169                 mLastGetTime = now;
170             }
171             return mTmpPoint.x;
172         }
173     }
174 
175     /**
176      * @deprecated Use {@link #getSize(Point)} instead.
177      */
178     @Deprecated
getHeight()179     public int getHeight() {
180         synchronized (mTmpPoint) {
181             long now = SystemClock.uptimeMillis();
182             if (now > (mLastGetTime+20)) {
183                 getSizeInternal(mTmpPoint, true);
184                 mLastGetTime = now;
185             }
186             return mTmpPoint.y;
187         }
188     }
189 
190     /**
191      * Gets the real size of the display without subtracting any window decor or
192      * applying any compatibility scale factors.
193      * <p>
194      * The real size may be smaller than the raw size when the window manager
195      * is emulating a smaller display (using adb shell am display-size).
196      * </p><p>
197      * The size is adjusted based on the current rotation of the display.
198      * </p>
199      * @hide
200      */
getRealSize(Point outSize)201     public void getRealSize(Point outSize) {
202         try {
203             IWindowManager wm = getWindowManager();
204             if (wm != null) {
205                 wm.getRealDisplaySize(outSize);
206             } else {
207                 // This is just for boot-strapping, initializing the
208                 // system process before the window manager is up.
209                 outSize.x = getRawWidth();
210                 outSize.y = getRawHeight();
211             }
212             if (DEBUG_DISPLAY_SIZE) Slog.v(
213                     TAG, "Returning real display size: " + outSize);
214         } catch (RemoteException e) {
215             Slog.w("Display", "Unable to get real display size", e);
216         }
217     }
218 
219     /**
220      * Gets the raw width of the display, in pixels.
221      * <p>
222      * The size is adjusted based on the current rotation of the display.
223      * </p>
224      * @hide
225      */
getRawWidth()226     public int getRawWidth() {
227         int w = getRawWidthNative();
228         if (DEBUG_DISPLAY_SIZE) Slog.v(
229                 TAG, "Returning raw display width: " + w);
230         return w;
231     }
getRawWidthNative()232     private native int getRawWidthNative();
233 
234     /**
235      * Gets the raw height of the display, in pixels.
236      * <p>
237      * The size is adjusted based on the current rotation of the display.
238      * </p>
239      * @hide
240      */
getRawHeight()241     public int getRawHeight() {
242         int h = getRawHeightNative();
243         if (DEBUG_DISPLAY_SIZE) Slog.v(
244                 TAG, "Returning raw display height: " + h);
245         return h;
246     }
getRawHeightNative()247     private native int getRawHeightNative();
248 
249     /**
250      * Returns the rotation of the screen from its "natural" orientation.
251      * The returned value may be {@link Surface#ROTATION_0 Surface.ROTATION_0}
252      * (no rotation), {@link Surface#ROTATION_90 Surface.ROTATION_90},
253      * {@link Surface#ROTATION_180 Surface.ROTATION_180}, or
254      * {@link Surface#ROTATION_270 Surface.ROTATION_270}.  For
255      * example, if a device has a naturally tall screen, and the user has
256      * turned it on its side to go into a landscape orientation, the value
257      * returned here may be either {@link Surface#ROTATION_90 Surface.ROTATION_90}
258      * or {@link Surface#ROTATION_270 Surface.ROTATION_270} depending on
259      * the direction it was turned.  The angle is the rotation of the drawn
260      * graphics on the screen, which is the opposite direction of the physical
261      * rotation of the device.  For example, if the device is rotated 90
262      * degrees counter-clockwise, to compensate rendering will be rotated by
263      * 90 degrees clockwise and thus the returned value here will be
264      * {@link Surface#ROTATION_90 Surface.ROTATION_90}.
265      */
getRotation()266     public int getRotation() {
267         return getOrientation();
268     }
269 
270     /**
271      * @deprecated use {@link #getRotation}
272      * @return orientation of this display.
273      */
getOrientation()274     @Deprecated native public int getOrientation();
275 
276     /**
277      * Return the native pixel format of the display.  The returned value
278      * may be one of the constants int {@link android.graphics.PixelFormat}.
279      */
getPixelFormat()280     public int getPixelFormat() {
281         return mPixelFormat;
282     }
283 
284     /**
285      * Return the refresh rate of this display in frames per second.
286      */
getRefreshRate()287     public float getRefreshRate() {
288         return mRefreshRate;
289     }
290 
291     /**
292      * Gets display metrics that describe the size and density of this display.
293      * <p>
294      * The size is adjusted based on the current rotation of the display.
295      * </p><p>
296      * The size returned by this method does not necessarily represent the
297      * actual raw size (native resolution) of the display.  The returned size may
298      * be adjusted to exclude certain system decor elements that are always visible.
299      * It may also be scaled to provide compatibility with older applications that
300      * were originally designed for smaller displays.
301      * </p>
302      *
303      * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
304      */
getMetrics(DisplayMetrics outMetrics)305     public void getMetrics(DisplayMetrics outMetrics) {
306         synchronized (mTmpPoint) {
307             getSizeInternal(mTmpPoint, false);
308             getMetricsWithSize(outMetrics, mTmpPoint.x, mTmpPoint.y);
309         }
310 
311         CompatibilityInfo ci = mCompatibilityInfo.getIfNeeded();
312         if (ci != null) {
313             ci.applyToDisplayMetrics(outMetrics);
314         }
315 
316         if (DEBUG_DISPLAY_SIZE) Slog.v(TAG, "Returning DisplayMetrics: "
317                 + outMetrics.widthPixels + "x" + outMetrics.heightPixels
318                 + " " + outMetrics.density);
319     }
320 
321     /**
322      * Gets display metrics based on the real size of this display.
323      * @hide
324      */
getRealMetrics(DisplayMetrics outMetrics)325     public void getRealMetrics(DisplayMetrics outMetrics) {
326         synchronized (mTmpPoint) {
327             getRealSize(mTmpPoint);
328             getMetricsWithSize(outMetrics, mTmpPoint.x, mTmpPoint.y);
329         }
330     }
331 
332     /**
333      * If the display is mirrored to an external HDMI display, returns the
334      * width of that display.
335      * @hide
336      */
getRawExternalWidth()337     public int getRawExternalWidth() {
338         return 1280;
339     }
340 
341     /**
342      * If the display is mirrored to an external HDMI display, returns the
343      * height of that display.
344      * @hide
345      */
getRawExternalHeight()346     public int getRawExternalHeight() {
347         return 720;
348     }
349 
350     /**
351      * Gets display metrics based on an explicit assumed display size.
352      * @hide
353      */
getMetricsWithSize(DisplayMetrics outMetrics, int width, int height)354     public void getMetricsWithSize(DisplayMetrics outMetrics,
355             int width, int height) {
356         outMetrics.densityDpi   = (int)((mDensity*DisplayMetrics.DENSITY_DEFAULT)+.5f);
357 
358         outMetrics.noncompatWidthPixels  = outMetrics.widthPixels = width;
359         outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
360 
361         outMetrics.density = outMetrics.noncompatDensity = mDensity;
362         outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density;
363         outMetrics.xdpi = outMetrics.noncompatXdpi = mDpiX;
364         outMetrics.ydpi = outMetrics.noncompatYdpi = mDpiY;
365     }
366 
getWindowManager()367     static IWindowManager getWindowManager() {
368         synchronized (sStaticInit) {
369             if (sWindowManager == null) {
370                 sWindowManager = IWindowManager.Stub.asInterface(
371                         ServiceManager.getService("window"));
372             }
373             return sWindowManager;
374         }
375     }
376 
377     /*
378      * We use a class initializer to allow the native code to cache some
379      * field offsets.
380      */
nativeClassInit()381     native private static void nativeClassInit();
382 
init(int display)383     private native void init(int display);
384 
385     private final CompatibilityInfoHolder mCompatibilityInfo;
386     private final int   mDisplay;
387     // Following fields are initialized from native code
388     private int         mPixelFormat;
389     private float       mRefreshRate;
390     /*package*/ float   mDensity;
391     /*package*/ float   mDpiX;
392     /*package*/ float   mDpiY;
393 
394     private final Point mTmpPoint = new Point();
395     private final DisplayMetrics mTmpMetrics = new DisplayMetrics();
396     private float mLastGetTime;
397 
398     private static final Object sStaticInit = new Object();
399     private static boolean sInitialized = false;
400     private static IWindowManager sWindowManager;
401 
402     /**
403      * Returns a display object which uses the metric's width/height instead.
404      * @hide
405      */
createCompatibleDisplay(int displayId, CompatibilityInfoHolder compat)406     public static Display createCompatibleDisplay(int displayId, CompatibilityInfoHolder compat) {
407         return new Display(displayId, compat);
408     }
409 }
410 
411