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 static com.android.server.display.DisplayDeviceInfo.TOUCH_NONE; 20 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.graphics.Point; 24 import android.graphics.Rect; 25 import android.hardware.display.DisplayManagerInternal; 26 import android.util.ArraySet; 27 import android.util.SparseArray; 28 import android.view.Display; 29 import android.view.DisplayEventReceiver; 30 import android.view.DisplayInfo; 31 import android.view.Surface; 32 import android.view.SurfaceControl; 33 34 import com.android.server.wm.utils.InsetUtils; 35 36 import java.io.PrintWriter; 37 import java.io.StringWriter; 38 import java.util.Arrays; 39 import java.util.Objects; 40 41 /** 42 * Describes how a logical display is configured. 43 * <p> 44 * At this time, we only support logical displays that are coupled to a particular 45 * primary display device from which the logical display derives its basic properties 46 * such as its size, density and refresh rate. 47 * </p><p> 48 * A logical display may be mirrored onto multiple display devices in addition to its 49 * primary display device. Note that the contents of a logical display may not 50 * always be visible, even on its primary display device, such as in the case where 51 * the primary display device is currently mirroring content from a different 52 * logical display. 53 * </p><p> 54 * This object is designed to encapsulate as much of the policy of logical 55 * displays as possible. The idea is to make it easy to implement new kinds of 56 * logical displays mostly by making local changes to this class. 57 * </p><p> 58 * Note: The display manager architecture does not actually require logical displays 59 * to be associated with any individual display device. Logical displays and 60 * display devices are orthogonal concepts. Some mapping will exist between 61 * logical displays and display devices but it can be many-to-many and 62 * and some might have no relation at all. 63 * </p><p> 64 * Logical displays are guarded by the {@link DisplayManagerService.SyncRoot} lock. 65 * </p> 66 */ 67 final class LogicalDisplay { 68 private static final String TAG = "LogicalDisplay"; 69 70 // The layer stack we use when the display has been blanked to prevent any 71 // of its content from appearing. 72 private static final int BLANK_LAYER_STACK = -1; 73 74 private static final DisplayInfo EMPTY_DISPLAY_INFO = new DisplayInfo(); 75 76 private final DisplayInfo mBaseDisplayInfo = new DisplayInfo(); 77 private final int mDisplayId; 78 private final int mLayerStack; 79 80 private int mDisplayGroupId = Display.INVALID_DISPLAY_GROUP; 81 82 /** 83 * Override information set by the window manager. Will be reported instead of {@link #mInfo} 84 * if not null. 85 * @see #setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo) 86 * @see #getDisplayInfoLocked() 87 */ 88 private DisplayInfo mOverrideDisplayInfo; 89 /** 90 * Current display info. Initialized with {@link #mBaseDisplayInfo}. Set to {@code null} if 91 * needs to be updated. 92 * @see #getDisplayInfoLocked() 93 */ 94 private final DisplayInfoProxy mInfo = new DisplayInfoProxy(null); 95 96 // The display device that this logical display is based on and which 97 // determines the base metrics that it uses. 98 private DisplayDevice mPrimaryDisplayDevice; 99 private DisplayDeviceInfo mPrimaryDisplayDeviceInfo; 100 101 // True if the logical display has unique content. 102 private boolean mHasContent; 103 104 private int mRequestedColorMode; 105 private boolean mRequestedMinimalPostProcessing; 106 107 private int[] mUserDisabledHdrTypes = {}; 108 109 private DisplayModeDirector.DesiredDisplayModeSpecs mDesiredDisplayModeSpecs = 110 new DisplayModeDirector.DesiredDisplayModeSpecs(); 111 112 // The display offsets to apply to the display projection. 113 private int mDisplayOffsetX; 114 private int mDisplayOffsetY; 115 116 /** 117 * The position of the display projection sent to SurfaceFlinger 118 */ 119 private final Point mDisplayPosition = new Point(); 120 121 /** 122 * {@code true} if display scaling is disabled, or {@code false} if the default scaling mode 123 * is used. 124 * @see #isDisplayScalingDisabled() 125 * @see #setDisplayScalingDisabledLocked(boolean) 126 */ 127 private boolean mDisplayScalingDisabled; 128 129 // Temporary rectangle used when needed. 130 private final Rect mTempLayerStackRect = new Rect(); 131 private final Rect mTempDisplayRect = new Rect(); 132 133 /** 134 * The UID mappings for refresh rate override 135 */ 136 private DisplayEventReceiver.FrameRateOverride[] mFrameRateOverrides; 137 138 /** 139 * Holds a set of UIDs that their frame rate override changed and needs to be notified 140 */ 141 private ArraySet<Integer> mPendingFrameRateOverrideUids; 142 143 /** 144 * Temporary frame rate override list, used when needed. 145 */ 146 private final SparseArray<Float> mTempFrameRateOverride; 147 148 // Indicates the display is enabled (allowed to be ON). 149 private boolean mIsEnabled; 150 151 // Indicates the display is part of a transition from one device-state ({@link 152 // DeviceStateManager}) to another. Being a "part" of a transition means that either 153 // the {@link mIsEnabled} is changing, or the underlying mPrimiaryDisplayDevice is changing. 154 private boolean mIsInTransition; 155 LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice)156 public LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice) { 157 mDisplayId = displayId; 158 mLayerStack = layerStack; 159 mPrimaryDisplayDevice = primaryDisplayDevice; 160 mPendingFrameRateOverrideUids = new ArraySet<>(); 161 mTempFrameRateOverride = new SparseArray<>(); 162 mIsEnabled = true; 163 mIsInTransition = false; 164 } 165 166 /** 167 * Gets the logical display id of this logical display. 168 * 169 * @return The logical display id. 170 */ getDisplayIdLocked()171 public int getDisplayIdLocked() { 172 return mDisplayId; 173 } 174 175 /** 176 * Gets the primary display device associated with this logical display. 177 * 178 * @return The primary display device. 179 */ getPrimaryDisplayDeviceLocked()180 public DisplayDevice getPrimaryDisplayDeviceLocked() { 181 return mPrimaryDisplayDevice; 182 } 183 184 /** 185 * Gets information about the logical display. 186 * 187 * @return The device info, which should be treated as immutable by the caller. 188 * The logical display should allocate a new display info object whenever 189 * the data changes. 190 */ getDisplayInfoLocked()191 public DisplayInfo getDisplayInfoLocked() { 192 if (mInfo.get() == null) { 193 DisplayInfo info = new DisplayInfo(); 194 info.copyFrom(mBaseDisplayInfo); 195 if (mOverrideDisplayInfo != null) { 196 info.appWidth = mOverrideDisplayInfo.appWidth; 197 info.appHeight = mOverrideDisplayInfo.appHeight; 198 info.smallestNominalAppWidth = mOverrideDisplayInfo.smallestNominalAppWidth; 199 info.smallestNominalAppHeight = mOverrideDisplayInfo.smallestNominalAppHeight; 200 info.largestNominalAppWidth = mOverrideDisplayInfo.largestNominalAppWidth; 201 info.largestNominalAppHeight = mOverrideDisplayInfo.largestNominalAppHeight; 202 info.logicalWidth = mOverrideDisplayInfo.logicalWidth; 203 info.logicalHeight = mOverrideDisplayInfo.logicalHeight; 204 info.physicalXDpi = mOverrideDisplayInfo.physicalXDpi; 205 info.physicalYDpi = mOverrideDisplayInfo.physicalYDpi; 206 info.rotation = mOverrideDisplayInfo.rotation; 207 info.displayCutout = mOverrideDisplayInfo.displayCutout; 208 info.logicalDensityDpi = mOverrideDisplayInfo.logicalDensityDpi; 209 info.roundedCorners = mOverrideDisplayInfo.roundedCorners; 210 } 211 mInfo.set(info); 212 } 213 return mInfo.get(); 214 } 215 216 /** 217 * Returns the frame rate overrides list 218 */ getFrameRateOverrides()219 public DisplayEventReceiver.FrameRateOverride[] getFrameRateOverrides() { 220 return mFrameRateOverrides; 221 } 222 223 /** 224 * Returns the list of uids that needs to be updated about their frame rate override 225 */ getPendingFrameRateOverrideUids()226 public ArraySet<Integer> getPendingFrameRateOverrideUids() { 227 return mPendingFrameRateOverrideUids; 228 } 229 230 /** 231 * Clears the list of uids that needs to be updated about their frame rate override 232 */ clearPendingFrameRateOverrideUids()233 public void clearPendingFrameRateOverrideUids() { 234 mPendingFrameRateOverrideUids = new ArraySet<>(); 235 } 236 237 /** 238 * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo) 239 */ getNonOverrideDisplayInfoLocked(DisplayInfo outInfo)240 void getNonOverrideDisplayInfoLocked(DisplayInfo outInfo) { 241 outInfo.copyFrom(mBaseDisplayInfo); 242 } 243 244 /** 245 * Sets overridden logical display information from the window manager. 246 * This method can be used to adjust application insets, rotation, and other 247 * properties that the window manager takes care of. 248 * 249 * @param info The logical display information, may be null. 250 */ setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo info)251 public boolean setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo info) { 252 if (info != null) { 253 if (mOverrideDisplayInfo == null) { 254 mOverrideDisplayInfo = new DisplayInfo(info); 255 mInfo.set(null); 256 return true; 257 } else if (!mOverrideDisplayInfo.equals(info)) { 258 mOverrideDisplayInfo.copyFrom(info); 259 mInfo.set(null); 260 return true; 261 } 262 } else if (mOverrideDisplayInfo != null) { 263 mOverrideDisplayInfo = null; 264 mInfo.set(null); 265 return true; 266 } 267 return false; 268 } 269 270 /** 271 * Returns true if the logical display is in a valid state. 272 * This method should be checked after calling {@link #updateLocked} to handle the 273 * case where a logical display should be removed because all of its associated 274 * display devices are gone or if it is otherwise no longer needed. 275 * 276 * @return True if the logical display is still valid. 277 */ isValidLocked()278 public boolean isValidLocked() { 279 return mPrimaryDisplayDevice != null; 280 } 281 282 /** 283 * Updates the {@link DisplayGroup} to which the logical display belongs. 284 * 285 * @param groupId Identifier for the {@link DisplayGroup}. 286 */ updateDisplayGroupIdLocked(int groupId)287 public void updateDisplayGroupIdLocked(int groupId) { 288 if (groupId != mDisplayGroupId) { 289 mDisplayGroupId = groupId; 290 mBaseDisplayInfo.displayGroupId = groupId; 291 mInfo.set(null); 292 } 293 } 294 295 /** 296 * Updates the state of the logical display based on the available display devices. 297 * The logical display might become invalid if it is attached to a display device 298 * that no longer exists. 299 * 300 * @param deviceRepo Repository of active {@link DisplayDevice}s. 301 */ updateLocked(DisplayDeviceRepository deviceRepo)302 public void updateLocked(DisplayDeviceRepository deviceRepo) { 303 // Nothing to update if already invalid. 304 if (mPrimaryDisplayDevice == null) { 305 return; 306 } 307 308 // Check whether logical display has become invalid. 309 if (!deviceRepo.containsLocked(mPrimaryDisplayDevice)) { 310 setPrimaryDisplayDeviceLocked(null); 311 return; 312 } 313 314 // Bootstrap the logical display using its associated primary physical display. 315 // We might use more elaborate configurations later. It's possible that the 316 // configuration of several physical displays might be used to determine the 317 // logical display that they are sharing. (eg. Adjust size for pixel-perfect 318 // mirroring over HDMI.) 319 DisplayDeviceInfo deviceInfo = mPrimaryDisplayDevice.getDisplayDeviceInfoLocked(); 320 if (!Objects.equals(mPrimaryDisplayDeviceInfo, deviceInfo)) { 321 mBaseDisplayInfo.layerStack = mLayerStack; 322 mBaseDisplayInfo.flags = 0; 323 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) { 324 mBaseDisplayInfo.flags |= Display.FLAG_SUPPORTS_PROTECTED_BUFFERS; 325 } 326 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SECURE) != 0) { 327 mBaseDisplayInfo.flags |= Display.FLAG_SECURE; 328 } 329 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_PRIVATE) != 0) { 330 mBaseDisplayInfo.flags |= Display.FLAG_PRIVATE; 331 // For private displays by default content is destroyed on removal. 332 mBaseDisplayInfo.removeMode = Display.REMOVE_MODE_DESTROY_CONTENT; 333 } 334 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_DESTROY_CONTENT_ON_REMOVAL) != 0) { 335 mBaseDisplayInfo.removeMode = Display.REMOVE_MODE_DESTROY_CONTENT; 336 } 337 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_PRESENTATION) != 0) { 338 mBaseDisplayInfo.flags |= Display.FLAG_PRESENTATION; 339 } 340 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_ROUND) != 0) { 341 mBaseDisplayInfo.flags |= Display.FLAG_ROUND; 342 } 343 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) { 344 mBaseDisplayInfo.flags |= Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; 345 } 346 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0) { 347 mBaseDisplayInfo.flags |= Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; 348 } 349 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_TRUSTED) != 0) { 350 mBaseDisplayInfo.flags |= Display.FLAG_TRUSTED; 351 } 352 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP) != 0) { 353 mBaseDisplayInfo.flags |= Display.FLAG_OWN_DISPLAY_GROUP; 354 } 355 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_ALWAYS_UNLOCKED) != 0) { 356 mBaseDisplayInfo.flags |= Display.FLAG_ALWAYS_UNLOCKED; 357 } 358 if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_TOUCH_FEEDBACK_DISABLED) != 0) { 359 mBaseDisplayInfo.flags |= Display.FLAG_TOUCH_FEEDBACK_DISABLED; 360 } 361 Rect maskingInsets = getMaskingInsets(deviceInfo); 362 int maskedWidth = deviceInfo.width - maskingInsets.left - maskingInsets.right; 363 int maskedHeight = deviceInfo.height - maskingInsets.top - maskingInsets.bottom; 364 365 mBaseDisplayInfo.type = deviceInfo.type; 366 mBaseDisplayInfo.address = deviceInfo.address; 367 mBaseDisplayInfo.deviceProductInfo = deviceInfo.deviceProductInfo; 368 mBaseDisplayInfo.name = deviceInfo.name; 369 mBaseDisplayInfo.uniqueId = deviceInfo.uniqueId; 370 mBaseDisplayInfo.appWidth = maskedWidth; 371 mBaseDisplayInfo.appHeight = maskedHeight; 372 mBaseDisplayInfo.logicalWidth = maskedWidth; 373 mBaseDisplayInfo.logicalHeight = maskedHeight; 374 mBaseDisplayInfo.rotation = Surface.ROTATION_0; 375 mBaseDisplayInfo.modeId = deviceInfo.modeId; 376 mBaseDisplayInfo.defaultModeId = deviceInfo.defaultModeId; 377 mBaseDisplayInfo.supportedModes = Arrays.copyOf( 378 deviceInfo.supportedModes, deviceInfo.supportedModes.length); 379 mBaseDisplayInfo.colorMode = deviceInfo.colorMode; 380 mBaseDisplayInfo.supportedColorModes = Arrays.copyOf( 381 deviceInfo.supportedColorModes, 382 deviceInfo.supportedColorModes.length); 383 mBaseDisplayInfo.hdrCapabilities = deviceInfo.hdrCapabilities; 384 mBaseDisplayInfo.userDisabledHdrTypes = mUserDisabledHdrTypes; 385 mBaseDisplayInfo.minimalPostProcessingSupported = 386 deviceInfo.allmSupported || deviceInfo.gameContentTypeSupported; 387 mBaseDisplayInfo.logicalDensityDpi = deviceInfo.densityDpi; 388 mBaseDisplayInfo.physicalXDpi = deviceInfo.xDpi; 389 mBaseDisplayInfo.physicalYDpi = deviceInfo.yDpi; 390 mBaseDisplayInfo.appVsyncOffsetNanos = deviceInfo.appVsyncOffsetNanos; 391 mBaseDisplayInfo.presentationDeadlineNanos = deviceInfo.presentationDeadlineNanos; 392 mBaseDisplayInfo.state = deviceInfo.state; 393 mBaseDisplayInfo.committedState = deviceInfo.committedState; 394 mBaseDisplayInfo.smallestNominalAppWidth = maskedWidth; 395 mBaseDisplayInfo.smallestNominalAppHeight = maskedHeight; 396 mBaseDisplayInfo.largestNominalAppWidth = maskedWidth; 397 mBaseDisplayInfo.largestNominalAppHeight = maskedHeight; 398 mBaseDisplayInfo.ownerUid = deviceInfo.ownerUid; 399 mBaseDisplayInfo.ownerPackageName = deviceInfo.ownerPackageName; 400 boolean maskCutout = 401 (deviceInfo.flags & DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT) != 0; 402 mBaseDisplayInfo.displayCutout = maskCutout ? null : deviceInfo.displayCutout; 403 mBaseDisplayInfo.displayId = mDisplayId; 404 mBaseDisplayInfo.displayGroupId = mDisplayGroupId; 405 updateFrameRateOverrides(deviceInfo); 406 mBaseDisplayInfo.brightnessMinimum = deviceInfo.brightnessMinimum; 407 mBaseDisplayInfo.brightnessMaximum = deviceInfo.brightnessMaximum; 408 mBaseDisplayInfo.brightnessDefault = deviceInfo.brightnessDefault; 409 mBaseDisplayInfo.roundedCorners = deviceInfo.roundedCorners; 410 mBaseDisplayInfo.installOrientation = deviceInfo.installOrientation; 411 mPrimaryDisplayDeviceInfo = deviceInfo; 412 mInfo.set(null); 413 } 414 } 415 updateFrameRateOverrides(DisplayDeviceInfo deviceInfo)416 private void updateFrameRateOverrides(DisplayDeviceInfo deviceInfo) { 417 mTempFrameRateOverride.clear(); 418 if (mFrameRateOverrides != null) { 419 for (DisplayEventReceiver.FrameRateOverride frameRateOverride 420 : mFrameRateOverrides) { 421 mTempFrameRateOverride.put(frameRateOverride.uid, 422 frameRateOverride.frameRateHz); 423 } 424 } 425 mFrameRateOverrides = deviceInfo.frameRateOverrides; 426 if (mFrameRateOverrides != null) { 427 for (DisplayEventReceiver.FrameRateOverride frameRateOverride 428 : mFrameRateOverrides) { 429 float refreshRate = mTempFrameRateOverride.get(frameRateOverride.uid, 0f); 430 if (refreshRate == 0 || frameRateOverride.frameRateHz != refreshRate) { 431 mTempFrameRateOverride.put(frameRateOverride.uid, 432 frameRateOverride.frameRateHz); 433 } else { 434 mTempFrameRateOverride.delete(frameRateOverride.uid); 435 } 436 } 437 } 438 for (int i = 0; i < mTempFrameRateOverride.size(); i++) { 439 mPendingFrameRateOverrideUids.add(mTempFrameRateOverride.keyAt(i)); 440 } 441 } 442 443 /** 444 * Return the insets currently applied to the display. 445 * 446 * Note that the base DisplayInfo already takes these insets into account, so if you want to 447 * find out the <b>true</b> size of the display, you need to add them back to the logical 448 * dimensions. 449 */ getInsets()450 public Rect getInsets() { 451 return getMaskingInsets(mPrimaryDisplayDeviceInfo); 452 } 453 454 /** 455 * Returns insets in ROTATION_0 for areas that are masked. 456 */ getMaskingInsets(DisplayDeviceInfo deviceInfo)457 private static Rect getMaskingInsets(DisplayDeviceInfo deviceInfo) { 458 boolean maskCutout = (deviceInfo.flags & DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT) != 0; 459 if (maskCutout && deviceInfo.displayCutout != null) { 460 // getSafeInsets is fixed at creation time and cannot change 461 return deviceInfo.displayCutout.getSafeInsets(); 462 } else { 463 return new Rect(); 464 } 465 } 466 467 /** 468 * Returns the position of the display's projection. 469 * 470 * @return The x, y coordinates of the display. The return object must be treated as immutable. 471 */ getDisplayPosition()472 Point getDisplayPosition() { 473 // Allocate a new object to avoid a data race. 474 return new Point(mDisplayPosition); 475 } 476 477 /** 478 * Applies the layer stack and transformation to the given display device 479 * so that it shows the contents of this logical display. 480 * 481 * We know that the given display device is only ever showing the contents of 482 * a single logical display, so this method is expected to blow away all of its 483 * transformation properties to make it happen regardless of what the 484 * display device was previously showing. 485 * 486 * The caller must have an open Surface transaction. 487 * 488 * The display device may not be the primary display device, in the case 489 * where the display is being mirrored. 490 * 491 * @param device The display device to modify. 492 * @param isBlanked True if the device is being blanked. 493 */ configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device, boolean isBlanked)494 public void configureDisplayLocked(SurfaceControl.Transaction t, 495 DisplayDevice device, 496 boolean isBlanked) { 497 // Set the layer stack. 498 device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack, mDisplayId); 499 // Also inform whether the device is the same one sent to inputflinger for its layerstack. 500 // Prevent displays that are disabled from receiving input. 501 // TODO(b/188914255): Remove once input can dispatch against device vs layerstack. 502 device.setDisplayFlagsLocked(t, 503 (isEnabledLocked() && device.getDisplayDeviceInfoLocked().touch != TOUCH_NONE) 504 ? SurfaceControl.DISPLAY_RECEIVES_INPUT 505 : 0); 506 507 // Set the color mode and allowed display mode. 508 if (device == mPrimaryDisplayDevice) { 509 device.setDesiredDisplayModeSpecsLocked(mDesiredDisplayModeSpecs); 510 device.setRequestedColorModeLocked(mRequestedColorMode); 511 } else { 512 // Reset to default for non primary displays 513 device.setDesiredDisplayModeSpecsLocked( 514 new DisplayModeDirector.DesiredDisplayModeSpecs()); 515 device.setRequestedColorModeLocked(0); 516 } 517 518 device.setAutoLowLatencyModeLocked(mRequestedMinimalPostProcessing); 519 device.setGameContentTypeLocked(mRequestedMinimalPostProcessing); 520 521 // Only grab the display info now as it may have been changed based on the requests above. 522 final DisplayInfo displayInfo = getDisplayInfoLocked(); 523 final DisplayDeviceInfo displayDeviceInfo = device.getDisplayDeviceInfoLocked(); 524 525 // Set the viewport. 526 // This is the area of the logical display that we intend to show on the 527 // display device. For now, it is always the full size of the logical display. 528 mTempLayerStackRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight); 529 530 // Set the orientation. 531 // The orientation specifies how the physical coordinate system of the display 532 // is rotated when the contents of the logical display are rendered. 533 int orientation = Surface.ROTATION_0; 534 if ((displayDeviceInfo.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0) { 535 orientation = displayInfo.rotation; 536 } 537 538 // Apply the physical rotation of the display device itself. 539 orientation = (orientation + displayDeviceInfo.rotation) % 4; 540 541 // Set the frame. 542 // The frame specifies the rotated physical coordinates into which the viewport 543 // is mapped. We need to take care to preserve the aspect ratio of the viewport. 544 // Currently we maximize the area to fill the display, but we could try to be 545 // more clever and match resolutions. 546 boolean rotated = (orientation == Surface.ROTATION_90 547 || orientation == Surface.ROTATION_270); 548 int physWidth = rotated ? displayDeviceInfo.height : displayDeviceInfo.width; 549 int physHeight = rotated ? displayDeviceInfo.width : displayDeviceInfo.height; 550 551 Rect maskingInsets = getMaskingInsets(displayDeviceInfo); 552 InsetUtils.rotateInsets(maskingInsets, orientation); 553 // Don't consider the masked area as available when calculating the scaling below. 554 physWidth -= maskingInsets.left + maskingInsets.right; 555 physHeight -= maskingInsets.top + maskingInsets.bottom; 556 557 // Determine whether the width or height is more constrained to be scaled. 558 // physWidth / displayInfo.logicalWidth => letter box 559 // or physHeight / displayInfo.logicalHeight => pillar box 560 // 561 // We avoid a division (and possible floating point imprecision) here by 562 // multiplying the fractions by the product of their denominators before 563 // comparing them. 564 int displayRectWidth, displayRectHeight; 565 if ((displayInfo.flags & Display.FLAG_SCALING_DISABLED) != 0 || mDisplayScalingDisabled) { 566 displayRectWidth = displayInfo.logicalWidth; 567 displayRectHeight = displayInfo.logicalHeight; 568 } else if (physWidth * displayInfo.logicalHeight 569 < physHeight * displayInfo.logicalWidth) { 570 // Letter box. 571 displayRectWidth = physWidth; 572 displayRectHeight = displayInfo.logicalHeight * physWidth / displayInfo.logicalWidth; 573 } else { 574 // Pillar box. 575 displayRectWidth = displayInfo.logicalWidth * physHeight / displayInfo.logicalHeight; 576 displayRectHeight = physHeight; 577 } 578 int displayRectTop = (physHeight - displayRectHeight) / 2; 579 int displayRectLeft = (physWidth - displayRectWidth) / 2; 580 mTempDisplayRect.set(displayRectLeft, displayRectTop, 581 displayRectLeft + displayRectWidth, displayRectTop + displayRectHeight); 582 583 // Now add back the offset for the masked area. 584 mTempDisplayRect.offset(maskingInsets.left, maskingInsets.top); 585 586 if (orientation == Surface.ROTATION_0) { 587 mTempDisplayRect.offset(mDisplayOffsetX, mDisplayOffsetY); 588 } else if (orientation == Surface.ROTATION_90) { 589 mTempDisplayRect.offset(mDisplayOffsetY, -mDisplayOffsetX); 590 } else if (orientation == Surface.ROTATION_180) { 591 mTempDisplayRect.offset(-mDisplayOffsetX, -mDisplayOffsetY); 592 } else { // Surface.ROTATION_270 593 mTempDisplayRect.offset(-mDisplayOffsetY, mDisplayOffsetX); 594 } 595 596 mDisplayPosition.set(mTempDisplayRect.left, mTempDisplayRect.top); 597 device.setProjectionLocked(t, orientation, mTempLayerStackRect, mTempDisplayRect); 598 } 599 600 /** 601 * Returns true if the logical display has unique content. 602 * <p> 603 * If the display has unique content then we will try to ensure that it is 604 * visible on at least its primary display device. Otherwise we will ignore the 605 * logical display and perhaps show mirrored content on the primary display device. 606 * </p> 607 * 608 * @return True if the display has unique content. 609 */ hasContentLocked()610 public boolean hasContentLocked() { 611 return mHasContent; 612 } 613 614 /** 615 * Sets whether the logical display has unique content. 616 * 617 * @param hasContent True if the display has unique content. 618 */ setHasContentLocked(boolean hasContent)619 public void setHasContentLocked(boolean hasContent) { 620 mHasContent = hasContent; 621 } 622 623 /** 624 * Sets the display configs the system can use. 625 */ setDesiredDisplayModeSpecsLocked( DisplayModeDirector.DesiredDisplayModeSpecs specs)626 public void setDesiredDisplayModeSpecsLocked( 627 DisplayModeDirector.DesiredDisplayModeSpecs specs) { 628 mDesiredDisplayModeSpecs = specs; 629 } 630 631 /** 632 * Returns the display configs the system can choose. 633 */ getDesiredDisplayModeSpecsLocked()634 public DisplayModeDirector.DesiredDisplayModeSpecs getDesiredDisplayModeSpecsLocked() { 635 return mDesiredDisplayModeSpecs; 636 } 637 638 /** 639 * Requests the given color mode. 640 */ setRequestedColorModeLocked(int colorMode)641 public void setRequestedColorModeLocked(int colorMode) { 642 mRequestedColorMode = colorMode; 643 } 644 645 /** 646 * Returns the last requested minimal post processing setting. 647 */ getRequestedMinimalPostProcessingLocked()648 public boolean getRequestedMinimalPostProcessingLocked() { 649 return mRequestedMinimalPostProcessing; 650 } 651 652 /** 653 * Instructs the connected display to do minimal post processing. This is implemented either 654 * via HDMI 2.1 ALLM or HDMI 1.4 ContentType=Game. 655 * 656 * @param on Whether to set minimal post processing on/off on the connected display. 657 */ setRequestedMinimalPostProcessingLocked(boolean on)658 public void setRequestedMinimalPostProcessingLocked(boolean on) { 659 mRequestedMinimalPostProcessing = on; 660 } 661 662 /** Returns the pending requested color mode. */ getRequestedColorModeLocked()663 public int getRequestedColorModeLocked() { 664 return mRequestedColorMode; 665 } 666 667 /** 668 * Gets the burn-in offset in X. 669 */ getDisplayOffsetXLocked()670 public int getDisplayOffsetXLocked() { 671 return mDisplayOffsetX; 672 } 673 674 /** 675 * Gets the burn-in offset in Y. 676 */ getDisplayOffsetYLocked()677 public int getDisplayOffsetYLocked() { 678 return mDisplayOffsetY; 679 } 680 681 /** 682 * Sets the burn-in offsets. 683 */ setDisplayOffsetsLocked(int x, int y)684 public void setDisplayOffsetsLocked(int x, int y) { 685 mDisplayOffsetX = x; 686 mDisplayOffsetY = y; 687 } 688 689 /** 690 * @return {@code true} if display scaling is disabled, or {@code false} if the default scaling 691 * mode is used. 692 */ isDisplayScalingDisabled()693 public boolean isDisplayScalingDisabled() { 694 return mDisplayScalingDisabled; 695 } 696 697 /** 698 * Disables scaling for a display. 699 * 700 * @param disableScaling {@code true} to disable scaling, 701 * {@code false} to use the default scaling behavior of the logical display. 702 */ setDisplayScalingDisabledLocked(boolean disableScaling)703 public void setDisplayScalingDisabledLocked(boolean disableScaling) { 704 mDisplayScalingDisabled = disableScaling; 705 } 706 setUserDisabledHdrTypes(@onNull int[] userDisabledHdrTypes)707 public void setUserDisabledHdrTypes(@NonNull int[] userDisabledHdrTypes) { 708 if (mUserDisabledHdrTypes != userDisabledHdrTypes) { 709 mUserDisabledHdrTypes = userDisabledHdrTypes; 710 mBaseDisplayInfo.userDisabledHdrTypes = userDisabledHdrTypes; 711 mInfo.set(null); 712 } 713 } 714 715 /** 716 * Swap the underlying {@link DisplayDevice} with the specified LogicalDisplay. 717 * 718 * @param targetDisplay The display with which to swap display-devices. 719 * @return {@code true} if the displays were swapped, {@code false} otherwise. 720 */ swapDisplaysLocked(@onNull LogicalDisplay targetDisplay)721 public void swapDisplaysLocked(@NonNull LogicalDisplay targetDisplay) { 722 final DisplayDevice oldTargetDevice = 723 targetDisplay.setPrimaryDisplayDeviceLocked(mPrimaryDisplayDevice); 724 setPrimaryDisplayDeviceLocked(oldTargetDevice); 725 } 726 727 /** 728 * Sets the primary display device to the specified device. 729 * 730 * @param device The new device to set. 731 * @return The previously set display device. 732 */ setPrimaryDisplayDeviceLocked(@ullable DisplayDevice device)733 public DisplayDevice setPrimaryDisplayDeviceLocked(@Nullable DisplayDevice device) { 734 final DisplayDevice old = mPrimaryDisplayDevice; 735 mPrimaryDisplayDevice = device; 736 737 // Reset all our display info data 738 mPrimaryDisplayDeviceInfo = null; 739 mBaseDisplayInfo.copyFrom(EMPTY_DISPLAY_INFO); 740 mInfo.set(null); 741 742 return old; 743 } 744 745 /** 746 * @return {@code true} if the LogicalDisplay is enabled or {@code false} 747 * if disabled indicating that the display should be hidden from the rest of the apps and 748 * framework. 749 */ isEnabledLocked()750 public boolean isEnabledLocked() { 751 return mIsEnabled; 752 } 753 754 /** 755 * Sets the display as enabled. 756 * 757 * @param enable True if enabled, false otherwise. 758 */ setEnabledLocked(boolean enabled)759 public void setEnabledLocked(boolean enabled) { 760 mIsEnabled = enabled; 761 } 762 763 /** 764 * @return {@code true} if the LogicalDisplay is in a transition phase. This is used to indicate 765 * that we are getting ready to swap the underlying display-device and the display should be 766 * rendered appropriately to reduce jank. 767 */ isInTransitionLocked()768 public boolean isInTransitionLocked() { 769 return mIsInTransition; 770 } 771 772 /** 773 * Sets the transition phase. 774 * @param isInTransition True if it display is in transition. 775 */ setIsInTransitionLocked(boolean isInTransition)776 public void setIsInTransitionLocked(boolean isInTransition) { 777 mIsInTransition = isInTransition; 778 } 779 dumpLocked(PrintWriter pw)780 public void dumpLocked(PrintWriter pw) { 781 pw.println("mDisplayId=" + mDisplayId); 782 pw.println("mIsEnabled=" + mIsEnabled); 783 pw.println("mIsInTransition=" + mIsInTransition); 784 pw.println("mLayerStack=" + mLayerStack); 785 pw.println("mHasContent=" + mHasContent); 786 pw.println("mDesiredDisplayModeSpecs={" + mDesiredDisplayModeSpecs + "}"); 787 pw.println("mRequestedColorMode=" + mRequestedColorMode); 788 pw.println("mDisplayOffset=(" + mDisplayOffsetX + ", " + mDisplayOffsetY + ")"); 789 pw.println("mDisplayScalingDisabled=" + mDisplayScalingDisabled); 790 pw.println("mPrimaryDisplayDevice=" + (mPrimaryDisplayDevice != null ? 791 mPrimaryDisplayDevice.getNameLocked() : "null")); 792 pw.println("mBaseDisplayInfo=" + mBaseDisplayInfo); 793 pw.println("mOverrideDisplayInfo=" + mOverrideDisplayInfo); 794 pw.println("mRequestedMinimalPostProcessing=" + mRequestedMinimalPostProcessing); 795 pw.println("mFrameRateOverrides=" + Arrays.toString(mFrameRateOverrides)); 796 pw.println("mPendingFrameRateOverrideUids=" + mPendingFrameRateOverrideUids); 797 } 798 799 @Override toString()800 public String toString() { 801 StringWriter sw = new StringWriter(); 802 dumpLocked(new PrintWriter(sw)); 803 return sw.toString(); 804 } 805 } 806