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