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