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