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