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 android.Manifest.permission.ADD_ALWAYS_UNLOCKED_DISPLAY; 20 import static android.Manifest.permission.ADD_TRUSTED_DISPLAY; 21 import static android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT; 22 import static android.Manifest.permission.CAPTURE_VIDEO_OUTPUT; 23 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; 24 import static android.Manifest.permission.MANAGE_DISPLAYS; 25 import static android.Manifest.permission.RESTRICT_DISPLAY_MODES; 26 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED; 27 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE; 28 import static android.hardware.display.DisplayManager.EventsMask; 29 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED; 30 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; 31 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; 32 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP; 33 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY; 34 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP; 35 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION; 36 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC; 37 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE; 38 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; 39 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED; 40 import static android.hardware.display.DisplayManagerGlobal.DisplayEvent; 41 import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL; 42 import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL; 43 import static android.hardware.display.DisplayViewport.VIEWPORT_VIRTUAL; 44 import static android.hardware.display.HdrConversionMode.HDR_CONVERSION_UNSUPPORTED; 45 import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL; 46 import static android.os.Process.FIRST_APPLICATION_UID; 47 import static android.os.Process.ROOT_UID; 48 import static android.provider.Settings.Secure.RESOLUTION_MODE_FULL; 49 import static android.provider.Settings.Secure.RESOLUTION_MODE_HIGH; 50 import static android.provider.Settings.Secure.RESOLUTION_MODE_UNKNOWN; 51 52 import static com.android.server.display.layout.Layout.Display.POSITION_REAR; 53 54 import android.Manifest; 55 import android.annotation.EnforcePermission; 56 import android.annotation.NonNull; 57 import android.annotation.Nullable; 58 import android.annotation.RequiresPermission; 59 import android.annotation.SuppressLint; 60 import android.annotation.UserIdInt; 61 import android.app.ActivityManager; 62 import android.app.ActivityManagerInternal; 63 import android.app.AppOpsManager; 64 import android.app.compat.CompatChanges; 65 import android.companion.virtual.IVirtualDevice; 66 import android.companion.virtual.VirtualDeviceManager; 67 import android.companion.virtual.flags.Flags; 68 import android.compat.annotation.ChangeId; 69 import android.compat.annotation.EnabledSince; 70 import android.content.BroadcastReceiver; 71 import android.content.Context; 72 import android.content.Intent; 73 import android.content.IntentFilter; 74 import android.content.pm.PackageManager; 75 import android.content.pm.ParceledListSlice; 76 import android.content.res.Resources; 77 import android.content.res.TypedArray; 78 import android.database.ContentObserver; 79 import android.graphics.ColorSpace; 80 import android.graphics.Point; 81 import android.hardware.OverlayProperties; 82 import android.hardware.Sensor; 83 import android.hardware.SensorManager; 84 import android.hardware.devicestate.DeviceState; 85 import android.hardware.devicestate.DeviceStateManager; 86 import android.hardware.devicestate.DeviceStateManagerInternal; 87 import android.hardware.display.AmbientBrightnessDayStats; 88 import android.hardware.display.BrightnessChangeEvent; 89 import android.hardware.display.BrightnessConfiguration; 90 import android.hardware.display.BrightnessInfo; 91 import android.hardware.display.Curve; 92 import android.hardware.display.DisplayManager; 93 import android.hardware.display.DisplayManagerGlobal; 94 import android.hardware.display.DisplayManagerInternal; 95 import android.hardware.display.DisplayManagerInternal.DisplayGroupListener; 96 import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener; 97 import android.hardware.display.DisplayViewport; 98 import android.hardware.display.DisplayedContentSample; 99 import android.hardware.display.DisplayedContentSamplingAttributes; 100 import android.hardware.display.HdrConversionMode; 101 import android.hardware.display.IDisplayManager; 102 import android.hardware.display.IDisplayManagerCallback; 103 import android.hardware.display.IVirtualDisplayCallback; 104 import android.hardware.display.VirtualDisplayConfig; 105 import android.hardware.display.WifiDisplayStatus; 106 import android.hardware.graphics.common.DisplayDecorationSupport; 107 import android.hardware.input.HostUsiVersion; 108 import android.media.projection.IMediaProjection; 109 import android.media.projection.IMediaProjectionManager; 110 import android.net.Uri; 111 import android.os.Binder; 112 import android.os.Handler; 113 import android.os.HandlerExecutor; 114 import android.os.IBinder; 115 import android.os.IBinder.DeathRecipient; 116 import android.os.IThermalService; 117 import android.os.Looper; 118 import android.os.Message; 119 import android.os.PowerManager; 120 import android.os.Process; 121 import android.os.RemoteException; 122 import android.os.ResultReceiver; 123 import android.os.ServiceManager; 124 import android.os.ShellCallback; 125 import android.os.SystemClock; 126 import android.os.SystemProperties; 127 import android.os.Trace; 128 import android.os.UserHandle; 129 import android.os.UserManager; 130 import android.provider.DeviceConfigInterface; 131 import android.provider.Settings; 132 import android.sysprop.DisplayProperties; 133 import android.text.TextUtils; 134 import android.util.ArraySet; 135 import android.util.EventLog; 136 import android.util.IndentingPrintWriter; 137 import android.util.IntArray; 138 import android.util.Pair; 139 import android.util.Slog; 140 import android.util.SparseArray; 141 import android.util.SparseIntArray; 142 import android.util.Spline; 143 import android.view.ContentRecordingSession; 144 import android.view.Display; 145 import android.view.DisplayEventReceiver; 146 import android.view.DisplayInfo; 147 import android.view.Surface; 148 import android.view.SurfaceControl; 149 import android.view.SurfaceControl.RefreshRateRange; 150 import android.window.DisplayWindowPolicyController; 151 import android.window.ScreenCapture; 152 153 import com.android.internal.annotations.GuardedBy; 154 import com.android.internal.annotations.VisibleForTesting; 155 import com.android.internal.display.BrightnessSynchronizer; 156 import com.android.internal.foldables.FoldGracePeriodProvider; 157 import com.android.internal.foldables.FoldLockSettingAvailabilityProvider; 158 import com.android.internal.os.BackgroundThread; 159 import com.android.internal.util.ArrayUtils; 160 import com.android.internal.util.DumpUtils; 161 import com.android.internal.util.FrameworkStatsLog; 162 import com.android.internal.util.SettingsWrapper; 163 import com.android.server.AnimationThread; 164 import com.android.server.DisplayThread; 165 import com.android.server.LocalServices; 166 import com.android.server.SystemService; 167 import com.android.server.UiThread; 168 import com.android.server.companion.virtual.VirtualDeviceManagerInternal; 169 import com.android.server.display.config.SensorData; 170 import com.android.server.display.feature.DeviceConfigParameterProvider; 171 import com.android.server.display.feature.DisplayManagerFlags; 172 import com.android.server.display.layout.Layout; 173 import com.android.server.display.mode.DisplayModeDirector; 174 import com.android.server.display.notifications.DisplayNotificationManager; 175 import com.android.server.display.utils.DebugUtils; 176 import com.android.server.display.utils.SensorUtils; 177 import com.android.server.input.InputManagerInternal; 178 import com.android.server.utils.FoldSettingProvider; 179 import com.android.server.wm.SurfaceAnimationThread; 180 import com.android.server.wm.WindowManagerInternal; 181 182 import java.io.FileDescriptor; 183 import java.io.PrintWriter; 184 import java.util.ArrayList; 185 import java.util.Arrays; 186 import java.util.List; 187 import java.util.Optional; 188 import java.util.Set; 189 import java.util.concurrent.CopyOnWriteArrayList; 190 import java.util.concurrent.atomic.AtomicLong; 191 import java.util.function.Consumer; 192 193 194 /** 195 * Manages attached displays. 196 * <p> 197 * The {@link DisplayManagerService} manages the global lifecycle of displays, 198 * decides how to configure logical displays based on the physical display devices currently 199 * attached, sends notifications to the system and to applications when the state 200 * changes, and so on. 201 * </p><p> 202 * The display manager service relies on a collection of {@link DisplayAdapter} components, 203 * for discovering and configuring physical display devices attached to the system. 204 * There are separate display adapters for each manner that devices are attached: 205 * one display adapter for physical displays, one for simulated non-functional 206 * displays when the system is headless, one for simulated overlay displays used for 207 * development, one for wifi displays, etc. 208 * </p><p> 209 * Display adapters are only weakly coupled to the display manager service. 210 * Display adapters communicate changes in display device state to the display manager 211 * service asynchronously via a {@link DisplayAdapter.Listener}, and through 212 * the {@link DisplayDeviceRepository.Listener}, which is ultimately registered 213 * by the display manager service. This separation of concerns is important for 214 * two main reasons. First, it neatly encapsulates the responsibilities of these 215 * two classes: display adapters handle individual display devices whereas 216 * the display manager service handles the global state. Second, it eliminates 217 * the potential for deadlocks resulting from asynchronous display device discovery. 218 * </p> 219 * 220 * <h3>Synchronization</h3> 221 * <p> 222 * Because the display manager may be accessed by multiple threads, the synchronization 223 * story gets a little complicated. In particular, the window manager may call into 224 * the display manager while holding a surface transaction with the expectation that 225 * it can apply changes immediately. Unfortunately, that means we can't just do 226 * everything asynchronously (*grump*). 227 * </p><p> 228 * To make this work, all of the objects that belong to the display manager must 229 * use the same lock. We call this lock the synchronization root and it has a unique 230 * type {@link DisplayManagerService.SyncRoot}. Methods that require this lock are 231 * named with the "Locked" suffix. 232 * </p><p> 233 * Where things get tricky is that the display manager is not allowed to make 234 * any potentially reentrant calls, especially into the window manager. We generally 235 * avoid this by making all potentially reentrant out-calls asynchronous. 236 * </p> 237 */ 238 @SuppressWarnings("MissingPermission") 239 public final class DisplayManagerService extends SystemService { 240 private static final String TAG = "DisplayManagerService"; 241 242 // To enable these logs, run: 243 // 'adb shell setprop persist.log.tag.DisplayManagerService DEBUG && adb reboot' 244 private static final boolean DEBUG = DebugUtils.isDebuggable(TAG); 245 246 // When this system property is set to 0, WFD is forcibly disabled on boot. 247 // When this system property is set to 1, WFD is forcibly enabled on boot. 248 // Otherwise WFD is enabled according to the value of config_enableWifiDisplay. 249 private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable"; 250 251 private static final String PROP_DEFAULT_DISPLAY_TOP_INSET = "persist.sys.displayinset.top"; 252 253 private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000; 254 // This value needs to be in sync with the threshold 255 // in RefreshRateConfigs::getFrameRateDivisor. 256 private static final float THRESHOLD_FOR_REFRESH_RATES_DIVISORS = 0.0009f; 257 258 private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1; 259 private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2; 260 private static final int MSG_DELIVER_DISPLAY_EVENT = 3; 261 private static final int MSG_REQUEST_TRAVERSAL = 4; 262 private static final int MSG_UPDATE_VIEWPORT = 5; 263 private static final int MSG_LOAD_BRIGHTNESS_CONFIGURATIONS = 6; 264 private static final int MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE = 7; 265 private static final int MSG_DELIVER_DISPLAY_GROUP_EVENT = 8; 266 private static final int MSG_RECEIVED_DEVICE_STATE = 9; 267 private static final int[] EMPTY_ARRAY = new int[0]; 268 private static final HdrConversionMode HDR_CONVERSION_MODE_UNSUPPORTED = new HdrConversionMode( 269 HDR_CONVERSION_UNSUPPORTED); 270 271 private final Context mContext; 272 private final DisplayManagerHandler mHandler; 273 private final Handler mUiHandler; 274 private final DisplayModeDirector mDisplayModeDirector; 275 private final ExternalDisplayPolicy mExternalDisplayPolicy; 276 private WindowManagerInternal mWindowManagerInternal; 277 private InputManagerInternal mInputManagerInternal; 278 private ActivityManagerInternal mActivityManagerInternal; 279 private final UidImportanceListener mUidImportanceListener = new UidImportanceListener(); 280 @Nullable 281 private IMediaProjectionManager mProjectionService; 282 private DeviceStateManagerInternal mDeviceStateManager; 283 @GuardedBy("mSyncRoot") 284 private int[] mUserDisabledHdrTypes = {}; 285 @Display.HdrCapabilities.HdrType 286 private int[] mSupportedHdrOutputType; 287 @GuardedBy("mSyncRoot") 288 private boolean mAreUserDisabledHdrTypesAllowed = true; 289 290 // This value indicates whether or not HDR output control is enabled. 291 // It is read from DeviceConfig and is updated via a listener if the config changes. 292 private volatile boolean mIsHdrOutputControlEnabled; 293 294 // Display mode chosen by user. 295 private Display.Mode mUserPreferredMode; 296 @HdrConversionMode.ConversionMode 297 private final int mDefaultHdrConversionMode; 298 // HDR conversion mode chosen by user 299 @GuardedBy("mSyncRoot") 300 private HdrConversionMode mHdrConversionMode = null; 301 // Actual HDR conversion mode, which takes app overrides into account. 302 private HdrConversionMode mOverrideHdrConversionMode = null; 303 @GuardedBy("mSyncRoot") 304 private int mSystemPreferredHdrOutputType = Display.HdrCapabilities.HDR_TYPE_INVALID; 305 306 307 // The synchronization root for the display manager. 308 // This lock guards most of the display manager's state. 309 // NOTE: This is synchronized on while holding WindowManagerService.mWindowMap so never call 310 // into WindowManagerService methods that require mWindowMap while holding this unless you are 311 // very very sure that no deadlock can occur. 312 private final SyncRoot mSyncRoot = new SyncRoot(); 313 314 // True if in safe mode. 315 // This option may disable certain display adapters. 316 public boolean mSafeMode; 317 318 // All callback records indexed by calling process id. 319 private final SparseArray<CallbackRecord> mCallbacks = new SparseArray<>(); 320 321 /** 322 * All {@link IVirtualDevice} and {@link DisplayWindowPolicyController}s indexed by 323 * {@link DisplayInfo#displayId}. 324 */ 325 final SparseArray<Pair<IVirtualDevice, DisplayWindowPolicyController>> 326 mDisplayWindowPolicyControllers = new SparseArray<>(); 327 328 /** 329 * Provides {@link HighBrightnessModeMetadata}s for {@link DisplayDevice}s. 330 */ 331 private final HighBrightnessModeMetadataMapper mHighBrightnessModeMetadataMapper = 332 new HighBrightnessModeMetadataMapper(); 333 334 // List of all currently registered display adapters. 335 private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<>(); 336 337 /** 338 * Repository of all active {@link DisplayDevice}s. 339 */ 340 private final DisplayDeviceRepository mDisplayDeviceRepo; 341 342 /** 343 * Contains all the {@link LogicalDisplay} instances and is responsible for mapping 344 * {@link DisplayDevice}s to {@link LogicalDisplay}s. DisplayManagerService listens to display 345 * event on this object. 346 */ 347 private final LogicalDisplayMapper mLogicalDisplayMapper; 348 349 // List of all display transaction listeners. 350 private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners = 351 new CopyOnWriteArrayList<>(); 352 353 /** List of all display group listeners. */ 354 private final CopyOnWriteArrayList<DisplayGroupListener> mDisplayGroupListeners = 355 new CopyOnWriteArrayList<>(); 356 357 /** All {@link DisplayPowerController}s indexed by {@link LogicalDisplay} ID. */ 358 private final SparseArray<DisplayPowerControllerInterface> mDisplayPowerControllers = 359 new SparseArray<>(); 360 361 /** {@link DisplayBlanker} used by all {@link DisplayPowerController}s. */ 362 private final DisplayBlanker mDisplayBlanker = new DisplayBlanker() { 363 // Synchronized to avoid race conditions when updating multiple display states. 364 @Override 365 public synchronized void requestDisplayState(int displayId, int state, float brightness, 366 float sdrBrightness) { 367 boolean allInactive = true; 368 boolean allOff = true; 369 final boolean stateChanged; 370 synchronized (mSyncRoot) { 371 final int index = mDisplayStates.indexOfKey(displayId); 372 if (index > -1) { 373 final int currentState = mDisplayStates.valueAt(index); 374 stateChanged = state != currentState; 375 if (stateChanged) { 376 final int size = mDisplayStates.size(); 377 for (int i = 0; i < size; i++) { 378 final int displayState = i == index ? state : mDisplayStates.valueAt(i); 379 if (displayState != Display.STATE_OFF) { 380 allOff = false; 381 } 382 if (Display.isActiveState(displayState)) { 383 allInactive = false; 384 } 385 if (!allOff && !allInactive) { 386 break; 387 } 388 } 389 } 390 } else { 391 stateChanged = false; 392 } 393 } 394 395 // The order of operations is important for legacy reasons. 396 if (state == Display.STATE_OFF) { 397 requestDisplayStateInternal(displayId, state, brightness, sdrBrightness); 398 } 399 400 if (stateChanged) { 401 mDisplayPowerCallbacks.onDisplayStateChange(allInactive, allOff); 402 } 403 404 if (state != Display.STATE_OFF) { 405 requestDisplayStateInternal(displayId, state, brightness, sdrBrightness); 406 } 407 } 408 }; 409 410 /** 411 * Used to inform {@link com.android.server.power.PowerManagerService} of changes to display 412 * state. 413 */ 414 private DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks; 415 416 /** The {@link Handler} used by all {@link DisplayPowerController}s. */ 417 private Handler mPowerHandler; 418 419 // A map from LogicalDisplay ID to display power state. 420 @GuardedBy("mSyncRoot") 421 private final SparseIntArray mDisplayStates = new SparseIntArray(); 422 423 // A map from LogicalDisplay ID to display brightness. 424 @GuardedBy("mSyncRoot") 425 private final SparseArray<BrightnessPair> mDisplayBrightnesses = new SparseArray<>(); 426 427 // Set to true when there are pending display changes that have yet to be applied 428 // to the surface flinger state. 429 private boolean mPendingTraversal; 430 431 // The Wifi display adapter, or null if not registered. 432 private WifiDisplayAdapter mWifiDisplayAdapter; 433 434 // The number of active wifi display scan requests. 435 private int mWifiDisplayScanRequestCount; 436 437 // The virtual display adapter, or null if not registered. 438 private VirtualDisplayAdapter mVirtualDisplayAdapter; 439 440 // The User ID of the current user 441 private @UserIdInt int mCurrentUserId; 442 443 // The stable device screen height and width. These are not tied to a specific display, even 444 // the default display, because they need to be stable over the course of the device's entire 445 // life, even if the default display changes (e.g. a new monitor is plugged into a PC-like 446 // device). 447 private Point mStableDisplaySize = new Point(); 448 449 // Whether the system has finished booting or not. 450 private boolean mSystemReady; 451 452 // The top inset of the default display. 453 // This gets persisted so that the boot animation knows how to transition from the display's 454 // full size to the size configured by the user. Right now we only persist and animate the top 455 // inset, but theoretically we could do it for all of them. 456 private int mDefaultDisplayTopInset; 457 458 // Viewports of the default display and the display that should receive touch 459 // input from an external source. Used by the input system. 460 @GuardedBy("mSyncRoot") 461 private final ArrayList<DisplayViewport> mViewports = new ArrayList<>(); 462 463 // Persistent data store for all internal settings maintained by the display manager service. 464 private final PersistentDataStore mPersistentDataStore = new PersistentDataStore(); 465 466 // Temporary callback list, used when sending display events to applications. 467 // May be used outside of the lock but only on the handler thread. 468 private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<>(); 469 470 // Pending callback records indexed by calling process uid and pid. 471 // Must be used outside of the lock mSyncRoot and should be self-locked. 472 @GuardedBy("mPendingCallbackSelfLocked") 473 private final SparseArray<SparseArray<PendingCallback>> mPendingCallbackSelfLocked = 474 new SparseArray<>(); 475 476 // Temporary viewports, used when sending new viewport information to the 477 // input system. May be used outside of the lock but only on the handler thread. 478 private final ArrayList<DisplayViewport> mTempViewports = new ArrayList<>(); 479 480 // The default color mode for default displays. Overrides the usual 481 // Display.Display.COLOR_MODE_DEFAULT for local displays. 482 private final int mDefaultDisplayDefaultColorMode; 483 484 // Lists of UIDs that are present on the displays. Maps displayId -> array of UIDs. 485 private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>(); 486 487 private final Injector mInjector; 488 489 // The minimum brightness curve, which guarantess that any brightness curve that dips below it 490 // is rejected by the system. 491 private final Curve mMinimumBrightnessCurve; 492 private final Spline mMinimumBrightnessSpline; 493 private final ColorSpace mWideColorSpace; 494 private final OverlayProperties mOverlayProperties; 495 496 private SensorManager mSensorManager; 497 private BrightnessTracker mBrightnessTracker; 498 499 private SmallAreaDetectionController mSmallAreaDetectionController; 500 501 502 // Whether minimal post processing is allowed by the user. 503 @GuardedBy("mSyncRoot") 504 private boolean mMinimalPostProcessingAllowed; 505 506 // Receives notifications about changes to Settings. 507 private SettingsObserver mSettingsObserver; 508 509 // Keeps note of what state the device is in, used for idle screen brightness mode. 510 private boolean mIsDocked; 511 private boolean mIsDreaming; 512 513 private boolean mBootCompleted = false; 514 515 // If we would like to keep a particular eye on a package, we can set the package name. 516 private final boolean mExtraDisplayEventLogging; 517 private final String mExtraDisplayLoggingPackageName; 518 519 private final BroadcastReceiver mIdleModeReceiver = new BroadcastReceiver() { 520 @Override 521 public void onReceive(Context context, Intent intent) { 522 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) { 523 int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 524 Intent.EXTRA_DOCK_STATE_UNDOCKED); 525 mIsDocked = dockState == Intent.EXTRA_DOCK_STATE_DESK 526 || dockState == Intent.EXTRA_DOCK_STATE_LE_DESK 527 || dockState == Intent.EXTRA_DOCK_STATE_HE_DESK; 528 } 529 if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) { 530 mIsDreaming = true; 531 } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) { 532 mIsDreaming = false; 533 } 534 setDockedAndIdleEnabled(/* enabled= */(mIsDocked && mIsDreaming), 535 Display.DEFAULT_DISPLAY); 536 } 537 }; 538 539 private final BroadcastReceiver mResolutionRestoreReceiver = new BroadcastReceiver() { 540 @Override 541 public void onReceive(Context context, Intent intent) { 542 if (Intent.ACTION_SETTING_RESTORED.equals(intent.getAction())) { 543 if (Settings.Secure.SCREEN_RESOLUTION_MODE.equals( 544 intent.getExtra(Intent.EXTRA_SETTING_NAME))) { 545 restoreResolutionFromBackup(); 546 } 547 } 548 } 549 }; 550 551 private final DisplayModeDirector.DisplayDeviceConfigProvider mDisplayDeviceConfigProvider = 552 displayId -> { 553 synchronized (mSyncRoot) { 554 final DisplayDevice device = getDeviceForDisplayLocked(displayId); 555 if (device == null) { 556 return null; 557 } 558 return device.getDisplayDeviceConfig(); 559 } 560 }; 561 562 private final BrightnessSynchronizer mBrightnessSynchronizer; 563 564 private final DeviceConfigParameterProvider mConfigParameterProvider; 565 566 private final DisplayManagerFlags mFlags; 567 568 private final DisplayNotificationManager mDisplayNotificationManager; 569 private final ExternalDisplayStatsService mExternalDisplayStatsService; 570 571 /** 572 * Applications use {@link android.view.Display#getRefreshRate} and 573 * {@link android.view.Display.Mode#getRefreshRate} to know what is the display refresh rate. 574 * Starting with Android S, the platform might throttle down applications frame rate to a 575 * divisor of the refresh rate if it is more preferable (for example if the application called 576 * to {@link android.view.Surface#setFrameRate}). 577 * Applications will experience {@link android.view.Choreographer#postFrameCallback} callbacks 578 * and backpressure at the throttled frame rate. 579 * 580 * {@link android.view.Display#getRefreshRate} will always return the application frame rate 581 * and not the physical display refresh rate to allow applications to do frame pacing correctly. 582 * 583 * {@link android.view.Display.Mode#getRefreshRate} will return the application frame rate if 584 * compiled to a previous release and starting with Android S it will return the physical 585 * display refresh rate. 586 */ 587 @ChangeId 588 @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S) 589 static final long DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE = 170503758L; 590 DisplayManagerService(Context context)591 public DisplayManagerService(Context context) { 592 this(context, new Injector()); 593 } 594 595 @VisibleForTesting DisplayManagerService(Context context, Injector injector)596 DisplayManagerService(Context context, Injector injector) { 597 super(context); 598 FoldSettingProvider foldSettingProvider = new FoldSettingProvider(context, 599 new SettingsWrapper(), 600 new FoldLockSettingAvailabilityProvider(context.getResources())); 601 mInjector = injector; 602 mContext = context; 603 mFlags = injector.getFlags(); 604 mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper()); 605 mUiHandler = UiThread.getHandler(); 606 mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore); 607 mLogicalDisplayMapper = new LogicalDisplayMapper(mContext, 608 foldSettingProvider, new FoldGracePeriodProvider(), 609 mDisplayDeviceRepo, new LogicalDisplayListener(), mSyncRoot, mHandler, mFlags); 610 mDisplayModeDirector = new DisplayModeDirector( 611 context, mHandler, mFlags, mDisplayDeviceConfigProvider); 612 mBrightnessSynchronizer = new BrightnessSynchronizer(mContext, 613 mFlags.isBrightnessIntRangeUserPerceptionEnabled()); 614 Resources resources = mContext.getResources(); 615 mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger( 616 com.android.internal.R.integer.config_defaultDisplayDefaultColorMode); 617 mDefaultDisplayTopInset = SystemProperties.getInt(PROP_DEFAULT_DISPLAY_TOP_INSET, -1); 618 mDefaultHdrConversionMode = mContext.getResources().getBoolean( 619 com.android.internal.R.bool.config_enableDefaultHdrConversionPassthrough) 620 ? HdrConversionMode.HDR_CONVERSION_PASSTHROUGH 621 : HdrConversionMode.HDR_CONVERSION_SYSTEM; 622 float[] lux = getFloatArray(resources.obtainTypedArray( 623 com.android.internal.R.array.config_minimumBrightnessCurveLux)); 624 float[] nits = getFloatArray(resources.obtainTypedArray( 625 com.android.internal.R.array.config_minimumBrightnessCurveNits)); 626 mMinimumBrightnessCurve = new Curve(lux, nits); 627 mMinimumBrightnessSpline = Spline.createSpline(lux, nits); 628 629 mCurrentUserId = UserHandle.USER_SYSTEM; 630 ColorSpace[] colorSpaces = SurfaceControl.getCompositionColorSpaces(); 631 mWideColorSpace = colorSpaces[1]; 632 mOverlayProperties = SurfaceControl.getOverlaySupport(); 633 mSystemReady = false; 634 mConfigParameterProvider = new DeviceConfigParameterProvider(DeviceConfigInterface.REAL); 635 mExtraDisplayLoggingPackageName = DisplayProperties.debug_vri_package().orElse(null); 636 mExtraDisplayEventLogging = !TextUtils.isEmpty(mExtraDisplayLoggingPackageName); 637 638 mExternalDisplayStatsService = new ExternalDisplayStatsService(mContext, mHandler); 639 mDisplayNotificationManager = new DisplayNotificationManager(mFlags, mContext, 640 mExternalDisplayStatsService); 641 mExternalDisplayPolicy = new ExternalDisplayPolicy(new ExternalDisplayPolicyInjector()); 642 } 643 setupSchedulerPolicies()644 public void setupSchedulerPolicies() { 645 // android.display and android.anim is critical to user experience and we should make sure 646 // it is not in the default foregroup groups, add it to top-app to make sure it uses all 647 // the cores and scheduling settings for top-app when it runs. 648 Process.setThreadGroupAndCpuset(DisplayThread.get().getThreadId(), 649 Process.THREAD_GROUP_TOP_APP); 650 Process.setThreadGroupAndCpuset(AnimationThread.get().getThreadId(), 651 Process.THREAD_GROUP_TOP_APP); 652 Process.setThreadGroupAndCpuset(SurfaceAnimationThread.get().getThreadId(), 653 Process.THREAD_GROUP_TOP_APP); 654 } 655 656 @Override onStart()657 public void onStart() { 658 // We need to pre-load the persistent data store so it's ready before the default display 659 // adapter is up so that we have it's configuration. We could load it lazily, but since 660 // we're going to have to read it in eventually we may as well do it here rather than after 661 // we've waited for the display to register itself with us. 662 synchronized (mSyncRoot) { 663 mPersistentDataStore.loadIfNeeded(); 664 loadStableDisplayValuesLocked(); 665 } 666 mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS); 667 668 // If there was a runtime restart then we may have stale caches left around, so we need to 669 // make sure to invalidate them upon every start. 670 DisplayManagerGlobal.invalidateLocalDisplayInfoCaches(); 671 672 publishBinderService(Context.DISPLAY_SERVICE, new BinderService(), 673 true /*allowIsolated*/, DUMP_FLAG_PRIORITY_CRITICAL); 674 publishLocalService(DisplayManagerInternal.class, new LocalService()); 675 } 676 677 @Override onBootPhase(int phase)678 public void onBootPhase(int phase) { 679 if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) { 680 synchronized (mSyncRoot) { 681 long timeout = SystemClock.uptimeMillis() 682 + mInjector.getDefaultDisplayDelayTimeout(); 683 while (mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY) == null 684 || mVirtualDisplayAdapter == null) { 685 long delay = timeout - SystemClock.uptimeMillis(); 686 if (delay <= 0) { 687 throw new RuntimeException("Timeout waiting for default display " 688 + "to be initialized. DefaultDisplay=" 689 + mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY) 690 + ", mVirtualDisplayAdapter=" + mVirtualDisplayAdapter); 691 } 692 if (DEBUG) { 693 Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay); 694 } 695 try { 696 mSyncRoot.wait(delay); 697 } catch (InterruptedException ex) { 698 } 699 } 700 } 701 } else if (phase == PHASE_BOOT_COMPLETED) { 702 synchronized (mSyncRoot) { 703 mBootCompleted = true; 704 for (int i = 0; i < mDisplayPowerControllers.size(); i++) { 705 mDisplayPowerControllers.valueAt(i).onBootCompleted(); 706 } 707 } 708 mDisplayModeDirector.onBootCompleted(); 709 mLogicalDisplayMapper.onBootCompleted(); 710 mDisplayNotificationManager.onBootCompleted(); 711 mExternalDisplayPolicy.onBootCompleted(); 712 } 713 } 714 715 @Override onUserSwitching(@ullable TargetUser from, @NonNull TargetUser to)716 public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) { 717 final int newUserId = to.getUserIdentifier(); 718 final int userSerial = getUserManager().getUserSerialNumber(newUserId); 719 synchronized (mSyncRoot) { 720 boolean userSwitching = mCurrentUserId != newUserId; 721 if (userSwitching) { 722 mCurrentUserId = newUserId; 723 } 724 mLogicalDisplayMapper.forEachLocked(logicalDisplay -> { 725 if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) { 726 return; 727 } 728 final DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get( 729 logicalDisplay.getDisplayIdLocked()); 730 if (dpc == null) { 731 return; 732 } 733 if (userSwitching) { 734 BrightnessConfiguration config = 735 getBrightnessConfigForDisplayWithPdsFallbackLocked( 736 logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId(), 737 userSerial); 738 dpc.setBrightnessConfiguration(config, /* shouldResetShortTermModel= */ true); 739 } 740 final DisplayDevice device = logicalDisplay.getPrimaryDisplayDeviceLocked(); 741 float newBrightness = device == null ? PowerManager.BRIGHTNESS_INVALID_FLOAT 742 : mPersistentDataStore.getBrightness(device, userSerial); 743 if (Float.isNaN(newBrightness)) { 744 newBrightness = logicalDisplay.getDisplayInfoLocked().brightnessDefault; 745 } 746 dpc.onSwitchUser(newUserId, userSerial, newBrightness); 747 }); 748 handleSettingsChange(); 749 } 750 } 751 752 /** 753 * The 2nd stage initialization 754 * TODO: Use dependencies or a boot phase 755 */ 756 @SuppressLint("AndroidFrameworkRequiresPermission") windowManagerAndInputReady()757 public void windowManagerAndInputReady() { 758 synchronized (mSyncRoot) { 759 mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); 760 mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); 761 mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); 762 ActivityManager activityManager = mContext.getSystemService(ActivityManager.class); 763 activityManager.addOnUidImportanceListener(mUidImportanceListener, IMPORTANCE_CACHED); 764 765 mDeviceStateManager = LocalServices.getService(DeviceStateManagerInternal.class); 766 mContext.getSystemService(DeviceStateManager.class).registerCallback( 767 new HandlerExecutor(mHandler), new DeviceStateListener()); 768 769 mLogicalDisplayMapper.onWindowManagerReady(); 770 scheduleTraversalLocked(false); 771 } 772 } 773 774 /** 775 * Called when the system is ready to go. 776 */ systemReady(boolean safeMode)777 public void systemReady(boolean safeMode) { 778 synchronized (mSyncRoot) { 779 mSafeMode = safeMode; 780 mSystemReady = true; 781 mIsHdrOutputControlEnabled = 782 mConfigParameterProvider.isHdrOutputControlFeatureEnabled(); 783 mConfigParameterProvider.addOnPropertiesChangedListener(BackgroundThread.getExecutor(), 784 properties -> mIsHdrOutputControlEnabled = 785 mConfigParameterProvider.isHdrOutputControlFeatureEnabled()); 786 // Just in case the top inset changed before the system was ready. At this point, any 787 // relevant configuration should be in place. 788 recordTopInsetLocked(mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY)); 789 790 updateSettingsLocked(); 791 updateUserDisabledHdrTypesFromSettingsLocked(); 792 updateUserPreferredDisplayModeSettingsLocked(); 793 if (mIsHdrOutputControlEnabled) { 794 updateHdrConversionModeSettingsLocked(); 795 } 796 } 797 798 mDisplayModeDirector.setDesiredDisplayModeSpecsListener( 799 new DesiredDisplayModeSpecsObserver()); 800 mDisplayModeDirector.start(mSensorManager); 801 802 mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS); 803 804 mSettingsObserver = new SettingsObserver(); 805 806 mBrightnessSynchronizer.startSynchronizing(); 807 808 final IntentFilter filter = new IntentFilter(); 809 filter.addAction(Intent.ACTION_DREAMING_STARTED); 810 filter.addAction(Intent.ACTION_DREAMING_STOPPED); 811 filter.addAction(Intent.ACTION_DOCK_EVENT); 812 813 mContext.registerReceiver(mIdleModeReceiver, filter); 814 815 if (mFlags.isResolutionBackupRestoreEnabled()) { 816 final IntentFilter restoreFilter = new IntentFilter(Intent.ACTION_SETTING_RESTORED); 817 mContext.registerReceiver(mResolutionRestoreReceiver, restoreFilter); 818 } 819 820 mSmallAreaDetectionController = (mFlags.isSmallAreaDetectionEnabled()) 821 ? SmallAreaDetectionController.create(mContext) : null; 822 } 823 824 @VisibleForTesting getDisplayHandler()825 Handler getDisplayHandler() { 826 return mHandler; 827 } 828 829 @VisibleForTesting getDisplayDeviceRepository()830 DisplayDeviceRepository getDisplayDeviceRepository() { 831 return mDisplayDeviceRepo; 832 } 833 834 @VisibleForTesting getLogicalDisplayMapper()835 LogicalDisplayMapper getLogicalDisplayMapper() { 836 return mLogicalDisplayMapper; 837 } 838 839 @VisibleForTesting isMinimalPostProcessingAllowed()840 boolean isMinimalPostProcessingAllowed() { 841 synchronized (mSyncRoot) { 842 return mMinimalPostProcessingAllowed; 843 } 844 } 845 846 @VisibleForTesting setMinimalPostProcessingAllowed(boolean allowed)847 void setMinimalPostProcessingAllowed(boolean allowed) { 848 synchronized (mSyncRoot) { 849 mMinimalPostProcessingAllowed = allowed; 850 } 851 } 852 getDisplayNotificationManager()853 DisplayNotificationManager getDisplayNotificationManager() { 854 return mDisplayNotificationManager; 855 } 856 loadStableDisplayValuesLocked()857 private void loadStableDisplayValuesLocked() { 858 final Point size = mPersistentDataStore.getStableDisplaySize(); 859 if (size.x > 0 && size.y > 0) { 860 // Just set these values directly so we don't write the display persistent data again 861 // unnecessarily 862 mStableDisplaySize.set(size.x, size.y); 863 } else { 864 final Resources res = mContext.getResources(); 865 final int width = res.getInteger( 866 com.android.internal.R.integer.config_stableDeviceDisplayWidth); 867 final int height = res.getInteger( 868 com.android.internal.R.integer.config_stableDeviceDisplayHeight); 869 if (width > 0 && height > 0) { 870 setStableDisplaySizeLocked(width, height); 871 } 872 } 873 } 874 getStableDisplaySizeInternal()875 private Point getStableDisplaySizeInternal() { 876 Point r = new Point(); 877 synchronized (mSyncRoot) { 878 if (mStableDisplaySize.x > 0 && mStableDisplaySize.y > 0) { 879 r.set(mStableDisplaySize.x, mStableDisplaySize.y); 880 } 881 } 882 return r; 883 } 884 registerDisplayTransactionListenerInternal( DisplayTransactionListener listener)885 private void registerDisplayTransactionListenerInternal( 886 DisplayTransactionListener listener) { 887 // List is self-synchronized copy-on-write. 888 mDisplayTransactionListeners.add(listener); 889 } 890 unregisterDisplayTransactionListenerInternal( DisplayTransactionListener listener)891 private void unregisterDisplayTransactionListenerInternal( 892 DisplayTransactionListener listener) { 893 // List is self-synchronized copy-on-write. 894 mDisplayTransactionListeners.remove(listener); 895 } 896 897 @VisibleForTesting setDisplayInfoOverrideFromWindowManagerInternal(int displayId, DisplayInfo info)898 void setDisplayInfoOverrideFromWindowManagerInternal(int displayId, DisplayInfo info) { 899 synchronized (mSyncRoot) { 900 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 901 if (display != null) { 902 if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) { 903 handleLogicalDisplayChangedLocked(display); 904 } 905 } 906 } 907 } 908 909 /** 910 * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo) 911 */ getNonOverrideDisplayInfoInternal(int displayId, DisplayInfo outInfo)912 private void getNonOverrideDisplayInfoInternal(int displayId, DisplayInfo outInfo) { 913 synchronized (mSyncRoot) { 914 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 915 if (display != null) { 916 display.getNonOverrideDisplayInfoLocked(outInfo); 917 } 918 } 919 } 920 921 @VisibleForTesting performTraversalInternal(SurfaceControl.Transaction t, SparseArray<SurfaceControl.Transaction> displayTransactions)922 void performTraversalInternal(SurfaceControl.Transaction t, 923 SparseArray<SurfaceControl.Transaction> displayTransactions) { 924 synchronized (mSyncRoot) { 925 if (!mPendingTraversal) { 926 return; 927 } 928 mPendingTraversal = false; 929 930 performTraversalLocked(t, displayTransactions); 931 } 932 933 // List is self-synchronized copy-on-write. 934 for (DisplayTransactionListener listener : mDisplayTransactionListeners) { 935 listener.onDisplayTransaction(t); 936 } 937 } 938 clampBrightness(int displayState, float brightnessState)939 private float clampBrightness(int displayState, float brightnessState) { 940 if (displayState == Display.STATE_OFF) { 941 brightnessState = PowerManager.BRIGHTNESS_OFF_FLOAT; 942 } else if (brightnessState != PowerManager.BRIGHTNESS_OFF_FLOAT 943 && brightnessState < PowerManager.BRIGHTNESS_MIN) { 944 brightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT; 945 } else if (brightnessState > PowerManager.BRIGHTNESS_MAX) { 946 brightnessState = PowerManager.BRIGHTNESS_MAX; 947 } 948 return brightnessState; 949 } 950 requestDisplayStateInternal(int displayId, int state, float brightnessState, float sdrBrightnessState)951 private void requestDisplayStateInternal(int displayId, int state, float brightnessState, 952 float sdrBrightnessState) { 953 if (state == Display.STATE_UNKNOWN) { 954 state = Display.STATE_ON; 955 } 956 957 brightnessState = clampBrightness(state, brightnessState); 958 sdrBrightnessState = clampBrightness(state, sdrBrightnessState); 959 960 // Update the display state within the lock. 961 // Note that we do not need to schedule traversals here although it 962 // may happen as a side-effect of displays changing state. 963 final Runnable runnable; 964 final String traceMessage; 965 synchronized (mSyncRoot) { 966 final int index = mDisplayStates.indexOfKey(displayId); 967 968 final BrightnessPair brightnessPair = 969 index < 0 ? null : mDisplayBrightnesses.valueAt(index); 970 if (index < 0 || (mDisplayStates.valueAt(index) == state 971 && brightnessPair.brightness == brightnessState 972 && brightnessPair.sdrBrightness == sdrBrightnessState)) { 973 return; // Display no longer exists or no change. 974 } 975 976 if (Trace.isTagEnabled(Trace.TRACE_TAG_POWER)) { 977 traceMessage = Display.stateToString(state) 978 + ", brightness=" + brightnessState 979 + ", sdrBrightness=" + sdrBrightnessState; 980 Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_POWER, 981 "requestDisplayStateInternal:" + displayId, 982 traceMessage, displayId); 983 } 984 985 mDisplayStates.setValueAt(index, state); 986 brightnessPair.brightness = brightnessState; 987 brightnessPair.sdrBrightness = sdrBrightnessState; 988 // TODO(b/297503094) Preventing disabled display from being turned on should happen 989 // elsewhere. 990 LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 991 if (!display.isEnabledLocked() && state != Display.STATE_OFF) { 992 // If the display is disabled, any request other than turning it off should fail. 993 return; 994 } 995 runnable = updateDisplayStateLocked(display.getPrimaryDisplayDeviceLocked()); 996 if (Trace.isTagEnabled(Trace.TRACE_TAG_POWER)) { 997 Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_POWER, 998 "requestDisplayStateInternal:" + displayId, displayId); 999 } 1000 } 1001 1002 // Setting the display power state can take hundreds of milliseconds 1003 // to complete so we defer the most expensive part of the work until 1004 // after we have exited the critical section to avoid blocking other 1005 // threads for a long time. 1006 if (runnable != null) { 1007 runnable.run(); 1008 } 1009 } 1010 1011 private class UidImportanceListener implements ActivityManager.OnUidImportanceListener { 1012 @Override 1013 public void onUidImportance(int uid, int importance) { 1014 synchronized (mPendingCallbackSelfLocked) { 1015 if (importance >= IMPORTANCE_GONE) { 1016 // Clean up as the app is already gone 1017 Slog.d(TAG, "Drop pending events for gone uid " + uid); 1018 mPendingCallbackSelfLocked.delete(uid); 1019 return; 1020 } else if (importance >= IMPORTANCE_CACHED) { 1021 // Nothing to do as the app is still in cached mode 1022 return; 1023 } 1024 1025 // Do we care about this uid? 1026 SparseArray<PendingCallback> pendingCallbacks = mPendingCallbackSelfLocked.get(uid); 1027 if (pendingCallbacks == null) { 1028 return; 1029 } 1030 1031 // Send the pending events out when a certain uid becomes non-cached 1032 if (DEBUG) { 1033 Slog.d(TAG, "Uid " + uid + " becomes " + importance); 1034 } 1035 for (int i = 0; i < pendingCallbacks.size(); i++) { 1036 PendingCallback pendingCallback = pendingCallbacks.valueAt(i); 1037 if (pendingCallback != null) { 1038 pendingCallback.sendPendingDisplayEvent(); 1039 } 1040 } 1041 mPendingCallbackSelfLocked.delete(uid); 1042 } 1043 } 1044 } 1045 1046 private class SettingsObserver extends ContentObserver { SettingsObserver()1047 SettingsObserver() { 1048 super(mHandler); 1049 1050 mContext.getContentResolver().registerContentObserver( 1051 Settings.Secure.getUriFor( 1052 Settings.Secure.MINIMAL_POST_PROCESSING_ALLOWED), false, this); 1053 } 1054 1055 @Override onChange(boolean selfChange, Uri uri)1056 public void onChange(boolean selfChange, Uri uri) { 1057 handleSettingsChange(); 1058 } 1059 } 1060 handleSettingsChange()1061 private void handleSettingsChange() { 1062 synchronized (mSyncRoot) { 1063 updateSettingsLocked(); 1064 scheduleTraversalLocked(false); 1065 } 1066 } 1067 updateSettingsLocked()1068 private void updateSettingsLocked() { 1069 setMinimalPostProcessingAllowed(Settings.Secure.getIntForUser( 1070 mContext.getContentResolver(), Settings.Secure.MINIMAL_POST_PROCESSING_ALLOWED, 1071 1, UserHandle.USER_CURRENT) != 0); 1072 } 1073 restoreResolutionFromBackup()1074 private void restoreResolutionFromBackup() { 1075 int savedMode = Settings.Secure.getIntForUser(mContext.getContentResolver(), 1076 Settings.Secure.SCREEN_RESOLUTION_MODE, 1077 RESOLUTION_MODE_UNKNOWN, UserHandle.USER_CURRENT); 1078 if (savedMode == RESOLUTION_MODE_UNKNOWN) { 1079 // Nothing to restore. 1080 return; 1081 } 1082 1083 synchronized (mSyncRoot) { 1084 LogicalDisplay display = 1085 mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY); 1086 DisplayDevice device = display == null ? null : display.getPrimaryDisplayDeviceLocked(); 1087 if (device == null) { 1088 Slog.w(TAG, "No default display device present to restore resolution mode"); 1089 return; 1090 } 1091 1092 Point[] supportedRes = device.getSupportedResolutionsLocked(); 1093 if (supportedRes.length != 2) { 1094 if (DEBUG) { 1095 Slog.d(TAG, "Skipping resolution restore - " + supportedRes.length); 1096 } 1097 return; 1098 } 1099 1100 // We follow the same logic as Settings but in reverse. If the display supports 2 1101 // resolutions, we treat the small (index=0) one as HIGH and the larger (index=1) 1102 // one as FULL and restore the correct resolution accordingly. 1103 int index = savedMode == RESOLUTION_MODE_HIGH ? 0 : 1; 1104 Point res = supportedRes[index]; 1105 Display.Mode newMode = new Display.Mode(res.x, res.y, /*refreshRate=*/ 0); 1106 Slog.i(TAG, "Restoring resolution from backup: (" + savedMode + ") " 1107 + res.x + "x" + res.y); 1108 setUserPreferredDisplayModeInternal(Display.DEFAULT_DISPLAY, newMode); 1109 } 1110 } 1111 updateUserDisabledHdrTypesFromSettingsLocked()1112 private void updateUserDisabledHdrTypesFromSettingsLocked() { 1113 mAreUserDisabledHdrTypesAllowed = (Settings.Global.getInt( 1114 mContext.getContentResolver(), 1115 Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED, 1116 1) != 0); 1117 1118 String userDisabledHdrTypes = Settings.Global.getString(mContext.getContentResolver(), 1119 Settings.Global.USER_DISABLED_HDR_FORMATS); 1120 1121 if (userDisabledHdrTypes != null) { 1122 try { 1123 String[] userDisabledHdrTypeStrings = 1124 TextUtils.split(userDisabledHdrTypes, ","); 1125 mUserDisabledHdrTypes = new int[userDisabledHdrTypeStrings.length]; 1126 for (int i = 0; i < userDisabledHdrTypeStrings.length; i++) { 1127 mUserDisabledHdrTypes[i] = Integer.parseInt(userDisabledHdrTypeStrings[i]); 1128 } 1129 1130 if (!mAreUserDisabledHdrTypesAllowed) { 1131 mLogicalDisplayMapper.forEachLocked( 1132 display -> { 1133 display.setUserDisabledHdrTypes(mUserDisabledHdrTypes); 1134 handleLogicalDisplayChangedLocked(display); 1135 }); 1136 } 1137 1138 } catch (NumberFormatException e) { 1139 Slog.e(TAG, "Failed to parse USER_DISABLED_HDR_FORMATS. " 1140 + "Clearing the setting.", e); 1141 clearUserDisabledHdrTypesLocked(); 1142 } 1143 } else { 1144 clearUserDisabledHdrTypesLocked(); 1145 } 1146 } 1147 clearUserDisabledHdrTypesLocked()1148 private void clearUserDisabledHdrTypesLocked() { 1149 synchronized (mSyncRoot) { 1150 mUserDisabledHdrTypes = new int[]{}; 1151 Settings.Global.putString(mContext.getContentResolver(), 1152 Settings.Global.USER_DISABLED_HDR_FORMATS, ""); 1153 } 1154 } 1155 updateUserPreferredDisplayModeSettingsLocked()1156 private void updateUserPreferredDisplayModeSettingsLocked() { 1157 final float refreshRate = Settings.Global.getFloat(mContext.getContentResolver(), 1158 Settings.Global.USER_PREFERRED_REFRESH_RATE, Display.INVALID_DISPLAY_REFRESH_RATE); 1159 final int height = Settings.Global.getInt(mContext.getContentResolver(), 1160 Settings.Global.USER_PREFERRED_RESOLUTION_HEIGHT, Display.INVALID_DISPLAY_HEIGHT); 1161 final int width = Settings.Global.getInt(mContext.getContentResolver(), 1162 Settings.Global.USER_PREFERRED_RESOLUTION_WIDTH, Display.INVALID_DISPLAY_WIDTH); 1163 Display.Mode mode = new Display.Mode(width, height, refreshRate); 1164 mUserPreferredMode = isResolutionAndRefreshRateValid(mode) ? mode : null; 1165 if (mUserPreferredMode != null) { 1166 mDisplayDeviceRepo.forEachLocked((DisplayDevice device) -> { 1167 device.setUserPreferredDisplayModeLocked(mode); 1168 }); 1169 } else { 1170 mLogicalDisplayMapper.forEachLocked(this::configurePreferredDisplayModeLocked); 1171 } 1172 } 1173 getDisplayInfoForFrameRateOverride(DisplayEventReceiver.FrameRateOverride[] frameRateOverrides, DisplayInfo info, int callingUid)1174 private DisplayInfo getDisplayInfoForFrameRateOverride(DisplayEventReceiver.FrameRateOverride[] 1175 frameRateOverrides, DisplayInfo info, int callingUid) { 1176 float frameRateHz = info.renderFrameRate; 1177 for (DisplayEventReceiver.FrameRateOverride frameRateOverride : frameRateOverrides) { 1178 if (frameRateOverride.uid == callingUid) { 1179 frameRateHz = frameRateOverride.frameRateHz; 1180 break; 1181 } 1182 } 1183 1184 if (frameRateHz == 0) { 1185 return info; 1186 } 1187 1188 // For non-apps users we always return the physical refresh rate from display mode 1189 boolean displayModeReturnsPhysicalRefreshRate = 1190 callingUid < FIRST_APPLICATION_UID 1191 || CompatChanges.isChangeEnabled( 1192 DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE, callingUid); 1193 1194 // Override the refresh rate only if it is a divisor of the current 1195 // refresh rate. This calculation needs to be in sync with the native code 1196 // in RefreshRateSelector::getFrameRateDivisor 1197 Display.Mode currentMode = info.getMode(); 1198 float numPeriods = currentMode.getRefreshRate() / frameRateHz; 1199 float numPeriodsRound = Math.round(numPeriods); 1200 if (Math.abs(numPeriods - numPeriodsRound) > THRESHOLD_FOR_REFRESH_RATES_DIVISORS) { 1201 return info; 1202 } 1203 frameRateHz = currentMode.getRefreshRate() / numPeriodsRound; 1204 1205 DisplayInfo overriddenInfo = new DisplayInfo(); 1206 overriddenInfo.copyFrom(info); 1207 for (Display.Mode mode : info.supportedModes) { 1208 if (!mode.equalsExceptRefreshRate(currentMode)) { 1209 continue; 1210 } 1211 1212 if (mode.getRefreshRate() >= frameRateHz - THRESHOLD_FOR_REFRESH_RATES_DIVISORS 1213 && mode.getRefreshRate() 1214 <= frameRateHz + THRESHOLD_FOR_REFRESH_RATES_DIVISORS) { 1215 if (DEBUG) { 1216 Slog.d(TAG, "found matching modeId " + mode.getModeId()); 1217 } 1218 overriddenInfo.refreshRateOverride = mode.getRefreshRate(); 1219 1220 if (!displayModeReturnsPhysicalRefreshRate) { 1221 overriddenInfo.modeId = mode.getModeId(); 1222 } 1223 return overriddenInfo; 1224 } 1225 } 1226 1227 overriddenInfo.refreshRateOverride = frameRateHz; 1228 if (!displayModeReturnsPhysicalRefreshRate) { 1229 overriddenInfo.supportedModes = Arrays.copyOf(info.supportedModes, 1230 info.supportedModes.length + 1); 1231 overriddenInfo.supportedModes[overriddenInfo.supportedModes.length - 1] = 1232 new Display.Mode(Display.DISPLAY_MODE_ID_FOR_FRAME_RATE_OVERRIDE, 1233 currentMode.getPhysicalWidth(), currentMode.getPhysicalHeight(), 1234 overriddenInfo.refreshRateOverride, 1235 currentMode.getVsyncRate(), 1236 new float[0], currentMode.getSupportedHdrTypes()); 1237 overriddenInfo.modeId = 1238 overriddenInfo.supportedModes[overriddenInfo.supportedModes.length - 1] 1239 .getModeId(); 1240 } 1241 return overriddenInfo; 1242 } 1243 getDisplayInfoInternal(int displayId, int callingUid)1244 private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) { 1245 synchronized (mSyncRoot) { 1246 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 1247 if (display != null) { 1248 final DisplayInfo info = 1249 getDisplayInfoForFrameRateOverride(display.getFrameRateOverrides(), 1250 display.getDisplayInfoLocked(), callingUid); 1251 if (info.hasAccess(callingUid) 1252 || isUidPresentOnDisplayInternal(callingUid, displayId)) { 1253 return info; 1254 } 1255 } 1256 return null; 1257 } 1258 } 1259 registerCallbackInternal(IDisplayManagerCallback callback, int callingPid, int callingUid, @EventsMask long eventsMask)1260 private void registerCallbackInternal(IDisplayManagerCallback callback, int callingPid, 1261 int callingUid, @EventsMask long eventsMask) { 1262 synchronized (mSyncRoot) { 1263 CallbackRecord record = mCallbacks.get(callingPid); 1264 1265 if (record != null) { 1266 record.updateEventsMask(eventsMask); 1267 return; 1268 } 1269 1270 record = new CallbackRecord(callingPid, callingUid, callback, eventsMask); 1271 try { 1272 IBinder binder = callback.asBinder(); 1273 binder.linkToDeath(record, 0); 1274 } catch (RemoteException ex) { 1275 // give up 1276 throw new RuntimeException(ex); 1277 } 1278 1279 mCallbacks.put(callingPid, record); 1280 } 1281 } 1282 onCallbackDied(CallbackRecord record)1283 private void onCallbackDied(CallbackRecord record) { 1284 synchronized (mSyncRoot) { 1285 mCallbacks.remove(record.mPid); 1286 stopWifiDisplayScanLocked(record); 1287 } 1288 } 1289 startWifiDisplayScanInternal(int callingPid)1290 private void startWifiDisplayScanInternal(int callingPid) { 1291 synchronized (mSyncRoot) { 1292 CallbackRecord record = mCallbacks.get(callingPid); 1293 if (record == null) { 1294 throw new IllegalStateException("The calling process has not " 1295 + "registered an IDisplayManagerCallback."); 1296 } 1297 startWifiDisplayScanLocked(record); 1298 } 1299 } 1300 startWifiDisplayScanLocked(CallbackRecord record)1301 private void startWifiDisplayScanLocked(CallbackRecord record) { 1302 if (!record.mWifiDisplayScanRequested) { 1303 record.mWifiDisplayScanRequested = true; 1304 if (mWifiDisplayScanRequestCount++ == 0) { 1305 if (mWifiDisplayAdapter != null) { 1306 mWifiDisplayAdapter.requestStartScanLocked(); 1307 } 1308 } 1309 } 1310 } 1311 stopWifiDisplayScanInternal(int callingPid)1312 private void stopWifiDisplayScanInternal(int callingPid) { 1313 synchronized (mSyncRoot) { 1314 CallbackRecord record = mCallbacks.get(callingPid); 1315 if (record == null) { 1316 throw new IllegalStateException("The calling process has not " 1317 + "registered an IDisplayManagerCallback."); 1318 } 1319 stopWifiDisplayScanLocked(record); 1320 } 1321 } 1322 stopWifiDisplayScanLocked(CallbackRecord record)1323 private void stopWifiDisplayScanLocked(CallbackRecord record) { 1324 if (record.mWifiDisplayScanRequested) { 1325 record.mWifiDisplayScanRequested = false; 1326 if (--mWifiDisplayScanRequestCount == 0) { 1327 if (mWifiDisplayAdapter != null) { 1328 mWifiDisplayAdapter.requestStopScanLocked(); 1329 } 1330 } else if (mWifiDisplayScanRequestCount < 0) { 1331 Slog.wtf(TAG, "mWifiDisplayScanRequestCount became negative: " 1332 + mWifiDisplayScanRequestCount); 1333 mWifiDisplayScanRequestCount = 0; 1334 } 1335 } 1336 } 1337 connectWifiDisplayInternal(String address)1338 private void connectWifiDisplayInternal(String address) { 1339 synchronized (mSyncRoot) { 1340 if (mWifiDisplayAdapter != null) { 1341 mWifiDisplayAdapter.requestConnectLocked(address); 1342 } 1343 } 1344 } 1345 pauseWifiDisplayInternal()1346 private void pauseWifiDisplayInternal() { 1347 synchronized (mSyncRoot) { 1348 if (mWifiDisplayAdapter != null) { 1349 mWifiDisplayAdapter.requestPauseLocked(); 1350 } 1351 } 1352 } 1353 resumeWifiDisplayInternal()1354 private void resumeWifiDisplayInternal() { 1355 synchronized (mSyncRoot) { 1356 if (mWifiDisplayAdapter != null) { 1357 mWifiDisplayAdapter.requestResumeLocked(); 1358 } 1359 } 1360 } 1361 disconnectWifiDisplayInternal()1362 private void disconnectWifiDisplayInternal() { 1363 synchronized (mSyncRoot) { 1364 if (mWifiDisplayAdapter != null) { 1365 mWifiDisplayAdapter.requestDisconnectLocked(); 1366 } 1367 } 1368 } 1369 renameWifiDisplayInternal(String address, String alias)1370 private void renameWifiDisplayInternal(String address, String alias) { 1371 synchronized (mSyncRoot) { 1372 if (mWifiDisplayAdapter != null) { 1373 mWifiDisplayAdapter.requestRenameLocked(address, alias); 1374 } 1375 } 1376 } 1377 forgetWifiDisplayInternal(String address)1378 private void forgetWifiDisplayInternal(String address) { 1379 synchronized (mSyncRoot) { 1380 if (mWifiDisplayAdapter != null) { 1381 mWifiDisplayAdapter.requestForgetLocked(address); 1382 } 1383 } 1384 } 1385 getWifiDisplayStatusInternal()1386 private WifiDisplayStatus getWifiDisplayStatusInternal() { 1387 synchronized (mSyncRoot) { 1388 if (mWifiDisplayAdapter != null) { 1389 return mWifiDisplayAdapter.getWifiDisplayStatusLocked(); 1390 } 1391 return new WifiDisplayStatus(); 1392 } 1393 } 1394 setUserDisabledHdrTypesInternal(int[] userDisabledHdrTypes)1395 private void setUserDisabledHdrTypesInternal(int[] userDisabledHdrTypes) { 1396 synchronized (mSyncRoot) { 1397 if (userDisabledHdrTypes == null) { 1398 Slog.e(TAG, "Null is not an expected argument to " 1399 + "setUserDisabledHdrTypesInternal"); 1400 return; 1401 } 1402 1403 // Verify if userDisabledHdrTypes contains expected HDR types 1404 if (!isSubsetOf(Display.HdrCapabilities.HDR_TYPES, userDisabledHdrTypes)) { 1405 Slog.e(TAG, "userDisabledHdrTypes contains unexpected types"); 1406 return; 1407 } 1408 1409 Arrays.sort(userDisabledHdrTypes); 1410 if (Arrays.equals(mUserDisabledHdrTypes, userDisabledHdrTypes)) { 1411 return; 1412 } 1413 String userDisabledFormatsString = ""; 1414 if (userDisabledHdrTypes.length != 0) { 1415 userDisabledFormatsString = TextUtils.join(",", 1416 Arrays.stream(userDisabledHdrTypes).boxed().toArray()); 1417 } 1418 Settings.Global.putString(mContext.getContentResolver(), 1419 Settings.Global.USER_DISABLED_HDR_FORMATS, userDisabledFormatsString); 1420 mUserDisabledHdrTypes = userDisabledHdrTypes; 1421 if (!mAreUserDisabledHdrTypesAllowed) { 1422 mLogicalDisplayMapper.forEachLocked( 1423 display -> { 1424 display.setUserDisabledHdrTypes(userDisabledHdrTypes); 1425 handleLogicalDisplayChangedLocked(display); 1426 }); 1427 } 1428 } 1429 } 1430 isSubsetOf(int[] sortedSuperset, int[] subset)1431 private boolean isSubsetOf(int[] sortedSuperset, int[] subset) { 1432 for (int i : subset) { 1433 if (Arrays.binarySearch(sortedSuperset, i) < 0) { 1434 return false; 1435 } 1436 } 1437 return true; 1438 } 1439 setAreUserDisabledHdrTypesAllowedInternal( boolean areUserDisabledHdrTypesAllowed)1440 private void setAreUserDisabledHdrTypesAllowedInternal( 1441 boolean areUserDisabledHdrTypesAllowed) { 1442 synchronized (mSyncRoot) { 1443 if (mAreUserDisabledHdrTypesAllowed == areUserDisabledHdrTypesAllowed) { 1444 return; 1445 } 1446 mAreUserDisabledHdrTypesAllowed = areUserDisabledHdrTypesAllowed; 1447 if (mUserDisabledHdrTypes.length == 0) { 1448 return; 1449 } 1450 Settings.Global.putInt(mContext.getContentResolver(), 1451 Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED, 1452 areUserDisabledHdrTypesAllowed ? 1 : 0); 1453 int userDisabledHdrTypes[] = {}; 1454 if (!mAreUserDisabledHdrTypesAllowed) { 1455 userDisabledHdrTypes = mUserDisabledHdrTypes; 1456 } 1457 int[] finalUserDisabledHdrTypes = userDisabledHdrTypes; 1458 mLogicalDisplayMapper.forEachLocked( 1459 display -> { 1460 display.setUserDisabledHdrTypes(finalUserDisabledHdrTypes); 1461 handleLogicalDisplayChangedLocked(display); 1462 }); 1463 } 1464 } 1465 requestColorModeInternal(int displayId, int colorMode)1466 private void requestColorModeInternal(int displayId, int colorMode) { 1467 synchronized (mSyncRoot) { 1468 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 1469 if (display != null && 1470 display.getRequestedColorModeLocked() != colorMode) { 1471 display.setRequestedColorModeLocked(colorMode); 1472 scheduleTraversalLocked(false); 1473 } 1474 } 1475 } 1476 validatePackageName(int uid, String packageName)1477 private boolean validatePackageName(int uid, String packageName) { 1478 // Root doesn't have a package name. 1479 if (uid == ROOT_UID) { 1480 return true; 1481 } 1482 if (packageName != null) { 1483 String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid); 1484 if (packageNames != null) { 1485 for (String n : packageNames) { 1486 if (n.equals(packageName)) { 1487 return true; 1488 } 1489 } 1490 } 1491 } 1492 return false; 1493 } 1494 canProjectVideo(IMediaProjection projection)1495 private boolean canProjectVideo(IMediaProjection projection) { 1496 if (projection != null) { 1497 try { 1498 if (projection.canProjectVideo()) { 1499 return true; 1500 } 1501 } catch (RemoteException e) { 1502 Slog.e(TAG, "Unable to query projection service for permissions", e); 1503 } 1504 } 1505 if (checkCallingPermission(CAPTURE_VIDEO_OUTPUT, "canProjectVideo()")) { 1506 return true; 1507 } 1508 return canProjectSecureVideo(projection); 1509 } 1510 canProjectSecureVideo(IMediaProjection projection)1511 private boolean canProjectSecureVideo(IMediaProjection projection) { 1512 if (projection != null) { 1513 try { 1514 if (projection.canProjectSecureVideo()) { 1515 return true; 1516 } 1517 } catch (RemoteException e) { 1518 Slog.e(TAG, "Unable to query projection service for permissions", e); 1519 } 1520 } 1521 return checkCallingPermission(CAPTURE_SECURE_VIDEO_OUTPUT, "canProjectSecureVideo()"); 1522 } 1523 checkCallingPermission(String permission, String func)1524 private boolean checkCallingPermission(String permission, String func) { 1525 if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) { 1526 return true; 1527 } 1528 final String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid() 1529 + ", uid=" + Binder.getCallingUid() + " requires " + permission; 1530 Slog.w(TAG, msg); 1531 return false; 1532 } 1533 createVirtualDisplayInternal(VirtualDisplayConfig virtualDisplayConfig, IVirtualDisplayCallback callback, IMediaProjection projection, IVirtualDevice virtualDevice, DisplayWindowPolicyController dwpc, String packageName)1534 private int createVirtualDisplayInternal(VirtualDisplayConfig virtualDisplayConfig, 1535 IVirtualDisplayCallback callback, IMediaProjection projection, 1536 IVirtualDevice virtualDevice, DisplayWindowPolicyController dwpc, String packageName) { 1537 final int callingUid = Binder.getCallingUid(); 1538 if (!validatePackageName(callingUid, packageName)) { 1539 throw new SecurityException("packageName must match the calling uid"); 1540 } 1541 if (callback == null) { 1542 throw new IllegalArgumentException("appToken must not be null"); 1543 } 1544 if (virtualDisplayConfig == null) { 1545 throw new IllegalArgumentException("virtualDisplayConfig must not be null"); 1546 } 1547 final Surface surface = virtualDisplayConfig.getSurface(); 1548 int flags = virtualDisplayConfig.getFlags(); 1549 if (virtualDevice != null) { 1550 final VirtualDeviceManager vdm = mContext.getSystemService(VirtualDeviceManager.class); 1551 try { 1552 if (!vdm.isValidVirtualDeviceId(virtualDevice.getDeviceId())) { 1553 throw new SecurityException("Invalid virtual device"); 1554 } 1555 } catch (RemoteException ex) { 1556 throw new SecurityException("Unable to validate virtual device"); 1557 } 1558 final VirtualDeviceManagerInternal localVdm = 1559 getLocalService(VirtualDeviceManagerInternal.class); 1560 flags |= localVdm.getBaseVirtualDisplayFlags(virtualDevice); 1561 } 1562 1563 if (surface != null && surface.isSingleBuffered()) { 1564 throw new IllegalArgumentException("Surface can't be single-buffered"); 1565 } 1566 1567 if ((flags & VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) { 1568 flags |= VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; 1569 1570 // Public displays can't be allowed to show content when locked. 1571 if ((flags & VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) { 1572 throw new IllegalArgumentException( 1573 "Public display must not be marked as SHOW_WHEN_LOCKED_INSECURE"); 1574 } 1575 } 1576 if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) { 1577 flags &= ~VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; 1578 } 1579 if ((flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) { 1580 flags &= ~VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP; 1581 } 1582 // Put the display in the virtual device's display group only if it's not a mirror display, 1583 // and if it doesn't need its own display group. So effectively, mirror displays go into the 1584 // default display group. 1585 if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP) == 0 1586 && (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) == 0 1587 && virtualDevice != null) { 1588 flags |= VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP; 1589 } 1590 1591 // Check if the host app is attempting to reuse the token or capture again on the same 1592 // MediaProjection instance. Don't start recording if so; MediaProjectionManagerService 1593 // decides how to respond based on the target SDK. 1594 boolean waitForPermissionConsent = false; 1595 final long firstToken = Binder.clearCallingIdentity(); 1596 try { 1597 if (projection != null) { 1598 if (!getProjectionService().isCurrentProjection(projection)) { 1599 throw new SecurityException("Cannot create VirtualDisplay with " 1600 + "non-current MediaProjection"); 1601 } 1602 if (!projection.isValid()) { 1603 // Just log; MediaProjectionManagerService throws an exception. 1604 Slog.w(TAG, "Reusing token: create virtual display for app reusing token"); 1605 // If the exception wasn't thrown, we continue and re-show the permission dialog 1606 getProjectionService().requestConsentForInvalidProjection(projection); 1607 // Declare that mirroring shouldn't begin until user reviews the permission 1608 // dialog. 1609 waitForPermissionConsent = true; 1610 } 1611 flags = projection.applyVirtualDisplayFlags(flags); 1612 } 1613 } catch (RemoteException e) { 1614 throw new SecurityException("Unable to validate media projection or flags", e); 1615 } finally { 1616 Binder.restoreCallingIdentity(firstToken); 1617 } 1618 1619 if (callingUid != Process.SYSTEM_UID 1620 && (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) { 1621 // Only a valid media projection or a virtual device can create a mirror virtual 1622 // display. 1623 if (!canProjectVideo(projection) 1624 && !isMirroringSupportedByVirtualDevice(virtualDevice)) { 1625 throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or " 1626 + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate " 1627 + "MediaProjection token in order to create a screen sharing virtual " 1628 + "display. In order to create a virtual display that does not perform " 1629 + "screen sharing (mirroring), please use the flag " 1630 + "VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY."); 1631 } 1632 } 1633 if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0) { 1634 if (!canProjectSecureVideo(projection)) { 1635 throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT " 1636 + "or an appropriate MediaProjection token to create a " 1637 + "secure virtual display."); 1638 } 1639 } 1640 1641 if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0) { 1642 if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) { 1643 EventLog.writeEvent(0x534e4554, "162627132", callingUid, 1644 "Attempt to create a trusted display without holding permission!"); 1645 throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to " 1646 + "create a trusted virtual display."); 1647 } 1648 } 1649 1650 // Mirror virtual displays created by a virtual device are not allowed to show 1651 // presentations. 1652 if (virtualDevice != null && (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0 1653 && (flags & VIRTUAL_DISPLAY_FLAG_PRESENTATION) != 0) { 1654 Slog.d(TAG, "Mirror displays created by a virtual device cannot show " 1655 + "presentations, hence ignoring flag VIRTUAL_DISPLAY_FLAG_PRESENTATION."); 1656 flags &= ~VIRTUAL_DISPLAY_FLAG_PRESENTATION; 1657 } 1658 1659 if (callingUid != Process.SYSTEM_UID 1660 && (flags & VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP) != 0) { 1661 // The virtualDevice instance has been validated above using isValidVirtualDevice 1662 if (virtualDevice == null 1663 && !checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) { 1664 throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to " 1665 + "create a virtual display which is not in the default DisplayGroup."); 1666 } 1667 } 1668 1669 if ((flags & VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED) != 0) { 1670 if (callingUid != Process.SYSTEM_UID 1671 && !checkCallingPermission(ADD_ALWAYS_UNLOCKED_DISPLAY, 1672 "createVirtualDisplay()")) { 1673 throw new SecurityException( 1674 "Requires ADD_ALWAYS_UNLOCKED_DISPLAY permission to " 1675 + "create an always unlocked virtual display."); 1676 } 1677 } 1678 1679 if ((flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) == 0) { 1680 flags &= ~VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; 1681 } 1682 1683 // Sometimes users can have sensitive information in system decoration windows. An app 1684 // could create a virtual display with system decorations support and read the user info 1685 // from the surface. 1686 // We should only allow adding flag VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS 1687 // to trusted virtual displays. 1688 final int trustedDisplayWithSysDecorFlag = 1689 (VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS 1690 | VIRTUAL_DISPLAY_FLAG_TRUSTED); 1691 if ((flags & trustedDisplayWithSysDecorFlag) 1692 == VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS 1693 && !checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "createVirtualDisplay()")) { 1694 throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); 1695 } 1696 1697 final long secondToken = Binder.clearCallingIdentity(); 1698 try { 1699 final int displayId; 1700 final String displayUniqueId = VirtualDisplayAdapter.generateDisplayUniqueId( 1701 packageName, callingUid, virtualDisplayConfig); 1702 1703 if (virtualDisplayConfig.isHomeSupported()) { 1704 if ((flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) == 0) { 1705 Slog.w(TAG, "Display created with home support but lacks " 1706 + "VIRTUAL_DISPLAY_FLAG_TRUSTED, ignoring the home support request."); 1707 } else if ((flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) { 1708 Slog.w(TAG, "Display created with home support but has " 1709 + "VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, ignoring the home support " 1710 + "request."); 1711 } else { 1712 mWindowManagerInternal.setHomeSupportedOnDisplay(displayUniqueId, 1713 Display.TYPE_VIRTUAL, true); 1714 } 1715 } 1716 1717 synchronized (mSyncRoot) { 1718 displayId = 1719 createVirtualDisplayLocked( 1720 callback, 1721 projection, 1722 callingUid, 1723 packageName, 1724 displayUniqueId, 1725 virtualDevice, 1726 surface, 1727 flags, 1728 virtualDisplayConfig); 1729 if (displayId != Display.INVALID_DISPLAY && virtualDevice != null && dwpc != null) { 1730 mDisplayWindowPolicyControllers.put( 1731 displayId, Pair.create(virtualDevice, dwpc)); 1732 Slog.d(TAG, "Virtual Display: successfully created virtual display"); 1733 } 1734 } 1735 1736 if (displayId == Display.INVALID_DISPLAY && virtualDisplayConfig.isHomeSupported() 1737 && (flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0) { 1738 // Failed to create the virtual display, so we should clean up the WM settings 1739 // because it won't receive the onDisplayRemoved callback. 1740 mWindowManagerInternal.clearDisplaySettings(displayUniqueId, Display.TYPE_VIRTUAL); 1741 } 1742 1743 // Build a session describing the MediaProjection instance, if there is one. A session 1744 // for a VirtualDisplay or physical display mirroring is handled in DisplayContent. 1745 ContentRecordingSession session = null; 1746 try { 1747 if (projection != null) { 1748 IBinder taskWindowContainerToken = projection.getLaunchCookie() == null ? null 1749 : projection.getLaunchCookie().binder; 1750 int taskId = projection.getTaskId(); 1751 if (taskWindowContainerToken == null) { 1752 // Record a particular display. 1753 session = ContentRecordingSession.createDisplaySession( 1754 virtualDisplayConfig.getDisplayIdToMirror()); 1755 } else { 1756 // Record a single task indicated by the launch cookie. 1757 session = ContentRecordingSession.createTaskSession( 1758 taskWindowContainerToken, taskId); 1759 } 1760 } 1761 } catch (RemoteException e) { 1762 Slog.e(TAG, "Unable to retrieve the projection's launch cookie", e); 1763 } 1764 1765 // Ensure session details are only set when mirroring (through VirtualDisplay flags or 1766 // MediaProjection). 1767 final boolean shouldMirror = 1768 projection != null || (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0; 1769 // When calling WindowManagerService#setContentRecordingSession, WindowManagerService 1770 // attempts to acquire a lock before executing its main body. Due to this, we need 1771 // to be sure that it isn't called while the DisplayManagerService is also holding 1772 // a lock, to avoid a deadlock scenario. 1773 if (shouldMirror && displayId != Display.INVALID_DISPLAY && session != null) { 1774 // Only attempt to set content recording session if there are details to set and a 1775 // VirtualDisplay has been successfully constructed. 1776 session.setVirtualDisplayId(displayId); 1777 // Don't start mirroring until user re-grants consent. 1778 session.setWaitingForConsent(waitForPermissionConsent); 1779 1780 // We set the content recording session here on the server side instead of using 1781 // a second AIDL call in MediaProjection. By ensuring that a virtual display has 1782 // been constructed before calling setContentRecordingSession, we avoid a race 1783 // condition between the DisplayManagerService & WindowManagerService which could 1784 // lead to the MediaProjection being pre-emptively torn down. 1785 try { 1786 if (!getProjectionService().setContentRecordingSession(session, projection)) { 1787 // Unable to start mirroring, so release VirtualDisplay. Projection service 1788 // handles stopping the projection. 1789 Slog.w(TAG, "Content Recording: failed to start mirroring - " 1790 + "releasing virtual display " + displayId); 1791 releaseVirtualDisplayInternal(callback.asBinder()); 1792 return Display.INVALID_DISPLAY; 1793 } else if (projection != null) { 1794 // Indicate that this projection has been used to record, and can't be used 1795 // again. 1796 Slog.d(TAG, "Content Recording: notifying MediaProjection of successful" 1797 + " VirtualDisplay creation."); 1798 projection.notifyVirtualDisplayCreated(displayId); 1799 } 1800 } catch (RemoteException e) { 1801 Slog.e(TAG, "Unable to tell MediaProjectionManagerService to set the " 1802 + "content recording session", e); 1803 return displayId; 1804 } 1805 Slog.d(TAG, "Virtual Display: successfully set up virtual display " 1806 + displayId); 1807 } 1808 return displayId; 1809 } finally { 1810 Binder.restoreCallingIdentity(secondToken); 1811 } 1812 } 1813 createVirtualDisplayLocked( IVirtualDisplayCallback callback, IMediaProjection projection, int callingUid, String packageName, String uniqueId, IVirtualDevice virtualDevice, Surface surface, int flags, VirtualDisplayConfig virtualDisplayConfig)1814 private int createVirtualDisplayLocked( 1815 IVirtualDisplayCallback callback, 1816 IMediaProjection projection, 1817 int callingUid, 1818 String packageName, 1819 String uniqueId, 1820 IVirtualDevice virtualDevice, 1821 Surface surface, 1822 int flags, 1823 VirtualDisplayConfig virtualDisplayConfig) { 1824 if (mVirtualDisplayAdapter == null) { 1825 Slog.w( 1826 TAG, 1827 "Rejecting request to create private virtual display " 1828 + "because the virtual display adapter is not available."); 1829 return -1; 1830 } 1831 1832 Slog.d(TAG, "Virtual Display: creating DisplayDevice with VirtualDisplayAdapter"); 1833 DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked( 1834 callback, projection, callingUid, packageName, uniqueId, surface, flags, 1835 virtualDisplayConfig); 1836 if (device == null) { 1837 Slog.w(TAG, "Virtual Display: VirtualDisplayAdapter failed to create DisplayDevice"); 1838 return -1; 1839 } 1840 1841 // If the display is to be added to a device display group, we need to make the 1842 // LogicalDisplayMapper aware of the link between the new display and its associated virtual 1843 // device before triggering DISPLAY_DEVICE_EVENT_ADDED. 1844 if ((flags & VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP) != 0) { 1845 if (virtualDevice != null) { 1846 try { 1847 final int virtualDeviceId = virtualDevice.getDeviceId(); 1848 mLogicalDisplayMapper.associateDisplayDeviceWithVirtualDevice( 1849 device, virtualDeviceId); 1850 } catch (RemoteException e) { 1851 e.rethrowFromSystemServer(); 1852 } 1853 } else { 1854 Slog.i( 1855 TAG, 1856 "Display created with VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP set, but no" 1857 + " virtual device. The display will not be added to a device display" 1858 + " group."); 1859 } 1860 } 1861 1862 // DisplayDevice events are handled manually for Virtual Displays. 1863 // TODO: multi-display Fix this so that generic add/remove events are not handled in a 1864 // different code path for virtual displays. Currently this happens so that we can 1865 // return a valid display ID synchronously upon successful Virtual Display creation. 1866 // This code can run on any binder thread, while onDisplayDeviceAdded() callbacks are 1867 // called on the DisplayThread (which we don't want to wait for?). 1868 // One option would be to actually wait here on the binder thread 1869 // to be notified when the virtual display is created (or failed). 1870 mDisplayDeviceRepo.onDisplayDeviceEvent(device, DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED); 1871 1872 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device); 1873 if (display != null) { 1874 return display.getDisplayIdLocked(); 1875 } 1876 1877 // Something weird happened and the logical display was not created. 1878 Slog.w(TAG, "Rejecting request to create virtual display " 1879 + "because the logical display was not created."); 1880 mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder()); 1881 mDisplayDeviceRepo.onDisplayDeviceEvent(device, 1882 DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED); 1883 return -1; 1884 } 1885 isMirroringSupportedByVirtualDevice(IVirtualDevice virtualDevice)1886 private static boolean isMirroringSupportedByVirtualDevice(IVirtualDevice virtualDevice) { 1887 return Flags.interactiveScreenMirror() && virtualDevice != null; 1888 } 1889 resizeVirtualDisplayInternal(IBinder appToken, int width, int height, int densityDpi)1890 private void resizeVirtualDisplayInternal(IBinder appToken, 1891 int width, int height, int densityDpi) { 1892 synchronized (mSyncRoot) { 1893 if (mVirtualDisplayAdapter == null) { 1894 return; 1895 } 1896 1897 mVirtualDisplayAdapter.resizeVirtualDisplayLocked(appToken, width, height, densityDpi); 1898 } 1899 } 1900 setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface)1901 private void setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface) { 1902 synchronized (mSyncRoot) { 1903 if (mVirtualDisplayAdapter == null) { 1904 return; 1905 } 1906 1907 mVirtualDisplayAdapter.setVirtualDisplaySurfaceLocked(appToken, surface); 1908 } 1909 } 1910 releaseVirtualDisplayInternal(IBinder appToken)1911 private void releaseVirtualDisplayInternal(IBinder appToken) { 1912 synchronized (mSyncRoot) { 1913 if (mVirtualDisplayAdapter == null) { 1914 return; 1915 } 1916 1917 DisplayDevice device = 1918 mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken); 1919 Slog.d(TAG, "Virtual Display: Display Device released"); 1920 if (device != null) { 1921 // TODO: multi-display - handle virtual displays the same as other display adapters. 1922 mDisplayDeviceRepo.onDisplayDeviceEvent(device, 1923 DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED); 1924 } 1925 } 1926 } 1927 setVirtualDisplayStateInternal(IBinder appToken, boolean isOn)1928 private void setVirtualDisplayStateInternal(IBinder appToken, boolean isOn) { 1929 synchronized (mSyncRoot) { 1930 if (mVirtualDisplayAdapter == null) { 1931 return; 1932 } 1933 1934 mVirtualDisplayAdapter.setVirtualDisplayStateLocked(appToken, isOn); 1935 } 1936 } 1937 registerDefaultDisplayAdapters()1938 private void registerDefaultDisplayAdapters() { 1939 // Register default display adapters. 1940 synchronized (mSyncRoot) { 1941 // main display adapter 1942 registerDisplayAdapterLocked(mInjector.getLocalDisplayAdapter(mSyncRoot, mContext, 1943 mHandler, mDisplayDeviceRepo, mFlags, 1944 mDisplayNotificationManager)); 1945 1946 // Standalone VR devices rely on a virtual display as their primary display for 1947 // 2D UI. We register virtual display adapter along side the main display adapter 1948 // here so that it is ready by the time the system sends the home Intent for 1949 // early apps like SetupWizard/Launcher. In particular, SUW is displayed using 1950 // the virtual display inside VR before any VR-specific apps even run. 1951 mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext, 1952 mHandler, mDisplayDeviceRepo, mFlags); 1953 if (mVirtualDisplayAdapter != null) { 1954 registerDisplayAdapterLocked(mVirtualDisplayAdapter); 1955 } 1956 } 1957 } 1958 registerAdditionalDisplayAdapters()1959 private void registerAdditionalDisplayAdapters() { 1960 synchronized (mSyncRoot) { 1961 if (shouldRegisterNonEssentialDisplayAdaptersLocked()) { 1962 registerOverlayDisplayAdapterLocked(); 1963 registerWifiDisplayAdapterLocked(); 1964 } 1965 } 1966 } 1967 registerOverlayDisplayAdapterLocked()1968 private void registerOverlayDisplayAdapterLocked() { 1969 registerDisplayAdapterLocked(new OverlayDisplayAdapter( 1970 mSyncRoot, mContext, mHandler, mDisplayDeviceRepo, mUiHandler, mFlags)); 1971 } 1972 registerWifiDisplayAdapterLocked()1973 private void registerWifiDisplayAdapterLocked() { 1974 if (mContext.getResources().getBoolean( 1975 com.android.internal.R.bool.config_enableWifiDisplay) 1976 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) { 1977 mWifiDisplayAdapter = new WifiDisplayAdapter( 1978 mSyncRoot, mContext, mHandler, mDisplayDeviceRepo, 1979 mPersistentDataStore, mFlags); 1980 registerDisplayAdapterLocked(mWifiDisplayAdapter); 1981 } 1982 } 1983 shouldRegisterNonEssentialDisplayAdaptersLocked()1984 private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() { 1985 // In safe mode, we disable non-essential display adapters to give the user 1986 // an opportunity to fix broken settings or other problems that might affect 1987 // system stability. 1988 return !mSafeMode; 1989 } 1990 registerDisplayAdapterLocked(DisplayAdapter adapter)1991 private void registerDisplayAdapterLocked(DisplayAdapter adapter) { 1992 mDisplayAdapters.add(adapter); 1993 adapter.registerLocked(); 1994 } 1995 1996 @GuardedBy("mSyncRoot") handleLogicalDisplayDisconnectedLocked(LogicalDisplay display)1997 private void handleLogicalDisplayDisconnectedLocked(LogicalDisplay display) { 1998 if (!mFlags.isConnectedDisplayManagementEnabled()) { 1999 Slog.e(TAG, "DisplayDisconnected shouldn't be received when the flag is off"); 2000 return; 2001 } 2002 releaseDisplayAndEmitEvent(display, DisplayManagerGlobal.EVENT_DISPLAY_DISCONNECTED); 2003 mExternalDisplayPolicy.handleLogicalDisplayDisconnectedLocked(display); 2004 } 2005 2006 @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG) setupLogicalDisplay(LogicalDisplay display)2007 private void setupLogicalDisplay(LogicalDisplay display) { 2008 final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); 2009 final int displayId = display.getDisplayIdLocked(); 2010 final boolean isDefault = displayId == Display.DEFAULT_DISPLAY; 2011 configureColorModeLocked(display, device); 2012 if (!mAreUserDisabledHdrTypesAllowed) { 2013 display.setUserDisabledHdrTypes(mUserDisabledHdrTypes); 2014 } 2015 if (isDefault) { 2016 notifyDefaultDisplayDeviceUpdated(display); 2017 recordStableDisplayStatsIfNeededLocked(display); 2018 recordTopInsetLocked(display); 2019 } 2020 if (mUserPreferredMode != null) { 2021 device.setUserPreferredDisplayModeLocked(mUserPreferredMode); 2022 } else { 2023 configurePreferredDisplayModeLocked(display); 2024 } 2025 2026 DisplayPowerControllerInterface dpc = addDisplayPowerControllerLocked(display); 2027 if (dpc != null) { 2028 final int leadDisplayId = display.getLeadDisplayIdLocked(); 2029 updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId); 2030 2031 // Loop through all the displays and check if any should follow this one - it could be 2032 // that the follower display was added before the lead display. 2033 mLogicalDisplayMapper.forEachLocked(d -> { 2034 if (d.getLeadDisplayIdLocked() == displayId) { 2035 DisplayPowerControllerInterface followerDpc = 2036 mDisplayPowerControllers.get(d.getDisplayIdLocked()); 2037 if (followerDpc != null) { 2038 updateDisplayPowerControllerLeaderLocked(followerDpc, displayId); 2039 } 2040 } 2041 }); 2042 } 2043 2044 mDisplayStates.append(displayId, Display.STATE_UNKNOWN); 2045 2046 final float brightnessDefault = display.getDisplayInfoLocked().brightnessDefault; 2047 mDisplayBrightnesses.append(displayId, 2048 new BrightnessPair(brightnessDefault, brightnessDefault)); 2049 2050 DisplayManagerGlobal.invalidateLocalDisplayInfoCaches(); 2051 } 2052 updateLogicalDisplayState(LogicalDisplay display)2053 private void updateLogicalDisplayState(LogicalDisplay display) { 2054 Runnable work = updateDisplayStateLocked(display.getPrimaryDisplayDeviceLocked()); 2055 if (work != null) { 2056 work.run(); 2057 } 2058 scheduleTraversalLocked(false); 2059 } 2060 2061 @SuppressLint("AndroidFrameworkRequiresPermission") handleLogicalDisplayConnectedLocked(LogicalDisplay display)2062 private void handleLogicalDisplayConnectedLocked(LogicalDisplay display) { 2063 if (!mFlags.isConnectedDisplayManagementEnabled()) { 2064 Slog.e(TAG, "DisplayConnected shouldn't be received when the flag is off"); 2065 return; 2066 } 2067 2068 setupLogicalDisplay(display); 2069 2070 if (ExternalDisplayPolicy.isExternalDisplayLocked(display)) { 2071 mExternalDisplayPolicy.handleExternalDisplayConnectedLocked(display); 2072 } else { 2073 sendDisplayEventLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_CONNECTED); 2074 } 2075 2076 updateLogicalDisplayState(display); 2077 } 2078 2079 @SuppressLint("AndroidFrameworkRequiresPermission") handleLogicalDisplayAddedLocked(LogicalDisplay display)2080 private void handleLogicalDisplayAddedLocked(LogicalDisplay display) { 2081 final int displayId = display.getDisplayIdLocked(); 2082 final boolean isDefault = displayId == Display.DEFAULT_DISPLAY; 2083 if (!mFlags.isConnectedDisplayManagementEnabled()) { 2084 setupLogicalDisplay(display); 2085 } 2086 2087 // Wake up waitForDefaultDisplay. 2088 if (isDefault) { 2089 mSyncRoot.notifyAll(); 2090 } 2091 2092 sendDisplayEventIfEnabledLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_ADDED); 2093 2094 updateLogicalDisplayState(display); 2095 2096 mExternalDisplayPolicy.handleLogicalDisplayAddedLocked(display); 2097 } 2098 handleLogicalDisplayChangedLocked(@onNull LogicalDisplay display)2099 private void handleLogicalDisplayChangedLocked(@NonNull LogicalDisplay display) { 2100 updateViewportPowerStateLocked(display); 2101 2102 final int displayId = display.getDisplayIdLocked(); 2103 if (displayId == Display.DEFAULT_DISPLAY) { 2104 recordTopInsetLocked(display); 2105 } 2106 // We don't bother invalidating the display info caches here because any changes to the 2107 // display info will trigger a cache invalidation inside of LogicalDisplay before we hit 2108 // this point. 2109 sendDisplayEventIfEnabledLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); 2110 2111 applyDisplayChangedLocked(display); 2112 } 2113 applyDisplayChangedLocked(@onNull LogicalDisplay display)2114 private void applyDisplayChangedLocked(@NonNull LogicalDisplay display) { 2115 final int displayId = display.getDisplayIdLocked(); 2116 scheduleTraversalLocked(false); 2117 mPersistentDataStore.saveIfNeeded(); 2118 2119 DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId); 2120 if (dpc != null) { 2121 final int leadDisplayId = display.getLeadDisplayIdLocked(); 2122 updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId); 2123 2124 HighBrightnessModeMetadata hbmMetadata = 2125 mHighBrightnessModeMetadataMapper.getHighBrightnessModeMetadataLocked(display); 2126 if (hbmMetadata != null) { 2127 dpc.onDisplayChanged(hbmMetadata, leadDisplayId); 2128 } 2129 } 2130 } 2131 updateDisplayPowerControllerLeaderLocked( @onNull DisplayPowerControllerInterface dpc, int leadDisplayId)2132 private void updateDisplayPowerControllerLeaderLocked( 2133 @NonNull DisplayPowerControllerInterface dpc, int leadDisplayId) { 2134 if (dpc.getLeadDisplayId() == leadDisplayId) { 2135 // Lead display hasn't changed, nothing to do. 2136 return; 2137 } 2138 2139 // If it has changed, then we need to unregister from the previous leader if there was one. 2140 final int prevLeaderId = dpc.getLeadDisplayId(); 2141 if (prevLeaderId != Layout.NO_LEAD_DISPLAY) { 2142 final DisplayPowerControllerInterface prevLeader = 2143 mDisplayPowerControllers.get(prevLeaderId); 2144 if (prevLeader != null) { 2145 prevLeader.removeDisplayBrightnessFollower(dpc); 2146 } 2147 } 2148 2149 // And then, if it's following, register it with the new one. 2150 if (leadDisplayId != Layout.NO_LEAD_DISPLAY) { 2151 final DisplayPowerControllerInterface newLeader = 2152 mDisplayPowerControllers.get(leadDisplayId); 2153 if (newLeader != null) { 2154 newLeader.addDisplayBrightnessFollower(dpc); 2155 } 2156 } 2157 } 2158 handleLogicalDisplayFrameRateOverridesChangedLocked( @onNull LogicalDisplay display)2159 private void handleLogicalDisplayFrameRateOverridesChangedLocked( 2160 @NonNull LogicalDisplay display) { 2161 final int displayId = display.getDisplayIdLocked(); 2162 // We don't bother invalidating the display info caches here because any changes to the 2163 // display info will trigger a cache invalidation inside of LogicalDisplay before we hit 2164 // this point. 2165 sendDisplayEventFrameRateOverrideLocked(displayId); 2166 scheduleTraversalLocked(false); 2167 } 2168 handleLogicalDisplayRemovedLocked(@onNull LogicalDisplay display)2169 private void handleLogicalDisplayRemovedLocked(@NonNull LogicalDisplay display) { 2170 // With display management, the display is removed when disabled, and it might still exist. 2171 // Resources must only be released when the disconnected signal is received. 2172 if (mFlags.isConnectedDisplayManagementEnabled()) { 2173 if (display.isValidLocked()) { 2174 updateViewportPowerStateLocked(display); 2175 } 2176 2177 // Note: This method is only called if the display was enabled before being removed. 2178 sendDisplayEventLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED); 2179 2180 if (display.isValidLocked()) { 2181 applyDisplayChangedLocked(display); 2182 } 2183 return; 2184 } 2185 2186 releaseDisplayAndEmitEvent(display, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED); 2187 } 2188 releaseDisplayAndEmitEvent(LogicalDisplay display, int event)2189 private void releaseDisplayAndEmitEvent(LogicalDisplay display, int event) { 2190 final int displayId = display.getDisplayIdLocked(); 2191 2192 final DisplayPowerControllerInterface dpc = 2193 mDisplayPowerControllers.removeReturnOld(displayId); 2194 if (dpc != null) { 2195 updateDisplayPowerControllerLeaderLocked(dpc, Layout.NO_LEAD_DISPLAY); 2196 dpc.stop(); 2197 } 2198 mDisplayStates.delete(displayId); 2199 mDisplayBrightnesses.delete(displayId); 2200 DisplayManagerGlobal.invalidateLocalDisplayInfoCaches(); 2201 2202 if (mDisplayWindowPolicyControllers.contains(displayId)) { 2203 final IVirtualDevice virtualDevice = 2204 mDisplayWindowPolicyControllers.removeReturnOld(displayId).first; 2205 if (virtualDevice != null) { 2206 mHandler.post(() -> { 2207 getLocalService(VirtualDeviceManagerInternal.class) 2208 .onVirtualDisplayRemoved(virtualDevice, displayId); 2209 }); 2210 } 2211 } 2212 2213 sendDisplayEventLocked(display, event); 2214 scheduleTraversalLocked(false); 2215 } 2216 handleLogicalDisplaySwappedLocked(@onNull LogicalDisplay display)2217 private void handleLogicalDisplaySwappedLocked(@NonNull LogicalDisplay display) { 2218 handleLogicalDisplayChangedLocked(display); 2219 2220 final int displayId = display.getDisplayIdLocked(); 2221 if (displayId == Display.DEFAULT_DISPLAY) { 2222 notifyDefaultDisplayDeviceUpdated(display); 2223 } 2224 mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATIONS); 2225 } 2226 handleLogicalDisplayHdrSdrRatioChangedLocked(@onNull LogicalDisplay display)2227 private void handleLogicalDisplayHdrSdrRatioChangedLocked(@NonNull LogicalDisplay display) { 2228 sendDisplayEventIfEnabledLocked(display, 2229 DisplayManagerGlobal.EVENT_DISPLAY_HDR_SDR_RATIO_CHANGED); 2230 } 2231 notifyDefaultDisplayDeviceUpdated(LogicalDisplay display)2232 private void notifyDefaultDisplayDeviceUpdated(LogicalDisplay display) { 2233 mDisplayModeDirector.defaultDisplayDeviceUpdated(display.getPrimaryDisplayDeviceLocked() 2234 .mDisplayDeviceConfig); 2235 } 2236 handleLogicalDisplayDeviceStateTransitionLocked(@onNull LogicalDisplay display)2237 private void handleLogicalDisplayDeviceStateTransitionLocked(@NonNull LogicalDisplay display) { 2238 final int displayId = display.getDisplayIdLocked(); 2239 final DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId); 2240 if (dpc != null) { 2241 final int leadDisplayId = display.getLeadDisplayIdLocked(); 2242 updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId); 2243 2244 HighBrightnessModeMetadata hbmMetadata = 2245 mHighBrightnessModeMetadataMapper.getHighBrightnessModeMetadataLocked(display); 2246 if (hbmMetadata != null) { 2247 dpc.onDisplayChanged(hbmMetadata, leadDisplayId); 2248 } 2249 } 2250 } 2251 updateDisplayStateLocked(DisplayDevice device)2252 private Runnable updateDisplayStateLocked(DisplayDevice device) { 2253 // Blank or unblank the display immediately to match the state requested 2254 // by the display power controller (if known). 2255 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 2256 if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) { 2257 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device); 2258 if (display == null) { 2259 return null; 2260 } 2261 final int displayId = display.getDisplayIdLocked(); 2262 final int state = mDisplayStates.get(displayId); 2263 2264 // Only send a request for display state if display state has already been initialized. 2265 if (state != Display.STATE_UNKNOWN) { 2266 final BrightnessPair brightnessPair = mDisplayBrightnesses.get(displayId); 2267 return device.requestDisplayStateLocked( 2268 state, 2269 brightnessPair.brightness, 2270 brightnessPair.sdrBrightness, 2271 display.getDisplayOffloadSessionLocked()); 2272 } 2273 } 2274 return null; 2275 } 2276 configureColorModeLocked(LogicalDisplay display, DisplayDevice device)2277 private void configureColorModeLocked(LogicalDisplay display, DisplayDevice device) { 2278 if (display.getPrimaryDisplayDeviceLocked() == device) { 2279 int colorMode = mPersistentDataStore.getColorMode(device); 2280 if (colorMode == Display.COLOR_MODE_INVALID) { 2281 if (display.getDisplayIdLocked() == Display.DEFAULT_DISPLAY) { 2282 colorMode = mDefaultDisplayDefaultColorMode; 2283 } else { 2284 colorMode = Display.COLOR_MODE_DEFAULT; 2285 } 2286 } 2287 display.setRequestedColorModeLocked(colorMode); 2288 } 2289 } 2290 configurePreferredDisplayModeLocked(LogicalDisplay display)2291 private void configurePreferredDisplayModeLocked(LogicalDisplay display) { 2292 final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); 2293 final Point userPreferredResolution = 2294 mPersistentDataStore.getUserPreferredResolution(device); 2295 final float refreshRate = mPersistentDataStore.getUserPreferredRefreshRate(device); 2296 if (userPreferredResolution == null && Float.isNaN(refreshRate)) { 2297 return; 2298 } 2299 Display.Mode.Builder modeBuilder = new Display.Mode.Builder(); 2300 if (userPreferredResolution != null) { 2301 modeBuilder.setResolution(userPreferredResolution.x, userPreferredResolution.y); 2302 } 2303 if (!Float.isNaN(refreshRate)) { 2304 modeBuilder.setRefreshRate(refreshRate); 2305 } 2306 device.setUserPreferredDisplayModeLocked(modeBuilder.build()); 2307 } 2308 2309 @GuardedBy("mSyncRoot") storeHdrConversionModeLocked(HdrConversionMode hdrConversionMode)2310 private void storeHdrConversionModeLocked(HdrConversionMode hdrConversionMode) { 2311 Settings.Global.putInt(mContext.getContentResolver(), 2312 Settings.Global.HDR_CONVERSION_MODE, hdrConversionMode.getConversionMode()); 2313 final int preferredHdrOutputType = 2314 hdrConversionMode.getConversionMode() == HdrConversionMode.HDR_CONVERSION_FORCE 2315 ? hdrConversionMode.getPreferredHdrOutputType() 2316 : Display.HdrCapabilities.HDR_TYPE_INVALID; 2317 Settings.Global.putInt(mContext.getContentResolver(), 2318 Settings.Global.HDR_FORCE_CONVERSION_TYPE, preferredHdrOutputType); 2319 } 2320 2321 @GuardedBy("mSyncRoot") updateHdrConversionModeSettingsLocked()2322 void updateHdrConversionModeSettingsLocked() { 2323 final int conversionMode = Settings.Global.getInt(mContext.getContentResolver(), 2324 Settings.Global.HDR_CONVERSION_MODE, mDefaultHdrConversionMode); 2325 final int preferredHdrOutputType = conversionMode == HdrConversionMode.HDR_CONVERSION_FORCE 2326 ? Settings.Global.getInt(mContext.getContentResolver(), 2327 Settings.Global.HDR_FORCE_CONVERSION_TYPE, 2328 Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION) 2329 : Display.HdrCapabilities.HDR_TYPE_INVALID; 2330 mHdrConversionMode = new HdrConversionMode(conversionMode, preferredHdrOutputType); 2331 setHdrConversionModeInternal(mHdrConversionMode); 2332 } 2333 2334 // If we've never recorded stable device stats for this device before and they aren't 2335 // explicitly configured, go ahead and record the stable device stats now based on the status 2336 // of the default display at first boot. recordStableDisplayStatsIfNeededLocked(LogicalDisplay d)2337 private void recordStableDisplayStatsIfNeededLocked(LogicalDisplay d) { 2338 if (mStableDisplaySize.x <= 0 && mStableDisplaySize.y <= 0) { 2339 DisplayInfo info = d.getDisplayInfoLocked(); 2340 setStableDisplaySizeLocked(info.getNaturalWidth(), info.getNaturalHeight()); 2341 } 2342 } 2343 recordTopInsetLocked(@ullable LogicalDisplay d)2344 private void recordTopInsetLocked(@Nullable LogicalDisplay d) { 2345 // We must only persist the inset after boot has completed, otherwise we will end up 2346 // overwriting the persisted value before the masking flag has been loaded from the 2347 // resource overlay. 2348 if (!mSystemReady || d == null) { 2349 return; 2350 } 2351 int topInset = d.getInsets().top; 2352 if (topInset == mDefaultDisplayTopInset) { 2353 return; 2354 } 2355 mDefaultDisplayTopInset = topInset; 2356 SystemProperties.set(PROP_DEFAULT_DISPLAY_TOP_INSET, Integer.toString(topInset)); 2357 } 2358 setStableDisplaySizeLocked(int width, int height)2359 private void setStableDisplaySizeLocked(int width, int height) { 2360 mStableDisplaySize = new Point(width, height); 2361 try { 2362 mPersistentDataStore.setStableDisplaySize(mStableDisplaySize); 2363 } finally { 2364 mPersistentDataStore.saveIfNeeded(); 2365 } 2366 } 2367 2368 @VisibleForTesting getMinimumBrightnessCurveInternal()2369 Curve getMinimumBrightnessCurveInternal() { 2370 return mMinimumBrightnessCurve; 2371 } 2372 getPreferredWideGamutColorSpaceIdInternal()2373 int getPreferredWideGamutColorSpaceIdInternal() { 2374 return mWideColorSpace.getId(); 2375 } 2376 getOverlaySupportInternal()2377 OverlayProperties getOverlaySupportInternal() { 2378 return mOverlayProperties; 2379 } 2380 setUserPreferredDisplayModeInternal(int displayId, Display.Mode mode)2381 void setUserPreferredDisplayModeInternal(int displayId, Display.Mode mode) { 2382 synchronized (mSyncRoot) { 2383 if (mode != null && !isResolutionAndRefreshRateValid(mode) 2384 && displayId == Display.INVALID_DISPLAY) { 2385 throw new IllegalArgumentException("width, height and refresh rate of mode should " 2386 + "be greater than 0 when setting the global user preferred display mode."); 2387 } 2388 2389 final int resolutionHeight = mode == null ? Display.INVALID_DISPLAY_HEIGHT 2390 : mode.getPhysicalHeight(); 2391 final int resolutionWidth = mode == null ? Display.INVALID_DISPLAY_WIDTH 2392 : mode.getPhysicalWidth(); 2393 final float refreshRate = mode == null ? Display.INVALID_DISPLAY_REFRESH_RATE 2394 : mode.getRefreshRate(); 2395 2396 storeModeInPersistentDataStoreLocked( 2397 displayId, resolutionWidth, resolutionHeight, refreshRate); 2398 if (displayId != Display.INVALID_DISPLAY) { 2399 setUserPreferredModeForDisplayLocked(displayId, mode); 2400 } else { 2401 mUserPreferredMode = mode; 2402 storeModeInGlobalSettingsLocked( 2403 resolutionWidth, resolutionHeight, refreshRate, mode); 2404 } 2405 } 2406 } 2407 storeModeInPersistentDataStoreLocked(int displayId, int resolutionWidth, int resolutionHeight, float refreshRate)2408 private void storeModeInPersistentDataStoreLocked(int displayId, int resolutionWidth, 2409 int resolutionHeight, float refreshRate) { 2410 DisplayDevice displayDevice = getDeviceForDisplayLocked(displayId); 2411 if (displayDevice == null) { 2412 return; 2413 } 2414 try { 2415 mPersistentDataStore.setUserPreferredResolution( 2416 displayDevice, resolutionWidth, resolutionHeight); 2417 mPersistentDataStore.setUserPreferredRefreshRate(displayDevice, refreshRate); 2418 } finally { 2419 mPersistentDataStore.saveIfNeeded(); 2420 } 2421 } 2422 setUserPreferredModeForDisplayLocked(int displayId, Display.Mode mode)2423 private void setUserPreferredModeForDisplayLocked(int displayId, Display.Mode mode) { 2424 DisplayDevice displayDevice = getDeviceForDisplayLocked(displayId); 2425 if (displayDevice == null) { 2426 return; 2427 } 2428 2429 // We do not yet support backup and restore for our PersistentDataStore, however, we want to 2430 // preserve the user's choice for HIGH/FULL resolution setting, so we when we are given a 2431 // a new resolution for the default display (normally stored in PDS), we will also save it 2432 // to a setting that is backed up. 2433 // TODO(b/330943343) - Consider a full fidelity DisplayBackupHelper for this instead. 2434 if (mFlags.isResolutionBackupRestoreEnabled() && displayId == Display.DEFAULT_DISPLAY) { 2435 // Checks to see which of the two resolutions is selected 2436 // TODO(b/330906790) Uses the same logic as Settings, but should be made to support 2437 // more than two resolutions using explicit mode enums long-term. 2438 Point[] resolutions = displayDevice.getSupportedResolutionsLocked(); 2439 if (resolutions.length == 2) { 2440 Point newMode = new Point(mode.getPhysicalWidth(), mode.getPhysicalHeight()); 2441 int resolutionMode = newMode.equals(resolutions[0]) ? RESOLUTION_MODE_HIGH 2442 : newMode.equals(resolutions[1]) ? RESOLUTION_MODE_FULL 2443 : RESOLUTION_MODE_UNKNOWN; 2444 Settings.Secure.putIntForUser(mContext.getContentResolver(), 2445 Settings.Secure.SCREEN_RESOLUTION_MODE, resolutionMode, 2446 UserHandle.USER_CURRENT); 2447 } 2448 } 2449 2450 displayDevice.setUserPreferredDisplayModeLocked(mode); 2451 } 2452 storeModeInGlobalSettingsLocked( int resolutionWidth, int resolutionHeight, float refreshRate, Display.Mode mode)2453 private void storeModeInGlobalSettingsLocked( 2454 int resolutionWidth, int resolutionHeight, float refreshRate, Display.Mode mode) { 2455 Settings.Global.putFloat(mContext.getContentResolver(), 2456 Settings.Global.USER_PREFERRED_REFRESH_RATE, refreshRate); 2457 Settings.Global.putInt(mContext.getContentResolver(), 2458 Settings.Global.USER_PREFERRED_RESOLUTION_HEIGHT, resolutionHeight); 2459 Settings.Global.putInt(mContext.getContentResolver(), 2460 Settings.Global.USER_PREFERRED_RESOLUTION_WIDTH, resolutionWidth); 2461 mDisplayDeviceRepo.forEachLocked((DisplayDevice device) -> { 2462 device.setUserPreferredDisplayModeLocked(mode); 2463 }); 2464 } 2465 2466 @GuardedBy("mSyncRoot") getEnabledAutoHdrTypesLocked()2467 private int[] getEnabledAutoHdrTypesLocked() { 2468 IntArray autoHdrOutputTypesArray = new IntArray(); 2469 for (int type : getSupportedHdrOutputTypesInternal()) { 2470 boolean isDisabled = false; 2471 for (int disabledType : mUserDisabledHdrTypes) { 2472 if (type == disabledType) { 2473 isDisabled = true; 2474 break; 2475 } 2476 } 2477 if (!isDisabled) { 2478 autoHdrOutputTypesArray.add(type); 2479 } 2480 } 2481 return autoHdrOutputTypesArray.toArray(); 2482 } 2483 2484 @GuardedBy("mSyncRoot") hdrConversionIntroducesLatencyLocked()2485 private boolean hdrConversionIntroducesLatencyLocked() { 2486 HdrConversionMode mode = getHdrConversionModeSettingInternal(); 2487 final int preferredHdrOutputType = 2488 mode.getConversionMode() == HdrConversionMode.HDR_CONVERSION_SYSTEM 2489 ? mSystemPreferredHdrOutputType : mode.getPreferredHdrOutputType(); 2490 if (preferredHdrOutputType != Display.HdrCapabilities.HDR_TYPE_INVALID) { 2491 int[] hdrTypesWithLatency = mInjector.getHdrOutputTypesWithLatency(); 2492 return ArrayUtils.contains(hdrTypesWithLatency, preferredHdrOutputType); 2493 } 2494 return false; 2495 } 2496 getUserPreferredDisplayModeInternal(int displayId)2497 Display.Mode getUserPreferredDisplayModeInternal(int displayId) { 2498 synchronized (mSyncRoot) { 2499 if (displayId == Display.INVALID_DISPLAY) { 2500 return mUserPreferredMode; 2501 } 2502 DisplayDevice displayDevice = getDeviceForDisplayLocked(displayId); 2503 if (displayDevice == null) { 2504 return null; 2505 } 2506 return displayDevice.getUserPreferredDisplayModeLocked(); 2507 } 2508 } 2509 getSystemPreferredDisplayModeInternal(int displayId)2510 Display.Mode getSystemPreferredDisplayModeInternal(int displayId) { 2511 synchronized (mSyncRoot) { 2512 final DisplayDevice device = getDeviceForDisplayLocked(displayId); 2513 if (device == null) { 2514 return null; 2515 } 2516 return device.getSystemPreferredDisplayModeLocked(); 2517 } 2518 } 2519 setHdrConversionModeInternal(HdrConversionMode hdrConversionMode)2520 void setHdrConversionModeInternal(HdrConversionMode hdrConversionMode) { 2521 if (!mInjector.getHdrOutputConversionSupport()) { 2522 return; 2523 } 2524 int[] autoHdrOutputTypes = null; 2525 synchronized (mSyncRoot) { 2526 if (hdrConversionMode.getConversionMode() == HdrConversionMode.HDR_CONVERSION_SYSTEM 2527 && hdrConversionMode.getPreferredHdrOutputType() 2528 != Display.HdrCapabilities.HDR_TYPE_INVALID) { 2529 throw new IllegalArgumentException("preferredHdrOutputType must not be set if" 2530 + " the conversion mode is HDR_CONVERSION_SYSTEM"); 2531 } 2532 mHdrConversionMode = hdrConversionMode; 2533 storeHdrConversionModeLocked(mHdrConversionMode); 2534 2535 // For auto mode, all supported HDR types are allowed except the ones specifically 2536 // disabled by the user. 2537 if (hdrConversionMode.getConversionMode() == HdrConversionMode.HDR_CONVERSION_SYSTEM) { 2538 autoHdrOutputTypes = getEnabledAutoHdrTypesLocked(); 2539 } 2540 2541 int conversionMode = hdrConversionMode.getConversionMode(); 2542 int preferredHdrType = hdrConversionMode.getPreferredHdrOutputType(); 2543 // If the HDR conversion is disabled by an app through WindowManager.LayoutParams, then 2544 // set HDR conversion mode to HDR_CONVERSION_PASSTHROUGH. 2545 if (mOverrideHdrConversionMode == null) { 2546 // HDR_CONVERSION_FORCE with HDR_TYPE_INVALID is used to represent forcing SDR type. 2547 // But, internally SDR is selected by using passthrough mode. 2548 if (conversionMode == HdrConversionMode.HDR_CONVERSION_FORCE 2549 && preferredHdrType == Display.HdrCapabilities.HDR_TYPE_INVALID) { 2550 conversionMode = HdrConversionMode.HDR_CONVERSION_PASSTHROUGH; 2551 } 2552 } else { 2553 conversionMode = mOverrideHdrConversionMode.getConversionMode(); 2554 preferredHdrType = mOverrideHdrConversionMode.getPreferredHdrOutputType(); 2555 autoHdrOutputTypes = null; 2556 } 2557 mSystemPreferredHdrOutputType = mInjector.setHdrConversionMode( 2558 conversionMode, preferredHdrType, autoHdrOutputTypes); 2559 } 2560 } 2561 getHdrConversionModeSettingInternal()2562 HdrConversionMode getHdrConversionModeSettingInternal() { 2563 if (!mInjector.getHdrOutputConversionSupport()) { 2564 return HDR_CONVERSION_MODE_UNSUPPORTED; 2565 } 2566 synchronized (mSyncRoot) { 2567 if (mHdrConversionMode != null) { 2568 return mHdrConversionMode; 2569 } 2570 } 2571 return new HdrConversionMode(mDefaultHdrConversionMode); 2572 } 2573 getHdrConversionModeInternal()2574 HdrConversionMode getHdrConversionModeInternal() { 2575 if (!mInjector.getHdrOutputConversionSupport()) { 2576 return HDR_CONVERSION_MODE_UNSUPPORTED; 2577 } 2578 HdrConversionMode mode; 2579 synchronized (mSyncRoot) { 2580 mode = mOverrideHdrConversionMode != null 2581 ? mOverrideHdrConversionMode 2582 : mHdrConversionMode; 2583 // Handle default: PASSTHROUGH. Don't include the system-preferred type. 2584 if (mode == null 2585 && mDefaultHdrConversionMode == HdrConversionMode.HDR_CONVERSION_PASSTHROUGH) { 2586 return new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_PASSTHROUGH); 2587 } 2588 // Handle default or current mode: SYSTEM. Include the system preferred type. 2589 // mOverrideHdrConversionMode and mHdrConversionMode do not include the system 2590 // preferred type, it is kept separately in mSystemPreferredHdrOutputType. 2591 if (mode == null 2592 || mode.getConversionMode() == HdrConversionMode.HDR_CONVERSION_SYSTEM) { 2593 return new HdrConversionMode( 2594 HdrConversionMode.HDR_CONVERSION_SYSTEM, mSystemPreferredHdrOutputType); 2595 } 2596 } 2597 return mode; 2598 } 2599 getSupportedHdrOutputTypesInternal()2600 private @Display.HdrCapabilities.HdrType int[] getSupportedHdrOutputTypesInternal() { 2601 if (mSupportedHdrOutputType == null) { 2602 mSupportedHdrOutputType = mInjector.getSupportedHdrOutputTypes(); 2603 } 2604 return mSupportedHdrOutputType; 2605 } 2606 setShouldAlwaysRespectAppRequestedModeInternal(boolean enabled)2607 void setShouldAlwaysRespectAppRequestedModeInternal(boolean enabled) { 2608 mDisplayModeDirector.setShouldAlwaysRespectAppRequestedMode(enabled); 2609 } 2610 shouldAlwaysRespectAppRequestedModeInternal()2611 boolean shouldAlwaysRespectAppRequestedModeInternal() { 2612 return mDisplayModeDirector.shouldAlwaysRespectAppRequestedMode(); 2613 } 2614 setRefreshRateSwitchingTypeInternal(@isplayManager.SwitchingType int newValue)2615 void setRefreshRateSwitchingTypeInternal(@DisplayManager.SwitchingType int newValue) { 2616 mDisplayModeDirector.setModeSwitchingType(newValue); 2617 } 2618 2619 @DisplayManager.SwitchingType getRefreshRateSwitchingTypeInternal()2620 int getRefreshRateSwitchingTypeInternal() { 2621 return mDisplayModeDirector.getModeSwitchingType(); 2622 } 2623 getDisplayDecorationSupportInternal(int displayId)2624 private DisplayDecorationSupport getDisplayDecorationSupportInternal(int displayId) { 2625 final IBinder displayToken = getDisplayToken(displayId); 2626 if (null == displayToken) { 2627 return null; 2628 } 2629 return SurfaceControl.getDisplayDecorationSupport(displayToken); 2630 } 2631 setBrightnessConfigurationForDisplayInternal( @ullable BrightnessConfiguration c, String uniqueId, @UserIdInt int userId, String packageName)2632 private void setBrightnessConfigurationForDisplayInternal( 2633 @Nullable BrightnessConfiguration c, String uniqueId, @UserIdInt int userId, 2634 String packageName) { 2635 validateBrightnessConfiguration(c); 2636 final int userSerial = getUserManager().getUserSerialNumber(userId); 2637 synchronized (mSyncRoot) { 2638 try { 2639 DisplayDevice displayDevice = mDisplayDeviceRepo.getByUniqueIdLocked(uniqueId); 2640 if (displayDevice == null) { 2641 return; 2642 } 2643 if (mLogicalDisplayMapper.getDisplayLocked(displayDevice) != null 2644 && mLogicalDisplayMapper.getDisplayLocked(displayDevice) 2645 .getDisplayInfoLocked().type == Display.TYPE_INTERNAL && c != null) { 2646 FrameworkStatsLog.write(FrameworkStatsLog.BRIGHTNESS_CONFIGURATION_UPDATED, 2647 c.getCurve().first, 2648 c.getCurve().second, 2649 // should not be logged for virtual displays 2650 uniqueId); 2651 } 2652 mPersistentDataStore.setBrightnessConfigurationForDisplayLocked(c, displayDevice, 2653 userSerial, packageName); 2654 } finally { 2655 mPersistentDataStore.saveIfNeeded(); 2656 } 2657 if (userId != mCurrentUserId) { 2658 return; 2659 } 2660 DisplayPowerControllerInterface dpc = getDpcFromUniqueIdLocked(uniqueId); 2661 if (dpc != null) { 2662 dpc.setBrightnessConfiguration(c, /* shouldResetShortTermModel= */ true); 2663 } 2664 } 2665 } 2666 getDpcFromUniqueIdLocked(String uniqueId)2667 private DisplayPowerControllerInterface getDpcFromUniqueIdLocked(String uniqueId) { 2668 final DisplayDevice displayDevice = mDisplayDeviceRepo.getByUniqueIdLocked(uniqueId); 2669 final LogicalDisplay logicalDisplay = mLogicalDisplayMapper.getDisplayLocked(displayDevice); 2670 if (logicalDisplay != null) { 2671 final int displayId = logicalDisplay.getDisplayIdLocked(); 2672 return mDisplayPowerControllers.get(displayId); 2673 } 2674 return null; 2675 } 2676 2677 @VisibleForTesting validateBrightnessConfiguration(BrightnessConfiguration config)2678 void validateBrightnessConfiguration(BrightnessConfiguration config) { 2679 if (config == null) { 2680 return; 2681 } 2682 if (isBrightnessConfigurationTooDark(config)) { 2683 throw new IllegalArgumentException("brightness curve is too dark"); 2684 } 2685 } 2686 isBrightnessConfigurationTooDark(BrightnessConfiguration config)2687 private boolean isBrightnessConfigurationTooDark(BrightnessConfiguration config) { 2688 Pair<float[], float[]> curve = config.getCurve(); 2689 float[] lux = curve.first; 2690 float[] nits = curve.second; 2691 for (int i = 0; i < lux.length; i++) { 2692 if (nits[i] < mMinimumBrightnessSpline.interpolate(lux[i])) { 2693 return true; 2694 } 2695 } 2696 return false; 2697 } 2698 loadBrightnessConfigurations()2699 private void loadBrightnessConfigurations() { 2700 int userSerial = getUserManager().getUserSerialNumber(mContext.getUserId()); 2701 synchronized (mSyncRoot) { 2702 mLogicalDisplayMapper.forEachLocked((logicalDisplay) -> { 2703 final String uniqueId = 2704 logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId(); 2705 final BrightnessConfiguration config = 2706 getBrightnessConfigForDisplayWithPdsFallbackLocked(uniqueId, userSerial); 2707 if (config != null) { 2708 final DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get( 2709 logicalDisplay.getDisplayIdLocked()); 2710 if (dpc != null) { 2711 dpc.setBrightnessConfiguration(config, 2712 /* shouldResetShortTermModel= */ false); 2713 } 2714 } 2715 }); 2716 } 2717 } 2718 performTraversalLocked(SurfaceControl.Transaction t, SparseArray<SurfaceControl.Transaction> displayTransactions)2719 private void performTraversalLocked(SurfaceControl.Transaction t, 2720 SparseArray<SurfaceControl.Transaction> displayTransactions) { 2721 // Clear all viewports before configuring displays so that we can keep 2722 // track of which ones we have configured. 2723 clearViewportsLocked(); 2724 2725 // Configure each display device. 2726 mLogicalDisplayMapper.forEachLocked((LogicalDisplay display) -> { 2727 final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); 2728 final SurfaceControl.Transaction displayTransaction = 2729 displayTransactions.get(display.getDisplayIdLocked(), t); 2730 if (device != null) { 2731 configureDisplayLocked(displayTransaction, device); 2732 device.performTraversalLocked(displayTransaction); 2733 } 2734 }); 2735 2736 // Tell the input system about these new viewports. 2737 if (mInputManagerInternal != null) { 2738 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT); 2739 } 2740 } 2741 setDisplayPropertiesInternal(int displayId, boolean hasContent, float requestedRefreshRate, int requestedModeId, float requestedMinRefreshRate, float requestedMaxRefreshRate, boolean preferMinimalPostProcessing, boolean disableHdrConversion, boolean inTraversal)2742 void setDisplayPropertiesInternal(int displayId, boolean hasContent, 2743 float requestedRefreshRate, int requestedModeId, float requestedMinRefreshRate, 2744 float requestedMaxRefreshRate, boolean preferMinimalPostProcessing, 2745 boolean disableHdrConversion, boolean inTraversal) { 2746 synchronized (mSyncRoot) { 2747 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 2748 if (display == null) { 2749 return; 2750 } 2751 2752 boolean shouldScheduleTraversal = false; 2753 2754 if (display.hasContentLocked() != hasContent) { 2755 if (DEBUG) { 2756 Slog.d(TAG, "Display " + displayId + " hasContent flag changed: " 2757 + "hasContent=" + hasContent + ", inTraversal=" + inTraversal); 2758 } 2759 2760 display.setHasContentLocked(hasContent); 2761 shouldScheduleTraversal = true; 2762 } 2763 2764 mDisplayModeDirector.getAppRequestObserver().setAppRequest(displayId, requestedModeId, 2765 requestedRefreshRate, requestedMinRefreshRate, requestedMaxRefreshRate); 2766 2767 // TODO(b/202378408) set minimal post-processing only if it's supported once we have a 2768 // separate API for disabling on-device processing. 2769 boolean mppRequest = isMinimalPostProcessingAllowed() && preferMinimalPostProcessing; 2770 // If HDR conversion introduces latency, disable that in case minimal 2771 // post-processing is requested 2772 boolean disableHdrConversionForLatency = 2773 mppRequest && hdrConversionIntroducesLatencyLocked(); 2774 2775 if (display.getRequestedMinimalPostProcessingLocked() != mppRequest) { 2776 display.setRequestedMinimalPostProcessingLocked(mppRequest); 2777 shouldScheduleTraversal = true; 2778 } 2779 2780 if (shouldScheduleTraversal) { 2781 scheduleTraversalLocked(inTraversal); 2782 } 2783 2784 if (mHdrConversionMode == null) { 2785 return; 2786 } 2787 // HDR conversion is disabled in two cases: 2788 // - HDR conversion introduces latency and minimal post-processing is requested 2789 // - app requests to disable HDR conversion 2790 if (mOverrideHdrConversionMode == null && (disableHdrConversion 2791 || disableHdrConversionForLatency)) { 2792 mOverrideHdrConversionMode = 2793 new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_PASSTHROUGH); 2794 setHdrConversionModeInternal(mHdrConversionMode); 2795 handleLogicalDisplayChangedLocked(display); 2796 } else if (mOverrideHdrConversionMode != null && !disableHdrConversion 2797 && !disableHdrConversionForLatency) { 2798 mOverrideHdrConversionMode = null; 2799 setHdrConversionModeInternal(mHdrConversionMode); 2800 handleLogicalDisplayChangedLocked(display); 2801 } 2802 } 2803 } 2804 setDisplayOffsetsInternal(int displayId, int x, int y)2805 private void setDisplayOffsetsInternal(int displayId, int x, int y) { 2806 synchronized (mSyncRoot) { 2807 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 2808 if (display == null) { 2809 return; 2810 } 2811 if (display.getDisplayOffsetXLocked() != x 2812 || display.getDisplayOffsetYLocked() != y) { 2813 if (DEBUG) { 2814 Slog.d(TAG, "Display " + displayId + " burn-in offset set to (" 2815 + x + ", " + y + ")"); 2816 } 2817 display.setDisplayOffsetsLocked(x, y); 2818 scheduleTraversalLocked(false); 2819 } 2820 } 2821 } 2822 setDisplayScalingDisabledInternal(int displayId, boolean disable)2823 private void setDisplayScalingDisabledInternal(int displayId, boolean disable) { 2824 synchronized (mSyncRoot) { 2825 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 2826 if (display == null) { 2827 return; 2828 } 2829 if (display.isDisplayScalingDisabled() != disable) { 2830 if (DEBUG) { 2831 Slog.d(TAG, "Display " + displayId + " content scaling disabled = " + disable); 2832 } 2833 display.setDisplayScalingDisabledLocked(disable); 2834 scheduleTraversalLocked(false); 2835 } 2836 } 2837 } 2838 2839 // Updates the lists of UIDs that are present on displays. setDisplayAccessUIDsInternal(SparseArray<IntArray> newDisplayAccessUIDs)2840 private void setDisplayAccessUIDsInternal(SparseArray<IntArray> newDisplayAccessUIDs) { 2841 synchronized (mSyncRoot) { 2842 mDisplayAccessUIDs.clear(); 2843 for (int i = newDisplayAccessUIDs.size() - 1; i >= 0; i--) { 2844 mDisplayAccessUIDs.append(newDisplayAccessUIDs.keyAt(i), 2845 newDisplayAccessUIDs.valueAt(i)); 2846 } 2847 } 2848 } 2849 2850 // Checks if provided UID's content is present on the display and UID has access to it. isUidPresentOnDisplayInternal(int uid, int displayId)2851 private boolean isUidPresentOnDisplayInternal(int uid, int displayId) { 2852 synchronized (mSyncRoot) { 2853 final IntArray displayUIDs = mDisplayAccessUIDs.get(displayId); 2854 return displayUIDs != null && displayUIDs.indexOf(uid) != -1; 2855 } 2856 } 2857 2858 @Nullable getDisplayToken(int displayId)2859 private IBinder getDisplayToken(int displayId) { 2860 synchronized (mSyncRoot) { 2861 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 2862 if (display != null) { 2863 final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); 2864 if (device != null) { 2865 return device.getDisplayTokenLocked(); 2866 } 2867 } 2868 } 2869 2870 return null; 2871 } 2872 systemScreenshotInternal(int displayId)2873 private ScreenCapture.ScreenshotHardwareBuffer systemScreenshotInternal(int displayId) { 2874 final ScreenCapture.DisplayCaptureArgs captureArgs; 2875 synchronized (mSyncRoot) { 2876 final IBinder token = getDisplayToken(displayId); 2877 if (token == null) { 2878 return null; 2879 } 2880 final LogicalDisplay logicalDisplay = mLogicalDisplayMapper.getDisplayLocked(displayId); 2881 if (logicalDisplay == null) { 2882 return null; 2883 } 2884 2885 final DisplayInfo displayInfo = logicalDisplay.getDisplayInfoLocked(); 2886 captureArgs = new ScreenCapture.DisplayCaptureArgs.Builder(token) 2887 .setSize(displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight()) 2888 .setCaptureSecureLayers(true) 2889 .setAllowProtected(true) 2890 .build(); 2891 } 2892 return ScreenCapture.captureDisplay(captureArgs); 2893 } 2894 userScreenshotInternal(int displayId)2895 private ScreenCapture.ScreenshotHardwareBuffer userScreenshotInternal(int displayId) { 2896 final ScreenCapture.DisplayCaptureArgs captureArgs; 2897 synchronized (mSyncRoot) { 2898 final IBinder token = getDisplayToken(displayId); 2899 if (token == null) { 2900 return null; 2901 } 2902 2903 captureArgs = new ScreenCapture.DisplayCaptureArgs.Builder(token) 2904 .build(); 2905 } 2906 return ScreenCapture.captureDisplay(captureArgs); 2907 } 2908 2909 @VisibleForTesting getDisplayedContentSamplingAttributesInternal( int displayId)2910 DisplayedContentSamplingAttributes getDisplayedContentSamplingAttributesInternal( 2911 int displayId) { 2912 final IBinder token = getDisplayToken(displayId); 2913 if (token == null) { 2914 return null; 2915 } 2916 return SurfaceControl.getDisplayedContentSamplingAttributes(token); 2917 } 2918 2919 @VisibleForTesting setDisplayedContentSamplingEnabledInternal( int displayId, boolean enable, int componentMask, int maxFrames)2920 boolean setDisplayedContentSamplingEnabledInternal( 2921 int displayId, boolean enable, int componentMask, int maxFrames) { 2922 final IBinder token = getDisplayToken(displayId); 2923 if (token == null) { 2924 return false; 2925 } 2926 return SurfaceControl.setDisplayedContentSamplingEnabled( 2927 token, enable, componentMask, maxFrames); 2928 } 2929 2930 @VisibleForTesting getDisplayedContentSampleInternal(int displayId, long maxFrames, long timestamp)2931 DisplayedContentSample getDisplayedContentSampleInternal(int displayId, 2932 long maxFrames, long timestamp) { 2933 final IBinder token = getDisplayToken(displayId); 2934 if (token == null) { 2935 return null; 2936 } 2937 return SurfaceControl.getDisplayedContentSample(token, maxFrames, timestamp); 2938 } 2939 resetBrightnessConfigurations()2940 void resetBrightnessConfigurations() { 2941 mPersistentDataStore.setBrightnessConfigurationForUser(null, mContext.getUserId(), 2942 mContext.getPackageName()); 2943 mLogicalDisplayMapper.forEachLocked((logicalDisplay -> { 2944 if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) { 2945 return; 2946 } 2947 final String uniqueId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId(); 2948 setBrightnessConfigurationForDisplayInternal(null, uniqueId, mContext.getUserId(), 2949 mContext.getPackageName()); 2950 })); 2951 } 2952 setAutoBrightnessLoggingEnabled(boolean enabled)2953 void setAutoBrightnessLoggingEnabled(boolean enabled) { 2954 synchronized (mSyncRoot) { 2955 final DisplayPowerControllerInterface displayPowerController = 2956 mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY); 2957 if (displayPowerController != null) { 2958 displayPowerController.setAutoBrightnessLoggingEnabled(enabled); 2959 } 2960 } 2961 } 2962 setDisplayWhiteBalanceLoggingEnabled(boolean enabled)2963 void setDisplayWhiteBalanceLoggingEnabled(boolean enabled) { 2964 synchronized (mSyncRoot) { 2965 final DisplayPowerControllerInterface displayPowerController = 2966 mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY); 2967 if (displayPowerController != null) { 2968 displayPowerController.setDisplayWhiteBalanceLoggingEnabled(enabled); 2969 } 2970 } 2971 } 2972 setDisplayModeDirectorLoggingEnabled(boolean enabled)2973 void setDisplayModeDirectorLoggingEnabled(boolean enabled) { 2974 synchronized (mSyncRoot) { 2975 mDisplayModeDirector.setLoggingEnabled(enabled); 2976 } 2977 } 2978 getActiveDisplayModeAtStart(int displayId)2979 Display.Mode getActiveDisplayModeAtStart(int displayId) { 2980 synchronized (mSyncRoot) { 2981 final DisplayDevice device = getDeviceForDisplayLocked(displayId); 2982 if (device == null) { 2983 return null; 2984 } 2985 return device.getActiveDisplayModeAtStartLocked(); 2986 } 2987 } 2988 setAmbientColorTemperatureOverride(float cct)2989 void setAmbientColorTemperatureOverride(float cct) { 2990 synchronized (mSyncRoot) { 2991 final DisplayPowerControllerInterface displayPowerController = 2992 mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY); 2993 if (displayPowerController != null) { 2994 displayPowerController.setAmbientColorTemperatureOverride(cct); 2995 } 2996 } 2997 } 2998 setDockedAndIdleEnabled(boolean enabled, int displayId)2999 void setDockedAndIdleEnabled(boolean enabled, int displayId) { 3000 synchronized (mSyncRoot) { 3001 final DisplayPowerControllerInterface displayPowerController = 3002 mDisplayPowerControllers.get(displayId); 3003 if (displayPowerController != null) { 3004 displayPowerController.setAutomaticScreenBrightnessMode(enabled 3005 ? AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_IDLE 3006 : AutomaticBrightnessController.AUTO_BRIGHTNESS_MODE_DEFAULT); 3007 } 3008 } 3009 } 3010 clearViewportsLocked()3011 private void clearViewportsLocked() { 3012 mViewports.clear(); 3013 } 3014 getViewportType(DisplayDeviceInfo info)3015 private Optional<Integer> getViewportType(DisplayDeviceInfo info) { 3016 // Get the corresponding viewport type. 3017 switch (info.touch) { 3018 case DisplayDeviceInfo.TOUCH_INTERNAL: 3019 return Optional.of(VIEWPORT_INTERNAL); 3020 case DisplayDeviceInfo.TOUCH_EXTERNAL: 3021 return Optional.of(VIEWPORT_EXTERNAL); 3022 case DisplayDeviceInfo.TOUCH_VIRTUAL: 3023 if (!TextUtils.isEmpty(info.uniqueId)) { 3024 return Optional.of(VIEWPORT_VIRTUAL); 3025 } 3026 // fallthrough 3027 default: 3028 if (DEBUG) { 3029 Slog.w(TAG, "Display " + info + " does not support input device matching."); 3030 } 3031 } 3032 return Optional.empty(); 3033 } 3034 configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device)3035 private void configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device) { 3036 final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 3037 3038 // Find the logical display that the display device is showing. 3039 // Certain displays only ever show their own content. 3040 LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device); 3041 3042 // Apply the logical display configuration to the display device. 3043 if (display == null) { 3044 // TODO: no logical display for the device, blank it 3045 Slog.w(TAG, "Missing logical display to use for physical display device: " 3046 + device.getDisplayDeviceInfoLocked()); 3047 return; 3048 } 3049 display.configureDisplayLocked(t, device, info.state == Display.STATE_OFF); 3050 final Optional<Integer> viewportType = getViewportType(info); 3051 if (viewportType.isPresent()) { 3052 populateViewportLocked(viewportType.get(), display.getDisplayIdLocked(), device, info); 3053 } 3054 } 3055 3056 /** 3057 * Get internal or external viewport. Create it if does not currently exist. 3058 * @param viewportType - either INTERNAL or EXTERNAL 3059 * @return the viewport with the requested type 3060 */ getViewportLocked(int viewportType, String uniqueId)3061 private DisplayViewport getViewportLocked(int viewportType, String uniqueId) { 3062 if (viewportType != VIEWPORT_INTERNAL && viewportType != VIEWPORT_EXTERNAL 3063 && viewportType != VIEWPORT_VIRTUAL) { 3064 Slog.wtf(TAG, "Cannot call getViewportByTypeLocked for type " 3065 + DisplayViewport.typeToString(viewportType)); 3066 return null; 3067 } 3068 3069 DisplayViewport viewport; 3070 final int count = mViewports.size(); 3071 for (int i = 0; i < count; i++) { 3072 viewport = mViewports.get(i); 3073 if (viewport.type == viewportType && uniqueId.equals(viewport.uniqueId)) { 3074 return viewport; 3075 } 3076 } 3077 3078 // Creates the viewport if none exists. 3079 viewport = new DisplayViewport(); 3080 viewport.type = viewportType; 3081 viewport.uniqueId = uniqueId; 3082 mViewports.add(viewport); 3083 return viewport; 3084 } 3085 populateViewportLocked(int viewportType, int displayId, DisplayDevice device, DisplayDeviceInfo info)3086 private void populateViewportLocked(int viewportType, int displayId, DisplayDevice device, 3087 DisplayDeviceInfo info) { 3088 final DisplayViewport viewport = getViewportLocked(viewportType, info.uniqueId); 3089 device.populateViewportLocked(viewport); 3090 viewport.valid = true; 3091 viewport.displayId = displayId; 3092 viewport.isActive = Display.isActiveState(info.state); 3093 } 3094 updateViewportPowerStateLocked(LogicalDisplay display)3095 private void updateViewportPowerStateLocked(LogicalDisplay display) { 3096 final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); 3097 final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 3098 final Optional<Integer> viewportType = getViewportType(info); 3099 if (viewportType.isPresent()) { 3100 for (DisplayViewport d : mViewports) { 3101 if (d.type == viewportType.get() && info.uniqueId.equals(d.uniqueId)) { 3102 // Update display view port power state 3103 d.isActive = Display.isActiveState(info.state); 3104 } 3105 } 3106 if (mInputManagerInternal != null) { 3107 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT); 3108 } 3109 } 3110 } 3111 3112 // Send a display event if the display is enabled sendDisplayEventIfEnabledLocked(@onNull LogicalDisplay display, @DisplayEvent int event)3113 private void sendDisplayEventIfEnabledLocked(@NonNull LogicalDisplay display, 3114 @DisplayEvent int event) { 3115 final boolean displayIsEnabled = display.isEnabledLocked(); 3116 if (Trace.isTagEnabled(Trace.TRACE_TAG_POWER)) { 3117 Trace.instant(Trace.TRACE_TAG_POWER, 3118 "sendDisplayEventLocked#event=" + event + ",displayEnabled=" 3119 + displayIsEnabled); 3120 } 3121 3122 // Only send updates outside of DisplayManagerService for enabled displays 3123 if (displayIsEnabled) { 3124 sendDisplayEventLocked(display, event); 3125 } else if (mExtraDisplayEventLogging) { 3126 Slog.i(TAG, "Not Sending Display Event; display is not enabled: " + display); 3127 } 3128 } 3129 sendDisplayEventLocked(@onNull LogicalDisplay display, @DisplayEvent int event)3130 private void sendDisplayEventLocked(@NonNull LogicalDisplay display, @DisplayEvent int event) { 3131 int displayId = display.getDisplayIdLocked(); 3132 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event); 3133 if (mExtraDisplayEventLogging) { 3134 Slog.i(TAG, "Deliver Display Event on Handler: " + event); 3135 } 3136 mHandler.sendMessage(msg); 3137 } 3138 sendDisplayGroupEvent(int groupId, int event)3139 private void sendDisplayGroupEvent(int groupId, int event) { 3140 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_GROUP_EVENT, groupId, event); 3141 mHandler.sendMessage(msg); 3142 } 3143 sendDisplayEventFrameRateOverrideLocked(int displayId)3144 private void sendDisplayEventFrameRateOverrideLocked(int displayId) { 3145 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE, 3146 displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); 3147 mHandler.sendMessage(msg); 3148 } 3149 3150 // Requests that performTraversals be called at a 3151 // later time to apply changes to surfaces and displays. scheduleTraversalLocked(boolean inTraversal)3152 private void scheduleTraversalLocked(boolean inTraversal) { 3153 if (!mPendingTraversal && mWindowManagerInternal != null) { 3154 mPendingTraversal = true; 3155 if (!inTraversal) { 3156 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL); 3157 } 3158 } 3159 } 3160 3161 // Check if the target app is in cached mode isUidCached(int uid)3162 private boolean isUidCached(int uid) { 3163 if (mActivityManagerInternal == null || uid < FIRST_APPLICATION_UID) { 3164 return false; 3165 } 3166 int procState = mActivityManagerInternal.getUidProcessState(uid); 3167 int importance = ActivityManager.RunningAppProcessInfo.procStateToImportance(procState); 3168 return importance >= IMPORTANCE_CACHED; 3169 } 3170 3171 // Runs on Handler thread. 3172 // Delivers display event notifications to callbacks. deliverDisplayEvent(int displayId, ArraySet<Integer> uids, @DisplayEvent int event)3173 private void deliverDisplayEvent(int displayId, ArraySet<Integer> uids, 3174 @DisplayEvent int event) { 3175 if (DEBUG || mExtraDisplayEventLogging) { 3176 Slog.d(TAG, "Delivering display event: displayId=" 3177 + displayId + ", event=" + event 3178 + (uids != null ? ", uids=" + uids : "")); 3179 } 3180 if (Trace.isTagEnabled(Trace.TRACE_TAG_POWER)) { 3181 Trace.instant(Trace.TRACE_TAG_POWER, 3182 "deliverDisplayEvent#event=" + event + ",displayId=" 3183 + displayId + (uids != null ? ", uids=" + uids : "")); 3184 } 3185 // Grab the lock and copy the callbacks. 3186 final int count; 3187 synchronized (mSyncRoot) { 3188 count = mCallbacks.size(); 3189 mTempCallbacks.clear(); 3190 for (int i = 0; i < count; i++) { 3191 if (uids == null || uids.contains(mCallbacks.valueAt(i).mUid)) { 3192 mTempCallbacks.add(mCallbacks.valueAt(i)); 3193 } 3194 } 3195 } 3196 3197 // After releasing the lock, send the notifications out. 3198 for (int i = 0; i < mTempCallbacks.size(); i++) { 3199 CallbackRecord callbackRecord = mTempCallbacks.get(i); 3200 final int uid = callbackRecord.mUid; 3201 final int pid = callbackRecord.mPid; 3202 if (isUidCached(uid)) { 3203 // For cached apps, save the pending event until it becomes non-cached 3204 synchronized (mPendingCallbackSelfLocked) { 3205 SparseArray<PendingCallback> pendingCallbacks = mPendingCallbackSelfLocked.get( 3206 uid); 3207 if (extraLogging(callbackRecord.mPackageName)) { 3208 Slog.i(TAG, "Uid is cached: " + uid 3209 + ", pendingCallbacks: " + pendingCallbacks); 3210 } 3211 if (pendingCallbacks == null) { 3212 pendingCallbacks = new SparseArray<>(); 3213 mPendingCallbackSelfLocked.put(uid, pendingCallbacks); 3214 } 3215 PendingCallback pendingCallback = pendingCallbacks.get(pid); 3216 if (pendingCallback == null) { 3217 pendingCallbacks.put(pid, 3218 new PendingCallback(callbackRecord, displayId, event)); 3219 } else { 3220 pendingCallback.addDisplayEvent(displayId, event); 3221 } 3222 } 3223 } else { 3224 callbackRecord.notifyDisplayEventAsync(displayId, event); 3225 } 3226 } 3227 mTempCallbacks.clear(); 3228 } 3229 extraLogging(String packageName)3230 private boolean extraLogging(String packageName) { 3231 return mExtraDisplayEventLogging && mExtraDisplayLoggingPackageName.equals(packageName); 3232 } 3233 3234 // Runs on Handler thread. 3235 // Delivers display group event notifications to callbacks. deliverDisplayGroupEvent(int groupId, int event)3236 private void deliverDisplayGroupEvent(int groupId, int event) { 3237 if (DEBUG) { 3238 Slog.d(TAG, "Delivering display group event: groupId=" + groupId + ", event=" 3239 + event); 3240 } 3241 3242 switch (event) { 3243 case LogicalDisplayMapper.DISPLAY_GROUP_EVENT_ADDED: 3244 for (DisplayGroupListener listener : mDisplayGroupListeners) { 3245 listener.onDisplayGroupAdded(groupId); 3246 } 3247 break; 3248 3249 case LogicalDisplayMapper.DISPLAY_GROUP_EVENT_CHANGED: 3250 for (DisplayGroupListener listener : mDisplayGroupListeners) { 3251 listener.onDisplayGroupChanged(groupId); 3252 } 3253 break; 3254 3255 case LogicalDisplayMapper.DISPLAY_GROUP_EVENT_REMOVED: 3256 for (DisplayGroupListener listener : mDisplayGroupListeners) { 3257 listener.onDisplayGroupRemoved(groupId); 3258 } 3259 break; 3260 } 3261 } 3262 getProjectionService()3263 private IMediaProjectionManager getProjectionService() { 3264 if (mProjectionService == null) { 3265 mProjectionService = mInjector.getProjectionService(); 3266 } 3267 return mProjectionService; 3268 } 3269 getUserManager()3270 private UserManager getUserManager() { 3271 return mContext.getSystemService(UserManager.class); 3272 } 3273 dumpInternal(PrintWriter pw)3274 private void dumpInternal(PrintWriter pw) { 3275 pw.println("DISPLAY MANAGER (dumpsys display)"); 3276 BrightnessTracker brightnessTrackerLocal; 3277 3278 synchronized (mSyncRoot) { 3279 brightnessTrackerLocal = mBrightnessTracker; 3280 3281 pw.println(" mSafeMode=" + mSafeMode); 3282 pw.println(" mPendingTraversal=" + mPendingTraversal); 3283 pw.println(" mViewports=" + mViewports); 3284 pw.println(" mDefaultDisplayDefaultColorMode=" + mDefaultDisplayDefaultColorMode); 3285 pw.println(" mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount); 3286 pw.println(" mStableDisplaySize=" + mStableDisplaySize); 3287 pw.println(" mMinimumBrightnessCurve=" + mMinimumBrightnessCurve); 3288 3289 if (mUserPreferredMode != null) { 3290 pw.println(" mUserPreferredMode=" + mUserPreferredMode); 3291 } 3292 3293 pw.println(); 3294 if (!mAreUserDisabledHdrTypesAllowed) { 3295 pw.println(" mUserDisabledHdrTypes: size=" + mUserDisabledHdrTypes.length); 3296 for (int type : mUserDisabledHdrTypes) { 3297 pw.println(" " + type); 3298 } 3299 } 3300 3301 if (mHdrConversionMode != null) { 3302 pw.println(" mHdrConversionMode=" + mHdrConversionMode); 3303 } 3304 3305 pw.println(); 3306 final int displayStateCount = mDisplayStates.size(); 3307 pw.println("Display States: size=" + displayStateCount); 3308 for (int i = 0; i < displayStateCount; i++) { 3309 final int displayId = mDisplayStates.keyAt(i); 3310 final int displayState = mDisplayStates.valueAt(i); 3311 final BrightnessPair brightnessPair = mDisplayBrightnesses.valueAt(i); 3312 pw.println(" Display Id=" + displayId); 3313 pw.println(" Display State=" + Display.stateToString(displayState)); 3314 pw.println(" Display Brightness=" + brightnessPair.brightness); 3315 pw.println(" Display SdrBrightness=" + brightnessPair.sdrBrightness); 3316 } 3317 3318 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 3319 ipw.increaseIndent(); 3320 3321 pw.println(); 3322 pw.println("Display Adapters: size=" + mDisplayAdapters.size()); 3323 for (DisplayAdapter adapter : mDisplayAdapters) { 3324 pw.println(" " + adapter.getName()); 3325 adapter.dumpLocked(ipw); 3326 } 3327 3328 pw.println(); 3329 pw.println("Display Devices: size=" + mDisplayDeviceRepo.sizeLocked()); 3330 mDisplayDeviceRepo.forEachLocked(device -> { 3331 pw.println(" " + device.getDisplayDeviceInfoLocked()); 3332 device.dumpLocked(ipw); 3333 }); 3334 3335 pw.println(); 3336 mLogicalDisplayMapper.dumpLocked(pw); 3337 3338 final int callbackCount = mCallbacks.size(); 3339 pw.println(); 3340 pw.println("Callbacks: size=" + callbackCount); 3341 for (int i = 0; i < callbackCount; i++) { 3342 CallbackRecord callback = mCallbacks.valueAt(i); 3343 pw.println(" " + i + ": mPid=" + callback.mPid 3344 + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested); 3345 } 3346 3347 final int displayPowerControllerCount = mDisplayPowerControllers.size(); 3348 pw.println(); 3349 pw.println("Display Power Controllers: size=" + displayPowerControllerCount); 3350 for (int i = 0; i < displayPowerControllerCount; i++) { 3351 mDisplayPowerControllers.valueAt(i).dump(pw); 3352 } 3353 pw.println(); 3354 mPersistentDataStore.dump(pw); 3355 3356 final int displayWindowPolicyControllerCount = mDisplayWindowPolicyControllers.size(); 3357 pw.println(); 3358 pw.println("Display Window Policy Controllers: size=" 3359 + displayWindowPolicyControllerCount); 3360 for (int i = 0; i < displayWindowPolicyControllerCount; i++) { 3361 pw.print("Display " + mDisplayWindowPolicyControllers.keyAt(i) + ":"); 3362 mDisplayWindowPolicyControllers.valueAt(i).second.dump(" ", pw); 3363 } 3364 } 3365 if (brightnessTrackerLocal != null) { 3366 pw.println(); 3367 brightnessTrackerLocal.dump(pw); 3368 } 3369 pw.println(); 3370 mDisplayModeDirector.dump(pw); 3371 mBrightnessSynchronizer.dump(pw); 3372 if (mSmallAreaDetectionController != null) { 3373 mSmallAreaDetectionController.dump(pw); 3374 } 3375 3376 pw.println(); 3377 mFlags.dump(pw); 3378 3379 } 3380 getFloatArray(TypedArray array)3381 private static float[] getFloatArray(TypedArray array) { 3382 int length = array.length(); 3383 float[] floatArray = new float[length]; 3384 for (int i = 0; i < length; i++) { 3385 floatArray[i] = array.getFloat(i, Float.NaN); 3386 } 3387 array.recycle(); 3388 return floatArray; 3389 } 3390 isResolutionAndRefreshRateValid(Display.Mode mode)3391 private static boolean isResolutionAndRefreshRateValid(Display.Mode mode) { 3392 return mode.getPhysicalWidth() > 0 && mode.getPhysicalHeight() > 0 3393 && mode.getRefreshRate() > 0.0f; 3394 } 3395 enableConnectedDisplay(int displayId, boolean enabled)3396 void enableConnectedDisplay(int displayId, boolean enabled) { 3397 synchronized (mSyncRoot) { 3398 final var logicalDisplay = mLogicalDisplayMapper.getDisplayLocked(displayId); 3399 if (logicalDisplay == null) { 3400 Slog.w(TAG, "enableConnectedDisplay: Can not find displayId=" + displayId); 3401 } else if (ExternalDisplayPolicy.isExternalDisplayLocked(logicalDisplay)) { 3402 mExternalDisplayPolicy.setExternalDisplayEnabledLocked(logicalDisplay, enabled); 3403 } else { 3404 mLogicalDisplayMapper.setDisplayEnabledLocked(logicalDisplay, enabled); 3405 } 3406 } 3407 } 3408 requestDisplayPower(int displayId, boolean on)3409 boolean requestDisplayPower(int displayId, boolean on) { 3410 synchronized (mSyncRoot) { 3411 final var display = mLogicalDisplayMapper.getDisplayLocked(displayId); 3412 if (display == null) { 3413 Slog.w(TAG, "requestDisplayPower: Cannot find a display with displayId=" 3414 + displayId); 3415 return false; 3416 } 3417 final BrightnessPair brightnessPair = mDisplayBrightnesses.get(displayId); 3418 var runnable = display.getPrimaryDisplayDeviceLocked().requestDisplayStateLocked( 3419 on ? Display.STATE_ON : Display.STATE_OFF, 3420 on ? brightnessPair.brightness : PowerManager.BRIGHTNESS_OFF_FLOAT, 3421 brightnessPair.sdrBrightness, 3422 display.getDisplayOffloadSessionLocked()); 3423 if (runnable == null) { 3424 Slog.w(TAG, "requestDisplayPower: Cannot update the power state to ON=" + on 3425 + " for a display with displayId=" + displayId + ", runnable is null"); 3426 return false; 3427 } 3428 runnable.run(); 3429 Slog.i(TAG, "requestDisplayPower(displayId=" + displayId + ", on=" + on + ")"); 3430 } 3431 return true; 3432 } 3433 3434 /** 3435 * This is the object that everything in the display manager locks on. 3436 * We make it an inner class within the {@link DisplayManagerService} to so that it is 3437 * clear that the object belongs to the display manager service and that it is 3438 * a unique object with a special purpose. 3439 */ 3440 public static final class SyncRoot { 3441 } 3442 3443 @VisibleForTesting 3444 static class Injector { getVirtualDisplayAdapter(SyncRoot syncRoot, Context context, Handler handler, DisplayAdapter.Listener displayAdapterListener, DisplayManagerFlags flags)3445 VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot, Context context, 3446 Handler handler, DisplayAdapter.Listener displayAdapterListener, 3447 DisplayManagerFlags flags) { 3448 return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener, 3449 flags); 3450 } 3451 getLocalDisplayAdapter(SyncRoot syncRoot, Context context, Handler handler, DisplayAdapter.Listener displayAdapterListener, DisplayManagerFlags flags, DisplayNotificationManager displayNotificationManager)3452 LocalDisplayAdapter getLocalDisplayAdapter(SyncRoot syncRoot, Context context, 3453 Handler handler, DisplayAdapter.Listener displayAdapterListener, 3454 DisplayManagerFlags flags, 3455 DisplayNotificationManager displayNotificationManager) { 3456 return new LocalDisplayAdapter(syncRoot, context, handler, displayAdapterListener, 3457 flags, displayNotificationManager); 3458 } 3459 getDefaultDisplayDelayTimeout()3460 long getDefaultDisplayDelayTimeout() { 3461 return WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT; 3462 } 3463 setHdrConversionMode(int conversionMode, int preferredHdrOutputType, int[] autoHdrTypes)3464 int setHdrConversionMode(int conversionMode, int preferredHdrOutputType, 3465 int[] autoHdrTypes) { 3466 return DisplayControl.setHdrConversionMode(conversionMode, preferredHdrOutputType, 3467 autoHdrTypes); 3468 } 3469 3470 @Display.HdrCapabilities.HdrType getSupportedHdrOutputTypes()3471 int[] getSupportedHdrOutputTypes() { 3472 return DisplayControl.getSupportedHdrOutputTypes(); 3473 } 3474 getHdrOutputTypesWithLatency()3475 int[] getHdrOutputTypesWithLatency() { 3476 return DisplayControl.getHdrOutputTypesWithLatency(); 3477 } 3478 getHdrOutputConversionSupport()3479 boolean getHdrOutputConversionSupport() { 3480 return DisplayControl.getHdrOutputConversionSupport(); 3481 } 3482 getProjectionService()3483 IMediaProjectionManager getProjectionService() { 3484 IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE); 3485 return IMediaProjectionManager.Stub.asInterface(b); 3486 } 3487 getFlags()3488 DisplayManagerFlags getFlags() { 3489 return new DisplayManagerFlags(); 3490 } 3491 } 3492 3493 @VisibleForTesting getDisplayDeviceInfoInternal(int displayId)3494 DisplayDeviceInfo getDisplayDeviceInfoInternal(int displayId) { 3495 synchronized (mSyncRoot) { 3496 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 3497 if (display != null) { 3498 final DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked(); 3499 return displayDevice.getDisplayDeviceInfoLocked(); 3500 } 3501 return null; 3502 } 3503 } 3504 3505 @VisibleForTesting getVirtualDisplaySurfaceInternal(IBinder appToken)3506 Surface getVirtualDisplaySurfaceInternal(IBinder appToken) { 3507 synchronized (mSyncRoot) { 3508 if (mVirtualDisplayAdapter == null) { 3509 return null; 3510 } 3511 return mVirtualDisplayAdapter.getVirtualDisplaySurfaceLocked(appToken); 3512 } 3513 } 3514 initializeDisplayPowerControllersLocked()3515 private void initializeDisplayPowerControllersLocked() { 3516 mLogicalDisplayMapper.forEachLocked(this::addDisplayPowerControllerLocked); 3517 } 3518 3519 @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG) addDisplayPowerControllerLocked( LogicalDisplay display)3520 private DisplayPowerControllerInterface addDisplayPowerControllerLocked( 3521 LogicalDisplay display) { 3522 if (mPowerHandler == null) { 3523 // initPowerManagement has not yet been called. 3524 return null; 3525 } 3526 3527 if (mBrightnessTracker == null && display.getDisplayIdLocked() == Display.DEFAULT_DISPLAY) { 3528 mBrightnessTracker = new BrightnessTracker(mContext, null); 3529 } 3530 3531 final int userSerial = getUserManager().getUserSerialNumber(mContext.getUserId()); 3532 final BrightnessSetting brightnessSetting = new BrightnessSetting(userSerial, 3533 mPersistentDataStore, display, mSyncRoot); 3534 final DisplayPowerControllerInterface displayPowerController; 3535 3536 // If display is internal and has a HighBrightnessModeMetadata mapping, use that. 3537 // Or create a new one and use that. 3538 // We also need to pass a mapping of the HighBrightnessModeTimeInfoMap to 3539 // displayPowerController, so the hbm info can be correctly associated 3540 // with the corresponding displaydevice. 3541 HighBrightnessModeMetadata hbmMetadata = 3542 mHighBrightnessModeMetadataMapper.getHighBrightnessModeMetadataLocked(display); 3543 displayPowerController = new DisplayPowerController( 3544 mContext, /* injector= */ null, mDisplayPowerCallbacks, mPowerHandler, 3545 mSensorManager, mDisplayBlanker, display, mBrightnessTracker, brightnessSetting, 3546 () -> handleBrightnessChange(display), hbmMetadata, mBootCompleted, mFlags); 3547 mDisplayPowerControllers.append(display.getDisplayIdLocked(), displayPowerController); 3548 return displayPowerController; 3549 } 3550 handleBrightnessChange(LogicalDisplay display)3551 private void handleBrightnessChange(LogicalDisplay display) { 3552 synchronized (mSyncRoot) { 3553 sendDisplayEventIfEnabledLocked(display, 3554 DisplayManagerGlobal.EVENT_DISPLAY_BRIGHTNESS_CHANGED); 3555 } 3556 } 3557 getDeviceForDisplayLocked(int displayId)3558 private DisplayDevice getDeviceForDisplayLocked(int displayId) { 3559 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 3560 return display == null ? null : display.getPrimaryDisplayDeviceLocked(); 3561 } 3562 getBrightnessConfigForDisplayWithPdsFallbackLocked( String uniqueId, int userSerial)3563 private BrightnessConfiguration getBrightnessConfigForDisplayWithPdsFallbackLocked( 3564 String uniqueId, int userSerial) { 3565 BrightnessConfiguration config = 3566 mPersistentDataStore.getBrightnessConfigurationForDisplayLocked( 3567 uniqueId, userSerial); 3568 if (config == null) { 3569 // Get from global configurations 3570 config = mPersistentDataStore.getBrightnessConfiguration(userSerial); 3571 } 3572 return config; 3573 } 3574 3575 private final class DisplayManagerHandler extends Handler { DisplayManagerHandler(Looper looper)3576 public DisplayManagerHandler(Looper looper) { 3577 super(looper, null, true /*async*/); 3578 } 3579 3580 @Override handleMessage(Message msg)3581 public void handleMessage(Message msg) { 3582 switch (msg.what) { 3583 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS: 3584 registerDefaultDisplayAdapters(); 3585 break; 3586 3587 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS: 3588 registerAdditionalDisplayAdapters(); 3589 break; 3590 3591 case MSG_DELIVER_DISPLAY_EVENT: 3592 deliverDisplayEvent(msg.arg1, null, msg.arg2); 3593 break; 3594 3595 case MSG_REQUEST_TRAVERSAL: 3596 mWindowManagerInternal.requestTraversalFromDisplayManager(); 3597 break; 3598 3599 case MSG_RECEIVED_DEVICE_STATE: 3600 mWindowManagerInternal.onDisplayManagerReceivedDeviceState(msg.arg1); 3601 break; 3602 3603 case MSG_UPDATE_VIEWPORT: { 3604 final boolean changed; 3605 synchronized (mSyncRoot) { 3606 changed = !mTempViewports.equals(mViewports); 3607 if (changed) { 3608 mTempViewports.clear(); 3609 for (DisplayViewport d : mViewports) { 3610 mTempViewports.add(d.makeCopy()); 3611 } 3612 } 3613 } 3614 if (changed) { 3615 mInputManagerInternal.setDisplayViewports(mTempViewports); 3616 } 3617 break; 3618 } 3619 3620 case MSG_LOAD_BRIGHTNESS_CONFIGURATIONS: 3621 loadBrightnessConfigurations(); 3622 break; 3623 3624 case MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE: 3625 ArraySet<Integer> uids; 3626 synchronized (mSyncRoot) { 3627 int displayId = msg.arg1; 3628 final LogicalDisplay display = 3629 mLogicalDisplayMapper.getDisplayLocked(displayId); 3630 if (display == null) { 3631 break; 3632 } 3633 uids = display.getPendingFrameRateOverrideUids(); 3634 display.clearPendingFrameRateOverrideUids(); 3635 } 3636 deliverDisplayEvent(msg.arg1, uids, msg.arg2); 3637 break; 3638 3639 case MSG_DELIVER_DISPLAY_GROUP_EVENT: 3640 deliverDisplayGroupEvent(msg.arg1, msg.arg2); 3641 break; 3642 3643 } 3644 } 3645 } 3646 3647 private final class LogicalDisplayListener implements LogicalDisplayMapper.Listener { 3648 3649 @GuardedBy("mSyncRoot") 3650 @Override onLogicalDisplayEventLocked(LogicalDisplay display, int event)3651 public void onLogicalDisplayEventLocked(LogicalDisplay display, int event) { 3652 switch (event) { 3653 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_ADDED: 3654 handleLogicalDisplayAddedLocked(display); 3655 break; 3656 3657 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_CHANGED: 3658 handleLogicalDisplayChangedLocked(display); 3659 break; 3660 3661 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REMOVED: 3662 handleLogicalDisplayRemovedLocked(display); 3663 break; 3664 3665 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_SWAPPED: 3666 handleLogicalDisplaySwappedLocked(display); 3667 break; 3668 3669 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED: 3670 handleLogicalDisplayFrameRateOverridesChangedLocked(display); 3671 break; 3672 3673 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION: 3674 handleLogicalDisplayDeviceStateTransitionLocked(display); 3675 break; 3676 3677 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_HDR_SDR_RATIO_CHANGED: 3678 handleLogicalDisplayHdrSdrRatioChangedLocked(display); 3679 break; 3680 3681 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_CONNECTED: 3682 handleLogicalDisplayConnectedLocked(display); 3683 break; 3684 3685 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_DISCONNECTED: 3686 handleLogicalDisplayDisconnectedLocked(display); 3687 break; 3688 } 3689 } 3690 3691 @Override onDisplayGroupEventLocked(int groupId, int event)3692 public void onDisplayGroupEventLocked(int groupId, int event) { 3693 sendDisplayGroupEvent(groupId, event); 3694 } 3695 3696 @Override onTraversalRequested()3697 public void onTraversalRequested() { 3698 synchronized (mSyncRoot) { 3699 scheduleTraversalLocked(false); 3700 } 3701 } 3702 } 3703 3704 private final class CallbackRecord implements DeathRecipient { 3705 public final int mPid; 3706 public final int mUid; 3707 private final IDisplayManagerCallback mCallback; 3708 private @EventsMask AtomicLong mEventsMask; 3709 private final String mPackageName; 3710 3711 public boolean mWifiDisplayScanRequested; 3712 CallbackRecord(int pid, int uid, IDisplayManagerCallback callback, @EventsMask long eventsMask)3713 CallbackRecord(int pid, int uid, IDisplayManagerCallback callback, 3714 @EventsMask long eventsMask) { 3715 mPid = pid; 3716 mUid = uid; 3717 mCallback = callback; 3718 mEventsMask = new AtomicLong(eventsMask); 3719 3720 String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid); 3721 mPackageName = packageNames == null ? null : packageNames[0]; 3722 } 3723 updateEventsMask(@ventsMask long eventsMask)3724 public void updateEventsMask(@EventsMask long eventsMask) { 3725 mEventsMask.set(eventsMask); 3726 } 3727 3728 @Override binderDied()3729 public void binderDied() { 3730 if (DEBUG || extraLogging(mPackageName)) { 3731 Slog.d(TAG, "Display listener for pid " + mPid + " died."); 3732 } 3733 if (Trace.isTagEnabled(Trace.TRACE_TAG_POWER)) { 3734 Trace.instant(Trace.TRACE_TAG_POWER, 3735 "displayManagerBinderDied#mPid=" + mPid); 3736 } 3737 onCallbackDied(this); 3738 } 3739 3740 /** 3741 * @return {@code false} if RemoteException happens; otherwise {@code true} for success. 3742 */ notifyDisplayEventAsync(int displayId, @DisplayEvent int event)3743 public boolean notifyDisplayEventAsync(int displayId, @DisplayEvent int event) { 3744 if (!shouldSendEvent(event)) { 3745 if (extraLogging(mPackageName)) { 3746 Slog.i(TAG, 3747 "Not sending displayEvent: " + event + " due to mask:" + mEventsMask); 3748 } 3749 if (Trace.isTagEnabled(Trace.TRACE_TAG_POWER)) { 3750 Trace.instant(Trace.TRACE_TAG_POWER, 3751 "notifyDisplayEventAsync#notSendingEvent=" + event + ",mEventsMask=" 3752 + mEventsMask); 3753 } 3754 return true; 3755 } 3756 3757 try { 3758 mCallback.onDisplayEvent(displayId, event); 3759 return true; 3760 } catch (RemoteException ex) { 3761 Slog.w(TAG, "Failed to notify process " 3762 + mPid + " that displays changed, assuming it died.", ex); 3763 binderDied(); 3764 return false; 3765 } 3766 } 3767 shouldSendEvent(@isplayEvent int event)3768 private boolean shouldSendEvent(@DisplayEvent int event) { 3769 final long mask = mEventsMask.get(); 3770 switch (event) { 3771 case DisplayManagerGlobal.EVENT_DISPLAY_ADDED: 3772 return (mask & DisplayManager.EVENT_FLAG_DISPLAY_ADDED) != 0; 3773 case DisplayManagerGlobal.EVENT_DISPLAY_CHANGED: 3774 return (mask & DisplayManager.EVENT_FLAG_DISPLAY_CHANGED) != 0; 3775 case DisplayManagerGlobal.EVENT_DISPLAY_BRIGHTNESS_CHANGED: 3776 return (mask & DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS) != 0; 3777 case DisplayManagerGlobal.EVENT_DISPLAY_REMOVED: 3778 return (mask & DisplayManager.EVENT_FLAG_DISPLAY_REMOVED) != 0; 3779 case DisplayManagerGlobal.EVENT_DISPLAY_HDR_SDR_RATIO_CHANGED: 3780 return (mask & DisplayManager.EVENT_FLAG_HDR_SDR_RATIO_CHANGED) != 0; 3781 case DisplayManagerGlobal.EVENT_DISPLAY_CONNECTED: 3782 // fallthrough 3783 case DisplayManagerGlobal.EVENT_DISPLAY_DISCONNECTED: 3784 return (mask & DisplayManager.EVENT_FLAG_DISPLAY_CONNECTION_CHANGED) != 0; 3785 default: 3786 // This should never happen. 3787 Slog.e(TAG, "Unknown display event " + event); 3788 return true; 3789 } 3790 } 3791 } 3792 3793 private static final class PendingCallback { 3794 private final CallbackRecord mCallbackRecord; 3795 private final ArrayList<Pair<Integer, Integer>> mDisplayEvents; 3796 PendingCallback(CallbackRecord cr, int displayId, int event)3797 PendingCallback(CallbackRecord cr, int displayId, int event) { 3798 mCallbackRecord = cr; 3799 mDisplayEvents = new ArrayList<>(); 3800 mDisplayEvents.add(new Pair<>(displayId, event)); 3801 } 3802 addDisplayEvent(int displayId, int event)3803 public void addDisplayEvent(int displayId, int event) { 3804 // Ignore redundant events. Further optimization is possible by merging adjacent events. 3805 Pair<Integer, Integer> last = mDisplayEvents.get(mDisplayEvents.size() - 1); 3806 if (last.first == displayId && last.second == event) { 3807 Slog.d(TAG, 3808 "Ignore redundant display event " + displayId + "/" + event + " to " 3809 + mCallbackRecord.mUid + "/" + mCallbackRecord.mPid); 3810 return; 3811 } 3812 3813 mDisplayEvents.add(new Pair<>(displayId, event)); 3814 } 3815 sendPendingDisplayEvent()3816 public void sendPendingDisplayEvent() { 3817 for (int i = 0; i < mDisplayEvents.size(); i++) { 3818 Pair<Integer, Integer> displayEvent = mDisplayEvents.get(i); 3819 if (DEBUG) { 3820 Slog.d(TAG, "Send pending display event #" + i + " " + displayEvent.first + "/" 3821 + displayEvent.second + " to " + mCallbackRecord.mUid + "/" 3822 + mCallbackRecord.mPid); 3823 } 3824 if (!mCallbackRecord.notifyDisplayEventAsync(displayEvent.first, 3825 displayEvent.second)) { 3826 Slog.d(TAG, "Drop pending events for dead process " + mCallbackRecord.mPid); 3827 break; 3828 } 3829 } 3830 mDisplayEvents.clear(); 3831 } 3832 } 3833 3834 @VisibleForTesting 3835 final class BinderService extends IDisplayManager.Stub { 3836 /** 3837 * Returns information about the specified logical display. 3838 * 3839 * @param displayId The logical display id. 3840 * @return The logical display info, return {@code null} if the display does not exist or 3841 * the calling UID isn't present on the display. The returned object must be treated as 3842 * immutable. 3843 */ 3844 @Override // Binder call getDisplayInfo(int displayId)3845 public DisplayInfo getDisplayInfo(int displayId) { 3846 final int callingUid = Binder.getCallingUid(); 3847 final long token = Binder.clearCallingIdentity(); 3848 try { 3849 return getDisplayInfoInternal(displayId, callingUid); 3850 } finally { 3851 Binder.restoreCallingIdentity(token); 3852 } 3853 } 3854 3855 /** 3856 * Returns the list of all display ids. 3857 */ 3858 @Override // Binder call getDisplayIds(boolean includeDisabled)3859 public int[] getDisplayIds(boolean includeDisabled) { 3860 final int callingUid = Binder.getCallingUid(); 3861 final long token = Binder.clearCallingIdentity(); 3862 try { 3863 synchronized (mSyncRoot) { 3864 return mLogicalDisplayMapper.getDisplayIdsLocked(callingUid, includeDisabled); 3865 } 3866 } finally { 3867 Binder.restoreCallingIdentity(token); 3868 } 3869 } 3870 3871 @Override // Binder call isUidPresentOnDisplay(int uid, int displayId)3872 public boolean isUidPresentOnDisplay(int uid, int displayId) { 3873 final long token = Binder.clearCallingIdentity(); 3874 try { 3875 return isUidPresentOnDisplayInternal(uid, displayId); 3876 } finally { 3877 Binder.restoreCallingIdentity(token); 3878 } 3879 } 3880 3881 /** 3882 * Returns the stable device display size, in pixels. 3883 */ 3884 @Override // Binder call getStableDisplaySize()3885 public Point getStableDisplaySize() { 3886 final long token = Binder.clearCallingIdentity(); 3887 try { 3888 return getStableDisplaySizeInternal(); 3889 } finally { 3890 Binder.restoreCallingIdentity(token); 3891 } 3892 } 3893 3894 @Override // Binder call registerCallback(IDisplayManagerCallback callback)3895 public void registerCallback(IDisplayManagerCallback callback) { 3896 registerCallbackWithEventMask(callback, DisplayManager.EVENT_FLAG_DISPLAY_ADDED 3897 | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED 3898 | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED); 3899 } 3900 3901 @Override // Binder call 3902 @SuppressLint("AndroidFrameworkRequiresPermission") // Permission only required sometimes registerCallbackWithEventMask(IDisplayManagerCallback callback, @EventsMask long eventsMask)3903 public void registerCallbackWithEventMask(IDisplayManagerCallback callback, 3904 @EventsMask long eventsMask) { 3905 if (callback == null) { 3906 throw new IllegalArgumentException("listener must not be null"); 3907 } 3908 3909 final int callingPid = Binder.getCallingPid(); 3910 final int callingUid = Binder.getCallingUid(); 3911 3912 if (mFlags.isConnectedDisplayManagementEnabled()) { 3913 if ((eventsMask & DisplayManager.EVENT_FLAG_DISPLAY_CONNECTION_CHANGED) != 0) { 3914 mContext.enforceCallingOrSelfPermission(MANAGE_DISPLAYS, 3915 "Permission required to get signals about connection events."); 3916 } 3917 } 3918 3919 final long token = Binder.clearCallingIdentity(); 3920 try { 3921 registerCallbackInternal(callback, callingPid, callingUid, eventsMask); 3922 } finally { 3923 Binder.restoreCallingIdentity(token); 3924 } 3925 } 3926 3927 @EnforcePermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) 3928 @Override // Binder call startWifiDisplayScan()3929 public void startWifiDisplayScan() { 3930 startWifiDisplayScan_enforcePermission(); 3931 3932 final int callingPid = Binder.getCallingPid(); 3933 final long token = Binder.clearCallingIdentity(); 3934 try { 3935 startWifiDisplayScanInternal(callingPid); 3936 } finally { 3937 Binder.restoreCallingIdentity(token); 3938 } 3939 } 3940 3941 @EnforcePermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) 3942 @Override // Binder call stopWifiDisplayScan()3943 public void stopWifiDisplayScan() { 3944 stopWifiDisplayScan_enforcePermission(); 3945 3946 final int callingPid = Binder.getCallingPid(); 3947 final long token = Binder.clearCallingIdentity(); 3948 try { 3949 stopWifiDisplayScanInternal(callingPid); 3950 } finally { 3951 Binder.restoreCallingIdentity(token); 3952 } 3953 } 3954 3955 @Override // Binder call connectWifiDisplay(String address)3956 public void connectWifiDisplay(String address) { 3957 if (address == null) { 3958 throw new IllegalArgumentException("address must not be null"); 3959 } 3960 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 3961 "Permission required to connect to a wifi display"); 3962 3963 final long token = Binder.clearCallingIdentity(); 3964 try { 3965 connectWifiDisplayInternal(address); 3966 } finally { 3967 Binder.restoreCallingIdentity(token); 3968 } 3969 } 3970 3971 @Override // Binder call disconnectWifiDisplay()3972 public void disconnectWifiDisplay() { 3973 // This request does not require special permissions. 3974 // Any app can request disconnection from the currently active wifi display. 3975 // This exception should no longer be needed once wifi display control moves 3976 // to the media router service. 3977 3978 final long token = Binder.clearCallingIdentity(); 3979 try { 3980 disconnectWifiDisplayInternal(); 3981 } finally { 3982 Binder.restoreCallingIdentity(token); 3983 } 3984 } 3985 3986 @Override // Binder call renameWifiDisplay(String address, String alias)3987 public void renameWifiDisplay(String address, String alias) { 3988 if (address == null) { 3989 throw new IllegalArgumentException("address must not be null"); 3990 } 3991 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 3992 "Permission required to rename to a wifi display"); 3993 3994 final long token = Binder.clearCallingIdentity(); 3995 try { 3996 renameWifiDisplayInternal(address, alias); 3997 } finally { 3998 Binder.restoreCallingIdentity(token); 3999 } 4000 } 4001 4002 @Override // Binder call forgetWifiDisplay(String address)4003 public void forgetWifiDisplay(String address) { 4004 if (address == null) { 4005 throw new IllegalArgumentException("address must not be null"); 4006 } 4007 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 4008 "Permission required to forget to a wifi display"); 4009 4010 final long token = Binder.clearCallingIdentity(); 4011 try { 4012 forgetWifiDisplayInternal(address); 4013 } finally { 4014 Binder.restoreCallingIdentity(token); 4015 } 4016 } 4017 4018 @EnforcePermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) 4019 @Override // Binder call pauseWifiDisplay()4020 public void pauseWifiDisplay() { 4021 pauseWifiDisplay_enforcePermission(); 4022 4023 final long token = Binder.clearCallingIdentity(); 4024 try { 4025 pauseWifiDisplayInternal(); 4026 } finally { 4027 Binder.restoreCallingIdentity(token); 4028 } 4029 } 4030 4031 @EnforcePermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) 4032 @Override // Binder call resumeWifiDisplay()4033 public void resumeWifiDisplay() { 4034 resumeWifiDisplay_enforcePermission(); 4035 4036 final long token = Binder.clearCallingIdentity(); 4037 try { 4038 resumeWifiDisplayInternal(); 4039 } finally { 4040 Binder.restoreCallingIdentity(token); 4041 } 4042 } 4043 4044 @Override // Binder call getWifiDisplayStatus()4045 public WifiDisplayStatus getWifiDisplayStatus() { 4046 // This request does not require special permissions. 4047 // Any app can get information about available wifi displays. 4048 4049 final long token = Binder.clearCallingIdentity(); 4050 try { 4051 return getWifiDisplayStatusInternal(); 4052 } finally { 4053 Binder.restoreCallingIdentity(token); 4054 } 4055 } 4056 4057 @EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) 4058 @Override // Binder call setUserDisabledHdrTypes(int[] userDisabledFormats)4059 public void setUserDisabledHdrTypes(int[] userDisabledFormats) { 4060 setUserDisabledHdrTypes_enforcePermission(); 4061 4062 final long token = Binder.clearCallingIdentity(); 4063 try { 4064 setUserDisabledHdrTypesInternal(userDisabledFormats); 4065 } finally { 4066 Binder.restoreCallingIdentity(token); 4067 } 4068 } 4069 4070 @Override overrideHdrTypes(int displayId, int[] modes)4071 public void overrideHdrTypes(int displayId, int[] modes) { 4072 IBinder displayToken; 4073 synchronized (mSyncRoot) { 4074 displayToken = getDisplayToken(displayId); 4075 if (displayToken == null) { 4076 throw new IllegalArgumentException("Invalid display: " + displayId); 4077 } 4078 } 4079 4080 DisplayControl.overrideHdrTypes(displayToken, modes); 4081 } 4082 4083 @EnforcePermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) 4084 @Override // Binder call setAreUserDisabledHdrTypesAllowed(boolean areUserDisabledHdrTypesAllowed)4085 public void setAreUserDisabledHdrTypesAllowed(boolean areUserDisabledHdrTypesAllowed) { 4086 setAreUserDisabledHdrTypesAllowed_enforcePermission(); 4087 final long token = Binder.clearCallingIdentity(); 4088 try { 4089 setAreUserDisabledHdrTypesAllowedInternal(areUserDisabledHdrTypesAllowed); 4090 } finally { 4091 Binder.restoreCallingIdentity(token); 4092 } 4093 } 4094 4095 @Override // Binder call areUserDisabledHdrTypesAllowed()4096 public boolean areUserDisabledHdrTypesAllowed() { 4097 synchronized (mSyncRoot) { 4098 return mAreUserDisabledHdrTypesAllowed; 4099 } 4100 } 4101 4102 @Override // Binder call getUserDisabledHdrTypes()4103 public int[] getUserDisabledHdrTypes() { 4104 synchronized (mSyncRoot) { 4105 return mUserDisabledHdrTypes; 4106 } 4107 } 4108 4109 @EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE) 4110 @Override // Binder call requestColorMode(int displayId, int colorMode)4111 public void requestColorMode(int displayId, int colorMode) { 4112 requestColorMode_enforcePermission(); 4113 final long token = Binder.clearCallingIdentity(); 4114 try { 4115 requestColorModeInternal(displayId, colorMode); 4116 } finally { 4117 Binder.restoreCallingIdentity(token); 4118 } 4119 } 4120 4121 @Override // Binder call createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig, IVirtualDisplayCallback callback, IMediaProjection projection, String packageName)4122 public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig, 4123 IVirtualDisplayCallback callback, IMediaProjection projection, 4124 String packageName) { 4125 return createVirtualDisplayInternal(virtualDisplayConfig, callback, projection, 4126 null, null, packageName); 4127 } 4128 4129 @Override // Binder call resizeVirtualDisplay(IVirtualDisplayCallback callback, int width, int height, int densityDpi)4130 public void resizeVirtualDisplay(IVirtualDisplayCallback callback, 4131 int width, int height, int densityDpi) { 4132 if (width <= 0 || height <= 0 || densityDpi <= 0) { 4133 throw new IllegalArgumentException("width, height, and densityDpi must be " 4134 + "greater than 0"); 4135 } 4136 final long token = Binder.clearCallingIdentity(); 4137 try { 4138 resizeVirtualDisplayInternal(callback.asBinder(), width, height, densityDpi); 4139 } finally { 4140 Binder.restoreCallingIdentity(token); 4141 } 4142 } 4143 4144 @Override // Binder call setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface)4145 public void setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface) { 4146 if (surface != null && surface.isSingleBuffered()) { 4147 throw new IllegalArgumentException("Surface can't be single-buffered"); 4148 } 4149 final long token = Binder.clearCallingIdentity(); 4150 try { 4151 setVirtualDisplaySurfaceInternal(callback.asBinder(), surface); 4152 } finally { 4153 Binder.restoreCallingIdentity(token); 4154 } 4155 } 4156 4157 @Override // Binder call releaseVirtualDisplay(IVirtualDisplayCallback callback)4158 public void releaseVirtualDisplay(IVirtualDisplayCallback callback) { 4159 final long token = Binder.clearCallingIdentity(); 4160 try { 4161 releaseVirtualDisplayInternal(callback.asBinder()); 4162 } finally { 4163 Binder.restoreCallingIdentity(token); 4164 } 4165 } 4166 4167 @Override // Binder call setVirtualDisplayState(IVirtualDisplayCallback callback, boolean isOn)4168 public void setVirtualDisplayState(IVirtualDisplayCallback callback, boolean isOn) { 4169 final long token = Binder.clearCallingIdentity(); 4170 try { 4171 setVirtualDisplayStateInternal(callback.asBinder(), isOn); 4172 } finally { 4173 Binder.restoreCallingIdentity(token); 4174 } 4175 } 4176 4177 @Override // Binder call dump(@onNull FileDescriptor fd, @NonNull final PrintWriter pw, String[] args)4178 public void dump(@NonNull FileDescriptor fd, @NonNull final PrintWriter pw, String[] args) { 4179 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 4180 4181 final long token = Binder.clearCallingIdentity(); 4182 try { 4183 dumpInternal(pw); 4184 } finally { 4185 Binder.restoreCallingIdentity(token); 4186 } 4187 } 4188 4189 @EnforcePermission(android.Manifest.permission.BRIGHTNESS_SLIDER_USAGE) 4190 @Override // Binder call getBrightnessEvents(String callingPackage)4191 public ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents(String callingPackage) { 4192 getBrightnessEvents_enforcePermission(); 4193 4194 final int callingUid = Binder.getCallingUid(); 4195 AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class); 4196 final int mode = appOpsManager.noteOp(AppOpsManager.OP_GET_USAGE_STATS, 4197 callingUid, callingPackage); 4198 final boolean hasUsageStats; 4199 if (mode == AppOpsManager.MODE_DEFAULT) { 4200 // The default behavior here is to check if PackageManager has given the app 4201 // permission. 4202 hasUsageStats = mContext.checkCallingPermission( 4203 Manifest.permission.PACKAGE_USAGE_STATS) 4204 == PackageManager.PERMISSION_GRANTED; 4205 } else { 4206 hasUsageStats = mode == AppOpsManager.MODE_ALLOWED; 4207 } 4208 4209 final int userId = UserHandle.getUserId(callingUid); 4210 final long token = Binder.clearCallingIdentity(); 4211 try { 4212 synchronized (mSyncRoot) { 4213 return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY) 4214 .getBrightnessEvents(userId, hasUsageStats); 4215 } 4216 } finally { 4217 Binder.restoreCallingIdentity(token); 4218 } 4219 } 4220 4221 @EnforcePermission(android.Manifest.permission.ACCESS_AMBIENT_LIGHT_STATS) 4222 @Override // Binder call getAmbientBrightnessStats()4223 public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats() { 4224 getAmbientBrightnessStats_enforcePermission(); 4225 final int callingUid = Binder.getCallingUid(); 4226 final int userId = UserHandle.getUserId(callingUid); 4227 final long token = Binder.clearCallingIdentity(); 4228 try { 4229 synchronized (mSyncRoot) { 4230 return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY) 4231 .getAmbientBrightnessStats(userId); 4232 } 4233 } finally { 4234 Binder.restoreCallingIdentity(token); 4235 } 4236 } 4237 4238 @EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) 4239 @Override // Binder call setBrightnessConfigurationForUser( BrightnessConfiguration c, @UserIdInt int userId, String packageName)4240 public void setBrightnessConfigurationForUser( 4241 BrightnessConfiguration c, @UserIdInt int userId, String packageName) { 4242 setBrightnessConfigurationForUser_enforcePermission(); 4243 if (userId != UserHandle.getCallingUserId()) { 4244 mContext.enforceCallingOrSelfPermission( 4245 Manifest.permission.INTERACT_ACROSS_USERS, 4246 "Permission required to change the display brightness" 4247 + " configuration of another user"); 4248 } 4249 final long token = Binder.clearCallingIdentity(); 4250 try { 4251 synchronized (mSyncRoot) { 4252 mLogicalDisplayMapper.forEachLocked(logicalDisplay -> { 4253 if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) { 4254 return; 4255 } 4256 final DisplayDevice displayDevice = 4257 logicalDisplay.getPrimaryDisplayDeviceLocked(); 4258 setBrightnessConfigurationForDisplayInternal(c, displayDevice.getUniqueId(), 4259 userId, packageName); 4260 }); 4261 } 4262 } finally { 4263 Binder.restoreCallingIdentity(token); 4264 } 4265 } 4266 4267 @EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) 4268 @Override // Binder call setBrightnessConfigurationForDisplay(BrightnessConfiguration c, String uniqueId, int userId, String packageName)4269 public void setBrightnessConfigurationForDisplay(BrightnessConfiguration c, 4270 String uniqueId, int userId, String packageName) { 4271 setBrightnessConfigurationForDisplay_enforcePermission(); 4272 if (userId != UserHandle.getCallingUserId()) { 4273 mContext.enforceCallingOrSelfPermission( 4274 Manifest.permission.INTERACT_ACROSS_USERS, 4275 "Permission required to change the display brightness" 4276 + " configuration of another user"); 4277 } 4278 final long token = Binder.clearCallingIdentity(); 4279 try { 4280 setBrightnessConfigurationForDisplayInternal(c, uniqueId, userId, packageName); 4281 } finally { 4282 Binder.restoreCallingIdentity(token); 4283 } 4284 } 4285 4286 @EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) 4287 @Override // Binder call getBrightnessConfigurationForDisplay(String uniqueId, int userId)4288 public BrightnessConfiguration getBrightnessConfigurationForDisplay(String uniqueId, 4289 int userId) { 4290 getBrightnessConfigurationForDisplay_enforcePermission(); 4291 if (userId != UserHandle.getCallingUserId()) { 4292 mContext.enforceCallingOrSelfPermission( 4293 Manifest.permission.INTERACT_ACROSS_USERS, 4294 "Permission required to read the display brightness" 4295 + " configuration of another user"); 4296 } 4297 final long token = Binder.clearCallingIdentity(); 4298 final int userSerial = getUserManager().getUserSerialNumber(userId); 4299 try { 4300 synchronized (mSyncRoot) { 4301 // Get from per-display configurations 4302 BrightnessConfiguration config = 4303 getBrightnessConfigForDisplayWithPdsFallbackLocked( 4304 uniqueId, userSerial); 4305 if (config == null) { 4306 // Get default configuration 4307 DisplayPowerControllerInterface dpc = getDpcFromUniqueIdLocked(uniqueId); 4308 if (dpc != null) { 4309 config = dpc.getDefaultBrightnessConfiguration(); 4310 } 4311 } 4312 return config; 4313 } 4314 } finally { 4315 Binder.restoreCallingIdentity(token); 4316 } 4317 } 4318 4319 4320 4321 @Override // Binder call getBrightnessConfigurationForUser(int userId)4322 public BrightnessConfiguration getBrightnessConfigurationForUser(int userId) { 4323 final String uniqueId; 4324 synchronized (mSyncRoot) { 4325 DisplayDevice displayDevice = mLogicalDisplayMapper.getDisplayLocked( 4326 Display.DEFAULT_DISPLAY).getPrimaryDisplayDeviceLocked(); 4327 uniqueId = displayDevice.getUniqueId(); 4328 } 4329 return getBrightnessConfigurationForDisplay(uniqueId, userId); 4330 4331 4332 } 4333 4334 @EnforcePermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) 4335 @Override // Binder call getDefaultBrightnessConfiguration()4336 public BrightnessConfiguration getDefaultBrightnessConfiguration() { 4337 getDefaultBrightnessConfiguration_enforcePermission(); 4338 final long token = Binder.clearCallingIdentity(); 4339 try { 4340 synchronized (mSyncRoot) { 4341 return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY) 4342 .getDefaultBrightnessConfiguration(); 4343 } 4344 } finally { 4345 Binder.restoreCallingIdentity(token); 4346 } 4347 } 4348 4349 @EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS) 4350 @Override getBrightnessInfo(int displayId)4351 public BrightnessInfo getBrightnessInfo(int displayId) { 4352 getBrightnessInfo_enforcePermission(); 4353 final long token = Binder.clearCallingIdentity(); 4354 try { 4355 synchronized (mSyncRoot) { 4356 LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked( 4357 displayId, /* includeDisabled= */ false); 4358 if (display == null || !display.isEnabledLocked()) { 4359 return null; 4360 } 4361 DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId); 4362 if (dpc != null) { 4363 return dpc.getBrightnessInfo(); 4364 } 4365 } 4366 } finally { 4367 Binder.restoreCallingIdentity(token); 4368 } 4369 return null; 4370 } 4371 4372 @Override // Binder call isMinimalPostProcessingRequested(int displayId)4373 public boolean isMinimalPostProcessingRequested(int displayId) { 4374 synchronized (mSyncRoot) { 4375 return mLogicalDisplayMapper.getDisplayLocked(displayId) 4376 .getRequestedMinimalPostProcessingLocked(); 4377 } 4378 } 4379 4380 @EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS) 4381 @Override // Binder call setTemporaryBrightness(int displayId, float brightness)4382 public void setTemporaryBrightness(int displayId, float brightness) { 4383 setTemporaryBrightness_enforcePermission(); 4384 final long token = Binder.clearCallingIdentity(); 4385 try { 4386 synchronized (mSyncRoot) { 4387 mDisplayPowerControllers.get(displayId) 4388 .setTemporaryBrightness(brightness); 4389 } 4390 } finally { 4391 Binder.restoreCallingIdentity(token); 4392 } 4393 } 4394 4395 @EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS) 4396 @Override // Binder call setBrightness(int displayId, float brightness)4397 public void setBrightness(int displayId, float brightness) { 4398 setBrightness_enforcePermission(); 4399 if (!isValidBrightness(brightness)) { 4400 Slog.w(TAG, "Attempted to set invalid brightness" + brightness); 4401 return; 4402 } 4403 final long token = Binder.clearCallingIdentity(); 4404 try { 4405 synchronized (mSyncRoot) { 4406 DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId); 4407 if (dpc != null) { 4408 dpc.setBrightness(brightness); 4409 } 4410 mPersistentDataStore.saveIfNeeded(); 4411 } 4412 } finally { 4413 Binder.restoreCallingIdentity(token); 4414 } 4415 } 4416 4417 @Override // Binder call getBrightness(int displayId)4418 public float getBrightness(int displayId) { 4419 float brightness = PowerManager.BRIGHTNESS_INVALID_FLOAT; 4420 mContext.enforceCallingOrSelfPermission( 4421 Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS, 4422 "Permission required to set the display's brightness"); 4423 final long token = Binder.clearCallingIdentity(); 4424 try { 4425 synchronized (mSyncRoot) { 4426 DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId); 4427 if (dpc != null) { 4428 brightness = dpc.getScreenBrightnessSetting(); 4429 } 4430 } 4431 } finally { 4432 Binder.restoreCallingIdentity(token); 4433 } 4434 return brightness; 4435 } 4436 4437 @EnforcePermission(android.Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS) 4438 @Override // Binder call setTemporaryAutoBrightnessAdjustment(float adjustment)4439 public void setTemporaryAutoBrightnessAdjustment(float adjustment) { 4440 setTemporaryAutoBrightnessAdjustment_enforcePermission(); 4441 final long token = Binder.clearCallingIdentity(); 4442 try { 4443 synchronized (mSyncRoot) { 4444 mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY) 4445 .setTemporaryAutoBrightnessAdjustment(adjustment); 4446 } 4447 } finally { 4448 Binder.restoreCallingIdentity(token); 4449 } 4450 } 4451 4452 @Override // Binder call onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, @NonNull String[] args, ShellCallback callback, @NonNull ResultReceiver resultReceiver)4453 public void onShellCommand(FileDescriptor in, FileDescriptor out, 4454 FileDescriptor err, @NonNull String[] args, ShellCallback callback, 4455 @NonNull ResultReceiver resultReceiver) { 4456 new DisplayManagerShellCommand(DisplayManagerService.this, mFlags).exec(this, in, out, 4457 err, args, callback, resultReceiver); 4458 } 4459 4460 @Override // Binder call getMinimumBrightnessCurve()4461 public Curve getMinimumBrightnessCurve() { 4462 final long token = Binder.clearCallingIdentity(); 4463 try { 4464 return getMinimumBrightnessCurveInternal(); 4465 } finally { 4466 Binder.restoreCallingIdentity(token); 4467 } 4468 } 4469 4470 @Override // Binder call getPreferredWideGamutColorSpaceId()4471 public int getPreferredWideGamutColorSpaceId() { 4472 final long token = Binder.clearCallingIdentity(); 4473 try { 4474 return getPreferredWideGamutColorSpaceIdInternal(); 4475 } finally { 4476 Binder.restoreCallingIdentity(token); 4477 } 4478 } 4479 4480 @EnforcePermission(android.Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE) 4481 @Override // Binder call setUserPreferredDisplayMode(int displayId, Display.Mode mode)4482 public void setUserPreferredDisplayMode(int displayId, Display.Mode mode) { 4483 setUserPreferredDisplayMode_enforcePermission(); 4484 final long token = Binder.clearCallingIdentity(); 4485 try { 4486 setUserPreferredDisplayModeInternal(displayId, mode); 4487 } finally { 4488 Binder.restoreCallingIdentity(token); 4489 } 4490 } 4491 4492 @Override // Binder call getUserPreferredDisplayMode(int displayId)4493 public Display.Mode getUserPreferredDisplayMode(int displayId) { 4494 final long token = Binder.clearCallingIdentity(); 4495 try { 4496 return getUserPreferredDisplayModeInternal(displayId); 4497 } finally { 4498 Binder.restoreCallingIdentity(token); 4499 } 4500 } 4501 4502 @Override // Binder call getSystemPreferredDisplayMode(int displayId)4503 public Display.Mode getSystemPreferredDisplayMode(int displayId) { 4504 final long token = Binder.clearCallingIdentity(); 4505 try { 4506 return getSystemPreferredDisplayModeInternal(displayId); 4507 } finally { 4508 Binder.restoreCallingIdentity(token); 4509 } 4510 } 4511 4512 @Override // Binder call setHdrConversionMode(HdrConversionMode hdrConversionMode)4513 public void setHdrConversionMode(HdrConversionMode hdrConversionMode) { 4514 if (!mIsHdrOutputControlEnabled) { 4515 return; 4516 } 4517 mContext.enforceCallingOrSelfPermission( 4518 Manifest.permission.MODIFY_HDR_CONVERSION_MODE, 4519 "Permission required to set the HDR conversion mode."); 4520 final long token = Binder.clearCallingIdentity(); 4521 try { 4522 setHdrConversionModeInternal(hdrConversionMode); 4523 } finally { 4524 Binder.restoreCallingIdentity(token); 4525 } 4526 } 4527 4528 @Override // Binder call getHdrConversionModeSetting()4529 public HdrConversionMode getHdrConversionModeSetting() { 4530 if (!mIsHdrOutputControlEnabled) { 4531 return HDR_CONVERSION_MODE_UNSUPPORTED; 4532 } 4533 final long token = Binder.clearCallingIdentity(); 4534 try { 4535 return getHdrConversionModeSettingInternal(); 4536 } finally { 4537 Binder.restoreCallingIdentity(token); 4538 } 4539 } 4540 4541 @Override // Binder call getHdrConversionMode()4542 public HdrConversionMode getHdrConversionMode() { 4543 if (!mIsHdrOutputControlEnabled) { 4544 return HDR_CONVERSION_MODE_UNSUPPORTED; 4545 } 4546 final long token = Binder.clearCallingIdentity(); 4547 try { 4548 return getHdrConversionModeInternal(); 4549 } finally { 4550 Binder.restoreCallingIdentity(token); 4551 } 4552 } 4553 4554 @Display.HdrCapabilities.HdrType 4555 @Override // Binder call getSupportedHdrOutputTypes()4556 public int[] getSupportedHdrOutputTypes() { 4557 if (!mIsHdrOutputControlEnabled) { 4558 return EMPTY_ARRAY; 4559 } 4560 final long token = Binder.clearCallingIdentity(); 4561 try { 4562 return getSupportedHdrOutputTypesInternal(); 4563 } finally { 4564 Binder.restoreCallingIdentity(token); 4565 } 4566 } 4567 4568 @EnforcePermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) 4569 @Override // Binder call setShouldAlwaysRespectAppRequestedMode(boolean enabled)4570 public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) { 4571 setShouldAlwaysRespectAppRequestedMode_enforcePermission(); 4572 final long token = Binder.clearCallingIdentity(); 4573 try { 4574 setShouldAlwaysRespectAppRequestedModeInternal(enabled); 4575 } finally { 4576 Binder.restoreCallingIdentity(token); 4577 } 4578 } 4579 4580 @EnforcePermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) 4581 @Override // Binder call shouldAlwaysRespectAppRequestedMode()4582 public boolean shouldAlwaysRespectAppRequestedMode() { 4583 shouldAlwaysRespectAppRequestedMode_enforcePermission(); 4584 final long token = Binder.clearCallingIdentity(); 4585 try { 4586 return shouldAlwaysRespectAppRequestedModeInternal(); 4587 } finally { 4588 Binder.restoreCallingIdentity(token); 4589 } 4590 } 4591 4592 @EnforcePermission(android.Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE) 4593 @Override // Binder call setRefreshRateSwitchingType(int newValue)4594 public void setRefreshRateSwitchingType(int newValue) { 4595 setRefreshRateSwitchingType_enforcePermission(); 4596 final long token = Binder.clearCallingIdentity(); 4597 try { 4598 setRefreshRateSwitchingTypeInternal(newValue); 4599 } finally { 4600 Binder.restoreCallingIdentity(token); 4601 } 4602 } 4603 4604 @Override // Binder call getRefreshRateSwitchingType()4605 public int getRefreshRateSwitchingType() { 4606 final long token = Binder.clearCallingIdentity(); 4607 try { 4608 return getRefreshRateSwitchingTypeInternal(); 4609 } finally { 4610 Binder.restoreCallingIdentity(token); 4611 } 4612 } 4613 4614 @Override // Binder call getDisplayDecorationSupport(int displayId)4615 public DisplayDecorationSupport getDisplayDecorationSupport(int displayId) { 4616 final long token = Binder.clearCallingIdentity(); 4617 try { 4618 return getDisplayDecorationSupportInternal(displayId); 4619 } finally { 4620 Binder.restoreCallingIdentity(token); 4621 } 4622 } 4623 4624 @Override setDisplayIdToMirror(IBinder token, int displayId)4625 public void setDisplayIdToMirror(IBinder token, int displayId) { 4626 synchronized (mSyncRoot) { 4627 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 4628 if (mVirtualDisplayAdapter != null) { 4629 mVirtualDisplayAdapter.setDisplayIdToMirror(token, 4630 display == null ? Display.INVALID_DISPLAY : displayId); 4631 } 4632 } 4633 } 4634 4635 @Override getOverlaySupport()4636 public OverlayProperties getOverlaySupport() { 4637 final long token = Binder.clearCallingIdentity(); 4638 try { 4639 return getOverlaySupportInternal(); 4640 } finally { 4641 Binder.restoreCallingIdentity(token); 4642 } 4643 } 4644 4645 @EnforcePermission(MANAGE_DISPLAYS) enableConnectedDisplay(int displayId)4646 public void enableConnectedDisplay(int displayId) { 4647 enableConnectedDisplay_enforcePermission(); 4648 DisplayManagerService.this.enableConnectedDisplay(displayId, true); 4649 } 4650 4651 @EnforcePermission(MANAGE_DISPLAYS) disableConnectedDisplay(int displayId)4652 public void disableConnectedDisplay(int displayId) { 4653 disableConnectedDisplay_enforcePermission(); 4654 DisplayManagerService.this.enableConnectedDisplay(displayId, false); 4655 } 4656 4657 @EnforcePermission(MANAGE_DISPLAYS) requestDisplayPower(int displayId, boolean on)4658 public boolean requestDisplayPower(int displayId, boolean on) { 4659 requestDisplayPower_enforcePermission(); 4660 return DisplayManagerService.this.requestDisplayPower(displayId, on); 4661 } 4662 4663 @EnforcePermission(RESTRICT_DISPLAY_MODES) 4664 @Override // Binder call requestDisplayModes(IBinder token, int displayId, @Nullable int[] modeIds)4665 public void requestDisplayModes(IBinder token, int displayId, @Nullable int[] modeIds) { 4666 requestDisplayModes_enforcePermission(); 4667 DisplayManagerService.this.mDisplayModeDirector.requestDisplayModes( 4668 token, displayId, modeIds); 4669 } 4670 } 4671 isValidBrightness(float brightness)4672 private static boolean isValidBrightness(float brightness) { 4673 return !Float.isNaN(brightness) 4674 && (brightness >= PowerManager.BRIGHTNESS_MIN) 4675 && (brightness <= PowerManager.BRIGHTNESS_MAX); 4676 } 4677 4678 @VisibleForTesting overrideSensorManager(SensorManager sensorManager)4679 void overrideSensorManager(SensorManager sensorManager) { 4680 synchronized (mSyncRoot) { 4681 mSensorManager = sensorManager; 4682 } 4683 } 4684 4685 @VisibleForTesting 4686 final class LocalService extends DisplayManagerInternal { 4687 4688 @Override initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler, SensorManager sensorManager)4689 public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler, 4690 SensorManager sensorManager) { 4691 synchronized (mSyncRoot) { 4692 mDisplayPowerCallbacks = callbacks; 4693 mSensorManager = sensorManager; 4694 mPowerHandler = handler; 4695 initializeDisplayPowerControllersLocked(); 4696 } 4697 4698 mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATIONS); 4699 } 4700 4701 @Override createVirtualDisplay(VirtualDisplayConfig config, IVirtualDisplayCallback callback, IVirtualDevice virtualDevice, DisplayWindowPolicyController dwpc, String packageName)4702 public int createVirtualDisplay(VirtualDisplayConfig config, 4703 IVirtualDisplayCallback callback, IVirtualDevice virtualDevice, 4704 DisplayWindowPolicyController dwpc, String packageName) { 4705 return createVirtualDisplayInternal(config, callback, null, virtualDevice, dwpc, 4706 packageName); 4707 } 4708 4709 @Override requestPowerState(int groupId, DisplayPowerRequest request, boolean waitForNegativeProximity)4710 public boolean requestPowerState(int groupId, DisplayPowerRequest request, 4711 boolean waitForNegativeProximity) { 4712 synchronized (mSyncRoot) { 4713 final DisplayGroup displayGroup = mLogicalDisplayMapper.getDisplayGroupLocked( 4714 groupId); 4715 if (displayGroup == null) { 4716 return true; 4717 } 4718 4719 final int size = displayGroup.getSizeLocked(); 4720 boolean ready = true; 4721 for (int i = 0; i < size; i++) { 4722 final int id = displayGroup.getIdLocked(i); 4723 final DisplayDevice displayDevice = mLogicalDisplayMapper.getDisplayLocked( 4724 id).getPrimaryDisplayDeviceLocked(); 4725 final int flags = displayDevice.getDisplayDeviceInfoLocked().flags; 4726 if ((flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) { 4727 final DisplayPowerControllerInterface displayPowerController = 4728 mDisplayPowerControllers.get(id); 4729 if (displayPowerController != null) { 4730 ready &= displayPowerController.requestPowerState(request, 4731 waitForNegativeProximity); 4732 } 4733 } 4734 } 4735 4736 return ready; 4737 } 4738 } 4739 4740 @Override isProximitySensorAvailable()4741 public boolean isProximitySensorAvailable() { 4742 synchronized (mSyncRoot) { 4743 return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY) 4744 .isProximitySensorAvailable(); 4745 } 4746 } 4747 4748 @Override registerDisplayGroupListener(DisplayGroupListener listener)4749 public void registerDisplayGroupListener(DisplayGroupListener listener) { 4750 mDisplayGroupListeners.add(listener); 4751 } 4752 4753 @Override unregisterDisplayGroupListener(DisplayGroupListener listener)4754 public void unregisterDisplayGroupListener(DisplayGroupListener listener) { 4755 mDisplayGroupListeners.remove(listener); 4756 } 4757 4758 @Override systemScreenshot(int displayId)4759 public ScreenCapture.ScreenshotHardwareBuffer systemScreenshot(int displayId) { 4760 return systemScreenshotInternal(displayId); 4761 } 4762 4763 @Override userScreenshot(int displayId)4764 public ScreenCapture.ScreenshotHardwareBuffer userScreenshot(int displayId) { 4765 return userScreenshotInternal(displayId); 4766 } 4767 4768 @Override getDisplayInfo(int displayId)4769 public DisplayInfo getDisplayInfo(int displayId) { 4770 return getDisplayInfoInternal(displayId, Process.myUid()); 4771 } 4772 4773 @Override getPossibleDisplayInfo(int displayId)4774 public Set<DisplayInfo> getPossibleDisplayInfo(int displayId) { 4775 synchronized (mSyncRoot) { 4776 Set<DisplayInfo> possibleInfo = new ArraySet<>(); 4777 // For each of supported device states, retrieve the display layout of that state, 4778 // and return all of the DisplayInfos (one per state) for the given display id. 4779 if (mDeviceStateManager == null) { 4780 Slog.w(TAG, "Can't get supported states since DeviceStateManager not ready"); 4781 return possibleInfo; 4782 } 4783 final int[] supportedStates = 4784 mDeviceStateManager.getSupportedStateIdentifiers(); 4785 // TODO(b/352019542): remove the log once b/345960547 is fixed. 4786 Slog.d(TAG, "supportedStates=" + Arrays.toString(supportedStates)); 4787 DisplayInfo displayInfo; 4788 for (int state : supportedStates) { 4789 displayInfo = mLogicalDisplayMapper.getDisplayInfoForStateLocked(state, 4790 displayId); 4791 if (displayInfo != null) { 4792 possibleInfo.add(displayInfo); 4793 } 4794 } 4795 // TODO(b/352019542): remove the log once b/345960547 is fixed. 4796 Slog.d(TAG, "possibleInfos=" + possibleInfo); 4797 return possibleInfo; 4798 } 4799 } 4800 4801 @Override getDisplayPosition(int displayId)4802 public Point getDisplayPosition(int displayId) { 4803 synchronized (mSyncRoot) { 4804 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 4805 if (display != null) { 4806 return display.getDisplayPosition(); 4807 } 4808 return null; 4809 } 4810 } 4811 4812 @Override registerDisplayTransactionListener(DisplayTransactionListener listener)4813 public void registerDisplayTransactionListener(DisplayTransactionListener listener) { 4814 if (listener == null) { 4815 throw new IllegalArgumentException("listener must not be null"); 4816 } 4817 4818 registerDisplayTransactionListenerInternal(listener); 4819 } 4820 4821 @Override unregisterDisplayTransactionListener(DisplayTransactionListener listener)4822 public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) { 4823 if (listener == null) { 4824 throw new IllegalArgumentException("listener must not be null"); 4825 } 4826 4827 unregisterDisplayTransactionListenerInternal(listener); 4828 } 4829 4830 @Override setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info)4831 public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) { 4832 setDisplayInfoOverrideFromWindowManagerInternal(displayId, info); 4833 } 4834 4835 @Override getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo)4836 public void getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo) { 4837 getNonOverrideDisplayInfoInternal(displayId, outInfo); 4838 } 4839 4840 @Override performTraversal(SurfaceControl.Transaction t, SparseArray<SurfaceControl.Transaction> displayTransactions)4841 public void performTraversal(SurfaceControl.Transaction t, 4842 SparseArray<SurfaceControl.Transaction> displayTransactions) { 4843 performTraversalInternal(t, displayTransactions); 4844 } 4845 4846 @Override setDisplayProperties(int displayId, boolean hasContent, float requestedRefreshRate, int requestedMode, float requestedMinRefreshRate, float requestedMaxRefreshRate, boolean requestedMinimalPostProcessing, boolean disableHdrConversion, boolean inTraversal)4847 public void setDisplayProperties(int displayId, boolean hasContent, 4848 float requestedRefreshRate, int requestedMode, float requestedMinRefreshRate, 4849 float requestedMaxRefreshRate, boolean requestedMinimalPostProcessing, 4850 boolean disableHdrConversion, boolean inTraversal) { 4851 setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate, 4852 requestedMode, requestedMinRefreshRate, requestedMaxRefreshRate, 4853 requestedMinimalPostProcessing, disableHdrConversion, inTraversal); 4854 } 4855 4856 @Override setDisplayOffsets(int displayId, int x, int y)4857 public void setDisplayOffsets(int displayId, int x, int y) { 4858 setDisplayOffsetsInternal(displayId, x, y); 4859 } 4860 4861 @Override setDisplayScalingDisabled(int displayId, boolean disableScaling)4862 public void setDisplayScalingDisabled(int displayId, boolean disableScaling) { 4863 setDisplayScalingDisabledInternal(displayId, disableScaling); 4864 } 4865 4866 @Override setDisplayAccessUIDs(SparseArray<IntArray> newDisplayAccessUIDs)4867 public void setDisplayAccessUIDs(SparseArray<IntArray> newDisplayAccessUIDs) { 4868 setDisplayAccessUIDsInternal(newDisplayAccessUIDs); 4869 } 4870 4871 @Override persistBrightnessTrackerState()4872 public void persistBrightnessTrackerState() { 4873 synchronized (mSyncRoot) { 4874 mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY) 4875 .persistBrightnessTrackerState(); 4876 } 4877 } 4878 4879 @Override onOverlayChanged()4880 public void onOverlayChanged() { 4881 synchronized (mSyncRoot) { 4882 mDisplayDeviceRepo.forEachLocked(DisplayDevice::onOverlayChangedLocked); 4883 } 4884 } 4885 4886 @Override getDisplayedContentSamplingAttributes( int displayId)4887 public DisplayedContentSamplingAttributes getDisplayedContentSamplingAttributes( 4888 int displayId) { 4889 return getDisplayedContentSamplingAttributesInternal(displayId); 4890 } 4891 4892 @Override setDisplayedContentSamplingEnabled( int displayId, boolean enable, int componentMask, int maxFrames)4893 public boolean setDisplayedContentSamplingEnabled( 4894 int displayId, boolean enable, int componentMask, int maxFrames) { 4895 return setDisplayedContentSamplingEnabledInternal( 4896 displayId, enable, componentMask, maxFrames); 4897 } 4898 4899 @Override getDisplayedContentSample(int displayId, long maxFrames, long timestamp)4900 public DisplayedContentSample getDisplayedContentSample(int displayId, 4901 long maxFrames, long timestamp) { 4902 return getDisplayedContentSampleInternal(displayId, maxFrames, timestamp); 4903 } 4904 4905 @Override ignoreProximitySensorUntilChanged()4906 public void ignoreProximitySensorUntilChanged() { 4907 mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY) 4908 .ignoreProximitySensorUntilChanged(); 4909 } 4910 4911 @Override getRefreshRateSwitchingType()4912 public int getRefreshRateSwitchingType() { 4913 return getRefreshRateSwitchingTypeInternal(); 4914 } 4915 4916 @Override getRefreshRateForDisplayAndSensor(int displayId, String sensorName, String sensorType)4917 public RefreshRateRange getRefreshRateForDisplayAndSensor(int displayId, String sensorName, 4918 String sensorType) { 4919 final SensorManager sensorManager; 4920 synchronized (mSyncRoot) { 4921 sensorManager = mSensorManager; 4922 } 4923 if (sensorManager == null) { 4924 return null; 4925 } 4926 4927 // Verify that the specified sensor exists. 4928 final Sensor sensor = SensorUtils.findSensor(sensorManager, sensorType, sensorName, 4929 SensorUtils.NO_FALLBACK); 4930 if (sensor == null) { 4931 return null; 4932 } 4933 4934 synchronized (mSyncRoot) { 4935 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 4936 if (display == null) { 4937 return null; 4938 } 4939 final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); 4940 if (device == null) { 4941 return null; 4942 } 4943 final DisplayDeviceConfig config = device.getDisplayDeviceConfig(); 4944 SensorData sensorData = config.getProximitySensor(); 4945 if (sensorData != null && sensorData.matches(sensorName, sensorType)) { 4946 return new RefreshRateRange(sensorData.minRefreshRate, 4947 sensorData.maxRefreshRate); 4948 } 4949 } 4950 return null; 4951 } 4952 4953 @Override getRefreshRateLimitations(int displayId)4954 public List<RefreshRateLimitation> getRefreshRateLimitations(int displayId) { 4955 final DisplayDeviceConfig config; 4956 synchronized (mSyncRoot) { 4957 final DisplayDevice device = getDeviceForDisplayLocked(displayId); 4958 if (device == null) { 4959 return null; 4960 } 4961 config = device.getDisplayDeviceConfig(); 4962 } 4963 return config.getRefreshRateLimitations(); 4964 } 4965 4966 @Override setWindowManagerMirroring(int displayId, boolean isMirroring)4967 public void setWindowManagerMirroring(int displayId, boolean isMirroring) { 4968 synchronized (mSyncRoot) { 4969 final DisplayDevice device = getDeviceForDisplayLocked(displayId); 4970 if (device != null) { 4971 device.setWindowManagerMirroringLocked(isMirroring); 4972 } 4973 } 4974 } 4975 4976 @Override getDisplaySurfaceDefaultSize(int displayId)4977 public Point getDisplaySurfaceDefaultSize(int displayId) { 4978 final DisplayDevice device; 4979 synchronized (mSyncRoot) { 4980 device = getDeviceForDisplayLocked(displayId); 4981 if (device == null) { 4982 return null; 4983 } 4984 return device.getDisplaySurfaceDefaultSizeLocked(); 4985 } 4986 } 4987 4988 @Override onEarlyInteractivityChange(boolean interactive)4989 public void onEarlyInteractivityChange(boolean interactive) { 4990 mLogicalDisplayMapper.onEarlyInteractivityChange(interactive); 4991 } 4992 4993 @Override getDisplayWindowPolicyController(int displayId)4994 public DisplayWindowPolicyController getDisplayWindowPolicyController(int displayId) { 4995 synchronized (mSyncRoot) { 4996 if (mDisplayWindowPolicyControllers.contains(displayId)) { 4997 return mDisplayWindowPolicyControllers.get(displayId).second; 4998 } 4999 return null; 5000 } 5001 } 5002 5003 @Override getDisplayIdToMirror(int displayId)5004 public int getDisplayIdToMirror(int displayId) { 5005 synchronized (mSyncRoot) { 5006 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 5007 if (display == null) { 5008 return Display.INVALID_DISPLAY; 5009 } 5010 5011 final DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked(); 5012 final boolean isRearDisplay = display.getDevicePositionLocked() == POSITION_REAR; 5013 final boolean ownContent = ((displayDevice.getDisplayDeviceInfoLocked().flags 5014 & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0) || isRearDisplay; 5015 // If the display has enabled mirroring, but specified that it will be managed by 5016 // WindowManager, return an invalid display id. This is to ensure we don't 5017 // accidentally select the display id to mirror based on DM logic and instead allow 5018 // the caller to specify what area to mirror. 5019 if (ownContent || displayDevice.isWindowManagerMirroringLocked()) { 5020 return Display.INVALID_DISPLAY; 5021 } 5022 5023 int displayIdToMirror = displayDevice.getDisplayIdToMirrorLocked(); 5024 LogicalDisplay displayToMirror = mLogicalDisplayMapper.getDisplayLocked( 5025 displayIdToMirror); 5026 // If the displayId for the requested mirror doesn't exist, fallback to mirroring 5027 // default display. 5028 if (displayToMirror == null) { 5029 displayIdToMirror = Display.DEFAULT_DISPLAY; 5030 } 5031 return displayIdToMirror; 5032 } 5033 } 5034 5035 @Override getDisplayNativePrimaries(int displayId)5036 public SurfaceControl.DisplayPrimaries getDisplayNativePrimaries(int displayId) { 5037 IBinder displayToken; 5038 synchronized (mSyncRoot) { 5039 displayToken = getDisplayToken(displayId); 5040 if (displayToken == null) { 5041 throw new IllegalArgumentException("Invalid displayId=" + displayId); 5042 } 5043 } 5044 5045 return SurfaceControl.getDisplayNativePrimaries(displayToken); 5046 } 5047 5048 @Override getHostUsiVersion(int displayId)5049 public HostUsiVersion getHostUsiVersion(int displayId) { 5050 synchronized (mSyncRoot) { 5051 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 5052 if (display == null) { 5053 return null; 5054 } 5055 5056 return display.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig() 5057 .getHostUsiVersion(); 5058 } 5059 } 5060 5061 @Override getAmbientLightSensorData(int displayId)5062 public AmbientLightSensorData getAmbientLightSensorData(int displayId) { 5063 synchronized (mSyncRoot) { 5064 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 5065 if (display == null) { 5066 return null; 5067 } 5068 final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); 5069 if (device == null) { 5070 return null; 5071 } 5072 SensorData data = device.getDisplayDeviceConfig().getAmbientLightSensor(); 5073 return new AmbientLightSensorData(data.name, data.type); 5074 } 5075 } 5076 5077 @Override getDisplayGroupIds()5078 public IntArray getDisplayGroupIds() { 5079 Set<Integer> visitedIds = new ArraySet<>(); 5080 IntArray displayGroupIds = new IntArray(); 5081 synchronized (mSyncRoot) { 5082 mLogicalDisplayMapper.forEachLocked(logicalDisplay -> { 5083 int groupId = mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked( 5084 logicalDisplay.getDisplayIdLocked()); 5085 if (!visitedIds.contains(groupId)) { 5086 visitedIds.add(groupId); 5087 displayGroupIds.add(groupId); 5088 } 5089 }); 5090 } 5091 return displayGroupIds; 5092 } 5093 5094 @Override registerDisplayOffloader( int displayId, @NonNull DisplayManagerInternal.DisplayOffloader displayOffloader)5095 public DisplayManagerInternal.DisplayOffloadSession registerDisplayOffloader( 5096 int displayId, @NonNull DisplayManagerInternal.DisplayOffloader displayOffloader) { 5097 if (!mFlags.isDisplayOffloadEnabled()) { 5098 return null; 5099 } 5100 synchronized (mSyncRoot) { 5101 LogicalDisplay logicalDisplay = mLogicalDisplayMapper.getDisplayLocked(displayId); 5102 if (logicalDisplay == null) { 5103 Slog.w(TAG, "registering DisplayOffloader: LogicalDisplay for displayId=" 5104 + displayId + " is not found. No Op."); 5105 return null; 5106 } 5107 5108 DisplayPowerControllerInterface displayPowerController = 5109 mDisplayPowerControllers.get(logicalDisplay.getDisplayIdLocked()); 5110 if (displayPowerController == null) { 5111 Slog.w(TAG, 5112 "setting doze state override: DisplayPowerController for displayId=" 5113 + displayId + " is unavailable. No Op."); 5114 return null; 5115 } 5116 5117 DisplayOffloadSessionImpl session = new DisplayOffloadSessionImpl(displayOffloader, 5118 displayPowerController); 5119 logicalDisplay.setDisplayOffloadSessionLocked(session); 5120 displayPowerController.setDisplayOffloadSession(session); 5121 return session; 5122 } 5123 } 5124 5125 @Override onPresentation(int displayId, boolean isShown)5126 public void onPresentation(int displayId, boolean isShown) { 5127 mExternalDisplayPolicy.onPresentation(displayId, isShown); 5128 } 5129 } 5130 5131 class DesiredDisplayModeSpecsObserver 5132 implements DisplayModeDirector.DesiredDisplayModeSpecsListener { 5133 5134 private final Consumer<LogicalDisplay> mSpecsChangedConsumer = display -> { 5135 int displayId = display.getDisplayIdLocked(); 5136 DisplayModeDirector.DesiredDisplayModeSpecs desiredDisplayModeSpecs = 5137 mDisplayModeDirector.getDesiredDisplayModeSpecs(displayId); 5138 DisplayModeDirector.DesiredDisplayModeSpecs existingDesiredDisplayModeSpecs = 5139 display.getDesiredDisplayModeSpecsLocked(); 5140 if (DEBUG) { 5141 Slog.i(TAG, 5142 "Comparing display specs: " + desiredDisplayModeSpecs 5143 + ", existing: " + existingDesiredDisplayModeSpecs); 5144 } 5145 if (!desiredDisplayModeSpecs.equals(existingDesiredDisplayModeSpecs)) { 5146 display.setDesiredDisplayModeSpecsLocked(desiredDisplayModeSpecs); 5147 mChanged = true; 5148 } 5149 }; 5150 5151 @GuardedBy("mSyncRoot") 5152 private boolean mChanged = false; 5153 onDesiredDisplayModeSpecsChanged()5154 public void onDesiredDisplayModeSpecsChanged() { 5155 synchronized (mSyncRoot) { 5156 mChanged = false; 5157 mLogicalDisplayMapper.forEachLocked(mSpecsChangedConsumer, 5158 /* includeDisabled= */ false); 5159 if (mChanged) { 5160 scheduleTraversalLocked(false); 5161 mChanged = false; 5162 } 5163 } 5164 } 5165 } 5166 5167 /** 5168 * Listens to changes in device state and reports the state to LogicalDisplayMapper. 5169 */ 5170 class DeviceStateListener implements DeviceStateManager.DeviceStateCallback { 5171 5172 @Override onDeviceStateChanged(DeviceState deviceState)5173 public void onDeviceStateChanged(DeviceState deviceState) { 5174 synchronized (mSyncRoot) { 5175 // Notify WindowManager that we are about to handle new device state, this should 5176 // be sent before any work related to the device state in DisplayManager, so 5177 // WindowManager could do implement that depends on the device state and display 5178 // changes (serializes device state update and display change events) 5179 Message msg = mHandler.obtainMessage(MSG_RECEIVED_DEVICE_STATE); 5180 msg.arg1 = deviceState.getIdentifier(); 5181 mHandler.sendMessage(msg); 5182 5183 mLogicalDisplayMapper 5184 .setDeviceStateLocked(deviceState.getIdentifier()); 5185 } 5186 } 5187 }; 5188 5189 private static class BrightnessPair { 5190 public float brightness; 5191 public float sdrBrightness; 5192 BrightnessPair(float brightness, float sdrBrightness)5193 BrightnessPair(float brightness, float sdrBrightness) { 5194 this.brightness = brightness; 5195 this.sdrBrightness = sdrBrightness; 5196 } 5197 } 5198 5199 /** 5200 * Functional interface for providing time. 5201 * TODO(b/184781936): merge with PowerManagerService.Clock 5202 */ 5203 @VisibleForTesting 5204 public interface Clock { 5205 /** 5206 * Returns current time in milliseconds since boot, not counting time spent in deep sleep. 5207 */ uptimeMillis()5208 long uptimeMillis(); 5209 } 5210 5211 /** 5212 * Implements necessary functionality for {@link ExternalDisplayPolicy} 5213 */ 5214 private class ExternalDisplayPolicyInjector implements ExternalDisplayPolicy.Injector { 5215 /** 5216 * Sends event for the display. 5217 */ 5218 @Override sendExternalDisplayEventLocked(@onNull final LogicalDisplay display, @DisplayEvent int event)5219 public void sendExternalDisplayEventLocked(@NonNull final LogicalDisplay display, 5220 @DisplayEvent int event) { 5221 sendDisplayEventLocked(display, event); 5222 } 5223 5224 /** 5225 * Gets thermal service 5226 */ 5227 @Override 5228 @Nullable getThermalService()5229 public IThermalService getThermalService() { 5230 return IThermalService.Stub.asInterface(ServiceManager.getService( 5231 Context.THERMAL_SERVICE)); 5232 } 5233 5234 /** 5235 * @return display manager flags. 5236 */ 5237 @Override 5238 @NonNull getFlags()5239 public DisplayManagerFlags getFlags() { 5240 return mFlags; 5241 } 5242 5243 /** 5244 * @return Logical display mapper. 5245 */ 5246 @Override 5247 @NonNull getLogicalDisplayMapper()5248 public LogicalDisplayMapper getLogicalDisplayMapper() { 5249 return mLogicalDisplayMapper; 5250 } 5251 5252 /** 5253 * @return Sync root, for synchronization on this object across display manager. 5254 */ 5255 @Override 5256 @NonNull getSyncRoot()5257 public SyncRoot getSyncRoot() { 5258 return mSyncRoot; 5259 } 5260 5261 /** 5262 * Notification manager for display manager 5263 */ 5264 @Override 5265 @NonNull getDisplayNotificationManager()5266 public DisplayNotificationManager getDisplayNotificationManager() { 5267 return mDisplayNotificationManager; 5268 } 5269 5270 /** 5271 * Handler to use for notification sending to avoid requiring POST_NOTIFICATION permission. 5272 */ 5273 @Override 5274 @NonNull getHandler()5275 public Handler getHandler() { 5276 return mHandler; 5277 } 5278 5279 /** 5280 * Gets service used for metrics collection. 5281 */ 5282 @Override 5283 @NonNull getExternalDisplayStatsService()5284 public ExternalDisplayStatsService getExternalDisplayStatsService() { 5285 return mExternalDisplayStatsService; 5286 } 5287 } 5288 } 5289