DisplayMetrics.java revision a53b828635fce8b6b2d3e3377d74d72070056623
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.util;
18
19import android.content.res.CompatibilityInfo;
20import android.content.res.Configuration;
21import android.os.*;
22
23
24/**
25 * A structure describing general information about a display, such as its
26 * size, density, and font scaling.
27 */
28public class DisplayMetrics {
29    /**
30     * Standard quantized DPI for low-density screens.
31     */
32    public static final int DENSITY_LOW = 120;
33
34    /**
35     * Standard quantized DPI for medium-density screens.
36     */
37    public static final int DENSITY_MEDIUM = 160;
38
39    /**
40     * Standard quantized DPI for high-density screens.
41     */
42    public static final int DENSITY_HIGH = 240;
43
44    /**
45     * The reference density used throughout the system.
46     */
47    public static final int DENSITY_DEFAULT = DENSITY_MEDIUM;
48
49    /**
50     * The device's density.
51     * @hide becase eventually this should be able to change while
52     * running, so shouldn't be a constant.
53     */
54    public static final int DENSITY_DEVICE = getDeviceDensity();
55
56    /**
57     * The absolute width of the display in pixels.
58     */
59    public int widthPixels;
60    /**
61     * The absolute height of the display in pixels.
62     */
63    public int heightPixels;
64    /**
65     * The logical density of the display.  This is a scaling factor for the
66     * Density Independent Pixel unit, where one DIP is one pixel on an
67     * approximately 160 dpi screen (for example a 240x320, 1.5"x2" screen),
68     * providing the baseline of the system's display. Thus on a 160dpi screen
69     * this density value will be 1; on a 106 dpi screen it would be .75; etc.
70     *
71     * <p>This value does not exactly follow the real screen size (as given by
72     * {@link #xdpi} and {@link #ydpi}, but rather is used to scale the size of
73     * the overall UI in steps based on gross changes in the display dpi.  For
74     * example, a 240x320 screen will have a density of 1 even if its width is
75     * 1.8", 1.3", etc. However, if the screen resolution is increased to
76     * 320x480 but the screen size remained 1.5"x2" then the density would be
77     * increased (probably to 1.5).
78     *
79     * @see #DENSITY_DEFAULT
80     */
81    public float density;
82    /**
83     * A scaling factor for fonts displayed on the display.  This is the same
84     * as {@link #density}, except that it may be adjusted in smaller
85     * increments at runtime based on a user preference for the font size.
86     */
87    public float scaledDensity;
88    /**
89     * The exact physical pixels per inch of the screen in the X dimension.
90     */
91    public float xdpi;
92    /**
93     * The exact physical pixels per inch of the screen in the Y dimension.
94     */
95    public float ydpi;
96
97    public DisplayMetrics() {
98    }
99
100    public void setTo(DisplayMetrics o) {
101        widthPixels = o.widthPixels;
102        heightPixels = o.heightPixels;
103        density = o.density;
104        scaledDensity = o.scaledDensity;
105        xdpi = o.xdpi;
106        ydpi = o.ydpi;
107    }
108
109    public void setToDefaults() {
110        widthPixels = 0;
111        heightPixels = 0;
112        density = DENSITY_DEVICE / (float) DENSITY_DEFAULT;
113        scaledDensity = density;
114        xdpi = DENSITY_DEVICE;
115        ydpi = DENSITY_DEVICE;
116    }
117
118    /**
119     * Update the display metrics based on the compatibility info and orientation
120     * NOTE: DO NOT EXPOSE THIS API!  It is introducing a circular dependency
121     * with the higher-level android.res package.
122     * {@hide}
123     */
124    public void updateMetrics(CompatibilityInfo compatibilityInfo, int orientation,
125            int screenLayout) {
126        if (!compatibilityInfo.isConfiguredExpandable()) {
127            // Note: this assume that configuration is updated before calling
128            // updateMetrics method.
129            if (screenLayout == Configuration.SCREENLAYOUT_LARGE) {
130                // This is a large screen device and the app is not
131                // compatible with large screens, to diddle it.
132
133                compatibilityInfo.setExpandable(false);
134                // Figure out the compatibility width and height of the screen.
135                int defaultWidth;
136                int defaultHeight;
137                switch (orientation) {
138                    case Configuration.ORIENTATION_LANDSCAPE: {
139                        defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density);
140                        defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density);
141                        break;
142                    }
143                    case Configuration.ORIENTATION_PORTRAIT:
144                    case Configuration.ORIENTATION_SQUARE:
145                    default: {
146                        defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density);
147                        defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density);
148                        break;
149                    }
150                    case Configuration.ORIENTATION_UNDEFINED: {
151                        // don't change
152                        return;
153                    }
154                }
155
156                if (defaultWidth < widthPixels) {
157                    // content/window's x offset in original pixels
158                    widthPixels = defaultWidth;
159                }
160                if (defaultHeight < heightPixels) {
161                    heightPixels = defaultHeight;
162                }
163
164            } else {
165                // the screen size is same as expected size. make it expandable
166                compatibilityInfo.setExpandable(true);
167            }
168        }
169        if (compatibilityInfo.isScalingRequired()) {
170            float invertedRatio = compatibilityInfo.applicationInvertedScale;
171            density *= invertedRatio;
172            scaledDensity *= invertedRatio;
173            xdpi *= invertedRatio;
174            ydpi *= invertedRatio;
175            widthPixels *= invertedRatio;
176            heightPixels *= invertedRatio;
177        }
178    }
179
180    @Override
181    public String toString() {
182        return "DisplayMetrics{density=" + density + ", width=" + widthPixels +
183            ", height=" + heightPixels + ", scaledDensity=" + scaledDensity +
184            ", xdpi=" + xdpi + ", ydpi=" + ydpi + "}";
185    }
186
187    private static int getDeviceDensity() {
188        // qemu.sf.lcd_density can be used to override ro.sf.lcd_density
189        // when running in the emulator, allowing for dynamic configurations.
190        // The reason for this is that ro.sf.lcd_density is write-once and is
191        // set by the init process when it parses build.prop before anything else.
192        return SystemProperties.getInt("qemu.sf.lcd_density",
193                SystemProperties.getInt("ro.sf.lcd_density", DENSITY_DEFAULT));
194    }
195}
196