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