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.graphics.PixelFormat; 20 import android.graphics.Point; 21 import android.graphics.Rect; 22 import android.hardware.display.DisplayManagerGlobal; 23 import android.os.SystemClock; 24 import android.util.DisplayMetrics; 25 import 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 */ 50 public final class Display { 51 private static final String TAG = "Display"; 52 private static final boolean DEBUG = false; 53 54 private final DisplayManagerGlobal mGlobal; 55 private final int mDisplayId; 56 private final int mLayerStack; 57 private final int mFlags; 58 private final int mType; 59 private final String mAddress; 60 private final CompatibilityInfoHolder mCompatibilityInfo; 61 62 private DisplayInfo mDisplayInfo; // never null 63 private boolean mIsValid; 64 65 // Temporary display metrics structure used for compatibility mode. 66 private final DisplayMetrics mTempMetrics = new DisplayMetrics(); 67 68 // We cache the app width and height properties briefly between calls 69 // to getHeight() and getWidth() to ensure that applications perceive 70 // consistent results when the size changes (most of the time). 71 // Applications should now be using getSize() instead. 72 private static final int CACHED_APP_SIZE_DURATION_MILLIS = 20; 73 private long mLastCachedAppSizeUpdate; 74 private int mCachedAppWidthCompat; 75 private int mCachedAppHeightCompat; 76 77 /** 78 * The default Display id, which is the id of the built-in primary display 79 * assuming there is one. 80 */ 81 public static final int DEFAULT_DISPLAY = 0; 82 83 /** 84 * Display flag: Indicates that the display supports compositing content 85 * that is stored in protected graphics buffers. 86 * <p> 87 * If this flag is set then the display device supports compositing protected buffers. 88 * </p><p> 89 * If this flag is not set then the display device may not support compositing 90 * protected buffers; the user may see a blank region on the screen instead of 91 * the protected content. 92 * </p><p> 93 * Secure (DRM) video decoders may allocate protected graphics buffers to request that 94 * a hardware-protected path be provided between the video decoder and the external 95 * display sink. If a hardware-protected path is not available, then content stored 96 * in protected graphics buffers may not be composited. 97 * </p><p> 98 * An application can use the absence of this flag as a hint that it should not use protected 99 * buffers for this display because the content may not be visible. For example, 100 * if the flag is not set then the application may choose not to show content on this 101 * display, show an informative error message, select an alternate content stream 102 * or adopt a different strategy for decoding content that does not rely on 103 * protected buffers. 104 * </p> 105 * 106 * @see #getFlags 107 */ 108 public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1 << 0; 109 110 /** 111 * Display flag: Indicates that the display has a secure video output and 112 * supports compositing secure surfaces. 113 * <p> 114 * If this flag is set then the display device has a secure video output 115 * and is capable of showing secure surfaces. It may also be capable of 116 * showing {@link #FLAG_SUPPORTS_PROTECTED_BUFFERS protected buffers}. 117 * </p><p> 118 * If this flag is not set then the display device may not have a secure video 119 * output; the user may see a blank region on the screen instead of 120 * the contents of secure surfaces or protected buffers. 121 * </p><p> 122 * Secure surfaces are used to prevent content rendered into those surfaces 123 * by applications from appearing in screenshots or from being viewed 124 * on non-secure displays. Protected buffers are used by secure video decoders 125 * for a similar purpose. 126 * </p><p> 127 * An application creates a window with a secure surface by specifying the 128 * {@link WindowManager.LayoutParams#FLAG_SECURE} window flag. 129 * Likewise, an application creates a {@link SurfaceView} with a secure surface 130 * by calling {@link SurfaceView#setSecure} before attaching the secure view to 131 * its containing window. 132 * </p><p> 133 * An application can use the absence of this flag as a hint that it should not create 134 * secure surfaces or protected buffers on this display because the content may 135 * not be visible. For example, if the flag is not set then the application may 136 * choose not to show content on this display, show an informative error message, 137 * select an alternate content stream or adopt a different strategy for decoding 138 * content that does not rely on secure surfaces or protected buffers. 139 * </p> 140 * 141 * @see #getFlags 142 */ 143 public static final int FLAG_SECURE = 1 << 1; 144 145 /** 146 * Display type: Unknown display type. 147 * @hide 148 */ 149 public static final int TYPE_UNKNOWN = 0; 150 151 /** 152 * Display type: Built-in display. 153 * @hide 154 */ 155 public static final int TYPE_BUILT_IN = 1; 156 157 /** 158 * Display type: HDMI display. 159 * @hide 160 */ 161 public static final int TYPE_HDMI = 2; 162 163 /** 164 * Display type: WiFi display. 165 * @hide 166 */ 167 public static final int TYPE_WIFI = 3; 168 169 /** 170 * Display type: Overlay display. 171 * @hide 172 */ 173 public static final int TYPE_OVERLAY = 4; 174 175 /** 176 * Internal method to create a display. 177 * Applications should use {@link android.view.WindowManager#getDefaultDisplay()} 178 * or {@link android.hardware.display.DisplayManager#getDisplay} 179 * to get a display object. 180 * 181 * @hide 182 */ Display(DisplayManagerGlobal global, int displayId, DisplayInfo displayInfo , CompatibilityInfoHolder compatibilityInfo)183 public Display(DisplayManagerGlobal global, 184 int displayId, DisplayInfo displayInfo /*not null*/, 185 CompatibilityInfoHolder compatibilityInfo) { 186 mGlobal = global; 187 mDisplayId = displayId; 188 mDisplayInfo = displayInfo; 189 mCompatibilityInfo = compatibilityInfo; 190 mIsValid = true; 191 192 // Cache properties that cannot change as long as the display is valid. 193 mLayerStack = displayInfo.layerStack; 194 mFlags = displayInfo.flags; 195 mType = displayInfo.type; 196 mAddress = displayInfo.address; 197 } 198 199 /** 200 * Gets the display id. 201 * <p> 202 * Each logical display has a unique id. 203 * The default display has id {@link #DEFAULT_DISPLAY}. 204 * </p> 205 */ getDisplayId()206 public int getDisplayId() { 207 return mDisplayId; 208 } 209 210 /** 211 * Returns true if this display is still valid, false if the display has been removed. 212 * 213 * If the display is invalid, then the methods of this class will 214 * continue to report the most recently observed display information. 215 * However, it is unwise (and rather fruitless) to continue using a 216 * {@link Display} object after the display's demise. 217 * 218 * It's possible for a display that was previously invalid to become 219 * valid again if a display with the same id is reconnected. 220 * 221 * @return True if the display is still valid. 222 */ isValid()223 public boolean isValid() { 224 synchronized (this) { 225 updateDisplayInfoLocked(); 226 return mIsValid; 227 } 228 } 229 230 /** 231 * Gets a full copy of the display information. 232 * 233 * @param outDisplayInfo The object to receive the copy of the display information. 234 * @return True if the display is still valid. 235 * @hide 236 */ getDisplayInfo(DisplayInfo outDisplayInfo)237 public boolean getDisplayInfo(DisplayInfo outDisplayInfo) { 238 synchronized (this) { 239 updateDisplayInfoLocked(); 240 outDisplayInfo.copyFrom(mDisplayInfo); 241 return mIsValid; 242 } 243 } 244 245 /** 246 * Gets the display's layer stack. 247 * 248 * Each display has its own independent layer stack upon which surfaces 249 * are placed to be managed by surface flinger. 250 * 251 * @return The display's layer stack number. 252 * @hide 253 */ getLayerStack()254 public int getLayerStack() { 255 return mLayerStack; 256 } 257 258 /** 259 * Returns a combination of flags that describe the capabilities of the display. 260 * 261 * @return The display flags. 262 * 263 * @see #FLAG_SUPPORTS_PROTECTED_BUFFERS 264 * @see #FLAG_SECURE 265 */ getFlags()266 public int getFlags() { 267 return mFlags; 268 } 269 270 /** 271 * Gets the display type. 272 * 273 * @return The display type. 274 * 275 * @see #TYPE_UNKNOWN 276 * @see #TYPE_BUILT_IN 277 * @see #TYPE_HDMI 278 * @see #TYPE_WIFI 279 * @see #TYPE_OVERLAY 280 * @hide 281 */ getType()282 public int getType() { 283 return mType; 284 } 285 286 /** 287 * Gets the display address, or null if none. 288 * Interpretation varies by display type. 289 * 290 * @return The display address. 291 * @hide 292 */ getAddress()293 public String getAddress() { 294 return mAddress; 295 } 296 297 /** 298 * Gets the compatibility info used by this display instance. 299 * 300 * @return The compatibility info holder, or null if none is required. 301 * @hide 302 */ getCompatibilityInfo()303 public CompatibilityInfoHolder getCompatibilityInfo() { 304 return mCompatibilityInfo; 305 } 306 307 /** 308 * Gets the name of the display. 309 * <p> 310 * Note that some displays may be renamed by the user. 311 * </p> 312 * 313 * @return The display's name. 314 */ getName()315 public String getName() { 316 synchronized (this) { 317 updateDisplayInfoLocked(); 318 return mDisplayInfo.name; 319 } 320 } 321 322 /** 323 * Gets the size of the display, in pixels. 324 * <p> 325 * Note that this value should <em>not</em> be used for computing layouts, 326 * since a device will typically have screen decoration (such as a status bar) 327 * along the edges of the display that reduce the amount of application 328 * space available from the size returned here. Layouts should instead use 329 * the window size. 330 * </p><p> 331 * The size is adjusted based on the current rotation of the display. 332 * </p><p> 333 * The size returned by this method does not necessarily represent the 334 * actual raw size (native resolution) of the display. The returned size may 335 * be adjusted to exclude certain system decoration elements that are always visible. 336 * It may also be scaled to provide compatibility with older applications that 337 * were originally designed for smaller displays. 338 * </p> 339 * 340 * @param outSize A {@link Point} object to receive the size information. 341 */ getSize(Point outSize)342 public void getSize(Point outSize) { 343 synchronized (this) { 344 updateDisplayInfoLocked(); 345 mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo); 346 outSize.x = mTempMetrics.widthPixels; 347 outSize.y = mTempMetrics.heightPixels; 348 } 349 } 350 351 /** 352 * Gets the size of the display as a rectangle, in pixels. 353 * 354 * @param outSize A {@link Rect} object to receive the size information. 355 * @see #getSize(Point) 356 */ getRectSize(Rect outSize)357 public void getRectSize(Rect outSize) { 358 synchronized (this) { 359 updateDisplayInfoLocked(); 360 mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo); 361 outSize.set(0, 0, mTempMetrics.widthPixels, mTempMetrics.heightPixels); 362 } 363 } 364 365 /** 366 * Return the range of display sizes an application can expect to encounter 367 * under normal operation, as long as there is no physical change in screen 368 * size. This is basically the sizes you will see as the orientation 369 * changes, taking into account whatever screen decoration there is in 370 * each rotation. For example, the status bar is always at the top of the 371 * screen, so it will reduce the height both in landscape and portrait, and 372 * the smallest height returned here will be the smaller of the two. 373 * 374 * This is intended for applications to get an idea of the range of sizes 375 * they will encounter while going through device rotations, to provide a 376 * stable UI through rotation. The sizes here take into account all standard 377 * system decorations that reduce the size actually available to the 378 * application: the status bar, navigation bar, system bar, etc. It does 379 * <em>not</em> take into account more transient elements like an IME 380 * soft keyboard. 381 * 382 * @param outSmallestSize Filled in with the smallest width and height 383 * that the application will encounter, in pixels (not dp units). The x 384 * (width) dimension here directly corresponds to 385 * {@link android.content.res.Configuration#smallestScreenWidthDp 386 * Configuration.smallestScreenWidthDp}, except the value here is in raw 387 * screen pixels rather than dp units. Your application may of course 388 * still get smaller space yet if, for example, a soft keyboard is 389 * being displayed. 390 * @param outLargestSize Filled in with the largest width and height 391 * that the application will encounter, in pixels (not dp units). Your 392 * application may of course still get larger space than this if, 393 * for example, screen decorations like the status bar are being hidden. 394 */ getCurrentSizeRange(Point outSmallestSize, Point outLargestSize)395 public void getCurrentSizeRange(Point outSmallestSize, Point outLargestSize) { 396 synchronized (this) { 397 updateDisplayInfoLocked(); 398 outSmallestSize.x = mDisplayInfo.smallestNominalAppWidth; 399 outSmallestSize.y = mDisplayInfo.smallestNominalAppHeight; 400 outLargestSize.x = mDisplayInfo.largestNominalAppWidth; 401 outLargestSize.y = mDisplayInfo.largestNominalAppHeight; 402 } 403 } 404 405 /** 406 * Return the maximum screen size dimension that will happen. This is 407 * mostly for wallpapers. 408 * @hide 409 */ getMaximumSizeDimension()410 public int getMaximumSizeDimension() { 411 synchronized (this) { 412 updateDisplayInfoLocked(); 413 return Math.max(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); 414 } 415 } 416 417 /** 418 * @deprecated Use {@link #getSize(Point)} instead. 419 */ 420 @Deprecated getWidth()421 public int getWidth() { 422 synchronized (this) { 423 updateCachedAppSizeIfNeededLocked(); 424 return mCachedAppWidthCompat; 425 } 426 } 427 428 /** 429 * @deprecated Use {@link #getSize(Point)} instead. 430 */ 431 @Deprecated getHeight()432 public int getHeight() { 433 synchronized (this) { 434 updateCachedAppSizeIfNeededLocked(); 435 return mCachedAppHeightCompat; 436 } 437 } 438 439 /** 440 * Returns the rotation of the screen from its "natural" orientation. 441 * The returned value may be {@link Surface#ROTATION_0 Surface.ROTATION_0} 442 * (no rotation), {@link Surface#ROTATION_90 Surface.ROTATION_90}, 443 * {@link Surface#ROTATION_180 Surface.ROTATION_180}, or 444 * {@link Surface#ROTATION_270 Surface.ROTATION_270}. For 445 * example, if a device has a naturally tall screen, and the user has 446 * turned it on its side to go into a landscape orientation, the value 447 * returned here may be either {@link Surface#ROTATION_90 Surface.ROTATION_90} 448 * or {@link Surface#ROTATION_270 Surface.ROTATION_270} depending on 449 * the direction it was turned. The angle is the rotation of the drawn 450 * graphics on the screen, which is the opposite direction of the physical 451 * rotation of the device. For example, if the device is rotated 90 452 * degrees counter-clockwise, to compensate rendering will be rotated by 453 * 90 degrees clockwise and thus the returned value here will be 454 * {@link Surface#ROTATION_90 Surface.ROTATION_90}. 455 */ getRotation()456 public int getRotation() { 457 synchronized (this) { 458 updateDisplayInfoLocked(); 459 return mDisplayInfo.rotation; 460 } 461 } 462 463 /** 464 * @deprecated use {@link #getRotation} 465 * @return orientation of this display. 466 */ 467 @Deprecated getOrientation()468 public int getOrientation() { 469 return getRotation(); 470 } 471 472 /** 473 * Gets the pixel format of the display. 474 * @return One of the constants defined in {@link android.graphics.PixelFormat}. 475 * 476 * @deprecated This method is no longer supported. 477 * The result is always {@link PixelFormat#RGBA_8888}. 478 */ 479 @Deprecated getPixelFormat()480 public int getPixelFormat() { 481 return PixelFormat.RGBA_8888; 482 } 483 484 /** 485 * Gets the refresh rate of this display in frames per second. 486 */ getRefreshRate()487 public float getRefreshRate() { 488 synchronized (this) { 489 updateDisplayInfoLocked(); 490 return mDisplayInfo.refreshRate; 491 } 492 } 493 494 /** 495 * Gets display metrics that describe the size and density of this display. 496 * <p> 497 * The size is adjusted based on the current rotation of the display. 498 * </p><p> 499 * The size returned by this method does not necessarily represent the 500 * actual raw size (native resolution) of the display. The returned size may 501 * be adjusted to exclude certain system decor elements that are always visible. 502 * It may also be scaled to provide compatibility with older applications that 503 * were originally designed for smaller displays. 504 * </p> 505 * 506 * @param outMetrics A {@link DisplayMetrics} object to receive the metrics. 507 */ getMetrics(DisplayMetrics outMetrics)508 public void getMetrics(DisplayMetrics outMetrics) { 509 synchronized (this) { 510 updateDisplayInfoLocked(); 511 mDisplayInfo.getAppMetrics(outMetrics, mCompatibilityInfo); 512 } 513 } 514 515 /** 516 * Gets the real size of the display without subtracting any window decor or 517 * applying any compatibility scale factors. 518 * <p> 519 * The size is adjusted based on the current rotation of the display. 520 * </p><p> 521 * The real size may be smaller than the physical size of the screen when the 522 * window manager is emulating a smaller display (using adb shell am display-size). 523 * </p> 524 * 525 * @param outSize Set to the real size of the display. 526 */ getRealSize(Point outSize)527 public void getRealSize(Point outSize) { 528 synchronized (this) { 529 updateDisplayInfoLocked(); 530 outSize.x = mDisplayInfo.logicalWidth; 531 outSize.y = mDisplayInfo.logicalHeight; 532 } 533 } 534 535 /** 536 * Gets display metrics based on the real size of this display. 537 * <p> 538 * The size is adjusted based on the current rotation of the display. 539 * </p><p> 540 * The real size may be smaller than the physical size of the screen when the 541 * window manager is emulating a smaller display (using adb shell am display-size). 542 * </p> 543 * 544 * @param outMetrics A {@link DisplayMetrics} object to receive the metrics. 545 */ getRealMetrics(DisplayMetrics outMetrics)546 public void getRealMetrics(DisplayMetrics outMetrics) { 547 synchronized (this) { 548 updateDisplayInfoLocked(); 549 mDisplayInfo.getLogicalMetrics(outMetrics, null); 550 } 551 } 552 updateDisplayInfoLocked()553 private void updateDisplayInfoLocked() { 554 // Note: The display manager caches display info objects on our behalf. 555 DisplayInfo newInfo = mGlobal.getDisplayInfo(mDisplayId); 556 if (newInfo == null) { 557 // Preserve the old mDisplayInfo after the display is removed. 558 if (mIsValid) { 559 mIsValid = false; 560 if (DEBUG) { 561 Log.d(TAG, "Logical display " + mDisplayId + " was removed."); 562 } 563 } 564 } else { 565 // Use the new display info. (It might be the same object if nothing changed.) 566 mDisplayInfo = newInfo; 567 if (!mIsValid) { 568 mIsValid = true; 569 if (DEBUG) { 570 Log.d(TAG, "Logical display " + mDisplayId + " was recreated."); 571 } 572 } 573 } 574 } 575 updateCachedAppSizeIfNeededLocked()576 private void updateCachedAppSizeIfNeededLocked() { 577 long now = SystemClock.uptimeMillis(); 578 if (now > mLastCachedAppSizeUpdate + CACHED_APP_SIZE_DURATION_MILLIS) { 579 updateDisplayInfoLocked(); 580 mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo); 581 mCachedAppWidthCompat = mTempMetrics.widthPixels; 582 mCachedAppHeightCompat = mTempMetrics.heightPixels; 583 mLastCachedAppSizeUpdate = now; 584 } 585 } 586 587 // For debugging purposes 588 @Override toString()589 public String toString() { 590 synchronized (this) { 591 updateDisplayInfoLocked(); 592 mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo); 593 return "Display id " + mDisplayId + ": " + mDisplayInfo 594 + ", " + mTempMetrics + ", isValid=" + mIsValid; 595 } 596 } 597 598 /** 599 * @hide 600 */ typeToString(int type)601 public static String typeToString(int type) { 602 switch (type) { 603 case TYPE_UNKNOWN: 604 return "UNKNOWN"; 605 case TYPE_BUILT_IN: 606 return "BUILT_IN"; 607 case TYPE_HDMI: 608 return "HDMI"; 609 case TYPE_WIFI: 610 return "WIFI"; 611 case TYPE_OVERLAY: 612 return "OVERLAY"; 613 default: 614 return Integer.toString(type); 615 } 616 } 617 } 618 619