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