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