1 /* 2 * Copyright (C) 2012 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.view.DisplayInfoProto.APP_HEIGHT; 20 import static android.view.DisplayInfoProto.APP_WIDTH; 21 import static android.view.DisplayInfoProto.FLAGS; 22 import static android.view.DisplayInfoProto.LOGICAL_HEIGHT; 23 import static android.view.DisplayInfoProto.LOGICAL_WIDTH; 24 import static android.view.DisplayInfoProto.NAME; 25 26 import android.annotation.Nullable; 27 import android.compat.annotation.UnsupportedAppUsage; 28 import android.content.res.CompatibilityInfo; 29 import android.content.res.Configuration; 30 import android.graphics.Rect; 31 import android.hardware.display.DeviceProductInfo; 32 import android.os.Build; 33 import android.os.Parcel; 34 import android.os.Parcelable; 35 import android.os.Process; 36 import android.util.ArraySet; 37 import android.util.DisplayMetrics; 38 import android.util.proto.ProtoOutputStream; 39 40 import java.util.Arrays; 41 import java.util.Objects; 42 43 /** 44 * Describes the characteristics of a particular logical display. 45 * @hide 46 */ 47 public final class DisplayInfo implements Parcelable { 48 /** 49 * The surface flinger layer stack associated with this logical display. 50 */ 51 public int layerStack; 52 53 /** 54 * Display flags. 55 */ 56 public int flags; 57 58 /** 59 * Display type. 60 */ 61 public int type; 62 63 /** 64 * Logical display identifier. 65 */ 66 public int displayId; 67 68 /** 69 * Display address, or null if none. 70 * Interpretation varies by display type. 71 */ 72 public DisplayAddress address; 73 74 /** 75 * Product-specific information about the display or the directly connected device on the 76 * display chain. For example, if the display is transitively connected, this field may contain 77 * product information about the intermediate device. 78 */ 79 public DeviceProductInfo deviceProductInfo; 80 81 /** 82 * The human-readable name of the display. 83 */ 84 public String name; 85 86 /** 87 * Unique identifier for the display. Shouldn't be displayed to the user. 88 */ 89 public String uniqueId; 90 91 /** 92 * The width of the portion of the display that is available to applications, in pixels. 93 * Represents the size of the display minus any system decorations. 94 */ 95 public int appWidth; 96 97 /** 98 * The height of the portion of the display that is available to applications, in pixels. 99 * Represents the size of the display minus any system decorations. 100 */ 101 public int appHeight; 102 103 /** 104 * The smallest value of {@link #appWidth} that an application is likely to encounter, 105 * in pixels, excepting cases where the width may be even smaller due to the presence 106 * of a soft keyboard, for example. 107 */ 108 public int smallestNominalAppWidth; 109 110 /** 111 * The smallest value of {@link #appHeight} that an application is likely to encounter, 112 * in pixels, excepting cases where the height may be even smaller due to the presence 113 * of a soft keyboard, for example. 114 */ 115 public int smallestNominalAppHeight; 116 117 /** 118 * The largest value of {@link #appWidth} that an application is likely to encounter, 119 * in pixels, excepting cases where the width may be even larger due to system decorations 120 * such as the status bar being hidden, for example. 121 */ 122 public int largestNominalAppWidth; 123 124 /** 125 * The largest value of {@link #appHeight} that an application is likely to encounter, 126 * in pixels, excepting cases where the height may be even larger due to system decorations 127 * such as the status bar being hidden, for example. 128 */ 129 public int largestNominalAppHeight; 130 131 /** 132 * The logical width of the display, in pixels. 133 * Represents the usable size of the display which may be smaller than the 134 * physical size when the system is emulating a smaller display. 135 */ 136 @UnsupportedAppUsage 137 public int logicalWidth; 138 139 /** 140 * The logical height of the display, in pixels. 141 * Represents the usable size of the display which may be smaller than the 142 * physical size when the system is emulating a smaller display. 143 */ 144 @UnsupportedAppUsage 145 public int logicalHeight; 146 147 /** 148 * The {@link DisplayCutout} if present, otherwise {@code null}. 149 * 150 * @hide 151 */ 152 // Remark on @UnsupportedAppUsage: Display.getCutout should be used instead 153 @Nullable 154 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) 155 public DisplayCutout displayCutout; 156 157 /** 158 * The rotation of the display relative to its natural orientation. 159 * May be one of {@link android.view.Surface#ROTATION_0}, 160 * {@link android.view.Surface#ROTATION_90}, {@link android.view.Surface#ROTATION_180}, 161 * {@link android.view.Surface#ROTATION_270}. 162 * <p> 163 * The value of this field is indeterminate if the logical display is presented on 164 * more than one physical display. 165 * </p> 166 */ 167 @Surface.Rotation 168 @UnsupportedAppUsage 169 public int rotation; 170 171 /** 172 * The active display mode. 173 */ 174 public int modeId; 175 176 /** 177 * The default display mode. 178 */ 179 public int defaultModeId; 180 181 /** 182 * The supported modes of this display. 183 */ 184 public Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY; 185 186 /** The active color mode. */ 187 public int colorMode; 188 189 /** The list of supported color modes */ 190 public int[] supportedColorModes = { Display.COLOR_MODE_DEFAULT }; 191 192 /** The display's HDR capabilities */ 193 public Display.HdrCapabilities hdrCapabilities; 194 195 /** 196 * Indicates whether the display can be switched into a mode with minimal post 197 * processing. 198 * 199 * @see android.view.Display#isMinimalPostProcessingSupported 200 */ 201 public boolean minimalPostProcessingSupported; 202 203 /** 204 * The logical display density which is the basis for density-independent 205 * pixels. 206 */ 207 public int logicalDensityDpi; 208 209 /** 210 * The exact physical pixels per inch of the screen in the X dimension. 211 * <p> 212 * The value of this field is indeterminate if the logical display is presented on 213 * more than one physical display. 214 * </p> 215 */ 216 public float physicalXDpi; 217 218 /** 219 * The exact physical pixels per inch of the screen in the Y dimension. 220 * <p> 221 * The value of this field is indeterminate if the logical display is presented on 222 * more than one physical display. 223 * </p> 224 */ 225 public float physicalYDpi; 226 227 /** 228 * This is a positive value indicating the phase offset of the VSYNC events provided by 229 * Choreographer relative to the display refresh. For example, if Choreographer reports 230 * that the refresh occurred at time N, it actually occurred at (N - appVsyncOffsetNanos). 231 */ 232 public long appVsyncOffsetNanos; 233 234 /** 235 * This is how far in advance a buffer must be queued for presentation at 236 * a given time. If you want a buffer to appear on the screen at 237 * time N, you must submit the buffer before (N - bufferDeadlineNanos). 238 */ 239 public long presentationDeadlineNanos; 240 241 /** 242 * The state of the display, such as {@link android.view.Display#STATE_ON}. 243 */ 244 public int state; 245 246 /** 247 * The UID of the application that owns this display, or zero if it is owned by the system. 248 * <p> 249 * If the display is private, then only the owner can use it. 250 * </p> 251 */ 252 public int ownerUid; 253 254 /** 255 * The package name of the application that owns this display, or null if it is 256 * owned by the system. 257 * <p> 258 * If the display is private, then only the owner can use it. 259 * </p> 260 */ 261 public String ownerPackageName; 262 263 /** 264 * @hide 265 * Get current remove mode of the display - what actions should be performed with the display's 266 * content when it is removed. 267 * 268 * @see Display#getRemoveMode() 269 */ 270 // TODO (b/114338689): Remove the flag and use IWindowManager#getRemoveContentMode 271 public int removeMode = Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY; 272 273 public static final @android.annotation.NonNull Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() { 274 @Override 275 public DisplayInfo createFromParcel(Parcel source) { 276 return new DisplayInfo(source); 277 } 278 279 @Override 280 public DisplayInfo[] newArray(int size) { 281 return new DisplayInfo[size]; 282 } 283 }; 284 285 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769467) DisplayInfo()286 public DisplayInfo() { 287 } 288 DisplayInfo(DisplayInfo other)289 public DisplayInfo(DisplayInfo other) { 290 copyFrom(other); 291 } 292 DisplayInfo(Parcel source)293 private DisplayInfo(Parcel source) { 294 readFromParcel(source); 295 } 296 297 @Override equals(Object o)298 public boolean equals(Object o) { 299 return o instanceof DisplayInfo && equals((DisplayInfo)o); 300 } 301 equals(DisplayInfo other)302 public boolean equals(DisplayInfo other) { 303 return other != null 304 && layerStack == other.layerStack 305 && flags == other.flags 306 && type == other.type 307 && displayId == other.displayId 308 && Objects.equals(address, other.address) 309 && Objects.equals(deviceProductInfo, other.deviceProductInfo) 310 && Objects.equals(uniqueId, other.uniqueId) 311 && appWidth == other.appWidth 312 && appHeight == other.appHeight 313 && smallestNominalAppWidth == other.smallestNominalAppWidth 314 && smallestNominalAppHeight == other.smallestNominalAppHeight 315 && largestNominalAppWidth == other.largestNominalAppWidth 316 && largestNominalAppHeight == other.largestNominalAppHeight 317 && logicalWidth == other.logicalWidth 318 && logicalHeight == other.logicalHeight 319 && Objects.equals(displayCutout, other.displayCutout) 320 && rotation == other.rotation 321 && modeId == other.modeId 322 && defaultModeId == other.defaultModeId 323 && colorMode == other.colorMode 324 && Arrays.equals(supportedColorModes, other.supportedColorModes) 325 && Objects.equals(hdrCapabilities, other.hdrCapabilities) 326 && minimalPostProcessingSupported == other.minimalPostProcessingSupported 327 && logicalDensityDpi == other.logicalDensityDpi 328 && physicalXDpi == other.physicalXDpi 329 && physicalYDpi == other.physicalYDpi 330 && appVsyncOffsetNanos == other.appVsyncOffsetNanos 331 && presentationDeadlineNanos == other.presentationDeadlineNanos 332 && state == other.state 333 && ownerUid == other.ownerUid 334 && Objects.equals(ownerPackageName, other.ownerPackageName) 335 && removeMode == other.removeMode; 336 } 337 338 @Override hashCode()339 public int hashCode() { 340 return 0; // don't care 341 } 342 copyFrom(DisplayInfo other)343 public void copyFrom(DisplayInfo other) { 344 layerStack = other.layerStack; 345 flags = other.flags; 346 type = other.type; 347 displayId = other.displayId; 348 address = other.address; 349 deviceProductInfo = other.deviceProductInfo; 350 name = other.name; 351 uniqueId = other.uniqueId; 352 appWidth = other.appWidth; 353 appHeight = other.appHeight; 354 smallestNominalAppWidth = other.smallestNominalAppWidth; 355 smallestNominalAppHeight = other.smallestNominalAppHeight; 356 largestNominalAppWidth = other.largestNominalAppWidth; 357 largestNominalAppHeight = other.largestNominalAppHeight; 358 logicalWidth = other.logicalWidth; 359 logicalHeight = other.logicalHeight; 360 displayCutout = other.displayCutout; 361 rotation = other.rotation; 362 modeId = other.modeId; 363 defaultModeId = other.defaultModeId; 364 supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length); 365 colorMode = other.colorMode; 366 supportedColorModes = Arrays.copyOf( 367 other.supportedColorModes, other.supportedColorModes.length); 368 hdrCapabilities = other.hdrCapabilities; 369 minimalPostProcessingSupported = other.minimalPostProcessingSupported; 370 logicalDensityDpi = other.logicalDensityDpi; 371 physicalXDpi = other.physicalXDpi; 372 physicalYDpi = other.physicalYDpi; 373 appVsyncOffsetNanos = other.appVsyncOffsetNanos; 374 presentationDeadlineNanos = other.presentationDeadlineNanos; 375 state = other.state; 376 ownerUid = other.ownerUid; 377 ownerPackageName = other.ownerPackageName; 378 removeMode = other.removeMode; 379 } 380 readFromParcel(Parcel source)381 public void readFromParcel(Parcel source) { 382 layerStack = source.readInt(); 383 flags = source.readInt(); 384 type = source.readInt(); 385 displayId = source.readInt(); 386 address = source.readParcelable(null); 387 deviceProductInfo = source.readParcelable(null); 388 name = source.readString8(); 389 appWidth = source.readInt(); 390 appHeight = source.readInt(); 391 smallestNominalAppWidth = source.readInt(); 392 smallestNominalAppHeight = source.readInt(); 393 largestNominalAppWidth = source.readInt(); 394 largestNominalAppHeight = source.readInt(); 395 logicalWidth = source.readInt(); 396 logicalHeight = source.readInt(); 397 displayCutout = DisplayCutout.ParcelableWrapper.readCutoutFromParcel(source); 398 rotation = source.readInt(); 399 modeId = source.readInt(); 400 defaultModeId = source.readInt(); 401 int nModes = source.readInt(); 402 supportedModes = new Display.Mode[nModes]; 403 for (int i = 0; i < nModes; i++) { 404 supportedModes[i] = Display.Mode.CREATOR.createFromParcel(source); 405 } 406 colorMode = source.readInt(); 407 int nColorModes = source.readInt(); 408 supportedColorModes = new int[nColorModes]; 409 for (int i = 0; i < nColorModes; i++) { 410 supportedColorModes[i] = source.readInt(); 411 } 412 hdrCapabilities = source.readParcelable(null); 413 minimalPostProcessingSupported = source.readBoolean(); 414 logicalDensityDpi = source.readInt(); 415 physicalXDpi = source.readFloat(); 416 physicalYDpi = source.readFloat(); 417 appVsyncOffsetNanos = source.readLong(); 418 presentationDeadlineNanos = source.readLong(); 419 state = source.readInt(); 420 ownerUid = source.readInt(); 421 ownerPackageName = source.readString8(); 422 uniqueId = source.readString8(); 423 removeMode = source.readInt(); 424 } 425 426 @Override writeToParcel(Parcel dest, int flags)427 public void writeToParcel(Parcel dest, int flags) { 428 dest.writeInt(layerStack); 429 dest.writeInt(this.flags); 430 dest.writeInt(type); 431 dest.writeInt(displayId); 432 dest.writeParcelable(address, flags); 433 dest.writeParcelable(deviceProductInfo, flags); 434 dest.writeString8(name); 435 dest.writeInt(appWidth); 436 dest.writeInt(appHeight); 437 dest.writeInt(smallestNominalAppWidth); 438 dest.writeInt(smallestNominalAppHeight); 439 dest.writeInt(largestNominalAppWidth); 440 dest.writeInt(largestNominalAppHeight); 441 dest.writeInt(logicalWidth); 442 dest.writeInt(logicalHeight); 443 DisplayCutout.ParcelableWrapper.writeCutoutToParcel(displayCutout, dest, flags); 444 dest.writeInt(rotation); 445 dest.writeInt(modeId); 446 dest.writeInt(defaultModeId); 447 dest.writeInt(supportedModes.length); 448 for (int i = 0; i < supportedModes.length; i++) { 449 supportedModes[i].writeToParcel(dest, flags); 450 } 451 dest.writeInt(colorMode); 452 dest.writeInt(supportedColorModes.length); 453 for (int i = 0; i < supportedColorModes.length; i++) { 454 dest.writeInt(supportedColorModes[i]); 455 } 456 dest.writeParcelable(hdrCapabilities, flags); 457 dest.writeBoolean(minimalPostProcessingSupported); 458 dest.writeInt(logicalDensityDpi); 459 dest.writeFloat(physicalXDpi); 460 dest.writeFloat(physicalYDpi); 461 dest.writeLong(appVsyncOffsetNanos); 462 dest.writeLong(presentationDeadlineNanos); 463 dest.writeInt(state); 464 dest.writeInt(ownerUid); 465 dest.writeString8(ownerPackageName); 466 dest.writeString8(uniqueId); 467 dest.writeInt(removeMode); 468 } 469 470 @Override describeContents()471 public int describeContents() { 472 return 0; 473 } 474 getMode()475 public Display.Mode getMode() { 476 return findMode(modeId); 477 } 478 getDefaultMode()479 public Display.Mode getDefaultMode() { 480 return findMode(defaultModeId); 481 } 482 findMode(int id)483 private Display.Mode findMode(int id) { 484 for (int i = 0; i < supportedModes.length; i++) { 485 if (supportedModes[i].getModeId() == id) { 486 return supportedModes[i]; 487 } 488 } 489 throw new IllegalStateException("Unable to locate mode " + id); 490 } 491 492 /** 493 * Returns the id of the "default" mode with the given refresh rate, or {@code 0} if no suitable 494 * mode could be found. 495 */ findDefaultModeByRefreshRate(float refreshRate)496 public int findDefaultModeByRefreshRate(float refreshRate) { 497 Display.Mode[] modes = supportedModes; 498 Display.Mode defaultMode = getDefaultMode(); 499 for (int i = 0; i < modes.length; i++) { 500 if (modes[i].matches( 501 defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), refreshRate)) { 502 return modes[i].getModeId(); 503 } 504 } 505 return 0; 506 } 507 508 /** 509 * Returns the list of supported refresh rates in the default mode. 510 */ getDefaultRefreshRates()511 public float[] getDefaultRefreshRates() { 512 Display.Mode[] modes = supportedModes; 513 ArraySet<Float> rates = new ArraySet<>(); 514 Display.Mode defaultMode = getDefaultMode(); 515 for (int i = 0; i < modes.length; i++) { 516 Display.Mode mode = modes[i]; 517 if (mode.getPhysicalWidth() == defaultMode.getPhysicalWidth() 518 && mode.getPhysicalHeight() == defaultMode.getPhysicalHeight()) { 519 rates.add(mode.getRefreshRate()); 520 } 521 } 522 float[] result = new float[rates.size()]; 523 int i = 0; 524 for (Float rate : rates) { 525 result[i++] = rate; 526 } 527 return result; 528 } 529 getAppMetrics(DisplayMetrics outMetrics)530 public void getAppMetrics(DisplayMetrics outMetrics) { 531 getAppMetrics(outMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); 532 } 533 getAppMetrics(DisplayMetrics outMetrics, DisplayAdjustments displayAdjustments)534 public void getAppMetrics(DisplayMetrics outMetrics, DisplayAdjustments displayAdjustments) { 535 getMetricsWithSize(outMetrics, displayAdjustments.getCompatibilityInfo(), 536 displayAdjustments.getConfiguration(), appWidth, appHeight); 537 } 538 getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci, Configuration configuration)539 public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci, 540 Configuration configuration) { 541 getMetricsWithSize(outMetrics, ci, configuration, appWidth, appHeight); 542 } 543 getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, Configuration configuration)544 public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, 545 Configuration configuration) { 546 getMetricsWithSize(outMetrics, compatInfo, configuration, logicalWidth, logicalHeight); 547 } 548 getNaturalWidth()549 public int getNaturalWidth() { 550 return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ? 551 logicalWidth : logicalHeight; 552 } 553 getNaturalHeight()554 public int getNaturalHeight() { 555 return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ? 556 logicalHeight : logicalWidth; 557 } 558 isHdr()559 public boolean isHdr() { 560 int[] types = hdrCapabilities != null ? hdrCapabilities.getSupportedHdrTypes() : null; 561 return types != null && types.length > 0; 562 } 563 isWideColorGamut()564 public boolean isWideColorGamut() { 565 for (int colorMode : supportedColorModes) { 566 if (colorMode == Display.COLOR_MODE_DCI_P3 || colorMode > Display.COLOR_MODE_SRGB) { 567 return true; 568 } 569 } 570 return false; 571 } 572 573 /** 574 * Returns true if the specified UID has access to this display. 575 */ hasAccess(int uid)576 public boolean hasAccess(int uid) { 577 return Display.hasAccess(uid, flags, ownerUid, displayId); 578 } 579 getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, Configuration configuration, int width, int height)580 private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, 581 Configuration configuration, int width, int height) { 582 outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi; 583 outMetrics.density = outMetrics.noncompatDensity = 584 logicalDensityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; 585 outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density; 586 outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi; 587 outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi; 588 589 final Rect appBounds = configuration != null 590 ? configuration.windowConfiguration.getAppBounds() : null; 591 width = appBounds != null ? appBounds.width() : width; 592 height = appBounds != null ? appBounds.height() : height; 593 594 outMetrics.noncompatWidthPixels = outMetrics.widthPixels = width; 595 outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height; 596 597 if (!compatInfo.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) { 598 compatInfo.applyToDisplayMetrics(outMetrics); 599 } 600 } 601 602 // For debugging purposes 603 @Override toString()604 public String toString() { 605 StringBuilder sb = new StringBuilder(); 606 sb.append("DisplayInfo{\""); 607 sb.append(name); 608 sb.append("\", displayId "); 609 sb.append(displayId); 610 sb.append(flagsToString(flags)); 611 sb.append(", real "); 612 sb.append(logicalWidth); 613 sb.append(" x "); 614 sb.append(logicalHeight); 615 sb.append(", largest app "); 616 sb.append(largestNominalAppWidth); 617 sb.append(" x "); 618 sb.append(largestNominalAppHeight); 619 sb.append(", smallest app "); 620 sb.append(smallestNominalAppWidth); 621 sb.append(" x "); 622 sb.append(smallestNominalAppHeight); 623 sb.append(", appVsyncOff "); 624 sb.append(appVsyncOffsetNanos); 625 sb.append(", presDeadline "); 626 sb.append(presentationDeadlineNanos); 627 sb.append(", mode "); 628 sb.append(modeId); 629 sb.append(", defaultMode "); 630 sb.append(defaultModeId); 631 sb.append(", modes "); 632 sb.append(Arrays.toString(supportedModes)); 633 sb.append(", hdrCapabilities "); 634 sb.append(hdrCapabilities); 635 sb.append(", minimalPostProcessingSupported "); 636 sb.append(minimalPostProcessingSupported); 637 sb.append(", rotation "); 638 sb.append(rotation); 639 sb.append(", state "); 640 sb.append(Display.stateToString(state)); 641 642 if (Process.myUid() != Process.SYSTEM_UID) { 643 sb.append("}"); 644 return sb.toString(); 645 } 646 647 sb.append(", type "); 648 sb.append(Display.typeToString(type)); 649 sb.append(", uniqueId \""); 650 sb.append(uniqueId); 651 sb.append("\", app "); 652 sb.append(appWidth); 653 sb.append(" x "); 654 sb.append(appHeight); 655 sb.append(", density "); 656 sb.append(logicalDensityDpi); 657 sb.append(" ("); 658 sb.append(physicalXDpi); 659 sb.append(" x "); 660 sb.append(physicalYDpi); 661 sb.append(") dpi, layerStack "); 662 sb.append(layerStack); 663 sb.append(", colorMode "); 664 sb.append(colorMode); 665 sb.append(", supportedColorModes "); 666 sb.append(Arrays.toString(supportedColorModes)); 667 if (address != null) { 668 sb.append(", address ").append(address); 669 } 670 sb.append(", deviceProductInfo "); 671 sb.append(deviceProductInfo); 672 if (ownerUid != 0 || ownerPackageName != null) { 673 sb.append(", owner ").append(ownerPackageName); 674 sb.append(" (uid ").append(ownerUid).append(")"); 675 } 676 sb.append(", removeMode "); 677 sb.append(removeMode); 678 sb.append("}"); 679 return sb.toString(); 680 } 681 682 /** 683 * Write to a protocol buffer output stream. 684 * Protocol buffer message definition at {@link android.view.DisplayInfoProto} 685 * 686 * @param protoOutputStream Stream to write the Rect object to. 687 * @param fieldId Field Id of the DisplayInfoProto as defined in the parent message 688 */ dumpDebug(ProtoOutputStream protoOutputStream, long fieldId)689 public void dumpDebug(ProtoOutputStream protoOutputStream, long fieldId) { 690 final long token = protoOutputStream.start(fieldId); 691 protoOutputStream.write(LOGICAL_WIDTH, logicalWidth); 692 protoOutputStream.write(LOGICAL_HEIGHT, logicalHeight); 693 protoOutputStream.write(APP_WIDTH, appWidth); 694 protoOutputStream.write(APP_HEIGHT, appHeight); 695 protoOutputStream.write(NAME, name); 696 protoOutputStream.write(FLAGS, flags); 697 protoOutputStream.end(token); 698 } 699 flagsToString(int flags)700 private static String flagsToString(int flags) { 701 StringBuilder result = new StringBuilder(); 702 if ((flags & Display.FLAG_SECURE) != 0) { 703 result.append(", FLAG_SECURE"); 704 } 705 if ((flags & Display.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) { 706 result.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS"); 707 } 708 if ((flags & Display.FLAG_PRIVATE) != 0) { 709 result.append(", FLAG_PRIVATE"); 710 } 711 if ((flags & Display.FLAG_PRESENTATION) != 0) { 712 result.append(", FLAG_PRESENTATION"); 713 } 714 if ((flags & Display.FLAG_SCALING_DISABLED) != 0) { 715 result.append(", FLAG_SCALING_DISABLED"); 716 } 717 if ((flags & Display.FLAG_ROUND) != 0) { 718 result.append(", FLAG_ROUND"); 719 } 720 if ((flags & Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) { 721 result.append(", FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD"); 722 } 723 if ((flags & Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0) { 724 result.append(", FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS"); 725 } 726 if ((flags & Display.FLAG_TRUSTED) != 0) { 727 result.append(", FLAG_TRUSTED"); 728 } 729 return result.toString(); 730 } 731 } 732