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