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