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