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 com.android.server.display; 18 19 import android.graphics.Point; 20 import android.graphics.Rect; 21 import android.hardware.display.DisplayManagerInternal; 22 import android.view.Display; 23 import android.view.DisplayInfo; 24 import android.view.Surface; 25 import android.view.SurfaceControl; 26 27 import com.android.server.wm.utils.InsetUtils; 28 29 import java.io.PrintWriter; 30 import java.util.Arrays; 31 import java.util.List; 32 import java.util.Objects; 33 34 /** 35 * Describes how a logical display is configured. 36 * <p> 37 * At this time, we only support logical displays that are coupled to a particular 38 * primary display device from which the logical display derives its basic properties 39 * such as its size, density and refresh rate. 40 * </p><p> 41 * A logical display may be mirrored onto multiple display devices in addition to its 42 * primary display device. Note that the contents of a logical display may not 43 * always be visible, even on its primary display device, such as in the case where 44 * the primary display device is currently mirroring content from a different 45 * logical display. 46 * </p><p> 47 * This object is designed to encapsulate as much of the policy of logical 48 * displays as possible. The idea is to make it easy to implement new kinds of 49 * logical displays mostly by making local changes to this class. 50 * </p><p> 51 * Note: The display manager architecture does not actually require logical displays 52 * to be associated with any individual display device. Logical displays and 53 * display devices are orthogonal concepts. Some mapping will exist between 54 * logical displays and display devices but it can be many-to-many and 55 * and some might have no relation at all. 56 * </p><p> 57 * Logical displays are guarded by the {@link DisplayManagerService.SyncRoot} lock. 58 * </p> 59 */ 60 final class LogicalDisplay { 61 private final DisplayInfo mBaseDisplayInfo = new DisplayInfo(); 62 63 // The layer stack we use when the display has been blanked to prevent any 64 // of its content from appearing. 65 private static final int BLANK_LAYER_STACK = -1; 66 67 private final int mDisplayId; 68 private final int mLayerStack; 69 /** 70 * Override information set by the window manager. Will be reported instead of {@link #mInfo} 71 * if not null. 72 * @see #setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo) 73 * @see #getDisplayInfoLocked() 74 */ 75 private DisplayInfo mOverrideDisplayInfo; 76 /** 77 * Current display info. Initialized with {@link #mBaseDisplayInfo}. Set to {@code null} if 78 * needs to be updated. 79 * @see #getDisplayInfoLocked() 80 */ 81 private final DisplayInfoProxy mInfo = new DisplayInfoProxy(null); 82 83 // The display device that this logical display is based on and which 84 // determines the base metrics that it uses. 85 private DisplayDevice mPrimaryDisplayDevice; 86 private DisplayDeviceInfo mPrimaryDisplayDeviceInfo; 87 88 // True if the logical display has unique content. 89 private boolean mHasContent; 90 91 private int mRequestedColorMode; 92 private boolean mRequestedMinimalPostProcessing; 93 94 private DisplayModeDirector.DesiredDisplayModeSpecs mDesiredDisplayModeSpecs = 95 new DisplayModeDirector.DesiredDisplayModeSpecs(); 96 97 // The display offsets to apply to the display projection. 98 private int mDisplayOffsetX; 99 private int mDisplayOffsetY; 100 101 /** 102 * The position of the display projection sent to SurfaceFlinger 103 */ 104 private final Point mDisplayPosition = new Point(); 105 106 /** 107 * {@code true} if display scaling is disabled, or {@code false} if the default scaling mode 108 * is used. 109 * @see #isDisplayScalingDisabled() 110 * @see #setDisplayScalingDisabledLocked(boolean) 111 */ 112 private boolean mDisplayScalingDisabled; 113 114 // Temporary rectangle used when needed. 115 private final Rect mTempLayerStackRect = new Rect(); 116 private final Rect mTempDisplayRect = new Rect(); 117 LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice)118 public LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice) { 119 mDisplayId = displayId; 120 mLayerStack = layerStack; 121 mPrimaryDisplayDevice = primaryDisplayDevice; 122 } 123 124 /** 125 * Gets the logical display id of this logical display. 126 * 127 * @return The logical display id. 128 */ getDisplayIdLocked()129 public int getDisplayIdLocked() { 130 return mDisplayId; 131 } 132 133 /** 134 * Gets the primary display device associated with this logical display. 135 * 136 * @return The primary display device. 137 */ getPrimaryDisplayDeviceLocked()138 public DisplayDevice getPrimaryDisplayDeviceLocked() { 139 return mPrimaryDisplayDevice; 140 } 141 142 /** 143 * Gets information about the logical display. 144 * 145 * @return The device info, which should be treated as immutable by the caller. 146 * The logical display should allocate a new display info object whenever 147 * the data changes. 148 */ getDisplayInfoLocked()149 public DisplayInfo getDisplayInfoLocked() { 150 if (mInfo.get() == null) { 151 DisplayInfo info = new DisplayInfo(); 152 info.copyFrom(mBaseDisplayInfo); 153 if (mOverrideDisplayInfo != null) { 154 info.appWidth = mOverrideDisplayInfo.appWidth; 155 info.appHeight = mOverrideDisplayInfo.appHeight; 156 info.smallestNominalAppWidth = mOverrideDisplayInfo.smallestNominalAppWidth; 157 info.smallestNominalAppHeight = mOverrideDisplayInfo.smallestNominalAppHeight; 158 info.largestNominalAppWidth = mOverrideDisplayInfo.largestNominalAppWidth; 159 info.largestNominalAppHeight = mOverrideDisplayInfo.largestNominalAppHeight; 160 info.logicalWidth = mOverrideDisplayInfo.logicalWidth; 161 info.logicalHeight = mOverrideDisplayInfo.logicalHeight; 162 info.rotation = mOverrideDisplayInfo.rotation; 163 info.displayCutout = mOverrideDisplayInfo.displayCutout; 164 info.logicalDensityDpi = mOverrideDisplayInfo.logicalDensityDpi; 165 info.physicalXDpi = mOverrideDisplayInfo.physicalXDpi; 166 info.physicalYDpi = mOverrideDisplayInfo.physicalYDpi; 167 } 168 mInfo.set(info); 169 } 170 return mInfo.get(); 171 } 172 173 /** 174 * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo) 175 */ getNonOverrideDisplayInfoLocked(DisplayInfo outInfo)176 void getNonOverrideDisplayInfoLocked(DisplayInfo outInfo) { 177 outInfo.copyFrom(mBaseDisplayInfo); 178 } 179 180 /** 181 * Sets overridden logical display information from the window manager. 182 * This method can be used to adjust application insets, rotation, and other 183 * properties that the window manager takes care of. 184 * 185 * @param info The logical display information, may be null. 186 */ setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo info)187 public boolean setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo info) { 188 if (info != null) { 189 if (mOverrideDisplayInfo == null) { 190 mOverrideDisplayInfo = new DisplayInfo(info); 191 mInfo.set(null); 192 return true; 193 } else if (!mOverrideDisplayInfo.equals(info)) { 194 mOverrideDisplayInfo.copyFrom(info); 195 mInfo.set(null); 196 return true; 197 } 198 } else if (mOverrideDisplayInfo != null) { 199 mOverrideDisplayInfo = null; 200 mInfo.set(null); 201 return true; 202 } 203 return false; 204 } 205 206 /** 207 * Returns true if the logical display is in a valid state. 208 * This method should be checked after calling {@link #updateLocked} to handle the 209 * case where a logical display should be removed because all of its associated 210 * display devices are gone or if it is otherwise no longer needed. 211 * 212 * @return True if the logical display is still valid. 213 */ isValidLocked()214 public boolean isValidLocked() { 215 return mPrimaryDisplayDevice != null; 216 } 217 218 /** 219 * Updates the state of the logical display based on the available display devices. 220 * The logical display might become invalid if it is attached to a display device 221 * that no longer exists. 222 * 223 * @param devices The list of all connected display devices. 224 */ updateLocked(List<DisplayDevice> devices)225 public void updateLocked(List<DisplayDevice> devices) { 226 // Nothing to update if already invalid. 227 if (mPrimaryDisplayDevice == null) { 228 return; 229 } 230 231 // Check whether logical display has become invalid. 232 if (!devices.contains(mPrimaryDisplayDevice)) { 233 mPrimaryDisplayDevice = null; 234 return; 235 } 236 237 // Bootstrap the logical display using its associated primary physical display. 238 // We might use more elaborate configurations later. It's possible that the 239 // configuration of several physical displays might be used to determine the 240 // logical display that they are sharing. (eg. Adjust size for pixel-perfect 241 // mirroring over HDMI.) 242 DisplayDeviceInfo deviceInfo = mPrimaryDisplayDevice.getDisplayDeviceInfoLocked(); 243 if (!Objects.equals(mPrimaryDisplayDeviceInfo, deviceInfo)) { 244 mBaseDisplayInfo.layerStack = mLayerStack; 245 mBaseDisplayInfo.flags = 0; 246 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) { 247 mBaseDisplayInfo.flags |= Display.FLAG_SUPPORTS_PROTECTED_BUFFERS; 248 } 249 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SECURE) != 0) { 250 mBaseDisplayInfo.flags |= Display.FLAG_SECURE; 251 } 252 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_PRIVATE) != 0) { 253 mBaseDisplayInfo.flags |= Display.FLAG_PRIVATE; 254 // For private displays by default content is destroyed on removal. 255 mBaseDisplayInfo.removeMode = Display.REMOVE_MODE_DESTROY_CONTENT; 256 } 257 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_DESTROY_CONTENT_ON_REMOVAL) != 0) { 258 mBaseDisplayInfo.removeMode = Display.REMOVE_MODE_DESTROY_CONTENT; 259 } 260 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_PRESENTATION) != 0) { 261 mBaseDisplayInfo.flags |= Display.FLAG_PRESENTATION; 262 } 263 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_ROUND) != 0) { 264 mBaseDisplayInfo.flags |= Display.FLAG_ROUND; 265 } 266 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) { 267 mBaseDisplayInfo.flags |= Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; 268 } 269 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0) { 270 mBaseDisplayInfo.flags |= Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; 271 } 272 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_TRUSTED) != 0) { 273 mBaseDisplayInfo.flags |= Display.FLAG_TRUSTED; 274 } 275 Rect maskingInsets = getMaskingInsets(deviceInfo); 276 int maskedWidth = deviceInfo.width - maskingInsets.left - maskingInsets.right; 277 int maskedHeight = deviceInfo.height - maskingInsets.top - maskingInsets.bottom; 278 279 mBaseDisplayInfo.type = deviceInfo.type; 280 mBaseDisplayInfo.address = deviceInfo.address; 281 mBaseDisplayInfo.deviceProductInfo = deviceInfo.deviceProductInfo; 282 mBaseDisplayInfo.name = deviceInfo.name; 283 mBaseDisplayInfo.uniqueId = deviceInfo.uniqueId; 284 mBaseDisplayInfo.appWidth = maskedWidth; 285 mBaseDisplayInfo.appHeight = maskedHeight; 286 mBaseDisplayInfo.logicalWidth = maskedWidth; 287 mBaseDisplayInfo.logicalHeight = maskedHeight; 288 mBaseDisplayInfo.rotation = Surface.ROTATION_0; 289 mBaseDisplayInfo.modeId = deviceInfo.modeId; 290 mBaseDisplayInfo.defaultModeId = deviceInfo.defaultModeId; 291 mBaseDisplayInfo.supportedModes = Arrays.copyOf( 292 deviceInfo.supportedModes, deviceInfo.supportedModes.length); 293 mBaseDisplayInfo.colorMode = deviceInfo.colorMode; 294 mBaseDisplayInfo.supportedColorModes = Arrays.copyOf( 295 deviceInfo.supportedColorModes, 296 deviceInfo.supportedColorModes.length); 297 mBaseDisplayInfo.hdrCapabilities = deviceInfo.hdrCapabilities; 298 mBaseDisplayInfo.minimalPostProcessingSupported = 299 deviceInfo.allmSupported || deviceInfo.gameContentTypeSupported; 300 mBaseDisplayInfo.logicalDensityDpi = deviceInfo.densityDpi; 301 mBaseDisplayInfo.physicalXDpi = deviceInfo.xDpi; 302 mBaseDisplayInfo.physicalYDpi = deviceInfo.yDpi; 303 mBaseDisplayInfo.appVsyncOffsetNanos = deviceInfo.appVsyncOffsetNanos; 304 mBaseDisplayInfo.presentationDeadlineNanos = deviceInfo.presentationDeadlineNanos; 305 mBaseDisplayInfo.state = deviceInfo.state; 306 mBaseDisplayInfo.smallestNominalAppWidth = maskedWidth; 307 mBaseDisplayInfo.smallestNominalAppHeight = maskedHeight; 308 mBaseDisplayInfo.largestNominalAppWidth = maskedWidth; 309 mBaseDisplayInfo.largestNominalAppHeight = maskedHeight; 310 mBaseDisplayInfo.ownerUid = deviceInfo.ownerUid; 311 mBaseDisplayInfo.ownerPackageName = deviceInfo.ownerPackageName; 312 boolean maskCutout = 313 (deviceInfo.flags & DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT) != 0; 314 mBaseDisplayInfo.displayCutout = maskCutout ? null : deviceInfo.displayCutout; 315 mBaseDisplayInfo.displayId = mDisplayId; 316 317 mPrimaryDisplayDeviceInfo = deviceInfo; 318 mInfo.set(null); 319 } 320 } 321 322 /** 323 * Return the insets currently applied to the display. 324 * 325 * Note that the base DisplayInfo already takes these insets into account, so if you want to 326 * find out the <b>true</b> size of the display, you need to add them back to the logical 327 * dimensions. 328 */ getInsets()329 public Rect getInsets() { 330 return getMaskingInsets(mPrimaryDisplayDeviceInfo); 331 } 332 333 /** 334 * Returns insets in ROTATION_0 for areas that are masked. 335 */ getMaskingInsets(DisplayDeviceInfo deviceInfo)336 private static Rect getMaskingInsets(DisplayDeviceInfo deviceInfo) { 337 boolean maskCutout = (deviceInfo.flags & DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT) != 0; 338 if (maskCutout && deviceInfo.displayCutout != null) { 339 // getSafeInsets is fixed at creation time and cannot change 340 return deviceInfo.displayCutout.getSafeInsets(); 341 } else { 342 return new Rect(); 343 } 344 } 345 346 /** 347 * Returns the position of the display's projection. 348 * 349 * @return The x, y coordinates of the display. The return object must be treated as immutable. 350 */ getDisplayPosition()351 Point getDisplayPosition() { 352 // Allocate a new object to avoid a data race. 353 return new Point(mDisplayPosition); 354 } 355 356 /** 357 * Applies the layer stack and transformation to the given display device 358 * so that it shows the contents of this logical display. 359 * 360 * We know that the given display device is only ever showing the contents of 361 * a single logical display, so this method is expected to blow away all of its 362 * transformation properties to make it happen regardless of what the 363 * display device was previously showing. 364 * 365 * The caller must have an open Surface transaction. 366 * 367 * The display device may not be the primary display device, in the case 368 * where the display is being mirrored. 369 * 370 * @param device The display device to modify. 371 * @param isBlanked True if the device is being blanked. 372 */ configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device, boolean isBlanked)373 public void configureDisplayLocked(SurfaceControl.Transaction t, 374 DisplayDevice device, 375 boolean isBlanked) { 376 // Set the layer stack. 377 device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack); 378 379 // Set the color mode and allowed display mode. 380 if (device == mPrimaryDisplayDevice) { 381 device.setDesiredDisplayModeSpecsLocked(mDesiredDisplayModeSpecs); 382 device.setRequestedColorModeLocked(mRequestedColorMode); 383 } else { 384 // Reset to default for non primary displays 385 device.setDesiredDisplayModeSpecsLocked( 386 new DisplayModeDirector.DesiredDisplayModeSpecs()); 387 device.setRequestedColorModeLocked(0); 388 } 389 390 device.setAutoLowLatencyModeLocked(mRequestedMinimalPostProcessing); 391 device.setGameContentTypeLocked(mRequestedMinimalPostProcessing); 392 393 // Only grab the display info now as it may have been changed based on the requests above. 394 final DisplayInfo displayInfo = getDisplayInfoLocked(); 395 final DisplayDeviceInfo displayDeviceInfo = device.getDisplayDeviceInfoLocked(); 396 397 // Set the viewport. 398 // This is the area of the logical display that we intend to show on the 399 // display device. For now, it is always the full size of the logical display. 400 mTempLayerStackRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight); 401 402 // Set the orientation. 403 // The orientation specifies how the physical coordinate system of the display 404 // is rotated when the contents of the logical display are rendered. 405 int orientation = Surface.ROTATION_0; 406 if ((displayDeviceInfo.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0) { 407 orientation = displayInfo.rotation; 408 } 409 410 // Apply the physical rotation of the display device itself. 411 orientation = (orientation + displayDeviceInfo.rotation) % 4; 412 413 // Set the frame. 414 // The frame specifies the rotated physical coordinates into which the viewport 415 // is mapped. We need to take care to preserve the aspect ratio of the viewport. 416 // Currently we maximize the area to fill the display, but we could try to be 417 // more clever and match resolutions. 418 boolean rotated = (orientation == Surface.ROTATION_90 419 || orientation == Surface.ROTATION_270); 420 int physWidth = rotated ? displayDeviceInfo.height : displayDeviceInfo.width; 421 int physHeight = rotated ? displayDeviceInfo.width : displayDeviceInfo.height; 422 423 Rect maskingInsets = getMaskingInsets(displayDeviceInfo); 424 InsetUtils.rotateInsets(maskingInsets, orientation); 425 // Don't consider the masked area as available when calculating the scaling below. 426 physWidth -= maskingInsets.left + maskingInsets.right; 427 physHeight -= maskingInsets.top + maskingInsets.bottom; 428 429 // Determine whether the width or height is more constrained to be scaled. 430 // physWidth / displayInfo.logicalWidth => letter box 431 // or physHeight / displayInfo.logicalHeight => pillar box 432 // 433 // We avoid a division (and possible floating point imprecision) here by 434 // multiplying the fractions by the product of their denominators before 435 // comparing them. 436 int displayRectWidth, displayRectHeight; 437 if ((displayInfo.flags & Display.FLAG_SCALING_DISABLED) != 0 || mDisplayScalingDisabled) { 438 displayRectWidth = displayInfo.logicalWidth; 439 displayRectHeight = displayInfo.logicalHeight; 440 } else if (physWidth * displayInfo.logicalHeight 441 < physHeight * displayInfo.logicalWidth) { 442 // Letter box. 443 displayRectWidth = physWidth; 444 displayRectHeight = displayInfo.logicalHeight * physWidth / displayInfo.logicalWidth; 445 } else { 446 // Pillar box. 447 displayRectWidth = displayInfo.logicalWidth * physHeight / displayInfo.logicalHeight; 448 displayRectHeight = physHeight; 449 } 450 int displayRectTop = (physHeight - displayRectHeight) / 2; 451 int displayRectLeft = (physWidth - displayRectWidth) / 2; 452 mTempDisplayRect.set(displayRectLeft, displayRectTop, 453 displayRectLeft + displayRectWidth, displayRectTop + displayRectHeight); 454 455 // Now add back the offset for the masked area. 456 mTempDisplayRect.offset(maskingInsets.left, maskingInsets.top); 457 458 if (orientation == Surface.ROTATION_0) { 459 mTempDisplayRect.offset(mDisplayOffsetX, mDisplayOffsetY); 460 } else if (orientation == Surface.ROTATION_90) { 461 mTempDisplayRect.offset(mDisplayOffsetY, -mDisplayOffsetX); 462 } else if (orientation == Surface.ROTATION_180) { 463 mTempDisplayRect.offset(-mDisplayOffsetX, -mDisplayOffsetY); 464 } else { // Surface.ROTATION_270 465 mTempDisplayRect.offset(-mDisplayOffsetY, mDisplayOffsetX); 466 } 467 468 mDisplayPosition.set(mTempDisplayRect.left, mTempDisplayRect.top); 469 device.setProjectionLocked(t, orientation, mTempLayerStackRect, mTempDisplayRect); 470 } 471 472 /** 473 * Returns true if the logical display has unique content. 474 * <p> 475 * If the display has unique content then we will try to ensure that it is 476 * visible on at least its primary display device. Otherwise we will ignore the 477 * logical display and perhaps show mirrored content on the primary display device. 478 * </p> 479 * 480 * @return True if the display has unique content. 481 */ hasContentLocked()482 public boolean hasContentLocked() { 483 return mHasContent; 484 } 485 486 /** 487 * Sets whether the logical display has unique content. 488 * 489 * @param hasContent True if the display has unique content. 490 */ setHasContentLocked(boolean hasContent)491 public void setHasContentLocked(boolean hasContent) { 492 mHasContent = hasContent; 493 } 494 495 /** 496 * Sets the display configs the system can use. 497 */ setDesiredDisplayModeSpecsLocked( DisplayModeDirector.DesiredDisplayModeSpecs specs)498 public void setDesiredDisplayModeSpecsLocked( 499 DisplayModeDirector.DesiredDisplayModeSpecs specs) { 500 mDesiredDisplayModeSpecs = specs; 501 } 502 503 /** 504 * Returns the display configs the system can choose. 505 */ getDesiredDisplayModeSpecsLocked()506 public DisplayModeDirector.DesiredDisplayModeSpecs getDesiredDisplayModeSpecsLocked() { 507 return mDesiredDisplayModeSpecs; 508 } 509 510 /** 511 * Requests the given color mode. 512 */ setRequestedColorModeLocked(int colorMode)513 public void setRequestedColorModeLocked(int colorMode) { 514 mRequestedColorMode = colorMode; 515 } 516 517 /** 518 * Returns the last requested minimal post processing setting. 519 */ getRequestedMinimalPostProcessingLocked()520 public boolean getRequestedMinimalPostProcessingLocked() { 521 return mRequestedMinimalPostProcessing; 522 } 523 524 /** 525 * Instructs the connected display to do minimal post processing. This is implemented either 526 * via HDMI 2.1 ALLM or HDMI 1.4 ContentType=Game. 527 * 528 * @param on Whether to set minimal post processing on/off on the connected display. 529 */ setRequestedMinimalPostProcessingLocked(boolean on)530 public void setRequestedMinimalPostProcessingLocked(boolean on) { 531 mRequestedMinimalPostProcessing = on; 532 } 533 534 /** Returns the pending requested color mode. */ getRequestedColorModeLocked()535 public int getRequestedColorModeLocked() { 536 return mRequestedColorMode; 537 } 538 539 /** 540 * Gets the burn-in offset in X. 541 */ getDisplayOffsetXLocked()542 public int getDisplayOffsetXLocked() { 543 return mDisplayOffsetX; 544 } 545 546 /** 547 * Gets the burn-in offset in Y. 548 */ getDisplayOffsetYLocked()549 public int getDisplayOffsetYLocked() { 550 return mDisplayOffsetY; 551 } 552 553 /** 554 * Sets the burn-in offsets. 555 */ setDisplayOffsetsLocked(int x, int y)556 public void setDisplayOffsetsLocked(int x, int y) { 557 mDisplayOffsetX = x; 558 mDisplayOffsetY = y; 559 } 560 561 /** 562 * @return {@code true} if display scaling is disabled, or {@code false} if the default scaling 563 * mode is used. 564 */ isDisplayScalingDisabled()565 public boolean isDisplayScalingDisabled() { 566 return mDisplayScalingDisabled; 567 } 568 569 /** 570 * Disables scaling for a display. 571 * 572 * @param disableScaling {@code true} to disable scaling, 573 * {@code false} to use the default scaling behavior of the logical display. 574 */ setDisplayScalingDisabledLocked(boolean disableScaling)575 public void setDisplayScalingDisabledLocked(boolean disableScaling) { 576 mDisplayScalingDisabled = disableScaling; 577 } 578 dumpLocked(PrintWriter pw)579 public void dumpLocked(PrintWriter pw) { 580 pw.println("mDisplayId=" + mDisplayId); 581 pw.println("mLayerStack=" + mLayerStack); 582 pw.println("mHasContent=" + mHasContent); 583 pw.println("mDesiredDisplayModeSpecs={" + mDesiredDisplayModeSpecs + "}"); 584 pw.println("mRequestedColorMode=" + mRequestedColorMode); 585 pw.println("mDisplayOffset=(" + mDisplayOffsetX + ", " + mDisplayOffsetY + ")"); 586 pw.println("mDisplayScalingDisabled=" + mDisplayScalingDisabled); 587 pw.println("mPrimaryDisplayDevice=" + (mPrimaryDisplayDevice != null ? 588 mPrimaryDisplayDevice.getNameLocked() : "null")); 589 pw.println("mBaseDisplayInfo=" + mBaseDisplayInfo); 590 pw.println("mOverrideDisplayInfo=" + mOverrideDisplayInfo); 591 pw.println("mRequestedMinimalPostProcessing=" + mRequestedMinimalPostProcessing); 592 } 593 } 594