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.util;
18 
19 import android.annotation.Nullable;
20 import android.compat.annotation.UnsupportedAppUsage;
21 import android.os.SystemProperties;
22 
23 /**
24  * A structure describing general information about a display, such as its
25  * size, density, and font scaling.
26  * <p>To access the DisplayMetrics members, retrieve display metrics like this:</p>
27  * <pre>context.getResources().getDisplayMetrics();</pre>
28  */
29 public class DisplayMetrics {
30     /**
31      * Standard quantized DPI for low-density screens.
32      */
33     public static final int DENSITY_LOW = 120;
34 
35     /**
36      * Intermediate density for screens that sit between {@link #DENSITY_LOW} (120dpi) and
37      * {@link #DENSITY_MEDIUM} (160dpi). This is not a density that applications should target,
38      * instead relying on the system to scale their {@link #DENSITY_MEDIUM} assets for them.
39      */
40     public static final int DENSITY_140 = 140;
41 
42     /**
43      * Standard quantized DPI for medium-density screens.
44      */
45     public static final int DENSITY_MEDIUM = 160;
46 
47     /**
48      * Intermediate density for screens that sit between {@link #DENSITY_MEDIUM} (160dpi) and
49      * {@link #DENSITY_HIGH} (240dpi). This is not a density that applications should target,
50      * instead relying on the system to scale their {@link #DENSITY_HIGH} assets for them.
51      */
52     public static final int DENSITY_180 = 180;
53 
54     /**
55      * Intermediate density for screens that sit between {@link #DENSITY_MEDIUM} (160dpi) and
56      * {@link #DENSITY_HIGH} (240dpi). This is not a density that applications should target,
57      * instead relying on the system to scale their {@link #DENSITY_HIGH} assets for them.
58      */
59     public static final int DENSITY_200 = 200;
60 
61     /**
62      * This is a secondary density, added for some common screen configurations.
63      * It is recommended that applications not generally target this as a first
64      * class density -- that is, don't supply specific graphics for this
65      * density, instead allow the platform to scale from other densities
66      * (typically {@link #DENSITY_HIGH}) as
67      * appropriate.  In most cases (such as using bitmaps in
68      * {@link android.graphics.drawable.Drawable}) the platform
69      * can perform this scaling at load time, so the only cost is some slight
70      * startup runtime overhead.
71      *
72      * <p>This density was original introduced to correspond with a
73      * 720p TV screen: the density for 1080p televisions is
74      * {@link #DENSITY_XHIGH}, and the value here provides the same UI
75      * size for a TV running at 720p.  It has also found use in 7" tablets,
76      * when these devices have 1280x720 displays.
77      */
78     public static final int DENSITY_TV = 213;
79 
80     /**
81      * Intermediate density for screens that sit between {@link #DENSITY_MEDIUM} (160dpi) and
82      * {@link #DENSITY_HIGH} (240dpi). This is not a density that applications should target,
83      * instead relying on the system to scale their {@link #DENSITY_HIGH} assets for them.
84      */
85     public static final int DENSITY_220 = 220;
86 
87     /**
88      * Standard quantized DPI for high-density screens.
89      */
90     public static final int DENSITY_HIGH = 240;
91 
92     /**
93      * Intermediate density for screens that sit between {@link #DENSITY_HIGH} (240dpi) and
94      * {@link #DENSITY_XHIGH} (320dpi). This is not a density that applications should target,
95      * instead relying on the system to scale their {@link #DENSITY_XHIGH} assets for them.
96      */
97     public static final int DENSITY_260 = 260;
98 
99     /**
100      * Intermediate density for screens that sit between {@link #DENSITY_HIGH} (240dpi) and
101      * {@link #DENSITY_XHIGH} (320dpi). This is not a density that applications should target,
102      * instead relying on the system to scale their {@link #DENSITY_XHIGH} assets for them.
103      */
104     public static final int DENSITY_280 = 280;
105 
106     /**
107      * Intermediate density for screens that sit between {@link #DENSITY_HIGH} (240dpi) and
108      * {@link #DENSITY_XHIGH} (320dpi). This is not a density that applications should target,
109      * instead relying on the system to scale their {@link #DENSITY_XHIGH} assets for them.
110      */
111     public static final int DENSITY_300 = 300;
112 
113     /**
114      * Standard quantized DPI for extra-high-density screens.
115      */
116     public static final int DENSITY_XHIGH = 320;
117 
118     /**
119      * Intermediate density for screens that sit somewhere between
120      * {@link #DENSITY_XHIGH} (320 dpi) and {@link #DENSITY_XXHIGH} (480 dpi).
121      * This is not a density that applications should target, instead relying
122      * on the system to scale their {@link #DENSITY_XXHIGH} assets for them.
123      */
124     public static final int DENSITY_340 = 340;
125 
126     /**
127      * Intermediate density for screens that sit somewhere between
128      * {@link #DENSITY_XHIGH} (320 dpi) and {@link #DENSITY_XXHIGH} (480 dpi).
129      * This is not a density that applications should target, instead relying
130      * on the system to scale their {@link #DENSITY_XXHIGH} assets for them.
131      */
132     public static final int DENSITY_360 = 360;
133 
134     /**
135      * Intermediate density for screens that sit somewhere between
136      * {@link #DENSITY_XHIGH} (320 dpi) and {@link #DENSITY_XXHIGH} (480 dpi).
137      * This is not a density that applications should target, instead relying
138      * on the system to scale their {@link #DENSITY_XXHIGH} assets for them.
139      */
140     public static final int DENSITY_400 = 400;
141 
142     /**
143      * Intermediate density for screens that sit somewhere between
144      * {@link #DENSITY_XHIGH} (320 dpi) and {@link #DENSITY_XXHIGH} (480 dpi).
145      * This is not a density that applications should target, instead relying
146      * on the system to scale their {@link #DENSITY_XXHIGH} assets for them.
147      */
148     public static final int DENSITY_420 = 420;
149 
150     /**
151      * Intermediate density for screens that sit somewhere between
152      * {@link #DENSITY_XHIGH} (320 dpi) and {@link #DENSITY_XXHIGH} (480 dpi).
153      * This is not a density that applications should target, instead relying
154      * on the system to scale their {@link #DENSITY_XXHIGH} assets for them.
155      */
156     public static final int DENSITY_440 = 440;
157 
158     /**
159      * Intermediate density for screens that sit somewhere between
160      * {@link #DENSITY_XHIGH} (320 dpi) and {@link #DENSITY_XXHIGH} (480 dpi).
161      * This is not a density that applications should target, instead relying
162      * on the system to scale their {@link #DENSITY_XXHIGH} assets for them.
163      */
164     public static final int DENSITY_450 = 450;
165 
166     /**
167      * Standard quantized DPI for extra-extra-high-density screens.
168      */
169     public static final int DENSITY_XXHIGH = 480;
170 
171     /**
172      * Intermediate density for screens that sit somewhere between
173      * {@link #DENSITY_XXHIGH} (480 dpi) and {@link #DENSITY_XXXHIGH} (640 dpi).
174      * This is not a density that applications should target, instead relying
175      * on the system to scale their {@link #DENSITY_XXXHIGH} assets for them.
176      */
177     public static final int DENSITY_560 = 560;
178 
179     /**
180      * Intermediate density for screens that sit somewhere between
181      * {@link #DENSITY_XXHIGH} (480 dpi) and {@link #DENSITY_XXXHIGH} (640 dpi).
182      * This is not a density that applications should target, instead relying
183      * on the system to scale their {@link #DENSITY_XXXHIGH} assets for them.
184      */
185     public static final int DENSITY_600 = 600;
186 
187     /**
188      * Standard quantized DPI for extra-extra-extra-high-density screens.  Applications
189      * should not generally worry about this density; relying on XHIGH graphics
190      * being scaled up to it should be sufficient for almost all cases.  A typical
191      * use of this density would be 4K television screens -- 3840x2160, which
192      * is 2x a traditional HD 1920x1080 screen which runs at DENSITY_XHIGH.
193      */
194     public static final int DENSITY_XXXHIGH = 640;
195 
196     /**
197      * The reference density used throughout the system.
198      */
199     public static final int DENSITY_DEFAULT = DENSITY_MEDIUM;
200 
201     /**
202      * Scaling factor to convert a density in DPI units to the density scale.
203      * @hide
204      */
205     public static final float DENSITY_DEFAULT_SCALE = 1.0f / DENSITY_DEFAULT;
206 
207     /**
208      * The device's current density.
209      * <p>
210      * This value reflects any changes made to the device density. To obtain
211      * the device's stable density, use {@link #DENSITY_DEVICE_STABLE}.
212      *
213      * @hide This value should not be used.
214      * @deprecated Use {@link #DENSITY_DEVICE_STABLE} to obtain the stable
215      *             device density or {@link #densityDpi} to obtain the current
216      *             density for a specific display.
217      */
218     @Deprecated
219     @UnsupportedAppUsage
220     public static int DENSITY_DEVICE = getDeviceDensity();
221 
222     /**
223      * The device's stable density.
224      * <p>
225      * This value is constant at run time and may not reflect the current
226      * display density. To obtain the current density for a specific display,
227      * use {@link #densityDpi}.
228      */
229     public static final int DENSITY_DEVICE_STABLE = getDeviceDensity();
230 
231     /**
232      * The absolute width of the available display size in pixels.
233      */
234     public int widthPixels;
235     /**
236      * The absolute height of the available display size in pixels.
237      */
238     public int heightPixels;
239     /**
240      * The logical density of the display.  This is a scaling factor for the
241      * Density Independent Pixel unit, where one DIP is one pixel on an
242      * approximately 160 dpi screen (for example a 240x320, 1.5"x2" screen),
243      * providing the baseline of the system's display. Thus on a 160dpi screen
244      * this density value will be 1; on a 120 dpi screen it would be .75; etc.
245      *
246      * <p>This value does not exactly follow the real screen size (as given by
247      * {@link #xdpi} and {@link #ydpi}), but rather is used to scale the size of
248      * the overall UI in steps based on gross changes in the display dpi.  For
249      * example, a 240x320 screen will have a density of 1 even if its width is
250      * 1.8", 1.3", etc. However, if the screen resolution is increased to
251      * 320x480 but the screen size remained 1.5"x2" then the density would be
252      * increased (probably to 1.5).
253      *
254      * @see #DENSITY_DEFAULT
255      */
256     public float density;
257     /**
258      * The screen density expressed as dots-per-inch.  May be either
259      * {@link #DENSITY_LOW}, {@link #DENSITY_MEDIUM}, or {@link #DENSITY_HIGH}.
260      */
261     public int densityDpi;
262     /**
263      * A scaling factor for fonts displayed on the display.  This is the same
264      * as {@link #density}, except that it may be adjusted in smaller
265      * increments at runtime based on a user preference for the font size.
266      */
267     public float scaledDensity;
268     /**
269      * The exact physical pixels per inch of the screen in the X dimension.
270      */
271     public float xdpi;
272     /**
273      * The exact physical pixels per inch of the screen in the Y dimension.
274      */
275     public float ydpi;
276 
277     /**
278      * The reported display width prior to any compatibility mode scaling
279      * being applied.
280      * @hide
281      */
282     @UnsupportedAppUsage
283     public int noncompatWidthPixels;
284     /**
285      * The reported display height prior to any compatibility mode scaling
286      * being applied.
287      * @hide
288      */
289     @UnsupportedAppUsage
290     public int noncompatHeightPixels;
291     /**
292      * The reported display density prior to any compatibility mode scaling
293      * being applied.
294      * @hide
295      */
296     public float noncompatDensity;
297     /**
298      * The reported display density prior to any compatibility mode scaling
299      * being applied.
300      * @hide
301      */
302     @UnsupportedAppUsage
303     public int noncompatDensityDpi;
304     /**
305      * The reported scaled density prior to any compatibility mode scaling
306      * being applied.
307      * @hide
308      */
309     public float noncompatScaledDensity;
310     /**
311      * The reported display xdpi prior to any compatibility mode scaling
312      * being applied.
313      * @hide
314      */
315     public float noncompatXdpi;
316     /**
317      * The reported display ydpi prior to any compatibility mode scaling
318      * being applied.
319      * @hide
320      */
321     public float noncompatYdpi;
322 
DisplayMetrics()323     public DisplayMetrics() {
324     }
325 
setTo(DisplayMetrics o)326     public void setTo(DisplayMetrics o) {
327         if (this == o) {
328             return;
329         }
330 
331         widthPixels = o.widthPixels;
332         heightPixels = o.heightPixels;
333         density = o.density;
334         densityDpi = o.densityDpi;
335         scaledDensity = o.scaledDensity;
336         xdpi = o.xdpi;
337         ydpi = o.ydpi;
338         noncompatWidthPixels = o.noncompatWidthPixels;
339         noncompatHeightPixels = o.noncompatHeightPixels;
340         noncompatDensity = o.noncompatDensity;
341         noncompatDensityDpi = o.noncompatDensityDpi;
342         noncompatScaledDensity = o.noncompatScaledDensity;
343         noncompatXdpi = o.noncompatXdpi;
344         noncompatYdpi = o.noncompatYdpi;
345     }
346 
setToDefaults()347     public void setToDefaults() {
348         widthPixels = 0;
349         heightPixels = 0;
350         density =  DENSITY_DEVICE / (float) DENSITY_DEFAULT;
351         densityDpi =  DENSITY_DEVICE;
352         scaledDensity = density;
353         xdpi = DENSITY_DEVICE;
354         ydpi = DENSITY_DEVICE;
355         noncompatWidthPixels = widthPixels;
356         noncompatHeightPixels = heightPixels;
357         noncompatDensity = density;
358         noncompatDensityDpi = densityDpi;
359         noncompatScaledDensity = scaledDensity;
360         noncompatXdpi = xdpi;
361         noncompatYdpi = ydpi;
362     }
363 
364     @Override
equals(@ullable Object o)365     public boolean equals(@Nullable Object o) {
366         return o instanceof DisplayMetrics && equals((DisplayMetrics)o);
367     }
368 
369     /**
370      * Returns true if these display metrics equal the other display metrics.
371      *
372      * @param other The display metrics with which to compare.
373      * @return True if the display metrics are equal.
374      */
equals(DisplayMetrics other)375     public boolean equals(DisplayMetrics other) {
376         return equalsPhysical(other)
377                 && scaledDensity == other.scaledDensity
378                 && noncompatScaledDensity == other.noncompatScaledDensity;
379     }
380 
381     /**
382      * Returns true if the physical aspects of the two display metrics
383      * are equal.  This ignores the scaled density, which is a logical
384      * attribute based on the current desired font size.
385      *
386      * @param other The display metrics with which to compare.
387      * @return True if the display metrics are equal.
388      * @hide
389      */
equalsPhysical(DisplayMetrics other)390     public boolean equalsPhysical(DisplayMetrics other) {
391         return other != null
392                 && widthPixels == other.widthPixels
393                 && heightPixels == other.heightPixels
394                 && density == other.density
395                 && densityDpi == other.densityDpi
396                 && xdpi == other.xdpi
397                 && ydpi == other.ydpi
398                 && noncompatWidthPixels == other.noncompatWidthPixels
399                 && noncompatHeightPixels == other.noncompatHeightPixels
400                 && noncompatDensity == other.noncompatDensity
401                 && noncompatDensityDpi == other.noncompatDensityDpi
402                 && noncompatXdpi == other.noncompatXdpi
403                 && noncompatYdpi == other.noncompatYdpi;
404     }
405 
406     @Override
hashCode()407     public int hashCode() {
408         return widthPixels * heightPixels * densityDpi;
409     }
410 
411     @Override
toString()412     public String toString() {
413         return "DisplayMetrics{density=" + density + ", width=" + widthPixels +
414             ", height=" + heightPixels + ", scaledDensity=" + scaledDensity +
415             ", xdpi=" + xdpi + ", ydpi=" + ydpi + "}";
416     }
417 
getDeviceDensity()418     private static int getDeviceDensity() {
419         // qemu.sf.lcd_density can be used to override ro.sf.lcd_density
420         // when running in the emulator, allowing for dynamic configurations.
421         // The reason for this is that ro.sf.lcd_density is write-once and is
422         // set by the init process when it parses build.prop before anything else.
423         return SystemProperties.getInt("qemu.sf.lcd_density",
424                 SystemProperties.getInt("ro.sf.lcd_density", DENSITY_DEFAULT));
425     }
426 }
427