Display.java revision 2ab1b7d9abc1b720b63ae01abcf1df0dc780eed4
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.graphics.PixelFormat; 20import android.graphics.Point; 21import android.graphics.Rect; 22import android.hardware.display.DisplayManager; 23import android.os.SystemClock; 24import android.util.DisplayMetrics; 25import android.util.Log; 26 27/** 28 * Provides information about the size and density of a logical display. 29 * <p> 30 * The display area is described in two different ways. 31 * <ul> 32 * <li>The application display area specifies the part of the display that may contain 33 * an application window, excluding the system decorations. The application display area may 34 * be smaller than the real display area because the system subtracts the space needed 35 * for decor elements such as the status bar. Use the following methods to query the 36 * application display area: {@link #getSize}, {@link #getRectSize} and {@link #getMetrics}.</li> 37 * <li>The real display area specifies the part of the display that contains content 38 * including the system decorations. Even so, the real display area may be smaller than the 39 * physical size of the display if the window manager is emulating a smaller display 40 * using (adb shell am display-size). Use the following methods to query the 41 * real display area: {@link #getRealSize}, {@link #getRealMetrics}.</li> 42 * </ul> 43 * </p><p> 44 * A logical display does not necessarily represent a particular physical display device 45 * such as the built-in screen or an external monitor. The contents of a logical 46 * display may be presented on one or more physical displays according to the devices 47 * that are currently attached and whether mirroring has been enabled. 48 * </p> 49 */ 50public final class Display { 51 private static final String TAG = "Display"; 52 53 private final int mDisplayId; 54 private final CompatibilityInfoHolder mCompatibilityInfo; 55 private final DisplayInfo mDisplayInfo = new DisplayInfo(); 56 57 // Temporary display metrics structure used for compatibility mode. 58 private final DisplayMetrics mTempMetrics = new DisplayMetrics(); 59 60 // We cache the app width and height properties briefly between calls 61 // to getHeight() and getWidth() to ensure that applications perceive 62 // consistent results when the size changes (most of the time). 63 // Applications should now be using getSize() instead. 64 private static final int CACHED_APP_SIZE_DURATION_MILLIS = 20; 65 private long mLastCachedAppSizeUpdate; 66 private int mCachedAppWidthCompat; 67 private int mCachedAppHeightCompat; 68 69 /** 70 * The default Display id. 71 */ 72 public static final int DEFAULT_DISPLAY = 0; 73 74 /** 75 * Uninitialized display. 76 * @hide 77 */ 78 public static final int NO_DISPLAY = -1; 79 80 /** 81 * Internal method to create a display. 82 * Applications should use {@link android.view.WindowManager#getDefaultDisplay()} 83 * to get a display object for the default display. 84 * 85 * @hide 86 */ 87 public Display(int displayId, CompatibilityInfoHolder compatibilityInfo) { 88 mDisplayId = displayId; 89 mCompatibilityInfo = compatibilityInfo; 90 } 91 92 /** 93 * Gets the display id. 94 * <p> 95 * Each logical display has a unique id. 96 * The default display has id {@link #DEFAULT_DISPLAY}. 97 * </p> 98 */ 99 public int getDisplayId() { 100 return mDisplayId; 101 } 102 103 /** 104 * Gets a full copy of the display information. 105 * 106 * @param outDisplayInfo The object to receive the copy of the display information. 107 * @hide 108 */ 109 public void getDisplayInfo(DisplayInfo outDisplayInfo) { 110 synchronized (this) { 111 updateDisplayInfoLocked(); 112 outDisplayInfo.copyFrom(mDisplayInfo); 113 } 114 } 115 116 /** 117 * Gets the size of the display, in pixels. 118 * <p> 119 * Note that this value should <em>not</em> be used for computing layouts, 120 * since a device will typically have screen decoration (such as a status bar) 121 * along the edges of the display that reduce the amount of application 122 * space available from the size returned here. Layouts should instead use 123 * the window size. 124 * </p><p> 125 * The size is adjusted based on the current rotation of the display. 126 * </p><p> 127 * The size returned by this method does not necessarily represent the 128 * actual raw size (native resolution) of the display. The returned size may 129 * be adjusted to exclude certain system decoration elements that are always visible. 130 * It may also be scaled to provide compatibility with older applications that 131 * were originally designed for smaller displays. 132 * </p> 133 * 134 * @param outSize A {@link Point} object to receive the size information. 135 */ 136 public void getSize(Point outSize) { 137 synchronized (this) { 138 updateDisplayInfoLocked(); 139 mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo); 140 outSize.x = mTempMetrics.widthPixels; 141 outSize.y = mTempMetrics.heightPixels; 142 } 143 } 144 145 /** 146 * Gets the size of the display as a rectangle, in pixels. 147 * 148 * @param outSize A {@link Rect} object to receive the size information. 149 * @see #getSize(Point) 150 */ 151 public void getRectSize(Rect outSize) { 152 synchronized (this) { 153 updateDisplayInfoLocked(); 154 mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo); 155 outSize.set(0, 0, mTempMetrics.widthPixels, mTempMetrics.heightPixels); 156 } 157 } 158 159 /** 160 * Return the range of display sizes an application can expect to encounter 161 * under normal operation, as long as there is no physical change in screen 162 * size. This is basically the sizes you will see as the orientation 163 * changes, taking into account whatever screen decoration there is in 164 * each rotation. For example, the status bar is always at the top of the 165 * screen, so it will reduce the height both in landscape and portrait, and 166 * the smallest height returned here will be the smaller of the two. 167 * 168 * This is intended for applications to get an idea of the range of sizes 169 * they will encounter while going through device rotations, to provide a 170 * stable UI through rotation. The sizes here take into account all standard 171 * system decorations that reduce the size actually available to the 172 * application: the status bar, navigation bar, system bar, etc. It does 173 * <em>not</em> take into account more transient elements like an IME 174 * soft keyboard. 175 * 176 * @param outSmallestSize Filled in with the smallest width and height 177 * that the application will encounter, in pixels (not dp units). The x 178 * (width) dimension here directly corresponds to 179 * {@link android.content.res.Configuration#smallestScreenWidthDp 180 * Configuration.smallestScreenWidthDp}, except the value here is in raw 181 * screen pixels rather than dp units. Your application may of course 182 * still get smaller space yet if, for example, a soft keyboard is 183 * being displayed. 184 * @param outLargestSize Filled in with the largest width and height 185 * that the application will encounter, in pixels (not dp units). Your 186 * application may of course still get larger space than this if, 187 * for example, screen decorations like the status bar are being hidden. 188 */ 189 public void getCurrentSizeRange(Point outSmallestSize, Point outLargestSize) { 190 synchronized (this) { 191 updateDisplayInfoLocked(); 192 outSmallestSize.x = mDisplayInfo.smallestNominalAppWidth; 193 outSmallestSize.y = mDisplayInfo.smallestNominalAppHeight; 194 outLargestSize.x = mDisplayInfo.largestNominalAppWidth; 195 outLargestSize.y = mDisplayInfo.largestNominalAppHeight; 196 } 197 } 198 199 /** 200 * Return the maximum screen size dimension that will happen. This is 201 * mostly for wallpapers. 202 * @hide 203 */ 204 public int getMaximumSizeDimension() { 205 synchronized (this) { 206 updateDisplayInfoLocked(); 207 return Math.max(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); 208 } 209 } 210 211 /** 212 * @deprecated Use {@link #getSize(Point)} instead. 213 */ 214 @Deprecated 215 public int getWidth() { 216 synchronized (this) { 217 updateCachedAppSizeIfNeededLocked(); 218 return mCachedAppWidthCompat; 219 } 220 } 221 222 /** 223 * @deprecated Use {@link #getSize(Point)} instead. 224 */ 225 @Deprecated 226 public int getHeight() { 227 synchronized (this) { 228 updateCachedAppSizeIfNeededLocked(); 229 return mCachedAppHeightCompat; 230 } 231 } 232 233 /** 234 * Returns the rotation of the screen from its "natural" orientation. 235 * The returned value may be {@link Surface#ROTATION_0 Surface.ROTATION_0} 236 * (no rotation), {@link Surface#ROTATION_90 Surface.ROTATION_90}, 237 * {@link Surface#ROTATION_180 Surface.ROTATION_180}, or 238 * {@link Surface#ROTATION_270 Surface.ROTATION_270}. For 239 * example, if a device has a naturally tall screen, and the user has 240 * turned it on its side to go into a landscape orientation, the value 241 * returned here may be either {@link Surface#ROTATION_90 Surface.ROTATION_90} 242 * or {@link Surface#ROTATION_270 Surface.ROTATION_270} depending on 243 * the direction it was turned. The angle is the rotation of the drawn 244 * graphics on the screen, which is the opposite direction of the physical 245 * rotation of the device. For example, if the device is rotated 90 246 * degrees counter-clockwise, to compensate rendering will be rotated by 247 * 90 degrees clockwise and thus the returned value here will be 248 * {@link Surface#ROTATION_90 Surface.ROTATION_90}. 249 */ 250 public int getRotation() { 251 synchronized (this) { 252 updateDisplayInfoLocked(); 253 return mDisplayInfo.rotation; 254 } 255 } 256 257 /** 258 * @deprecated use {@link #getRotation} 259 * @return orientation of this display. 260 */ 261 @Deprecated 262 public int getOrientation() { 263 return getRotation(); 264 } 265 266 /** 267 * Gets the pixel format of the display. 268 * @return One of the constants defined in {@link android.graphics.PixelFormat}. 269 * 270 * @deprecated This method is no longer supported. 271 * The result is always {@link PixelFormat#RGBA_8888}. 272 */ 273 @Deprecated 274 public int getPixelFormat() { 275 return PixelFormat.RGBA_8888; 276 } 277 278 /** 279 * Gets the refresh rate of this display in frames per second. 280 */ 281 public float getRefreshRate() { 282 synchronized (this) { 283 updateDisplayInfoLocked(); 284 return mDisplayInfo.refreshRate; 285 } 286 } 287 288 /** 289 * Gets display metrics that describe the size and density of this display. 290 * <p> 291 * The size is adjusted based on the current rotation of the display. 292 * </p><p> 293 * The size returned by this method does not necessarily represent the 294 * actual raw size (native resolution) of the display. The returned size may 295 * be adjusted to exclude certain system decor elements that are always visible. 296 * It may also be scaled to provide compatibility with older applications that 297 * were originally designed for smaller displays. 298 * </p> 299 * 300 * @param outMetrics A {@link DisplayMetrics} object to receive the metrics. 301 */ 302 public void getMetrics(DisplayMetrics outMetrics) { 303 synchronized (this) { 304 updateDisplayInfoLocked(); 305 mDisplayInfo.getAppMetrics(outMetrics, mCompatibilityInfo); 306 } 307 } 308 309 /** 310 * Gets the real size of the display without subtracting any window decor or 311 * applying any compatibility scale factors. 312 * <p> 313 * The size is adjusted based on the current rotation of the display. 314 * </p><p> 315 * The real size may be smaller than the physical size of the screen when the 316 * window manager is emulating a smaller display (using adb shell am display-size). 317 * </p> 318 * 319 * @param outSize Set to the real size of the display. 320 */ 321 public void getRealSize(Point outSize) { 322 synchronized (this) { 323 updateDisplayInfoLocked(); 324 outSize.x = mDisplayInfo.logicalWidth; 325 outSize.y = mDisplayInfo.logicalHeight; 326 } 327 } 328 329 /** 330 * Gets display metrics based on the real size of this display. 331 * <p> 332 * The size is adjusted based on the current rotation of the display. 333 * </p><p> 334 * The real size may be smaller than the physical size of the screen when the 335 * window manager is emulating a smaller display (using adb shell am display-size). 336 * </p> 337 * 338 * @param outMetrics A {@link DisplayMetrics} object to receive the metrics. 339 */ 340 public void getRealMetrics(DisplayMetrics outMetrics) { 341 synchronized (this) { 342 updateDisplayInfoLocked(); 343 mDisplayInfo.getLogicalMetrics(outMetrics, null); 344 } 345 } 346 347 private void updateDisplayInfoLocked() { 348 // TODO: only refresh the display information when needed 349 if (!DisplayManager.getInstance().getDisplayInfo(mDisplayId, mDisplayInfo)) { 350 Log.e(TAG, "Could not get information about logical display " + mDisplayId); 351 } 352 } 353 354 private void updateCachedAppSizeIfNeededLocked() { 355 long now = SystemClock.uptimeMillis(); 356 if (now > mLastCachedAppSizeUpdate + CACHED_APP_SIZE_DURATION_MILLIS) { 357 updateDisplayInfoLocked(); 358 mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo); 359 mCachedAppWidthCompat = mTempMetrics.widthPixels; 360 mCachedAppHeightCompat = mTempMetrics.heightPixels; 361 mLastCachedAppSizeUpdate = now; 362 } 363 } 364} 365 366