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.PixelFormat; 21 import android.graphics.Point; 22 import android.graphics.Rect; 23 import android.hardware.display.DisplayManagerGlobal; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 import android.os.Process; 27 import android.os.SystemClock; 28 import android.util.DisplayMetrics; 29 import android.util.Log; 30 31 import java.util.Arrays; 32 33 /** 34 * Provides information about the size and density of a logical display. 35 * <p> 36 * The display area is described in two different ways. 37 * <ul> 38 * <li>The application display area specifies the part of the display that may contain 39 * an application window, excluding the system decorations. The application display area may 40 * be smaller than the real display area because the system subtracts the space needed 41 * for decor elements such as the status bar. Use the following methods to query the 42 * application display area: {@link #getSize}, {@link #getRectSize} and {@link #getMetrics}.</li> 43 * <li>The real display area specifies the part of the display that contains content 44 * including the system decorations. Even so, the real display area may be smaller than the 45 * physical size of the display if the window manager is emulating a smaller display 46 * using (adb shell am display-size). Use the following methods to query the 47 * real display area: {@link #getRealSize}, {@link #getRealMetrics}.</li> 48 * </ul> 49 * </p><p> 50 * A logical display does not necessarily represent a particular physical display device 51 * such as the built-in screen or an external monitor. The contents of a logical 52 * display may be presented on one or more physical displays according to the devices 53 * that are currently attached and whether mirroring has been enabled. 54 * </p> 55 */ 56 public final class Display { 57 private static final String TAG = "Display"; 58 private static final boolean DEBUG = false; 59 60 private final DisplayManagerGlobal mGlobal; 61 private final int mDisplayId; 62 private final int mLayerStack; 63 private final int mFlags; 64 private final int mType; 65 private final String mAddress; 66 private final int mOwnerUid; 67 private final String mOwnerPackageName; 68 private final DisplayAdjustments mDisplayAdjustments; 69 70 private DisplayInfo mDisplayInfo; // never null 71 private boolean mIsValid; 72 73 // Temporary display metrics structure used for compatibility mode. 74 private final DisplayMetrics mTempMetrics = new DisplayMetrics(); 75 76 // We cache the app width and height properties briefly between calls 77 // to getHeight() and getWidth() to ensure that applications perceive 78 // consistent results when the size changes (most of the time). 79 // Applications should now be using getSize() instead. 80 private static final int CACHED_APP_SIZE_DURATION_MILLIS = 20; 81 private long mLastCachedAppSizeUpdate; 82 private int mCachedAppWidthCompat; 83 private int mCachedAppHeightCompat; 84 85 /** 86 * The default Display id, which is the id of the built-in primary display 87 * assuming there is one. 88 */ 89 public static final int DEFAULT_DISPLAY = 0; 90 91 /** 92 * Invalid display id. 93 */ 94 public static final int INVALID_DISPLAY = -1; 95 96 /** 97 * Display flag: Indicates that the display supports compositing content 98 * that is stored in protected graphics buffers. 99 * <p> 100 * If this flag is set then the display device supports compositing protected buffers. 101 * </p><p> 102 * If this flag is not set then the display device may not support compositing 103 * protected buffers; the user may see a blank region on the screen instead of 104 * the protected content. 105 * </p><p> 106 * Secure (DRM) video decoders may allocate protected graphics buffers to request that 107 * a hardware-protected path be provided between the video decoder and the external 108 * display sink. If a hardware-protected path is not available, then content stored 109 * in protected graphics buffers may not be composited. 110 * </p><p> 111 * An application can use the absence of this flag as a hint that it should not use protected 112 * buffers for this display because the content may not be visible. For example, 113 * if the flag is not set then the application may choose not to show content on this 114 * display, show an informative error message, select an alternate content stream 115 * or adopt a different strategy for decoding content that does not rely on 116 * protected buffers. 117 * </p> 118 * 119 * @see #getFlags 120 */ 121 public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1 << 0; 122 123 /** 124 * Display flag: Indicates that the display has a secure video output and 125 * supports compositing secure surfaces. 126 * <p> 127 * If this flag is set then the display device has a secure video output 128 * and is capable of showing secure surfaces. It may also be capable of 129 * showing {@link #FLAG_SUPPORTS_PROTECTED_BUFFERS protected buffers}. 130 * </p><p> 131 * If this flag is not set then the display device may not have a secure video 132 * output; the user may see a blank region on the screen instead of 133 * the contents of secure surfaces or protected buffers. 134 * </p><p> 135 * Secure surfaces are used to prevent content rendered into those surfaces 136 * by applications from appearing in screenshots or from being viewed 137 * on non-secure displays. Protected buffers are used by secure video decoders 138 * for a similar purpose. 139 * </p><p> 140 * An application creates a window with a secure surface by specifying the 141 * {@link WindowManager.LayoutParams#FLAG_SECURE} window flag. 142 * Likewise, an application creates a {@link SurfaceView} with a secure surface 143 * by calling {@link SurfaceView#setSecure} before attaching the secure view to 144 * its containing window. 145 * </p><p> 146 * An application can use the absence of this flag as a hint that it should not create 147 * secure surfaces or protected buffers on this display because the content may 148 * not be visible. For example, if the flag is not set then the application may 149 * choose not to show content on this display, show an informative error message, 150 * select an alternate content stream or adopt a different strategy for decoding 151 * content that does not rely on secure surfaces or protected buffers. 152 * </p> 153 * 154 * @see #getFlags 155 */ 156 public static final int FLAG_SECURE = 1 << 1; 157 158 /** 159 * Display flag: Indicates that the display is private. Only the application that 160 * owns the display can create windows on it. 161 * 162 * @see #getFlags 163 */ 164 public static final int FLAG_PRIVATE = 1 << 2; 165 166 /** 167 * Display flag: Indicates that the display is a presentation display. 168 * <p> 169 * This flag identifies secondary displays that are suitable for 170 * use as presentation displays such as HDMI or Wireless displays. Applications 171 * may automatically project their content to presentation displays to provide 172 * richer second screen experiences. 173 * </p> 174 * 175 * @see #getFlags 176 */ 177 public static final int FLAG_PRESENTATION = 1 << 3; 178 179 /** 180 * Display flag: Indicates that the display has a round shape. 181 * <p> 182 * This flag identifies displays that are circular, elliptical or otherwise 183 * do not permit the user to see all the way to the logical corners of the display. 184 * </p> 185 * 186 * @see #getFlags 187 */ 188 public static final int FLAG_ROUND = 1 << 4; 189 190 /** 191 * Display flag: Indicates that the contents of the display should not be scaled 192 * to fit the physical screen dimensions. Used for development only to emulate 193 * devices with smaller physicals screens while preserving density. 194 * 195 * @hide 196 */ 197 public static final int FLAG_SCALING_DISABLED = 1 << 30; 198 199 /** 200 * Display type: Unknown display type. 201 * @hide 202 */ 203 public static final int TYPE_UNKNOWN = 0; 204 205 /** 206 * Display type: Built-in display. 207 * @hide 208 */ 209 public static final int TYPE_BUILT_IN = 1; 210 211 /** 212 * Display type: HDMI display. 213 * @hide 214 */ 215 public static final int TYPE_HDMI = 2; 216 217 /** 218 * Display type: WiFi display. 219 * @hide 220 */ 221 public static final int TYPE_WIFI = 3; 222 223 /** 224 * Display type: Overlay display. 225 * @hide 226 */ 227 public static final int TYPE_OVERLAY = 4; 228 229 /** 230 * Display type: Virtual display. 231 * @hide 232 */ 233 public static final int TYPE_VIRTUAL = 5; 234 235 /** 236 * Display state: The display state is unknown. 237 * 238 * @see #getState 239 */ 240 public static final int STATE_UNKNOWN = 0; 241 242 /** 243 * Display state: The display is off. 244 * 245 * @see #getState 246 */ 247 public static final int STATE_OFF = 1; 248 249 /** 250 * Display state: The display is on. 251 * 252 * @see #getState 253 */ 254 public static final int STATE_ON = 2; 255 256 /** 257 * Display state: The display is dozing in a low power state; it is still 258 * on but is optimized for showing system-provided content while the 259 * device is non-interactive. 260 * 261 * @see #getState 262 * @see android.os.PowerManager#isInteractive 263 */ 264 public static final int STATE_DOZE = 3; 265 266 /** 267 * Display state: The display is dozing in a suspended low power state; it is still 268 * on but is optimized for showing static system-provided content while the device 269 * is non-interactive. This mode may be used to conserve even more power by allowing 270 * the hardware to stop applying frame buffer updates from the graphics subsystem or 271 * to take over the display and manage it autonomously to implement low power always-on 272 * display functionality. 273 * 274 * @see #getState 275 * @see android.os.PowerManager#isInteractive 276 */ 277 public static final int STATE_DOZE_SUSPEND = 4; 278 279 /** 280 * Internal method to create a display. 281 * Applications should use {@link android.view.WindowManager#getDefaultDisplay()} 282 * or {@link android.hardware.display.DisplayManager#getDisplay} 283 * to get a display object. 284 * 285 * @hide 286 */ Display(DisplayManagerGlobal global, int displayId, DisplayInfo displayInfo , DisplayAdjustments daj)287 public Display(DisplayManagerGlobal global, 288 int displayId, DisplayInfo displayInfo /*not null*/, 289 DisplayAdjustments daj) { 290 mGlobal = global; 291 mDisplayId = displayId; 292 mDisplayInfo = displayInfo; 293 mDisplayAdjustments = new DisplayAdjustments(daj); 294 mIsValid = true; 295 296 // Cache properties that cannot change as long as the display is valid. 297 mLayerStack = displayInfo.layerStack; 298 mFlags = displayInfo.flags; 299 mType = displayInfo.type; 300 mAddress = displayInfo.address; 301 mOwnerUid = displayInfo.ownerUid; 302 mOwnerPackageName = displayInfo.ownerPackageName; 303 } 304 305 /** 306 * Gets the display id. 307 * <p> 308 * Each logical display has a unique id. 309 * The default display has id {@link #DEFAULT_DISPLAY}. 310 * </p> 311 */ getDisplayId()312 public int getDisplayId() { 313 return mDisplayId; 314 } 315 316 /** 317 * Returns true if this display is still valid, false if the display has been removed. 318 * 319 * If the display is invalid, then the methods of this class will 320 * continue to report the most recently observed display information. 321 * However, it is unwise (and rather fruitless) to continue using a 322 * {@link Display} object after the display's demise. 323 * 324 * It's possible for a display that was previously invalid to become 325 * valid again if a display with the same id is reconnected. 326 * 327 * @return True if the display is still valid. 328 */ isValid()329 public boolean isValid() { 330 synchronized (this) { 331 updateDisplayInfoLocked(); 332 return mIsValid; 333 } 334 } 335 336 /** 337 * Gets a full copy of the display information. 338 * 339 * @param outDisplayInfo The object to receive the copy of the display information. 340 * @return True if the display is still valid. 341 * @hide 342 */ getDisplayInfo(DisplayInfo outDisplayInfo)343 public boolean getDisplayInfo(DisplayInfo outDisplayInfo) { 344 synchronized (this) { 345 updateDisplayInfoLocked(); 346 outDisplayInfo.copyFrom(mDisplayInfo); 347 return mIsValid; 348 } 349 } 350 351 /** 352 * Gets the display's layer stack. 353 * 354 * Each display has its own independent layer stack upon which surfaces 355 * are placed to be managed by surface flinger. 356 * 357 * @return The display's layer stack number. 358 * @hide 359 */ getLayerStack()360 public int getLayerStack() { 361 return mLayerStack; 362 } 363 364 /** 365 * Returns a combination of flags that describe the capabilities of the display. 366 * 367 * @return The display flags. 368 * 369 * @see #FLAG_SUPPORTS_PROTECTED_BUFFERS 370 * @see #FLAG_SECURE 371 * @see #FLAG_PRIVATE 372 */ getFlags()373 public int getFlags() { 374 return mFlags; 375 } 376 377 /** 378 * Gets the display type. 379 * 380 * @return The display type. 381 * 382 * @see #TYPE_UNKNOWN 383 * @see #TYPE_BUILT_IN 384 * @see #TYPE_HDMI 385 * @see #TYPE_WIFI 386 * @see #TYPE_OVERLAY 387 * @see #TYPE_VIRTUAL 388 * @hide 389 */ getType()390 public int getType() { 391 return mType; 392 } 393 394 /** 395 * Gets the display address, or null if none. 396 * Interpretation varies by display type. 397 * 398 * @return The display address. 399 * @hide 400 */ getAddress()401 public String getAddress() { 402 return mAddress; 403 } 404 405 /** 406 * Gets the UID of the application that owns this display, or zero if it is 407 * owned by the system. 408 * <p> 409 * If the display is private, then only the owner can use it. 410 * </p> 411 * 412 * @hide 413 */ getOwnerUid()414 public int getOwnerUid() { 415 return mOwnerUid; 416 } 417 418 /** 419 * Gets the package name of the application that owns this display, or null if it is 420 * owned by the system. 421 * <p> 422 * If the display is private, then only the owner can use it. 423 * </p> 424 * 425 * @hide 426 */ getOwnerPackageName()427 public String getOwnerPackageName() { 428 return mOwnerPackageName; 429 } 430 431 /** 432 * Gets the compatibility info used by this display instance. 433 * 434 * @return The display adjustments holder, or null if none is required. 435 * @hide 436 */ getDisplayAdjustments()437 public DisplayAdjustments getDisplayAdjustments() { 438 return mDisplayAdjustments; 439 } 440 441 /** 442 * Gets the name of the display. 443 * <p> 444 * Note that some displays may be renamed by the user. 445 * </p> 446 * 447 * @return The display's name. 448 */ getName()449 public String getName() { 450 synchronized (this) { 451 updateDisplayInfoLocked(); 452 return mDisplayInfo.name; 453 } 454 } 455 456 /** 457 * Gets the size of the display, in pixels. 458 * <p> 459 * Note that this value should <em>not</em> be used for computing layouts, 460 * since a device will typically have screen decoration (such as a status bar) 461 * along the edges of the display that reduce the amount of application 462 * space available from the size returned here. Layouts should instead use 463 * the window size. 464 * </p><p> 465 * The size is adjusted based on the current rotation of the display. 466 * </p><p> 467 * The size returned by this method does not necessarily represent the 468 * actual raw size (native resolution) of the display. The returned size may 469 * be adjusted to exclude certain system decoration elements that are always visible. 470 * It may also be scaled to provide compatibility with older applications that 471 * were originally designed for smaller displays. 472 * </p> 473 * 474 * @param outSize A {@link Point} object to receive the size information. 475 */ getSize(Point outSize)476 public void getSize(Point outSize) { 477 synchronized (this) { 478 updateDisplayInfoLocked(); 479 mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments); 480 outSize.x = mTempMetrics.widthPixels; 481 outSize.y = mTempMetrics.heightPixels; 482 } 483 } 484 485 /** 486 * Gets the size of the display as a rectangle, in pixels. 487 * 488 * @param outSize A {@link Rect} object to receive the size information. 489 * @see #getSize(Point) 490 */ getRectSize(Rect outSize)491 public void getRectSize(Rect outSize) { 492 synchronized (this) { 493 updateDisplayInfoLocked(); 494 mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments); 495 outSize.set(0, 0, mTempMetrics.widthPixels, mTempMetrics.heightPixels); 496 } 497 } 498 499 /** 500 * Return the range of display sizes an application can expect to encounter 501 * under normal operation, as long as there is no physical change in screen 502 * size. This is basically the sizes you will see as the orientation 503 * changes, taking into account whatever screen decoration there is in 504 * each rotation. For example, the status bar is always at the top of the 505 * screen, so it will reduce the height both in landscape and portrait, and 506 * the smallest height returned here will be the smaller of the two. 507 * 508 * This is intended for applications to get an idea of the range of sizes 509 * they will encounter while going through device rotations, to provide a 510 * stable UI through rotation. The sizes here take into account all standard 511 * system decorations that reduce the size actually available to the 512 * application: the status bar, navigation bar, system bar, etc. It does 513 * <em>not</em> take into account more transient elements like an IME 514 * soft keyboard. 515 * 516 * @param outSmallestSize Filled in with the smallest width and height 517 * that the application will encounter, in pixels (not dp units). The x 518 * (width) dimension here directly corresponds to 519 * {@link android.content.res.Configuration#smallestScreenWidthDp 520 * Configuration.smallestScreenWidthDp}, except the value here is in raw 521 * screen pixels rather than dp units. Your application may of course 522 * still get smaller space yet if, for example, a soft keyboard is 523 * being displayed. 524 * @param outLargestSize Filled in with the largest width and height 525 * that the application will encounter, in pixels (not dp units). Your 526 * application may of course still get larger space than this if, 527 * for example, screen decorations like the status bar are being hidden. 528 */ getCurrentSizeRange(Point outSmallestSize, Point outLargestSize)529 public void getCurrentSizeRange(Point outSmallestSize, Point outLargestSize) { 530 synchronized (this) { 531 updateDisplayInfoLocked(); 532 outSmallestSize.x = mDisplayInfo.smallestNominalAppWidth; 533 outSmallestSize.y = mDisplayInfo.smallestNominalAppHeight; 534 outLargestSize.x = mDisplayInfo.largestNominalAppWidth; 535 outLargestSize.y = mDisplayInfo.largestNominalAppHeight; 536 } 537 } 538 539 /** 540 * Return the maximum screen size dimension that will happen. This is 541 * mostly for wallpapers. 542 * @hide 543 */ getMaximumSizeDimension()544 public int getMaximumSizeDimension() { 545 synchronized (this) { 546 updateDisplayInfoLocked(); 547 return Math.max(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); 548 } 549 } 550 551 /** 552 * @deprecated Use {@link #getSize(Point)} instead. 553 */ 554 @Deprecated getWidth()555 public int getWidth() { 556 synchronized (this) { 557 updateCachedAppSizeIfNeededLocked(); 558 return mCachedAppWidthCompat; 559 } 560 } 561 562 /** 563 * @deprecated Use {@link #getSize(Point)} instead. 564 */ 565 @Deprecated getHeight()566 public int getHeight() { 567 synchronized (this) { 568 updateCachedAppSizeIfNeededLocked(); 569 return mCachedAppHeightCompat; 570 } 571 } 572 573 /** 574 * @hide 575 * Return a rectangle defining the insets of the overscan region of the display. 576 * Each field of the rectangle is the number of pixels the overscan area extends 577 * into the display on that side. 578 */ getOverscanInsets(Rect outRect)579 public void getOverscanInsets(Rect outRect) { 580 synchronized (this) { 581 updateDisplayInfoLocked(); 582 outRect.set(mDisplayInfo.overscanLeft, mDisplayInfo.overscanTop, 583 mDisplayInfo.overscanRight, mDisplayInfo.overscanBottom); 584 } 585 } 586 587 /** 588 * Returns the rotation of the screen from its "natural" orientation. 589 * The returned value may be {@link Surface#ROTATION_0 Surface.ROTATION_0} 590 * (no rotation), {@link Surface#ROTATION_90 Surface.ROTATION_90}, 591 * {@link Surface#ROTATION_180 Surface.ROTATION_180}, or 592 * {@link Surface#ROTATION_270 Surface.ROTATION_270}. For 593 * example, if a device has a naturally tall screen, and the user has 594 * turned it on its side to go into a landscape orientation, the value 595 * returned here may be either {@link Surface#ROTATION_90 Surface.ROTATION_90} 596 * or {@link Surface#ROTATION_270 Surface.ROTATION_270} depending on 597 * the direction it was turned. The angle is the rotation of the drawn 598 * graphics on the screen, which is the opposite direction of the physical 599 * rotation of the device. For example, if the device is rotated 90 600 * degrees counter-clockwise, to compensate rendering will be rotated by 601 * 90 degrees clockwise and thus the returned value here will be 602 * {@link Surface#ROTATION_90 Surface.ROTATION_90}. 603 */ 604 @Surface.Rotation getRotation()605 public int getRotation() { 606 synchronized (this) { 607 updateDisplayInfoLocked(); 608 return mDisplayInfo.rotation; 609 } 610 } 611 612 /** 613 * @deprecated use {@link #getRotation} 614 * @return orientation of this display. 615 */ 616 @Deprecated 617 @Surface.Rotation getOrientation()618 public int getOrientation() { 619 return getRotation(); 620 } 621 622 /** 623 * Gets the pixel format of the display. 624 * @return One of the constants defined in {@link android.graphics.PixelFormat}. 625 * 626 * @deprecated This method is no longer supported. 627 * The result is always {@link PixelFormat#RGBA_8888}. 628 */ 629 @Deprecated getPixelFormat()630 public int getPixelFormat() { 631 return PixelFormat.RGBA_8888; 632 } 633 634 /** 635 * Gets the refresh rate of this display in frames per second. 636 */ getRefreshRate()637 public float getRefreshRate() { 638 synchronized (this) { 639 updateDisplayInfoLocked(); 640 return mDisplayInfo.getMode().getRefreshRate(); 641 } 642 } 643 644 /** 645 * Get the supported refresh rates of this display in frames per second. 646 * <p> 647 * This method only returns refresh rates for the display's default modes. For more options, use 648 * {@link #getSupportedModes()}. 649 * 650 * @deprecated use {@link #getSupportedModes()} instead 651 */ 652 @Deprecated getSupportedRefreshRates()653 public float[] getSupportedRefreshRates() { 654 synchronized (this) { 655 updateDisplayInfoLocked(); 656 return mDisplayInfo.getDefaultRefreshRates(); 657 } 658 } 659 660 /** 661 * Returns the active mode of the display. 662 */ getMode()663 public Mode getMode() { 664 synchronized (this) { 665 updateDisplayInfoLocked(); 666 return mDisplayInfo.getMode(); 667 } 668 } 669 670 /** 671 * Gets the supported modes of this display. 672 */ getSupportedModes()673 public Mode[] getSupportedModes() { 674 synchronized (this) { 675 updateDisplayInfoLocked(); 676 final Display.Mode[] modes = mDisplayInfo.supportedModes; 677 return Arrays.copyOf(modes, modes.length); 678 } 679 } 680 681 /** 682 * Gets the app VSYNC offset, in nanoseconds. This is a positive value indicating 683 * the phase offset of the VSYNC events provided by Choreographer relative to the 684 * display refresh. For example, if Choreographer reports that the refresh occurred 685 * at time N, it actually occurred at (N - appVsyncOffset). 686 * <p> 687 * Apps generally do not need to be aware of this. It's only useful for fine-grained 688 * A/V synchronization. 689 */ getAppVsyncOffsetNanos()690 public long getAppVsyncOffsetNanos() { 691 synchronized (this) { 692 updateDisplayInfoLocked(); 693 return mDisplayInfo.appVsyncOffsetNanos; 694 } 695 } 696 697 /** 698 * This is how far in advance a buffer must be queued for presentation at 699 * a given time. If you want a buffer to appear on the screen at 700 * time N, you must submit the buffer before (N - presentationDeadline). 701 * <p> 702 * The desired presentation time for GLES rendering may be set with 703 * {@link android.opengl.EGLExt#eglPresentationTimeANDROID}. For video decoding, use 704 * {@link android.media.MediaCodec#releaseOutputBuffer(int, long)}. Times are 705 * expressed in nanoseconds, using the system monotonic clock 706 * ({@link System#nanoTime}). 707 */ getPresentationDeadlineNanos()708 public long getPresentationDeadlineNanos() { 709 synchronized (this) { 710 updateDisplayInfoLocked(); 711 return mDisplayInfo.presentationDeadlineNanos; 712 } 713 } 714 715 /** 716 * Gets display metrics that describe the size and density of this display. 717 * <p> 718 * The size is adjusted based on the current rotation of the display. 719 * </p><p> 720 * The size returned by this method does not necessarily represent the 721 * actual raw size (native resolution) of the display. The returned size may 722 * be adjusted to exclude certain system decor elements that are always visible. 723 * It may also be scaled to provide compatibility with older applications that 724 * were originally designed for smaller displays. 725 * </p> 726 * 727 * @param outMetrics A {@link DisplayMetrics} object to receive the metrics. 728 */ getMetrics(DisplayMetrics outMetrics)729 public void getMetrics(DisplayMetrics outMetrics) { 730 synchronized (this) { 731 updateDisplayInfoLocked(); 732 mDisplayInfo.getAppMetrics(outMetrics, mDisplayAdjustments); 733 } 734 } 735 736 /** 737 * Gets the real size of the display without subtracting any window decor or 738 * applying any compatibility scale factors. 739 * <p> 740 * The size is adjusted based on the current rotation of the display. 741 * </p><p> 742 * The real size may be smaller than the physical size of the screen when the 743 * window manager is emulating a smaller display (using adb shell am display-size). 744 * </p> 745 * 746 * @param outSize Set to the real size of the display. 747 */ getRealSize(Point outSize)748 public void getRealSize(Point outSize) { 749 synchronized (this) { 750 updateDisplayInfoLocked(); 751 outSize.x = mDisplayInfo.logicalWidth; 752 outSize.y = mDisplayInfo.logicalHeight; 753 } 754 } 755 756 /** 757 * Gets display metrics based on the real size of this display. 758 * <p> 759 * The size is adjusted based on the current rotation of the display. 760 * </p><p> 761 * The real size may be smaller than the physical size of the screen when the 762 * window manager is emulating a smaller display (using adb shell am display-size). 763 * </p> 764 * 765 * @param outMetrics A {@link DisplayMetrics} object to receive the metrics. 766 */ getRealMetrics(DisplayMetrics outMetrics)767 public void getRealMetrics(DisplayMetrics outMetrics) { 768 synchronized (this) { 769 updateDisplayInfoLocked(); 770 mDisplayInfo.getLogicalMetrics(outMetrics, 771 CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, 772 mDisplayAdjustments.getConfiguration()); 773 } 774 } 775 776 /** 777 * Gets the state of the display, such as whether it is on or off. 778 * 779 * @return The state of the display: one of {@link #STATE_OFF}, {@link #STATE_ON}, 780 * {@link #STATE_DOZE}, {@link #STATE_DOZE_SUSPEND}, or {@link #STATE_UNKNOWN}. 781 */ getState()782 public int getState() { 783 synchronized (this) { 784 updateDisplayInfoLocked(); 785 return mIsValid ? mDisplayInfo.state : STATE_UNKNOWN; 786 } 787 } 788 789 /** 790 * Returns true if the specified UID has access to this display. 791 * @hide 792 */ hasAccess(int uid)793 public boolean hasAccess(int uid) { 794 return Display.hasAccess(uid, mFlags, mOwnerUid); 795 } 796 797 /** @hide */ hasAccess(int uid, int flags, int ownerUid)798 public static boolean hasAccess(int uid, int flags, int ownerUid) { 799 return (flags & Display.FLAG_PRIVATE) == 0 800 || uid == ownerUid 801 || uid == Process.SYSTEM_UID 802 || uid == 0; 803 } 804 805 /** 806 * Returns true if the display is a public presentation display. 807 * @hide 808 */ isPublicPresentation()809 public boolean isPublicPresentation() { 810 return (mFlags & (Display.FLAG_PRIVATE | Display.FLAG_PRESENTATION)) == 811 Display.FLAG_PRESENTATION; 812 } 813 updateDisplayInfoLocked()814 private void updateDisplayInfoLocked() { 815 // Note: The display manager caches display info objects on our behalf. 816 DisplayInfo newInfo = mGlobal.getDisplayInfo(mDisplayId); 817 if (newInfo == null) { 818 // Preserve the old mDisplayInfo after the display is removed. 819 if (mIsValid) { 820 mIsValid = false; 821 if (DEBUG) { 822 Log.d(TAG, "Logical display " + mDisplayId + " was removed."); 823 } 824 } 825 } else { 826 // Use the new display info. (It might be the same object if nothing changed.) 827 mDisplayInfo = newInfo; 828 if (!mIsValid) { 829 mIsValid = true; 830 if (DEBUG) { 831 Log.d(TAG, "Logical display " + mDisplayId + " was recreated."); 832 } 833 } 834 } 835 } 836 updateCachedAppSizeIfNeededLocked()837 private void updateCachedAppSizeIfNeededLocked() { 838 long now = SystemClock.uptimeMillis(); 839 if (now > mLastCachedAppSizeUpdate + CACHED_APP_SIZE_DURATION_MILLIS) { 840 updateDisplayInfoLocked(); 841 mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments); 842 mCachedAppWidthCompat = mTempMetrics.widthPixels; 843 mCachedAppHeightCompat = mTempMetrics.heightPixels; 844 mLastCachedAppSizeUpdate = now; 845 } 846 } 847 848 // For debugging purposes 849 @Override toString()850 public String toString() { 851 synchronized (this) { 852 updateDisplayInfoLocked(); 853 mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments); 854 return "Display id " + mDisplayId + ": " + mDisplayInfo 855 + ", " + mTempMetrics + ", isValid=" + mIsValid; 856 } 857 } 858 859 /** 860 * @hide 861 */ typeToString(int type)862 public static String typeToString(int type) { 863 switch (type) { 864 case TYPE_UNKNOWN: 865 return "UNKNOWN"; 866 case TYPE_BUILT_IN: 867 return "BUILT_IN"; 868 case TYPE_HDMI: 869 return "HDMI"; 870 case TYPE_WIFI: 871 return "WIFI"; 872 case TYPE_OVERLAY: 873 return "OVERLAY"; 874 case TYPE_VIRTUAL: 875 return "VIRTUAL"; 876 default: 877 return Integer.toString(type); 878 } 879 } 880 881 /** 882 * @hide 883 */ stateToString(int state)884 public static String stateToString(int state) { 885 switch (state) { 886 case STATE_UNKNOWN: 887 return "UNKNOWN"; 888 case STATE_OFF: 889 return "OFF"; 890 case STATE_ON: 891 return "ON"; 892 case STATE_DOZE: 893 return "DOZE"; 894 case STATE_DOZE_SUSPEND: 895 return "DOZE_SUSPEND"; 896 default: 897 return Integer.toString(state); 898 } 899 } 900 901 /** 902 * Returns true if display updates may be suspended while in the specified 903 * display power state. 904 * @hide 905 */ isSuspendedState(int state)906 public static boolean isSuspendedState(int state) { 907 return state == STATE_OFF || state == STATE_DOZE_SUSPEND; 908 } 909 910 /** 911 * A mode supported by a given display. 912 * 913 * @see Display#getSupportedModes() 914 */ 915 public static final class Mode implements Parcelable { 916 /** 917 * @hide 918 */ 919 public static final Mode[] EMPTY_ARRAY = new Mode[0]; 920 921 private final int mModeId; 922 private final int mWidth; 923 private final int mHeight; 924 private final float mRefreshRate; 925 926 /** 927 * @hide 928 */ Mode(int modeId, int width, int height, float refreshRate)929 public Mode(int modeId, int width, int height, float refreshRate) { 930 mModeId = modeId; 931 mWidth = width; 932 mHeight = height; 933 mRefreshRate = refreshRate; 934 } 935 936 /** 937 * Returns this mode's id. 938 */ getModeId()939 public int getModeId() { 940 return mModeId; 941 } 942 943 /** 944 * Returns the physical width of the display in pixels when configured in this mode's 945 * resolution. 946 * <p> 947 * Note that due to application UI scaling, the number of pixels made available to 948 * applications when the mode is active (as reported by {@link Display#getWidth()} may 949 * differ from the mode's actual resolution (as reported by this function). 950 * <p> 951 * For example, applications running on a 4K display may have their UI laid out and rendered 952 * in 1080p and then scaled up. Applications can take advantage of the extra resolution by 953 * rendering content through a {@link android.view.SurfaceView} using full size buffers. 954 */ getPhysicalWidth()955 public int getPhysicalWidth() { 956 return mWidth; 957 } 958 959 /** 960 * Returns the physical height of the display in pixels when configured in this mode's 961 * resolution. 962 * <p> 963 * Note that due to application UI scaling, the number of pixels made available to 964 * applications when the mode is active (as reported by {@link Display#getHeight()} may 965 * differ from the mode's actual resolution (as reported by this function). 966 * <p> 967 * For example, applications running on a 4K display may have their UI laid out and rendered 968 * in 1080p and then scaled up. Applications can take advantage of the extra resolution by 969 * rendering content through a {@link android.view.SurfaceView} using full size buffers. 970 */ getPhysicalHeight()971 public int getPhysicalHeight() { 972 return mHeight; 973 } 974 975 /** 976 * Returns the refresh rate in frames per second. 977 */ getRefreshRate()978 public float getRefreshRate() { 979 return mRefreshRate; 980 } 981 982 /** 983 * Returns {@code true} if this mode matches the given parameters. 984 * 985 * @hide 986 */ matches(int width, int height, float refreshRate)987 public boolean matches(int width, int height, float refreshRate) { 988 return mWidth == width && 989 mHeight == height && 990 Float.floatToIntBits(mRefreshRate) == Float.floatToIntBits(refreshRate); 991 } 992 993 @Override equals(Object other)994 public boolean equals(Object other) { 995 if (this == other) { 996 return true; 997 } 998 if (!(other instanceof Mode)) { 999 return false; 1000 } 1001 Mode that = (Mode) other; 1002 return mModeId == that.mModeId && matches(that.mWidth, that.mHeight, that.mRefreshRate); 1003 } 1004 1005 @Override hashCode()1006 public int hashCode() { 1007 int hash = 1; 1008 hash = hash * 17 + mModeId; 1009 hash = hash * 17 + mWidth; 1010 hash = hash * 17 + mHeight; 1011 hash = hash * 17 + Float.floatToIntBits(mRefreshRate); 1012 return hash; 1013 } 1014 1015 @Override toString()1016 public String toString() { 1017 return new StringBuilder("{") 1018 .append("id=").append(mModeId) 1019 .append(", width=").append(mWidth) 1020 .append(", height=").append(mHeight) 1021 .append(", fps=").append(mRefreshRate) 1022 .append("}") 1023 .toString(); 1024 } 1025 1026 @Override describeContents()1027 public int describeContents() { 1028 return 0; 1029 } 1030 Mode(Parcel in)1031 private Mode(Parcel in) { 1032 this(in.readInt(), in.readInt(), in.readInt(), in.readFloat()); 1033 } 1034 1035 @Override writeToParcel(Parcel out, int parcelableFlags)1036 public void writeToParcel(Parcel out, int parcelableFlags) { 1037 out.writeInt(mModeId); 1038 out.writeInt(mWidth); 1039 out.writeInt(mHeight); 1040 out.writeFloat(mRefreshRate); 1041 } 1042 1043 @SuppressWarnings("hiding") 1044 public static final Parcelable.Creator<Mode> CREATOR 1045 = new Parcelable.Creator<Mode>() { 1046 @Override 1047 public Mode createFromParcel(Parcel in) { 1048 return new Mode(in); 1049 } 1050 1051 @Override 1052 public Mode[] newArray(int size) { 1053 return new Mode[size]; 1054 } 1055 }; 1056 } 1057 } 1058