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