Display.java revision 836e262aa8e2f66548231ab11eb3b3e91d0e7901
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.content.res.CompatibilityInfo; 20import android.graphics.Point; 21import android.graphics.Rect; 22import android.os.RemoteException; 23import android.os.ServiceManager; 24import android.os.SystemClock; 25import android.util.DisplayMetrics; 26import android.util.Slog; 27 28/** 29 * Provides information about the display size and density. 30 */ 31public class Display { 32 static final String TAG = "Display"; 33 static final boolean DEBUG_DISPLAY_SIZE = true; 34 35 /** 36 * The default Display id. 37 */ 38 public static final int DEFAULT_DISPLAY = 0; 39 40 /** 41 * Use {@link android.view.WindowManager#getDefaultDisplay() 42 * WindowManager.getDefaultDisplay()} to create a Display object. 43 * Display gives you access to some information about a particular display 44 * connected to the device. 45 */ 46 Display(int display, CompatibilityInfoHolder compatInfo) { 47 // initalize the statics when this class is first instansiated. This is 48 // done here instead of in the static block because Zygote 49 synchronized (sStaticInit) { 50 if (!sInitialized) { 51 nativeClassInit(); 52 sInitialized = true; 53 } 54 } 55 mCompatibilityInfo = compatInfo != null ? compatInfo : new CompatibilityInfoHolder(); 56 mDisplay = display; 57 init(display); 58 } 59 60 /** 61 * Returns the index of this display. This is currently undefined; do 62 * not use. 63 */ 64 public int getDisplayId() { 65 return mDisplay; 66 } 67 68 /** 69 * Returns the number of displays connected to the device. This is 70 * currently undefined; do not use. 71 */ 72 native static int getDisplayCount(); 73 74 /** 75 * Gets the size of the display, in pixels. 76 * <p> 77 * Note that this value should <em>not</em> be used for computing layouts, 78 * since a device will typically have screen decoration (such as a status bar) 79 * along the edges of the display that reduce the amount of application 80 * space available from the size returned here. Layouts should instead use 81 * the window size. 82 * </p><p> 83 * The size is adjusted based on the current rotation of the display. 84 * </p><p> 85 * The size returned by this method does not necessarily represent the 86 * actual raw size (native resolution) of the display. The returned size may 87 * be adjusted to exclude certain system decor elements that are always visible. 88 * It may also be scaled to provide compatibility with older applications that 89 * were originally designed for smaller displays. 90 * </p> 91 * 92 * @param outSize A {@link Point} object to receive the size information. 93 */ 94 public void getSize(Point outSize) { 95 getSizeInternal(outSize, true); 96 } 97 98 private void getSizeInternal(Point outSize, boolean doCompat) { 99 try { 100 IWindowManager wm = getWindowManager(); 101 if (wm != null) { 102 wm.getDisplaySize(outSize); 103 CompatibilityInfo ci; 104 if (doCompat && (ci=mCompatibilityInfo.getIfNeeded()) != null) { 105 synchronized (mTmpMetrics) { 106 mTmpMetrics.noncompatWidthPixels = outSize.x; 107 mTmpMetrics.noncompatHeightPixels = outSize.y; 108 mTmpMetrics.density = mDensity; 109 ci.applyToDisplayMetrics(mTmpMetrics); 110 outSize.x = mTmpMetrics.widthPixels; 111 outSize.y = mTmpMetrics.heightPixels; 112 } 113 } 114 } else { 115 // This is just for boot-strapping, initializing the 116 // system process before the window manager is up. 117 outSize.x = getRawWidth(); 118 outSize.y = getRawHeight(); 119 } 120 if (DEBUG_DISPLAY_SIZE && doCompat) Slog.v( 121 TAG, "Returning display size: " + outSize); 122 } catch (RemoteException e) { 123 Slog.w("Display", "Unable to get display size", e); 124 } 125 } 126 127 /** 128 * Gets the size of the display as a rectangle, in pixels. 129 * 130 * @param outSize A {@link Rect} object to receive the size information. 131 * @see #getSize(Point) 132 */ 133 public void getRectSize(Rect outSize) { 134 synchronized (mTmpPoint) { 135 getSizeInternal(mTmpPoint, true); 136 outSize.set(0, 0, mTmpPoint.x, mTmpPoint.y); 137 } 138 } 139 140 /** 141 * Return the maximum screen size dimension that will happen. This is 142 * mostly for wallpapers. 143 * @hide 144 */ 145 public int getMaximumSizeDimension() { 146 try { 147 IWindowManager wm = getWindowManager(); 148 return wm.getMaximumSizeDimension(); 149 } catch (RemoteException e) { 150 Slog.w("Display", "Unable to get display maximum size dimension", e); 151 return 0; 152 } 153 } 154 155 /** 156 * @deprecated Use {@link #getSize(Point)} instead. 157 */ 158 @Deprecated 159 public int getWidth() { 160 synchronized (mTmpPoint) { 161 long now = SystemClock.uptimeMillis(); 162 if (now > (mLastGetTime+20)) { 163 getSizeInternal(mTmpPoint, true); 164 mLastGetTime = now; 165 } 166 return mTmpPoint.x; 167 } 168 } 169 170 /** 171 * @deprecated Use {@link #getSize(Point)} instead. 172 */ 173 @Deprecated 174 public int getHeight() { 175 synchronized (mTmpPoint) { 176 long now = SystemClock.uptimeMillis(); 177 if (now > (mLastGetTime+20)) { 178 getSizeInternal(mTmpPoint, true); 179 mLastGetTime = now; 180 } 181 return mTmpPoint.y; 182 } 183 } 184 185 /** 186 * Gets the real size of the display without subtracting any window decor or 187 * applying any compatibility scale factors. 188 * <p> 189 * The real size may be smaller than the raw size when the window manager 190 * is emulating a smaller display (using adb shell am display-size). 191 * </p><p> 192 * The size is adjusted based on the current rotation of the display. 193 * </p> 194 * @hide 195 */ 196 public void getRealSize(Point outSize) { 197 try { 198 IWindowManager wm = getWindowManager(); 199 if (wm != null) { 200 wm.getRealDisplaySize(outSize); 201 } else { 202 // This is just for boot-strapping, initializing the 203 // system process before the window manager is up. 204 outSize.x = getRawWidth(); 205 outSize.y = getRawHeight(); 206 } 207 if (DEBUG_DISPLAY_SIZE) Slog.v( 208 TAG, "Returning real display size: " + outSize); 209 } catch (RemoteException e) { 210 Slog.w("Display", "Unable to get real display size", e); 211 } 212 } 213 214 /** 215 * Gets the raw width of the display, in pixels. 216 * <p> 217 * The size is adjusted based on the current rotation of the display. 218 * </p> 219 * @hide 220 */ 221 public int getRawWidth() { 222 int w = getRawWidthNative(); 223 if (DEBUG_DISPLAY_SIZE) Slog.v( 224 TAG, "Returning raw display width: " + w); 225 return w; 226 } 227 private native int getRawWidthNative(); 228 229 /** 230 * Gets the raw height of the display, in pixels. 231 * <p> 232 * The size is adjusted based on the current rotation of the display. 233 * </p> 234 * @hide 235 */ 236 public int getRawHeight() { 237 int h = getRawHeightNative(); 238 if (DEBUG_DISPLAY_SIZE) Slog.v( 239 TAG, "Returning raw display height: " + h); 240 return h; 241 } 242 private native int getRawHeightNative(); 243 244 /** 245 * Returns the rotation of the screen from its "natural" orientation. 246 * The returned value may be {@link Surface#ROTATION_0 Surface.ROTATION_0} 247 * (no rotation), {@link Surface#ROTATION_90 Surface.ROTATION_90}, 248 * {@link Surface#ROTATION_180 Surface.ROTATION_180}, or 249 * {@link Surface#ROTATION_270 Surface.ROTATION_270}. For 250 * example, if a device has a naturally tall screen, and the user has 251 * turned it on its side to go into a landscape orientation, the value 252 * returned here may be either {@link Surface#ROTATION_90 Surface.ROTATION_90} 253 * or {@link Surface#ROTATION_270 Surface.ROTATION_270} depending on 254 * the direction it was turned. The angle is the rotation of the drawn 255 * graphics on the screen, which is the opposite direction of the physical 256 * rotation of the device. For example, if the device is rotated 90 257 * degrees counter-clockwise, to compensate rendering will be rotated by 258 * 90 degrees clockwise and thus the returned value here will be 259 * {@link Surface#ROTATION_90 Surface.ROTATION_90}. 260 */ 261 public int getRotation() { 262 return getOrientation(); 263 } 264 265 /** 266 * @deprecated use {@link #getRotation} 267 * @return orientation of this display. 268 */ 269 @Deprecated native public int getOrientation(); 270 271 /** 272 * Return the native pixel format of the display. The returned value 273 * may be one of the constants int {@link android.graphics.PixelFormat}. 274 */ 275 public int getPixelFormat() { 276 return mPixelFormat; 277 } 278 279 /** 280 * Return the refresh rate of this display in frames per second. 281 */ 282 public float getRefreshRate() { 283 return mRefreshRate; 284 } 285 286 /** 287 * Gets display metrics that describe the size and density of this display. 288 * <p> 289 * The size is adjusted based on the current rotation of the display. 290 * </p><p> 291 * The size returned by this method does not necessarily represent the 292 * actual raw size (native resolution) of the display. The returned size may 293 * be adjusted to exclude certain system decor elements that are always visible. 294 * It may also be scaled to provide compatibility with older applications that 295 * were originally designed for smaller displays. 296 * </p> 297 * 298 * @param outMetrics A {@link DisplayMetrics} object to receive the metrics. 299 */ 300 public void getMetrics(DisplayMetrics outMetrics) { 301 synchronized (mTmpPoint) { 302 getSizeInternal(mTmpPoint, false); 303 getMetricsWithSize(outMetrics, mTmpPoint.x, mTmpPoint.y); 304 } 305 306 CompatibilityInfo ci = mCompatibilityInfo.getIfNeeded(); 307 if (ci != null) { 308 ci.applyToDisplayMetrics(outMetrics); 309 } 310 311 if (DEBUG_DISPLAY_SIZE) Slog.v(TAG, "Returning DisplayMetrics: " 312 + outMetrics.widthPixels + "x" + outMetrics.heightPixels 313 + " " + outMetrics.density); 314 } 315 316 /** 317 * Gets display metrics based on the real size of this display. 318 * @hide 319 */ 320 public void getRealMetrics(DisplayMetrics outMetrics) { 321 synchronized (mTmpPoint) { 322 getRealSize(mTmpPoint); 323 getMetricsWithSize(outMetrics, mTmpPoint.x, mTmpPoint.y); 324 } 325 } 326 327 /** 328 * If the display is mirrored to an external HDMI display, returns the 329 * width of that display. 330 * @hide 331 */ 332 public int getRawExternalWidth() { 333 return 1280; 334 } 335 336 /** 337 * If the display is mirrored to an external HDMI display, returns the 338 * height of that display. 339 * @hide 340 */ 341 public int getRawExternalHeight() { 342 return 720; 343 } 344 345 /** 346 * Gets display metrics based on an explicit assumed display size. 347 * @hide 348 */ 349 public void getMetricsWithSize(DisplayMetrics outMetrics, 350 int width, int height) { 351 outMetrics.densityDpi = (int)((mDensity*DisplayMetrics.DENSITY_DEFAULT)+.5f); 352 353 outMetrics.noncompatWidthPixels = outMetrics.widthPixels = width; 354 outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height; 355 356 outMetrics.density = outMetrics.noncompatDensity = mDensity; 357 outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density; 358 outMetrics.xdpi = outMetrics.noncompatXdpi = mDpiX; 359 outMetrics.ydpi = outMetrics.noncompatYdpi = mDpiY; 360 } 361 362 static IWindowManager getWindowManager() { 363 synchronized (sStaticInit) { 364 if (sWindowManager == null) { 365 sWindowManager = IWindowManager.Stub.asInterface( 366 ServiceManager.getService("window")); 367 } 368 return sWindowManager; 369 } 370 } 371 372 /* 373 * We use a class initializer to allow the native code to cache some 374 * field offsets. 375 */ 376 native private static void nativeClassInit(); 377 378 private native void init(int display); 379 380 private final CompatibilityInfoHolder mCompatibilityInfo; 381 private final int mDisplay; 382 // Following fields are initialized from native code 383 private int mPixelFormat; 384 private float mRefreshRate; 385 /*package*/ float mDensity; 386 /*package*/ float mDpiX; 387 /*package*/ float mDpiY; 388 389 private final Point mTmpPoint = new Point(); 390 private final DisplayMetrics mTmpMetrics = new DisplayMetrics(); 391 private float mLastGetTime; 392 393 private static final Object sStaticInit = new Object(); 394 private static boolean sInitialized = false; 395 private static IWindowManager sWindowManager; 396 397 /** 398 * Returns a display object which uses the metric's width/height instead. 399 * @hide 400 */ 401 public static Display createCompatibleDisplay(int displayId, CompatibilityInfoHolder compat) { 402 return new Display(displayId, compat); 403 } 404} 405 406