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