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