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_TRUSTED_DISPLAY; 20 import static android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT; 21 import static android.Manifest.permission.CAPTURE_VIDEO_OUTPUT; 22 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; 23 import static android.hardware.display.DisplayManager.EventsMask; 24 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; 25 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; 26 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY; 27 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP; 28 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC; 29 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE; 30 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; 31 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED; 32 import static android.hardware.display.DisplayManagerGlobal.DisplayEvent; 33 import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL; 34 import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL; 35 import static android.hardware.display.DisplayViewport.VIEWPORT_VIRTUAL; 36 37 import android.Manifest; 38 import android.annotation.NonNull; 39 import android.annotation.Nullable; 40 import android.annotation.UserIdInt; 41 import android.app.AppOpsManager; 42 import android.app.compat.CompatChanges; 43 import android.compat.annotation.ChangeId; 44 import android.compat.annotation.EnabledSince; 45 import android.content.Context; 46 import android.content.pm.PackageManager; 47 import android.content.pm.ParceledListSlice; 48 import android.content.res.Resources; 49 import android.content.res.TypedArray; 50 import android.database.ContentObserver; 51 import android.graphics.ColorSpace; 52 import android.graphics.Point; 53 import android.hardware.Sensor; 54 import android.hardware.SensorManager; 55 import android.hardware.devicestate.DeviceStateManager; 56 import android.hardware.display.AmbientBrightnessDayStats; 57 import android.hardware.display.BrightnessChangeEvent; 58 import android.hardware.display.BrightnessConfiguration; 59 import android.hardware.display.BrightnessInfo; 60 import android.hardware.display.Curve; 61 import android.hardware.display.DisplayManager; 62 import android.hardware.display.DisplayManagerGlobal; 63 import android.hardware.display.DisplayManagerInternal; 64 import android.hardware.display.DisplayManagerInternal.DisplayGroupListener; 65 import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener; 66 import android.hardware.display.DisplayManagerInternal.RefreshRateLimitation; 67 import android.hardware.display.DisplayManagerInternal.RefreshRateRange; 68 import android.hardware.display.DisplayViewport; 69 import android.hardware.display.DisplayedContentSample; 70 import android.hardware.display.DisplayedContentSamplingAttributes; 71 import android.hardware.display.IDisplayManager; 72 import android.hardware.display.IDisplayManagerCallback; 73 import android.hardware.display.IVirtualDisplayCallback; 74 import android.hardware.display.VirtualDisplayConfig; 75 import android.hardware.display.WifiDisplayStatus; 76 import android.hardware.input.InputManagerInternal; 77 import android.media.projection.IMediaProjection; 78 import android.media.projection.IMediaProjectionManager; 79 import android.net.Uri; 80 import android.os.Binder; 81 import android.os.Handler; 82 import android.os.HandlerExecutor; 83 import android.os.IBinder; 84 import android.os.IBinder.DeathRecipient; 85 import android.os.Looper; 86 import android.os.Message; 87 import android.os.PowerManager; 88 import android.os.Process; 89 import android.os.RemoteException; 90 import android.os.ResultReceiver; 91 import android.os.ServiceManager; 92 import android.os.ShellCallback; 93 import android.os.SystemClock; 94 import android.os.SystemProperties; 95 import android.os.Trace; 96 import android.os.UserHandle; 97 import android.os.UserManager; 98 import android.provider.Settings; 99 import android.sysprop.DisplayProperties; 100 import android.text.TextUtils; 101 import android.util.ArraySet; 102 import android.util.EventLog; 103 import android.util.IntArray; 104 import android.util.Pair; 105 import android.util.Slog; 106 import android.util.SparseArray; 107 import android.util.SparseIntArray; 108 import android.util.Spline; 109 import android.view.Display; 110 import android.view.DisplayEventReceiver; 111 import android.view.DisplayInfo; 112 import android.view.Surface; 113 import android.view.SurfaceControl; 114 115 import com.android.internal.annotations.GuardedBy; 116 import com.android.internal.annotations.VisibleForTesting; 117 import com.android.internal.display.BrightnessSynchronizer; 118 import com.android.internal.util.DumpUtils; 119 import com.android.internal.util.IndentingPrintWriter; 120 import com.android.server.AnimationThread; 121 import com.android.server.DisplayThread; 122 import com.android.server.LocalServices; 123 import com.android.server.SystemService; 124 import com.android.server.UiThread; 125 import com.android.server.display.DisplayDeviceConfig.SensorData; 126 import com.android.server.display.utils.SensorUtils; 127 import com.android.server.wm.SurfaceAnimationThread; 128 import com.android.server.wm.WindowManagerInternal; 129 130 import java.io.FileDescriptor; 131 import java.io.PrintWriter; 132 import java.util.ArrayList; 133 import java.util.Arrays; 134 import java.util.List; 135 import java.util.Optional; 136 import java.util.concurrent.CopyOnWriteArrayList; 137 import java.util.concurrent.atomic.AtomicLong; 138 import java.util.function.Consumer; 139 140 /** 141 * Manages attached displays. 142 * <p> 143 * The {@link DisplayManagerService} manages the global lifecycle of displays, 144 * decides how to configure logical displays based on the physical display devices currently 145 * attached, sends notifications to the system and to applications when the state 146 * changes, and so on. 147 * </p><p> 148 * The display manager service relies on a collection of {@link DisplayAdapter} components, 149 * for discovering and configuring physical display devices attached to the system. 150 * There are separate display adapters for each manner that devices are attached: 151 * one display adapter for physical displays, one for simulated non-functional 152 * displays when the system is headless, one for simulated overlay displays used for 153 * development, one for wifi displays, etc. 154 * </p><p> 155 * Display adapters are only weakly coupled to the display manager service. 156 * Display adapters communicate changes in display device state to the display manager 157 * service asynchronously via a {@link DisplayAdapter.Listener}, and through 158 * the {@link DisplayDeviceRepository.Listener}, which is ultimately registered 159 * by the display manager service. This separation of concerns is important for 160 * two main reasons. First, it neatly encapsulates the responsibilities of these 161 * two classes: display adapters handle individual display devices whereas 162 * the display manager service handles the global state. Second, it eliminates 163 * the potential for deadlocks resulting from asynchronous display device discovery. 164 * </p> 165 * 166 * <h3>Synchronization</h3> 167 * <p> 168 * Because the display manager may be accessed by multiple threads, the synchronization 169 * story gets a little complicated. In particular, the window manager may call into 170 * the display manager while holding a surface transaction with the expectation that 171 * it can apply changes immediately. Unfortunately, that means we can't just do 172 * everything asynchronously (*grump*). 173 * </p><p> 174 * To make this work, all of the objects that belong to the display manager must 175 * use the same lock. We call this lock the synchronization root and it has a unique 176 * type {@link DisplayManagerService.SyncRoot}. Methods that require this lock are 177 * named with the "Locked" suffix. 178 * </p><p> 179 * Where things get tricky is that the display manager is not allowed to make 180 * any potentially reentrant calls, especially into the window manager. We generally 181 * avoid this by making all potentially reentrant out-calls asynchronous. 182 * </p> 183 */ 184 public final class DisplayManagerService extends SystemService { 185 private static final String TAG = "DisplayManagerService"; 186 private static final boolean DEBUG = false; 187 188 // When this system property is set to 0, WFD is forcibly disabled on boot. 189 // When this system property is set to 1, WFD is forcibly enabled on boot. 190 // Otherwise WFD is enabled according to the value of config_enableWifiDisplay. 191 private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable"; 192 193 private static final String PROP_DEFAULT_DISPLAY_TOP_INSET = "persist.sys.displayinset.top"; 194 private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000; 195 // This value needs to be in sync with the threshold 196 // in RefreshRateConfigs::getFrameRateDivider. 197 private static final float THRESHOLD_FOR_REFRESH_RATES_DIVIDERS = 0.0009f; 198 199 private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1; 200 private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2; 201 private static final int MSG_DELIVER_DISPLAY_EVENT = 3; 202 private static final int MSG_REQUEST_TRAVERSAL = 4; 203 private static final int MSG_UPDATE_VIEWPORT = 5; 204 private static final int MSG_LOAD_BRIGHTNESS_CONFIGURATIONS = 6; 205 private static final int MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE = 7; 206 private static final int MSG_DELIVER_DISPLAY_GROUP_EVENT = 8; 207 208 private final Context mContext; 209 private final DisplayManagerHandler mHandler; 210 private final Handler mUiHandler; 211 private final DisplayModeDirector mDisplayModeDirector; 212 private WindowManagerInternal mWindowManagerInternal; 213 private InputManagerInternal mInputManagerInternal; 214 private IMediaProjectionManager mProjectionService; 215 private int[] mUserDisabledHdrTypes = {}; 216 private boolean mAreUserDisabledHdrTypesAllowed = true; 217 218 // The synchronization root for the display manager. 219 // This lock guards most of the display manager's state. 220 // NOTE: This is synchronized on while holding WindowManagerService.mWindowMap so never call 221 // into WindowManagerService methods that require mWindowMap while holding this unless you are 222 // very very sure that no deadlock can occur. 223 private final SyncRoot mSyncRoot = new SyncRoot(); 224 225 // True if in safe mode. 226 // This option may disable certain display adapters. 227 public boolean mSafeMode; 228 229 // True if we are in a special boot mode where only core applications and 230 // services should be started. This option may disable certain display adapters. 231 public boolean mOnlyCore; 232 233 // All callback records indexed by calling process id. 234 public final SparseArray<CallbackRecord> mCallbacks = 235 new SparseArray<CallbackRecord>(); 236 237 // List of all currently registered display adapters. 238 private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>(); 239 240 /** 241 * Repository of all active {@link DisplayDevice}s. 242 */ 243 private final DisplayDeviceRepository mDisplayDeviceRepo; 244 245 /** 246 * Contains all the {@link LogicalDisplay} instances and is responsible for mapping 247 * {@link DisplayDevice}s to {@link LogicalDisplay}s. DisplayManagerService listens to display 248 * event on this object. 249 */ 250 private final LogicalDisplayMapper mLogicalDisplayMapper; 251 252 // List of all display transaction listeners. 253 private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners = 254 new CopyOnWriteArrayList<DisplayTransactionListener>(); 255 256 /** List of all display group listeners. */ 257 private final CopyOnWriteArrayList<DisplayGroupListener> mDisplayGroupListeners = 258 new CopyOnWriteArrayList<>(); 259 260 /** All {@link DisplayPowerController}s indexed by {@link LogicalDisplay} ID. */ 261 private final SparseArray<DisplayPowerController> mDisplayPowerControllers = 262 new SparseArray<>(); 263 264 /** {@link DisplayBlanker} used by all {@link DisplayPowerController}s. */ 265 private final DisplayBlanker mDisplayBlanker = new DisplayBlanker() { 266 // Synchronized to avoid race conditions when updating multiple display states. 267 @Override 268 public synchronized void requestDisplayState(int displayId, int state, float brightness, 269 float sdrBrightness) { 270 boolean allInactive = true; 271 boolean allOff = true; 272 final boolean stateChanged; 273 synchronized (mSyncRoot) { 274 final int index = mDisplayStates.indexOfKey(displayId); 275 if (index > -1) { 276 final int currentState = mDisplayStates.valueAt(index); 277 stateChanged = state != currentState; 278 if (stateChanged) { 279 final int size = mDisplayStates.size(); 280 for (int i = 0; i < size; i++) { 281 final int displayState = i == index ? state : mDisplayStates.valueAt(i); 282 if (displayState != Display.STATE_OFF) { 283 allOff = false; 284 } 285 if (Display.isActiveState(displayState)) { 286 allInactive = false; 287 } 288 if (!allOff && !allInactive) { 289 break; 290 } 291 } 292 } 293 } else { 294 stateChanged = false; 295 } 296 } 297 298 // The order of operations is important for legacy reasons. 299 if (state == Display.STATE_OFF) { 300 requestDisplayStateInternal(displayId, state, brightness, sdrBrightness); 301 } 302 303 if (stateChanged) { 304 mDisplayPowerCallbacks.onDisplayStateChange(allInactive, allOff); 305 } 306 307 if (state != Display.STATE_OFF) { 308 requestDisplayStateInternal(displayId, state, brightness, sdrBrightness); 309 } 310 } 311 }; 312 313 /** 314 * Used to inform {@link com.android.server.power.PowerManagerService} of changes to display 315 * state. 316 */ 317 private DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks; 318 319 /** The {@link Handler} used by all {@link DisplayPowerController}s. */ 320 private Handler mPowerHandler; 321 322 // A map from LogicalDisplay ID to display power state. 323 @GuardedBy("mSyncRoot") 324 private final SparseIntArray mDisplayStates = new SparseIntArray(); 325 326 // A map from LogicalDisplay ID to display brightness. 327 @GuardedBy("mSyncRoot") 328 private final SparseArray<BrightnessPair> mDisplayBrightnesses = new SparseArray<>(); 329 330 // Set to true when there are pending display changes that have yet to be applied 331 // to the surface flinger state. 332 private boolean mPendingTraversal; 333 334 // The Wifi display adapter, or null if not registered. 335 private WifiDisplayAdapter mWifiDisplayAdapter; 336 337 // The number of active wifi display scan requests. 338 private int mWifiDisplayScanRequestCount; 339 340 // The virtual display adapter, or null if not registered. 341 private VirtualDisplayAdapter mVirtualDisplayAdapter; 342 343 // The User ID of the current user 344 private @UserIdInt int mCurrentUserId; 345 346 // The stable device screen height and width. These are not tied to a specific display, even 347 // the default display, because they need to be stable over the course of the device's entire 348 // life, even if the default display changes (e.g. a new monitor is plugged into a PC-like 349 // device). 350 private Point mStableDisplaySize = new Point(); 351 352 // Whether the system has finished booting or not. 353 private boolean mSystemReady; 354 355 // The top inset of the default display. 356 // This gets persisted so that the boot animation knows how to transition from the display's 357 // full size to the size configured by the user. Right now we only persist and animate the top 358 // inset, but theoretically we could do it for all of them. 359 private int mDefaultDisplayTopInset; 360 361 // Viewports of the default display and the display that should receive touch 362 // input from an external source. Used by the input system. 363 @GuardedBy("mSyncRoot") 364 private final ArrayList<DisplayViewport> mViewports = new ArrayList<>(); 365 366 // Persistent data store for all internal settings maintained by the display manager service. 367 private final PersistentDataStore mPersistentDataStore = new PersistentDataStore(); 368 369 // Temporary callback list, used when sending display events to applications. 370 // May be used outside of the lock but only on the handler thread. 371 private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>(); 372 373 // Temporary viewports, used when sending new viewport information to the 374 // input system. May be used outside of the lock but only on the handler thread. 375 private final ArrayList<DisplayViewport> mTempViewports = new ArrayList<>(); 376 377 // The default color mode for default displays. Overrides the usual 378 // Display.Display.COLOR_MODE_DEFAULT for displays with the 379 // DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY flag set. 380 private final int mDefaultDisplayDefaultColorMode; 381 382 // Lists of UIDs that are present on the displays. Maps displayId -> array of UIDs. 383 private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>(); 384 385 private final Injector mInjector; 386 387 // The minimum brightness curve, which guarantess that any brightness curve that dips below it 388 // is rejected by the system. 389 private final Curve mMinimumBrightnessCurve; 390 private final Spline mMinimumBrightnessSpline; 391 private final ColorSpace mWideColorSpace; 392 393 private SensorManager mSensorManager; 394 private BrightnessTracker mBrightnessTracker; 395 396 397 // Whether minimal post processing is allowed by the user. 398 @GuardedBy("mSyncRoot") 399 private boolean mMinimalPostProcessingAllowed; 400 401 // Receives notifications about changes to Settings. 402 private SettingsObserver mSettingsObserver; 403 404 private final boolean mAllowNonNativeRefreshRateOverride; 405 406 private final BrightnessSynchronizer mBrightnessSynchronizer; 407 408 /** 409 * Applications use {@link android.view.Display#getRefreshRate} and 410 * {@link android.view.Display.Mode#getRefreshRate} to know what is the display refresh rate. 411 * Starting with Android S, the platform might throttle down applications frame rate to a 412 * divisor of the refresh rate if it is more preferable (for example if the application called 413 * to {@link android.view.Surface#setFrameRate}). 414 * Applications will experience {@link android.view.Choreographer#postFrameCallback} callbacks 415 * and backpressure at the throttled frame rate. 416 * 417 * {@link android.view.Display#getRefreshRate} will always return the application frame rate 418 * and not the physical display refresh rate to allow applications to do frame pacing correctly. 419 * 420 * {@link android.view.Display.Mode#getRefreshRate} will return the application frame rate if 421 * compiled to a previous release and starting with Android S it will return the physical 422 * display refresh rate. 423 */ 424 @ChangeId 425 @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S) 426 static final long DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE = 170503758L; 427 DisplayManagerService(Context context)428 public DisplayManagerService(Context context) { 429 this(context, new Injector()); 430 } 431 432 @VisibleForTesting DisplayManagerService(Context context, Injector injector)433 DisplayManagerService(Context context, Injector injector) { 434 super(context); 435 mInjector = injector; 436 mContext = context; 437 mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper()); 438 mUiHandler = UiThread.getHandler(); 439 mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore); 440 mLogicalDisplayMapper = new LogicalDisplayMapper(mContext, mDisplayDeviceRepo, 441 new LogicalDisplayListener(), mSyncRoot, mHandler); 442 mDisplayModeDirector = new DisplayModeDirector(context, mHandler); 443 mBrightnessSynchronizer = new BrightnessSynchronizer(mContext); 444 Resources resources = mContext.getResources(); 445 mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger( 446 com.android.internal.R.integer.config_defaultDisplayDefaultColorMode); 447 mDefaultDisplayTopInset = SystemProperties.getInt(PROP_DEFAULT_DISPLAY_TOP_INSET, -1); 448 float[] lux = getFloatArray(resources.obtainTypedArray( 449 com.android.internal.R.array.config_minimumBrightnessCurveLux)); 450 float[] nits = getFloatArray(resources.obtainTypedArray( 451 com.android.internal.R.array.config_minimumBrightnessCurveNits)); 452 mMinimumBrightnessCurve = new Curve(lux, nits); 453 mMinimumBrightnessSpline = Spline.createSpline(lux, nits); 454 455 mCurrentUserId = UserHandle.USER_SYSTEM; 456 ColorSpace[] colorSpaces = SurfaceControl.getCompositionColorSpaces(); 457 mWideColorSpace = colorSpaces[1]; 458 mAllowNonNativeRefreshRateOverride = mInjector.getAllowNonNativeRefreshRateOverride(); 459 460 mSystemReady = false; 461 } 462 setupSchedulerPolicies()463 public void setupSchedulerPolicies() { 464 // android.display and android.anim is critical to user experience and we should make sure 465 // it is not in the default foregroup groups, add it to top-app to make sure it uses all 466 // the cores and scheduling settings for top-app when it runs. 467 Process.setThreadGroupAndCpuset(DisplayThread.get().getThreadId(), 468 Process.THREAD_GROUP_TOP_APP); 469 Process.setThreadGroupAndCpuset(AnimationThread.get().getThreadId(), 470 Process.THREAD_GROUP_TOP_APP); 471 Process.setThreadGroupAndCpuset(SurfaceAnimationThread.get().getThreadId(), 472 Process.THREAD_GROUP_TOP_APP); 473 } 474 475 @Override onStart()476 public void onStart() { 477 // We need to pre-load the persistent data store so it's ready before the default display 478 // adapter is up so that we have it's configuration. We could load it lazily, but since 479 // we're going to have to read it in eventually we may as well do it here rather than after 480 // we've waited for the display to register itself with us. 481 synchronized (mSyncRoot) { 482 mPersistentDataStore.loadIfNeeded(); 483 loadStableDisplayValuesLocked(); 484 } 485 mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS); 486 487 // If there was a runtime restart then we may have stale caches left around, so we need to 488 // make sure to invalidate them upon every start. 489 DisplayManagerGlobal.invalidateLocalDisplayInfoCaches(); 490 491 publishBinderService(Context.DISPLAY_SERVICE, new BinderService(), 492 true /*allowIsolated*/); 493 publishLocalService(DisplayManagerInternal.class, new LocalService()); 494 } 495 496 @Override onBootPhase(int phase)497 public void onBootPhase(int phase) { 498 if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) { 499 synchronized (mSyncRoot) { 500 long timeout = SystemClock.uptimeMillis() 501 + mInjector.getDefaultDisplayDelayTimeout(); 502 while (mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY) == null 503 || mVirtualDisplayAdapter == null) { 504 long delay = timeout - SystemClock.uptimeMillis(); 505 if (delay <= 0) { 506 throw new RuntimeException("Timeout waiting for default display " 507 + "to be initialized. DefaultDisplay=" 508 + mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY) 509 + ", mVirtualDisplayAdapter=" + mVirtualDisplayAdapter); 510 } 511 if (DEBUG) { 512 Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay); 513 } 514 try { 515 mSyncRoot.wait(delay); 516 } catch (InterruptedException ex) { 517 } 518 } 519 } 520 } else if (phase == PHASE_BOOT_COMPLETED) { 521 mDisplayModeDirector.onBootCompleted(); 522 } 523 } 524 525 @Override onUserSwitching(@ullable TargetUser from, @NonNull TargetUser to)526 public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) { 527 final int newUserId = to.getUserIdentifier(); 528 final int userSerial = getUserManager().getUserSerialNumber(newUserId); 529 synchronized (mSyncRoot) { 530 boolean userSwitching = mCurrentUserId != newUserId; 531 if (userSwitching) { 532 mCurrentUserId = newUserId; 533 } 534 mLogicalDisplayMapper.forEachLocked(logicalDisplay -> { 535 if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) { 536 return; 537 } 538 final DisplayPowerController dpc = mDisplayPowerControllers.get( 539 logicalDisplay.getDisplayIdLocked()); 540 if (dpc == null) { 541 return; 542 } 543 if (userSwitching) { 544 BrightnessConfiguration config = 545 getBrightnessConfigForDisplayWithPdsFallbackLocked( 546 logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId(), 547 userSerial); 548 dpc.setBrightnessConfiguration(config); 549 } 550 dpc.onSwitchUser(newUserId); 551 }); 552 handleSettingsChange(); 553 } 554 } 555 556 // TODO: Use dependencies or a boot phase windowManagerAndInputReady()557 public void windowManagerAndInputReady() { 558 synchronized (mSyncRoot) { 559 mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); 560 mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); 561 562 DeviceStateManager deviceStateManager = 563 mContext.getSystemService(DeviceStateManager.class); 564 deviceStateManager.registerCallback(new HandlerExecutor(mHandler), 565 new DeviceStateListener()); 566 567 scheduleTraversalLocked(false); 568 } 569 } 570 571 /** 572 * Called when the system is ready to go. 573 */ systemReady(boolean safeMode, boolean onlyCore)574 public void systemReady(boolean safeMode, boolean onlyCore) { 575 synchronized (mSyncRoot) { 576 mSafeMode = safeMode; 577 mOnlyCore = onlyCore; 578 mSystemReady = true; 579 // Just in case the top inset changed before the system was ready. At this point, any 580 // relevant configuration should be in place. 581 recordTopInsetLocked(mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY)); 582 583 updateSettingsLocked(); 584 585 updateUserDisabledHdrTypesFromSettingsLocked(); 586 } 587 588 mDisplayModeDirector.setDesiredDisplayModeSpecsListener( 589 new DesiredDisplayModeSpecsObserver()); 590 mDisplayModeDirector.start(mSensorManager); 591 592 mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS); 593 594 mSettingsObserver = new SettingsObserver(); 595 596 mBrightnessSynchronizer.startSynchronizing(); 597 } 598 599 @VisibleForTesting getDisplayHandler()600 Handler getDisplayHandler() { 601 return mHandler; 602 } 603 604 @VisibleForTesting getDisplayDeviceRepository()605 DisplayDeviceRepository getDisplayDeviceRepository() { 606 return mDisplayDeviceRepo; 607 } 608 loadStableDisplayValuesLocked()609 private void loadStableDisplayValuesLocked() { 610 final Point size = mPersistentDataStore.getStableDisplaySize(); 611 if (size.x > 0 && size.y > 0) { 612 // Just set these values directly so we don't write the display persistent data again 613 // unnecessarily 614 mStableDisplaySize.set(size.x, size.y); 615 } else { 616 final Resources res = mContext.getResources(); 617 final int width = res.getInteger( 618 com.android.internal.R.integer.config_stableDeviceDisplayWidth); 619 final int height = res.getInteger( 620 com.android.internal.R.integer.config_stableDeviceDisplayHeight); 621 if (width > 0 && height > 0) { 622 setStableDisplaySizeLocked(width, height); 623 } 624 } 625 } 626 getStableDisplaySizeInternal()627 private Point getStableDisplaySizeInternal() { 628 Point r = new Point(); 629 synchronized (mSyncRoot) { 630 if (mStableDisplaySize.x > 0 && mStableDisplaySize.y > 0) { 631 r.set(mStableDisplaySize.x, mStableDisplaySize.y); 632 } 633 } 634 return r; 635 } 636 registerDisplayTransactionListenerInternal( DisplayTransactionListener listener)637 private void registerDisplayTransactionListenerInternal( 638 DisplayTransactionListener listener) { 639 // List is self-synchronized copy-on-write. 640 mDisplayTransactionListeners.add(listener); 641 } 642 unregisterDisplayTransactionListenerInternal( DisplayTransactionListener listener)643 private void unregisterDisplayTransactionListenerInternal( 644 DisplayTransactionListener listener) { 645 // List is self-synchronized copy-on-write. 646 mDisplayTransactionListeners.remove(listener); 647 } 648 649 @VisibleForTesting setDisplayInfoOverrideFromWindowManagerInternal(int displayId, DisplayInfo info)650 void setDisplayInfoOverrideFromWindowManagerInternal(int displayId, DisplayInfo info) { 651 synchronized (mSyncRoot) { 652 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 653 if (display != null) { 654 if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) { 655 handleLogicalDisplayChangedLocked(display); 656 scheduleTraversalLocked(false); 657 } 658 } 659 } 660 } 661 662 /** 663 * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo) 664 */ getNonOverrideDisplayInfoInternal(int displayId, DisplayInfo outInfo)665 private void getNonOverrideDisplayInfoInternal(int displayId, DisplayInfo outInfo) { 666 synchronized (mSyncRoot) { 667 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 668 if (display != null) { 669 display.getNonOverrideDisplayInfoLocked(outInfo); 670 } 671 } 672 } 673 674 @VisibleForTesting performTraversalInternal(SurfaceControl.Transaction t)675 void performTraversalInternal(SurfaceControl.Transaction t) { 676 synchronized (mSyncRoot) { 677 if (!mPendingTraversal) { 678 return; 679 } 680 mPendingTraversal = false; 681 682 performTraversalLocked(t); 683 } 684 685 // List is self-synchronized copy-on-write. 686 for (DisplayTransactionListener listener : mDisplayTransactionListeners) { 687 listener.onDisplayTransaction(t); 688 } 689 } 690 clampBrightness(int displayState, float brightnessState)691 private float clampBrightness(int displayState, float brightnessState) { 692 if (displayState == Display.STATE_OFF) { 693 brightnessState = PowerManager.BRIGHTNESS_OFF_FLOAT; 694 } else if (brightnessState != PowerManager.BRIGHTNESS_OFF_FLOAT 695 && brightnessState < PowerManager.BRIGHTNESS_MIN) { 696 brightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT; 697 } else if (brightnessState > PowerManager.BRIGHTNESS_MAX) { 698 brightnessState = PowerManager.BRIGHTNESS_MAX; 699 } 700 return brightnessState; 701 } 702 requestDisplayStateInternal(int displayId, int state, float brightnessState, float sdrBrightnessState)703 private void requestDisplayStateInternal(int displayId, int state, float brightnessState, 704 float sdrBrightnessState) { 705 if (state == Display.STATE_UNKNOWN) { 706 state = Display.STATE_ON; 707 } 708 709 brightnessState = clampBrightness(state, brightnessState); 710 sdrBrightnessState = clampBrightness(state, sdrBrightnessState); 711 712 // Update the display state within the lock. 713 // Note that we do not need to schedule traversals here although it 714 // may happen as a side-effect of displays changing state. 715 final Runnable runnable; 716 final String traceMessage; 717 synchronized (mSyncRoot) { 718 final int index = mDisplayStates.indexOfKey(displayId); 719 720 final BrightnessPair brightnessPair = 721 index < 0 ? null : mDisplayBrightnesses.valueAt(index); 722 if (index < 0 || (mDisplayStates.valueAt(index) == state 723 && brightnessPair.brightness == brightnessState 724 && brightnessPair.sdrBrightness == sdrBrightnessState)) { 725 return; // Display no longer exists or no change. 726 } 727 728 traceMessage = "requestDisplayStateInternal(" 729 + displayId + ", " 730 + Display.stateToString(state) 731 + ", brightness=" + brightnessState 732 + ", sdrBrightness=" + sdrBrightnessState + ")"; 733 Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, traceMessage, displayId); 734 735 mDisplayStates.setValueAt(index, state); 736 brightnessPair.brightness = brightnessState; 737 brightnessPair.sdrBrightness = sdrBrightnessState; 738 runnable = updateDisplayStateLocked(mLogicalDisplayMapper.getDisplayLocked(displayId) 739 .getPrimaryDisplayDeviceLocked()); 740 } 741 742 // Setting the display power state can take hundreds of milliseconds 743 // to complete so we defer the most expensive part of the work until 744 // after we have exited the critical section to avoid blocking other 745 // threads for a long time. 746 if (runnable != null) { 747 runnable.run(); 748 } 749 Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, traceMessage, displayId); 750 } 751 752 private class SettingsObserver extends ContentObserver { 753 SettingsObserver() { 754 super(mHandler); 755 756 mContext.getContentResolver().registerContentObserver( 757 Settings.Secure.getUriFor( 758 Settings.Secure.MINIMAL_POST_PROCESSING_ALLOWED), false, this); 759 } 760 761 @Override 762 public void onChange(boolean selfChange, Uri uri) { 763 handleSettingsChange(); 764 } 765 } 766 767 private void handleSettingsChange() { 768 synchronized (mSyncRoot) { 769 updateSettingsLocked(); 770 scheduleTraversalLocked(false); 771 } 772 } 773 774 private void updateSettingsLocked() { 775 mMinimalPostProcessingAllowed = Settings.Secure.getIntForUser(mContext.getContentResolver(), 776 Settings.Secure.MINIMAL_POST_PROCESSING_ALLOWED, 1, UserHandle.USER_CURRENT) != 0; 777 } 778 779 private void updateUserDisabledHdrTypesFromSettingsLocked() { 780 mAreUserDisabledHdrTypesAllowed = (Settings.Global.getInt( 781 mContext.getContentResolver(), 782 Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED, 783 1) != 0); 784 785 String userDisabledHdrTypes = Settings.Global.getString(mContext.getContentResolver(), 786 Settings.Global.USER_DISABLED_HDR_FORMATS); 787 788 if (userDisabledHdrTypes != null) { 789 try { 790 String[] userDisabledHdrTypeStrings = 791 TextUtils.split(userDisabledHdrTypes, ","); 792 mUserDisabledHdrTypes = new int[userDisabledHdrTypeStrings.length]; 793 for (int i = 0; i < userDisabledHdrTypeStrings.length; i++) { 794 mUserDisabledHdrTypes[i] = Integer.parseInt(userDisabledHdrTypeStrings[i]); 795 } 796 } catch (NumberFormatException e) { 797 Slog.e(TAG, 798 "Failed to parse USER_DISABLED_HDR_FORMATS. " 799 + "Clearing the setting.", e); 800 clearUserDisabledHdrTypesLocked(); 801 } 802 } else { 803 clearUserDisabledHdrTypesLocked(); 804 } 805 } 806 807 private void clearUserDisabledHdrTypesLocked() { 808 mUserDisabledHdrTypes = new int[]{}; 809 synchronized (mSyncRoot) { 810 Settings.Global.putString(mContext.getContentResolver(), 811 Settings.Global.USER_DISABLED_HDR_FORMATS, ""); 812 } 813 } 814 815 private DisplayInfo getDisplayInfoForFrameRateOverride(DisplayEventReceiver.FrameRateOverride[] 816 frameRateOverrides, DisplayInfo info, int callingUid) { 817 float frameRateHz = 0; 818 for (DisplayEventReceiver.FrameRateOverride frameRateOverride : frameRateOverrides) { 819 if (frameRateOverride.uid == callingUid) { 820 frameRateHz = frameRateOverride.frameRateHz; 821 break; 822 } 823 } 824 if (frameRateHz == 0) { 825 return info; 826 } 827 828 // Override the refresh rate only if it is a divider of the current 829 // refresh rate. This calculation needs to be in sync with the native code 830 // in RefreshRateConfigs::getFrameRateDivider 831 Display.Mode currentMode = info.getMode(); 832 float numPeriods = currentMode.getRefreshRate() / frameRateHz; 833 float numPeriodsRound = Math.round(numPeriods); 834 if (Math.abs(numPeriods - numPeriodsRound) > THRESHOLD_FOR_REFRESH_RATES_DIVIDERS) { 835 return info; 836 } 837 frameRateHz = currentMode.getRefreshRate() / numPeriodsRound; 838 839 DisplayInfo overriddenInfo = new DisplayInfo(); 840 overriddenInfo.copyFrom(info); 841 for (Display.Mode mode : info.supportedModes) { 842 if (!mode.equalsExceptRefreshRate(currentMode)) { 843 continue; 844 } 845 846 if (mode.getRefreshRate() >= frameRateHz - THRESHOLD_FOR_REFRESH_RATES_DIVIDERS 847 && mode.getRefreshRate() 848 <= frameRateHz + THRESHOLD_FOR_REFRESH_RATES_DIVIDERS) { 849 if (DEBUG) { 850 Slog.d(TAG, "found matching modeId " + mode.getModeId()); 851 } 852 overriddenInfo.refreshRateOverride = mode.getRefreshRate(); 853 854 if (!CompatChanges.isChangeEnabled(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE, 855 callingUid)) { 856 overriddenInfo.modeId = mode.getModeId(); 857 } 858 return overriddenInfo; 859 } 860 } 861 862 if (mAllowNonNativeRefreshRateOverride) { 863 overriddenInfo.refreshRateOverride = frameRateHz; 864 if (!CompatChanges.isChangeEnabled(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE, 865 callingUid)) { 866 overriddenInfo.supportedModes = Arrays.copyOf(info.supportedModes, 867 info.supportedModes.length + 1); 868 overriddenInfo.supportedModes[overriddenInfo.supportedModes.length - 1] = 869 new Display.Mode(Display.DISPLAY_MODE_ID_FOR_FRAME_RATE_OVERRIDE, 870 currentMode.getPhysicalWidth(), currentMode.getPhysicalHeight(), 871 overriddenInfo.refreshRateOverride); 872 overriddenInfo.modeId = 873 overriddenInfo.supportedModes[overriddenInfo.supportedModes.length - 1] 874 .getModeId(); 875 } 876 return overriddenInfo; 877 } 878 879 return info; 880 } 881 882 private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) { 883 synchronized (mSyncRoot) { 884 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 885 if (display != null) { 886 final DisplayInfo info = 887 getDisplayInfoForFrameRateOverride(display.getFrameRateOverrides(), 888 display.getDisplayInfoLocked(), callingUid); 889 if (info.hasAccess(callingUid) 890 || isUidPresentOnDisplayInternal(callingUid, displayId)) { 891 return info; 892 } 893 } 894 return null; 895 } 896 } 897 898 private void registerCallbackInternal(IDisplayManagerCallback callback, int callingPid, 899 int callingUid, @EventsMask long eventsMask) { 900 synchronized (mSyncRoot) { 901 CallbackRecord record = mCallbacks.get(callingPid); 902 903 if (record != null) { 904 record.updateEventsMask(eventsMask); 905 return; 906 } 907 908 record = new CallbackRecord(callingPid, callingUid, callback, eventsMask); 909 try { 910 IBinder binder = callback.asBinder(); 911 binder.linkToDeath(record, 0); 912 } catch (RemoteException ex) { 913 // give up 914 throw new RuntimeException(ex); 915 } 916 917 mCallbacks.put(callingPid, record); 918 } 919 } 920 921 private void onCallbackDied(CallbackRecord record) { 922 synchronized (mSyncRoot) { 923 mCallbacks.remove(record.mPid); 924 stopWifiDisplayScanLocked(record); 925 } 926 } 927 928 private void startWifiDisplayScanInternal(int callingPid) { 929 synchronized (mSyncRoot) { 930 CallbackRecord record = mCallbacks.get(callingPid); 931 if (record == null) { 932 throw new IllegalStateException("The calling process has not " 933 + "registered an IDisplayManagerCallback."); 934 } 935 startWifiDisplayScanLocked(record); 936 } 937 } 938 939 private void startWifiDisplayScanLocked(CallbackRecord record) { 940 if (!record.mWifiDisplayScanRequested) { 941 record.mWifiDisplayScanRequested = true; 942 if (mWifiDisplayScanRequestCount++ == 0) { 943 if (mWifiDisplayAdapter != null) { 944 mWifiDisplayAdapter.requestStartScanLocked(); 945 } 946 } 947 } 948 } 949 950 private void stopWifiDisplayScanInternal(int callingPid) { 951 synchronized (mSyncRoot) { 952 CallbackRecord record = mCallbacks.get(callingPid); 953 if (record == null) { 954 throw new IllegalStateException("The calling process has not " 955 + "registered an IDisplayManagerCallback."); 956 } 957 stopWifiDisplayScanLocked(record); 958 } 959 } 960 961 private void stopWifiDisplayScanLocked(CallbackRecord record) { 962 if (record.mWifiDisplayScanRequested) { 963 record.mWifiDisplayScanRequested = false; 964 if (--mWifiDisplayScanRequestCount == 0) { 965 if (mWifiDisplayAdapter != null) { 966 mWifiDisplayAdapter.requestStopScanLocked(); 967 } 968 } else if (mWifiDisplayScanRequestCount < 0) { 969 Slog.wtf(TAG, "mWifiDisplayScanRequestCount became negative: " 970 + mWifiDisplayScanRequestCount); 971 mWifiDisplayScanRequestCount = 0; 972 } 973 } 974 } 975 976 private void connectWifiDisplayInternal(String address) { 977 synchronized (mSyncRoot) { 978 if (mWifiDisplayAdapter != null) { 979 mWifiDisplayAdapter.requestConnectLocked(address); 980 } 981 } 982 } 983 984 private void pauseWifiDisplayInternal() { 985 synchronized (mSyncRoot) { 986 if (mWifiDisplayAdapter != null) { 987 mWifiDisplayAdapter.requestPauseLocked(); 988 } 989 } 990 } 991 992 private void resumeWifiDisplayInternal() { 993 synchronized (mSyncRoot) { 994 if (mWifiDisplayAdapter != null) { 995 mWifiDisplayAdapter.requestResumeLocked(); 996 } 997 } 998 } 999 1000 private void disconnectWifiDisplayInternal() { 1001 synchronized (mSyncRoot) { 1002 if (mWifiDisplayAdapter != null) { 1003 mWifiDisplayAdapter.requestDisconnectLocked(); 1004 } 1005 } 1006 } 1007 1008 private void renameWifiDisplayInternal(String address, String alias) { 1009 synchronized (mSyncRoot) { 1010 if (mWifiDisplayAdapter != null) { 1011 mWifiDisplayAdapter.requestRenameLocked(address, alias); 1012 } 1013 } 1014 } 1015 1016 private void forgetWifiDisplayInternal(String address) { 1017 synchronized (mSyncRoot) { 1018 if (mWifiDisplayAdapter != null) { 1019 mWifiDisplayAdapter.requestForgetLocked(address); 1020 } 1021 } 1022 } 1023 1024 private WifiDisplayStatus getWifiDisplayStatusInternal() { 1025 synchronized (mSyncRoot) { 1026 if (mWifiDisplayAdapter != null) { 1027 return mWifiDisplayAdapter.getWifiDisplayStatusLocked(); 1028 } 1029 return new WifiDisplayStatus(); 1030 } 1031 } 1032 1033 private void setUserDisabledHdrTypesInternal(int[] userDisabledHdrTypes) { 1034 synchronized (mSyncRoot) { 1035 if (userDisabledHdrTypes == null) { 1036 Slog.e(TAG, "Null is not an expected argument to " 1037 + "setUserDisabledHdrTypesInternal"); 1038 return; 1039 } 1040 Arrays.sort(userDisabledHdrTypes); 1041 if (Arrays.equals(mUserDisabledHdrTypes, userDisabledHdrTypes)) { 1042 return; 1043 } 1044 String userDisabledFormatsString = ""; 1045 if (userDisabledHdrTypes.length != 0) { 1046 userDisabledFormatsString = TextUtils.join(",", 1047 Arrays.stream(userDisabledHdrTypes).boxed().toArray()); 1048 } 1049 Settings.Global.putString(mContext.getContentResolver(), 1050 Settings.Global.USER_DISABLED_HDR_FORMATS, userDisabledFormatsString); 1051 mUserDisabledHdrTypes = userDisabledHdrTypes; 1052 if (!mAreUserDisabledHdrTypesAllowed) { 1053 mLogicalDisplayMapper.forEachLocked( 1054 display -> { 1055 display.setUserDisabledHdrTypes(userDisabledHdrTypes); 1056 handleLogicalDisplayChangedLocked(display); 1057 }); 1058 } 1059 } 1060 } 1061 1062 private void setAreUserDisabledHdrTypesAllowedInternal( 1063 boolean areUserDisabledHdrTypesAllowed) { 1064 synchronized (mSyncRoot) { 1065 if (mAreUserDisabledHdrTypesAllowed == areUserDisabledHdrTypesAllowed) { 1066 return; 1067 } 1068 mAreUserDisabledHdrTypesAllowed = areUserDisabledHdrTypesAllowed; 1069 if (mUserDisabledHdrTypes.length == 0) { 1070 return; 1071 } 1072 Settings.Global.putInt(mContext.getContentResolver(), 1073 Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED, 1074 areUserDisabledHdrTypesAllowed ? 1 : 0); 1075 int userDisabledHdrTypes[] = {}; 1076 if (!mAreUserDisabledHdrTypesAllowed) { 1077 userDisabledHdrTypes = mUserDisabledHdrTypes; 1078 } 1079 int[] finalUserDisabledHdrTypes = userDisabledHdrTypes; 1080 mLogicalDisplayMapper.forEachLocked( 1081 display -> { 1082 display.setUserDisabledHdrTypes(finalUserDisabledHdrTypes); 1083 handleLogicalDisplayChangedLocked(display); 1084 }); 1085 } 1086 } 1087 1088 private void requestColorModeInternal(int displayId, int colorMode) { 1089 synchronized (mSyncRoot) { 1090 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 1091 if (display != null && 1092 display.getRequestedColorModeLocked() != colorMode) { 1093 display.setRequestedColorModeLocked(colorMode); 1094 scheduleTraversalLocked(false); 1095 } 1096 } 1097 } 1098 1099 private int createVirtualDisplayInternal(IVirtualDisplayCallback callback, 1100 IMediaProjection projection, int callingUid, String packageName, Surface surface, 1101 int flags, VirtualDisplayConfig virtualDisplayConfig) { 1102 synchronized (mSyncRoot) { 1103 if (mVirtualDisplayAdapter == null) { 1104 Slog.w(TAG, "Rejecting request to create private virtual display " 1105 + "because the virtual display adapter is not available."); 1106 return -1; 1107 } 1108 1109 DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked( 1110 callback, projection, callingUid, packageName, surface, flags, 1111 virtualDisplayConfig); 1112 if (device == null) { 1113 return -1; 1114 } 1115 1116 // DisplayDevice events are handled manually for Virtual Displays. 1117 // TODO: multi-display Fix this so that generic add/remove events are not handled in a 1118 // different code path for virtual displays. Currently this happens so that we can 1119 // return a valid display ID synchronously upon successful Virtual Display creation. 1120 // This code can run on any binder thread, while onDisplayDeviceAdded() callbacks are 1121 // called on the DisplayThread (which we don't want to wait for?). 1122 // One option would be to actually wait here on the binder thread 1123 // to be notified when the virtual display is created (or failed). 1124 mDisplayDeviceRepo.onDisplayDeviceEvent(device, 1125 DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED); 1126 1127 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device); 1128 if (display != null) { 1129 return display.getDisplayIdLocked(); 1130 } 1131 1132 // Something weird happened and the logical display was not created. 1133 Slog.w(TAG, "Rejecting request to create virtual display " 1134 + "because the logical display was not created."); 1135 mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder()); 1136 mDisplayDeviceRepo.onDisplayDeviceEvent(device, 1137 DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED); 1138 } 1139 return -1; 1140 } 1141 1142 private void resizeVirtualDisplayInternal(IBinder appToken, 1143 int width, int height, int densityDpi) { 1144 synchronized (mSyncRoot) { 1145 if (mVirtualDisplayAdapter == null) { 1146 return; 1147 } 1148 1149 mVirtualDisplayAdapter.resizeVirtualDisplayLocked(appToken, width, height, densityDpi); 1150 } 1151 } 1152 1153 private void setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface) { 1154 synchronized (mSyncRoot) { 1155 if (mVirtualDisplayAdapter == null) { 1156 return; 1157 } 1158 1159 mVirtualDisplayAdapter.setVirtualDisplaySurfaceLocked(appToken, surface); 1160 } 1161 } 1162 1163 private void releaseVirtualDisplayInternal(IBinder appToken) { 1164 synchronized (mSyncRoot) { 1165 if (mVirtualDisplayAdapter == null) { 1166 return; 1167 } 1168 1169 DisplayDevice device = 1170 mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken); 1171 if (device != null) { 1172 // TODO: multi-display - handle virtual displays the same as other display adapters. 1173 mDisplayDeviceRepo.onDisplayDeviceEvent(device, 1174 DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED); 1175 } 1176 } 1177 } 1178 1179 private void setVirtualDisplayStateInternal(IBinder appToken, boolean isOn) { 1180 synchronized (mSyncRoot) { 1181 if (mVirtualDisplayAdapter == null) { 1182 return; 1183 } 1184 1185 mVirtualDisplayAdapter.setVirtualDisplayStateLocked(appToken, isOn); 1186 } 1187 } 1188 1189 private void registerDefaultDisplayAdapters() { 1190 // Register default display adapters. 1191 synchronized (mSyncRoot) { 1192 // main display adapter 1193 registerDisplayAdapterLocked(new LocalDisplayAdapter( 1194 mSyncRoot, mContext, mHandler, mDisplayDeviceRepo)); 1195 1196 // Standalone VR devices rely on a virtual display as their primary display for 1197 // 2D UI. We register virtual display adapter along side the main display adapter 1198 // here so that it is ready by the time the system sends the home Intent for 1199 // early apps like SetupWizard/Launcher. In particular, SUW is displayed using 1200 // the virtual display inside VR before any VR-specific apps even run. 1201 mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext, 1202 mHandler, mDisplayDeviceRepo); 1203 if (mVirtualDisplayAdapter != null) { 1204 registerDisplayAdapterLocked(mVirtualDisplayAdapter); 1205 } 1206 } 1207 } 1208 1209 private void registerAdditionalDisplayAdapters() { 1210 synchronized (mSyncRoot) { 1211 if (shouldRegisterNonEssentialDisplayAdaptersLocked()) { 1212 registerOverlayDisplayAdapterLocked(); 1213 registerWifiDisplayAdapterLocked(); 1214 } 1215 } 1216 } 1217 1218 private void registerOverlayDisplayAdapterLocked() { 1219 registerDisplayAdapterLocked(new OverlayDisplayAdapter( 1220 mSyncRoot, mContext, mHandler, mDisplayDeviceRepo, mUiHandler)); 1221 } 1222 1223 private void registerWifiDisplayAdapterLocked() { 1224 if (mContext.getResources().getBoolean( 1225 com.android.internal.R.bool.config_enableWifiDisplay) 1226 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) { 1227 mWifiDisplayAdapter = new WifiDisplayAdapter( 1228 mSyncRoot, mContext, mHandler, mDisplayDeviceRepo, 1229 mPersistentDataStore); 1230 registerDisplayAdapterLocked(mWifiDisplayAdapter); 1231 } 1232 } 1233 1234 private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() { 1235 // In safe mode, we disable non-essential display adapters to give the user 1236 // an opportunity to fix broken settings or other problems that might affect 1237 // system stability. 1238 // In only-core mode, we disable non-essential display adapters to minimize 1239 // the number of dependencies that are started while in this mode and to 1240 // prevent problems that might occur due to the device being encrypted. 1241 return !mSafeMode && !mOnlyCore; 1242 } 1243 1244 private void registerDisplayAdapterLocked(DisplayAdapter adapter) { 1245 mDisplayAdapters.add(adapter); 1246 adapter.registerLocked(); 1247 } 1248 1249 private void handleLogicalDisplayAddedLocked(LogicalDisplay display) { 1250 final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); 1251 final int displayId = display.getDisplayIdLocked(); 1252 final boolean isDefault = displayId == Display.DEFAULT_DISPLAY; 1253 configureColorModeLocked(display, device); 1254 if (!mAreUserDisabledHdrTypesAllowed) { 1255 display.setUserDisabledHdrTypes(mUserDisabledHdrTypes); 1256 } 1257 if (isDefault) { 1258 recordStableDisplayStatsIfNeededLocked(display); 1259 recordTopInsetLocked(display); 1260 } 1261 addDisplayPowerControllerLocked(display); 1262 mDisplayStates.append(displayId, Display.STATE_UNKNOWN); 1263 1264 final float brightnessDefault = display.getDisplayInfoLocked().brightnessDefault; 1265 mDisplayBrightnesses.append(displayId, 1266 new BrightnessPair(brightnessDefault, brightnessDefault)); 1267 1268 DisplayManagerGlobal.invalidateLocalDisplayInfoCaches(); 1269 1270 // Wake up waitForDefaultDisplay. 1271 if (isDefault) { 1272 mSyncRoot.notifyAll(); 1273 } 1274 1275 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED); 1276 1277 Runnable work = updateDisplayStateLocked(device); 1278 if (work != null) { 1279 work.run(); 1280 } 1281 scheduleTraversalLocked(false); 1282 } 1283 1284 private void handleLogicalDisplayChangedLocked(@NonNull LogicalDisplay display) { 1285 updateViewportPowerStateLocked(display); 1286 1287 final int displayId = display.getDisplayIdLocked(); 1288 if (displayId == Display.DEFAULT_DISPLAY) { 1289 recordTopInsetLocked(display); 1290 } 1291 // We don't bother invalidating the display info caches here because any changes to the 1292 // display info will trigger a cache invalidation inside of LogicalDisplay before we hit 1293 // this point. 1294 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); 1295 scheduleTraversalLocked(false); 1296 mPersistentDataStore.saveIfNeeded(); 1297 1298 DisplayPowerController dpc = mDisplayPowerControllers.get(displayId); 1299 if (dpc != null) { 1300 dpc.onDisplayChanged(); 1301 } 1302 } 1303 1304 private void handleLogicalDisplayFrameRateOverridesChangedLocked( 1305 @NonNull LogicalDisplay display) { 1306 final int displayId = display.getDisplayIdLocked(); 1307 // We don't bother invalidating the display info caches here because any changes to the 1308 // display info will trigger a cache invalidation inside of LogicalDisplay before we hit 1309 // this point. 1310 sendDisplayEventFrameRateOverrideLocked(displayId); 1311 scheduleTraversalLocked(false); 1312 } 1313 1314 private void handleLogicalDisplayRemovedLocked(@NonNull LogicalDisplay display) { 1315 final int displayId = display.getDisplayIdLocked(); 1316 final DisplayPowerController dpc = mDisplayPowerControllers.removeReturnOld(displayId); 1317 if (dpc != null) { 1318 dpc.stop(); 1319 } 1320 mDisplayStates.delete(displayId); 1321 mDisplayBrightnesses.delete(displayId); 1322 DisplayManagerGlobal.invalidateLocalDisplayInfoCaches(); 1323 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED); 1324 scheduleTraversalLocked(false); 1325 } 1326 1327 private void handleLogicalDisplaySwappedLocked(@NonNull LogicalDisplay display) { 1328 final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); 1329 final Runnable work = updateDisplayStateLocked(device); 1330 if (work != null) { 1331 mHandler.post(work); 1332 } 1333 final int displayId = display.getDisplayIdLocked(); 1334 DisplayPowerController dpc = mDisplayPowerControllers.get(displayId); 1335 if (dpc != null) { 1336 dpc.onDisplayChanged(); 1337 } 1338 mPersistentDataStore.saveIfNeeded(); 1339 mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATIONS); 1340 handleLogicalDisplayChangedLocked(display); 1341 } 1342 1343 private void handleLogicalDisplayDeviceStateTransitionLocked(@NonNull LogicalDisplay display) { 1344 final int displayId = display.getDisplayIdLocked(); 1345 final DisplayPowerController dpc = mDisplayPowerControllers.get(displayId); 1346 if (dpc != null) { 1347 dpc.onDeviceStateTransition(); 1348 } 1349 } 1350 1351 private Runnable updateDisplayStateLocked(DisplayDevice device) { 1352 // Blank or unblank the display immediately to match the state requested 1353 // by the display power controller (if known). 1354 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 1355 if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) { 1356 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device); 1357 if (display == null) { 1358 return null; 1359 } 1360 final int displayId = display.getDisplayIdLocked(); 1361 final int state = mDisplayStates.get(displayId); 1362 1363 // Only send a request for display state if display state has already been initialized. 1364 if (state != Display.STATE_UNKNOWN) { 1365 final BrightnessPair brightnessPair = mDisplayBrightnesses.get(displayId); 1366 return device.requestDisplayStateLocked(state, brightnessPair.brightness, 1367 brightnessPair.sdrBrightness); 1368 } 1369 } 1370 return null; 1371 } 1372 1373 private void configureColorModeLocked(LogicalDisplay display, DisplayDevice device) { 1374 if (display.getPrimaryDisplayDeviceLocked() == device) { 1375 int colorMode = mPersistentDataStore.getColorMode(device); 1376 if (colorMode == Display.COLOR_MODE_INVALID) { 1377 if ((device.getDisplayDeviceInfoLocked().flags 1378 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) { 1379 colorMode = mDefaultDisplayDefaultColorMode; 1380 } else { 1381 colorMode = Display.COLOR_MODE_DEFAULT; 1382 } 1383 } 1384 display.setRequestedColorModeLocked(colorMode); 1385 } 1386 } 1387 1388 // If we've never recorded stable device stats for this device before and they aren't 1389 // explicitly configured, go ahead and record the stable device stats now based on the status 1390 // of the default display at first boot. 1391 private void recordStableDisplayStatsIfNeededLocked(LogicalDisplay d) { 1392 if (mStableDisplaySize.x <= 0 && mStableDisplaySize.y <= 0) { 1393 DisplayInfo info = d.getDisplayInfoLocked(); 1394 setStableDisplaySizeLocked(info.getNaturalWidth(), info.getNaturalHeight()); 1395 } 1396 } 1397 1398 private void recordTopInsetLocked(@Nullable LogicalDisplay d) { 1399 // We must only persist the inset after boot has completed, otherwise we will end up 1400 // overwriting the persisted value before the masking flag has been loaded from the 1401 // resource overlay. 1402 if (!mSystemReady || d == null) { 1403 return; 1404 } 1405 int topInset = d.getInsets().top; 1406 if (topInset == mDefaultDisplayTopInset) { 1407 return; 1408 } 1409 mDefaultDisplayTopInset = topInset; 1410 SystemProperties.set(PROP_DEFAULT_DISPLAY_TOP_INSET, Integer.toString(topInset)); 1411 } 1412 1413 private void setStableDisplaySizeLocked(int width, int height) { 1414 mStableDisplaySize = new Point(width, height); 1415 try { 1416 mPersistentDataStore.setStableDisplaySize(mStableDisplaySize); 1417 } finally { 1418 mPersistentDataStore.saveIfNeeded(); 1419 } 1420 } 1421 1422 @VisibleForTesting 1423 Curve getMinimumBrightnessCurveInternal() { 1424 return mMinimumBrightnessCurve; 1425 } 1426 1427 int getPreferredWideGamutColorSpaceIdInternal() { 1428 return mWideColorSpace.getId(); 1429 } 1430 1431 void setShouldAlwaysRespectAppRequestedModeInternal(boolean enabled) { 1432 mDisplayModeDirector.setShouldAlwaysRespectAppRequestedMode(enabled); 1433 } 1434 1435 boolean shouldAlwaysRespectAppRequestedModeInternal() { 1436 return mDisplayModeDirector.shouldAlwaysRespectAppRequestedMode(); 1437 } 1438 1439 void setRefreshRateSwitchingTypeInternal(@DisplayManager.SwitchingType int newValue) { 1440 mDisplayModeDirector.setModeSwitchingType(newValue); 1441 } 1442 1443 @DisplayManager.SwitchingType 1444 int getRefreshRateSwitchingTypeInternal() { 1445 return mDisplayModeDirector.getModeSwitchingType(); 1446 } 1447 1448 private void setBrightnessConfigurationForDisplayInternal( 1449 @Nullable BrightnessConfiguration c, String uniqueId, @UserIdInt int userId, 1450 String packageName) { 1451 validateBrightnessConfiguration(c); 1452 final int userSerial = getUserManager().getUserSerialNumber(userId); 1453 synchronized (mSyncRoot) { 1454 try { 1455 DisplayDevice displayDevice = mDisplayDeviceRepo.getByUniqueIdLocked(uniqueId); 1456 if (displayDevice == null) { 1457 return; 1458 } 1459 mPersistentDataStore.setBrightnessConfigurationForDisplayLocked(c, displayDevice, 1460 userSerial, packageName); 1461 } finally { 1462 mPersistentDataStore.saveIfNeeded(); 1463 } 1464 if (userId != mCurrentUserId) { 1465 return; 1466 } 1467 DisplayPowerController dpc = getDpcFromUniqueIdLocked(uniqueId); 1468 if (dpc != null) { 1469 dpc.setBrightnessConfiguration(c); 1470 } 1471 } 1472 } 1473 1474 private DisplayPowerController getDpcFromUniqueIdLocked(String uniqueId) { 1475 final DisplayDevice displayDevice = mDisplayDeviceRepo.getByUniqueIdLocked(uniqueId); 1476 final LogicalDisplay logicalDisplay = mLogicalDisplayMapper.getDisplayLocked(displayDevice); 1477 if (logicalDisplay != null) { 1478 final int displayId = logicalDisplay.getDisplayIdLocked(); 1479 return mDisplayPowerControllers.get(displayId); 1480 } 1481 return null; 1482 } 1483 1484 @VisibleForTesting 1485 void validateBrightnessConfiguration(BrightnessConfiguration config) { 1486 if (config == null) { 1487 return; 1488 } 1489 if (isBrightnessConfigurationTooDark(config)) { 1490 throw new IllegalArgumentException("brightness curve is too dark"); 1491 } 1492 } 1493 1494 private boolean isBrightnessConfigurationTooDark(BrightnessConfiguration config) { 1495 Pair<float[], float[]> curve = config.getCurve(); 1496 float[] lux = curve.first; 1497 float[] nits = curve.second; 1498 for (int i = 0; i < lux.length; i++) { 1499 if (nits[i] < mMinimumBrightnessSpline.interpolate(lux[i])) { 1500 return true; 1501 } 1502 } 1503 return false; 1504 } 1505 1506 private void loadBrightnessConfigurations() { 1507 int userSerial = getUserManager().getUserSerialNumber(mContext.getUserId()); 1508 synchronized (mSyncRoot) { 1509 mLogicalDisplayMapper.forEachLocked((logicalDisplay) -> { 1510 final String uniqueId = 1511 logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId(); 1512 final BrightnessConfiguration config = 1513 getBrightnessConfigForDisplayWithPdsFallbackLocked(uniqueId, userSerial); 1514 if (config != null) { 1515 final DisplayPowerController dpc = mDisplayPowerControllers.get( 1516 logicalDisplay.getDisplayIdLocked()); 1517 if (dpc != null) { 1518 dpc.setBrightnessConfiguration(config); 1519 } 1520 } 1521 }); 1522 } 1523 } 1524 1525 private void performTraversalLocked(SurfaceControl.Transaction t) { 1526 // Clear all viewports before configuring displays so that we can keep 1527 // track of which ones we have configured. 1528 clearViewportsLocked(); 1529 1530 // Configure each display device. 1531 mLogicalDisplayMapper.forEachLocked((LogicalDisplay display) -> { 1532 final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); 1533 if (device != null) { 1534 configureDisplayLocked(t, device); 1535 device.performTraversalLocked(t); 1536 } 1537 }); 1538 1539 // Tell the input system about these new viewports. 1540 if (mInputManagerInternal != null) { 1541 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT); 1542 } 1543 } 1544 1545 private void setDisplayPropertiesInternal(int displayId, boolean hasContent, 1546 float requestedRefreshRate, int requestedModeId, float requestedMinRefreshRate, 1547 float requestedMaxRefreshRate, boolean preferMinimalPostProcessing, 1548 boolean inTraversal) { 1549 synchronized (mSyncRoot) { 1550 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 1551 if (display == null) { 1552 return; 1553 } 1554 1555 boolean shouldScheduleTraversal = false; 1556 1557 if (display.hasContentLocked() != hasContent) { 1558 if (DEBUG) { 1559 Slog.d(TAG, "Display " + displayId + " hasContent flag changed: " 1560 + "hasContent=" + hasContent + ", inTraversal=" + inTraversal); 1561 } 1562 1563 display.setHasContentLocked(hasContent); 1564 shouldScheduleTraversal = true; 1565 } 1566 if (requestedModeId == 0 && requestedRefreshRate != 0) { 1567 // Scan supported modes returned by display.getInfo() to find a mode with the same 1568 // size as the default display mode but with the specified refresh rate instead. 1569 Display.Mode mode = display.getDisplayInfoLocked().findDefaultModeByRefreshRate( 1570 requestedRefreshRate); 1571 if (mode != null) { 1572 requestedModeId = mode.getModeId(); 1573 } else { 1574 Slog.e(TAG, "Couldn't find a mode for the requestedRefreshRate: " 1575 + requestedRefreshRate + " on Display: " + displayId); 1576 } 1577 } 1578 mDisplayModeDirector.getAppRequestObserver().setAppRequest( 1579 displayId, requestedModeId, requestedMinRefreshRate, requestedMaxRefreshRate); 1580 1581 if (display.getDisplayInfoLocked().minimalPostProcessingSupported) { 1582 boolean mppRequest = mMinimalPostProcessingAllowed && preferMinimalPostProcessing; 1583 1584 if (display.getRequestedMinimalPostProcessingLocked() != mppRequest) { 1585 display.setRequestedMinimalPostProcessingLocked(mppRequest); 1586 shouldScheduleTraversal = true; 1587 } 1588 } 1589 1590 if (shouldScheduleTraversal) { 1591 scheduleTraversalLocked(inTraversal); 1592 } 1593 } 1594 } 1595 1596 private void setDisplayOffsetsInternal(int displayId, int x, int y) { 1597 synchronized (mSyncRoot) { 1598 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 1599 if (display == null) { 1600 return; 1601 } 1602 if (display.getDisplayOffsetXLocked() != x 1603 || display.getDisplayOffsetYLocked() != y) { 1604 if (DEBUG) { 1605 Slog.d(TAG, "Display " + displayId + " burn-in offset set to (" 1606 + x + ", " + y + ")"); 1607 } 1608 display.setDisplayOffsetsLocked(x, y); 1609 scheduleTraversalLocked(false); 1610 } 1611 } 1612 } 1613 1614 private void setDisplayScalingDisabledInternal(int displayId, boolean disable) { 1615 synchronized (mSyncRoot) { 1616 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 1617 if (display == null) { 1618 return; 1619 } 1620 if (display.isDisplayScalingDisabled() != disable) { 1621 if (DEBUG) { 1622 Slog.d(TAG, "Display " + displayId + " content scaling disabled = " + disable); 1623 } 1624 display.setDisplayScalingDisabledLocked(disable); 1625 scheduleTraversalLocked(false); 1626 } 1627 } 1628 } 1629 1630 // Updates the lists of UIDs that are present on displays. 1631 private void setDisplayAccessUIDsInternal(SparseArray<IntArray> newDisplayAccessUIDs) { 1632 synchronized (mSyncRoot) { 1633 mDisplayAccessUIDs.clear(); 1634 for (int i = newDisplayAccessUIDs.size() - 1; i >= 0; i--) { 1635 mDisplayAccessUIDs.append(newDisplayAccessUIDs.keyAt(i), 1636 newDisplayAccessUIDs.valueAt(i)); 1637 } 1638 } 1639 } 1640 1641 // Checks if provided UID's content is present on the display and UID has access to it. 1642 private boolean isUidPresentOnDisplayInternal(int uid, int displayId) { 1643 synchronized (mSyncRoot) { 1644 final IntArray displayUIDs = mDisplayAccessUIDs.get(displayId); 1645 return displayUIDs != null && displayUIDs.indexOf(uid) != -1; 1646 } 1647 } 1648 1649 @Nullable 1650 private IBinder getDisplayToken(int displayId) { 1651 synchronized (mSyncRoot) { 1652 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 1653 if (display != null) { 1654 final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); 1655 if (device != null) { 1656 return device.getDisplayTokenLocked(); 1657 } 1658 } 1659 } 1660 1661 return null; 1662 } 1663 1664 private SurfaceControl.ScreenshotHardwareBuffer systemScreenshotInternal(int displayId) { 1665 synchronized (mSyncRoot) { 1666 final IBinder token = getDisplayToken(displayId); 1667 if (token == null) { 1668 return null; 1669 } 1670 final LogicalDisplay logicalDisplay = mLogicalDisplayMapper.getDisplayLocked(displayId); 1671 if (logicalDisplay == null) { 1672 return null; 1673 } 1674 1675 final DisplayInfo displayInfo = logicalDisplay.getDisplayInfoLocked(); 1676 final SurfaceControl.DisplayCaptureArgs captureArgs = 1677 new SurfaceControl.DisplayCaptureArgs.Builder(token) 1678 .setSize(displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight()) 1679 .setUseIdentityTransform(true) 1680 .setCaptureSecureLayers(true) 1681 .setAllowProtected(true) 1682 .build(); 1683 return SurfaceControl.captureDisplay(captureArgs); 1684 } 1685 } 1686 1687 private SurfaceControl.ScreenshotHardwareBuffer userScreenshotInternal(int displayId) { 1688 synchronized (mSyncRoot) { 1689 final IBinder token = getDisplayToken(displayId); 1690 if (token == null) { 1691 return null; 1692 } 1693 1694 final SurfaceControl.DisplayCaptureArgs captureArgs = 1695 new SurfaceControl.DisplayCaptureArgs.Builder(token) 1696 .build(); 1697 return SurfaceControl.captureDisplay(captureArgs); 1698 } 1699 } 1700 1701 @VisibleForTesting 1702 DisplayedContentSamplingAttributes getDisplayedContentSamplingAttributesInternal( 1703 int displayId) { 1704 final IBinder token = getDisplayToken(displayId); 1705 if (token == null) { 1706 return null; 1707 } 1708 return SurfaceControl.getDisplayedContentSamplingAttributes(token); 1709 } 1710 1711 @VisibleForTesting 1712 boolean setDisplayedContentSamplingEnabledInternal( 1713 int displayId, boolean enable, int componentMask, int maxFrames) { 1714 final IBinder token = getDisplayToken(displayId); 1715 if (token == null) { 1716 return false; 1717 } 1718 return SurfaceControl.setDisplayedContentSamplingEnabled( 1719 token, enable, componentMask, maxFrames); 1720 } 1721 1722 @VisibleForTesting 1723 DisplayedContentSample getDisplayedContentSampleInternal(int displayId, 1724 long maxFrames, long timestamp) { 1725 final IBinder token = getDisplayToken(displayId); 1726 if (token == null) { 1727 return null; 1728 } 1729 return SurfaceControl.getDisplayedContentSample(token, maxFrames, timestamp); 1730 } 1731 1732 void resetBrightnessConfigurations() { 1733 mPersistentDataStore.setBrightnessConfigurationForUser(null, mContext.getUserId(), 1734 mContext.getPackageName()); 1735 mLogicalDisplayMapper.forEachLocked((logicalDisplay -> { 1736 if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) { 1737 return; 1738 } 1739 final String uniqueId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId(); 1740 setBrightnessConfigurationForDisplayInternal(null, uniqueId, mContext.getUserId(), 1741 mContext.getPackageName()); 1742 })); 1743 } 1744 1745 void setAutoBrightnessLoggingEnabled(boolean enabled) { 1746 synchronized (mSyncRoot) { 1747 final DisplayPowerController displayPowerController = mDisplayPowerControllers.get( 1748 Display.DEFAULT_DISPLAY); 1749 if (displayPowerController != null) { 1750 displayPowerController.setAutoBrightnessLoggingEnabled(enabled); 1751 } 1752 } 1753 } 1754 1755 void setDisplayWhiteBalanceLoggingEnabled(boolean enabled) { 1756 synchronized (mSyncRoot) { 1757 final DisplayPowerController displayPowerController = mDisplayPowerControllers.get( 1758 Display.DEFAULT_DISPLAY); 1759 if (displayPowerController != null) { 1760 displayPowerController.setDisplayWhiteBalanceLoggingEnabled(enabled); 1761 } 1762 } 1763 } 1764 1765 void setDisplayModeDirectorLoggingEnabled(boolean enabled) { 1766 synchronized (mSyncRoot) { 1767 if (mDisplayModeDirector != null) { 1768 mDisplayModeDirector.setLoggingEnabled(enabled); 1769 } 1770 } 1771 } 1772 1773 void setAmbientColorTemperatureOverride(float cct) { 1774 synchronized (mSyncRoot) { 1775 final DisplayPowerController displayPowerController = mDisplayPowerControllers.get( 1776 Display.DEFAULT_DISPLAY); 1777 if (displayPowerController != null) { 1778 displayPowerController.setAmbientColorTemperatureOverride(cct); 1779 } 1780 } 1781 } 1782 1783 private void clearViewportsLocked() { 1784 mViewports.clear(); 1785 } 1786 1787 private Optional<Integer> getViewportType(DisplayDeviceInfo info) { 1788 // Get the corresponding viewport type. 1789 switch (info.touch) { 1790 case DisplayDeviceInfo.TOUCH_INTERNAL: 1791 return Optional.of(VIEWPORT_INTERNAL); 1792 case DisplayDeviceInfo.TOUCH_EXTERNAL: 1793 return Optional.of(VIEWPORT_EXTERNAL); 1794 case DisplayDeviceInfo.TOUCH_VIRTUAL: 1795 if (!TextUtils.isEmpty(info.uniqueId)) { 1796 return Optional.of(VIEWPORT_VIRTUAL); 1797 } 1798 // fallthrough 1799 default: 1800 Slog.w(TAG, "Display " + info + " does not support input device matching."); 1801 } 1802 return Optional.empty(); 1803 } 1804 1805 private void configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device) { 1806 final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 1807 final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0; 1808 1809 // Mirror the part of WM hierarchy that corresponds to the provided window token. 1810 IBinder windowTokenClientToMirror = device.getWindowTokenClientToMirrorLocked(); 1811 1812 // Find the logical display that the display device is showing. 1813 // Certain displays only ever show their own content. 1814 LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device); 1815 if (!ownContent && windowTokenClientToMirror == null) { 1816 if (display != null && !display.hasContentLocked()) { 1817 // If the display does not have any content of its own, then 1818 // automatically mirror the requested logical display contents if possible. 1819 display = mLogicalDisplayMapper.getDisplayLocked( 1820 device.getDisplayIdToMirrorLocked()); 1821 } 1822 if (display == null) { 1823 display = mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY); 1824 } 1825 } 1826 1827 // Apply the logical display configuration to the display device. 1828 if (display == null) { 1829 // TODO: no logical display for the device, blank it 1830 Slog.w(TAG, "Missing logical display to use for physical display device: " 1831 + device.getDisplayDeviceInfoLocked()); 1832 return; 1833 } 1834 display.configureDisplayLocked(t, device, info.state == Display.STATE_OFF); 1835 final Optional<Integer> viewportType = getViewportType(info); 1836 if (viewportType.isPresent()) { 1837 populateViewportLocked(viewportType.get(), display.getDisplayIdLocked(), device, info); 1838 } 1839 } 1840 1841 /** 1842 * Get internal or external viewport. Create it if does not currently exist. 1843 * @param viewportType - either INTERNAL or EXTERNAL 1844 * @return the viewport with the requested type 1845 */ 1846 private DisplayViewport getViewportLocked(int viewportType, String uniqueId) { 1847 if (viewportType != VIEWPORT_INTERNAL && viewportType != VIEWPORT_EXTERNAL 1848 && viewportType != VIEWPORT_VIRTUAL) { 1849 Slog.wtf(TAG, "Cannot call getViewportByTypeLocked for type " 1850 + DisplayViewport.typeToString(viewportType)); 1851 return null; 1852 } 1853 1854 DisplayViewport viewport; 1855 final int count = mViewports.size(); 1856 for (int i = 0; i < count; i++) { 1857 viewport = mViewports.get(i); 1858 if (viewport.type == viewportType && uniqueId.equals(viewport.uniqueId)) { 1859 return viewport; 1860 } 1861 } 1862 1863 // Creates the viewport if none exists. 1864 viewport = new DisplayViewport(); 1865 viewport.type = viewportType; 1866 viewport.uniqueId = uniqueId; 1867 mViewports.add(viewport); 1868 return viewport; 1869 } 1870 1871 private void populateViewportLocked(int viewportType, int displayId, DisplayDevice device, 1872 DisplayDeviceInfo info) { 1873 final DisplayViewport viewport = getViewportLocked(viewportType, info.uniqueId); 1874 device.populateViewportLocked(viewport); 1875 viewport.valid = true; 1876 viewport.displayId = displayId; 1877 viewport.isActive = Display.isActiveState(info.state); 1878 } 1879 1880 private void updateViewportPowerStateLocked(LogicalDisplay display) { 1881 final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); 1882 final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 1883 final Optional<Integer> viewportType = getViewportType(info); 1884 if (viewportType.isPresent()) { 1885 for (DisplayViewport d : mViewports) { 1886 if (d.type == viewportType.get() && info.uniqueId.equals(d.uniqueId)) { 1887 // Update display view port power state 1888 d.isActive = Display.isActiveState(info.state); 1889 } 1890 } 1891 if (mInputManagerInternal != null) { 1892 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT); 1893 } 1894 } 1895 } 1896 1897 private void sendDisplayEventLocked(int displayId, @DisplayEvent int event) { 1898 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event); 1899 mHandler.sendMessage(msg); 1900 } 1901 1902 private void sendDisplayGroupEvent(int groupId, int event) { 1903 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_GROUP_EVENT, groupId, event); 1904 mHandler.sendMessage(msg); 1905 } 1906 1907 private void sendDisplayEventFrameRateOverrideLocked(int displayId) { 1908 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE, 1909 displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); 1910 mHandler.sendMessage(msg); 1911 } 1912 1913 // Requests that performTraversals be called at a 1914 // later time to apply changes to surfaces and displays. 1915 private void scheduleTraversalLocked(boolean inTraversal) { 1916 if (!mPendingTraversal && mWindowManagerInternal != null) { 1917 mPendingTraversal = true; 1918 if (!inTraversal) { 1919 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL); 1920 } 1921 } 1922 } 1923 1924 // Runs on Handler thread. 1925 // Delivers display event notifications to callbacks. 1926 private void deliverDisplayEvent(int displayId, ArraySet<Integer> uids, 1927 @DisplayEvent int event) { 1928 if (DEBUG) { 1929 Slog.d(TAG, "Delivering display event: displayId=" 1930 + displayId + ", event=" + event); 1931 } 1932 1933 // Grab the lock and copy the callbacks. 1934 final int count; 1935 synchronized (mSyncRoot) { 1936 count = mCallbacks.size(); 1937 mTempCallbacks.clear(); 1938 for (int i = 0; i < count; i++) { 1939 if (uids == null || uids.contains(mCallbacks.valueAt(i).mUid)) { 1940 mTempCallbacks.add(mCallbacks.valueAt(i)); 1941 } 1942 } 1943 } 1944 1945 // After releasing the lock, send the notifications out. 1946 for (int i = 0; i < mTempCallbacks.size(); i++) { 1947 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event); 1948 } 1949 mTempCallbacks.clear(); 1950 } 1951 1952 // Runs on Handler thread. 1953 // Delivers display group event notifications to callbacks. 1954 private void deliverDisplayGroupEvent(int groupId, int event) { 1955 if (DEBUG) { 1956 Slog.d(TAG, "Delivering display group event: groupId=" + groupId + ", event=" 1957 + event); 1958 } 1959 1960 switch (event) { 1961 case LogicalDisplayMapper.DISPLAY_GROUP_EVENT_ADDED: 1962 for (DisplayGroupListener listener : mDisplayGroupListeners) { 1963 listener.onDisplayGroupAdded(groupId); 1964 } 1965 break; 1966 1967 case LogicalDisplayMapper.DISPLAY_GROUP_EVENT_CHANGED: 1968 for (DisplayGroupListener listener : mDisplayGroupListeners) { 1969 listener.onDisplayGroupChanged(groupId); 1970 } 1971 break; 1972 1973 case LogicalDisplayMapper.DISPLAY_GROUP_EVENT_REMOVED: 1974 for (DisplayGroupListener listener : mDisplayGroupListeners) { 1975 listener.onDisplayGroupRemoved(groupId); 1976 } 1977 break; 1978 } 1979 } 1980 1981 private IMediaProjectionManager getProjectionService() { 1982 if (mProjectionService == null) { 1983 IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE); 1984 mProjectionService = IMediaProjectionManager.Stub.asInterface(b); 1985 } 1986 return mProjectionService; 1987 } 1988 1989 private UserManager getUserManager() { 1990 return mContext.getSystemService(UserManager.class); 1991 } 1992 1993 private void dumpInternal(PrintWriter pw) { 1994 pw.println("DISPLAY MANAGER (dumpsys display)"); 1995 1996 synchronized (mSyncRoot) { 1997 pw.println(" mOnlyCode=" + mOnlyCore); 1998 pw.println(" mSafeMode=" + mSafeMode); 1999 pw.println(" mPendingTraversal=" + mPendingTraversal); 2000 pw.println(" mViewports=" + mViewports); 2001 pw.println(" mDefaultDisplayDefaultColorMode=" + mDefaultDisplayDefaultColorMode); 2002 pw.println(" mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount); 2003 pw.println(" mStableDisplaySize=" + mStableDisplaySize); 2004 pw.println(" mMinimumBrightnessCurve=" + mMinimumBrightnessCurve); 2005 2006 pw.println(); 2007 if (!mAreUserDisabledHdrTypesAllowed) { 2008 pw.println(" mUserDisabledHdrTypes: size=" + mUserDisabledHdrTypes.length); 2009 for (int type : mUserDisabledHdrTypes) { 2010 pw.println(" " + type); 2011 } 2012 } 2013 2014 pw.println(); 2015 final int displayStateCount = mDisplayStates.size(); 2016 pw.println("Display States: size=" + displayStateCount); 2017 for (int i = 0; i < displayStateCount; i++) { 2018 final int displayId = mDisplayStates.keyAt(i); 2019 final int displayState = mDisplayStates.valueAt(i); 2020 final BrightnessPair brightnessPair = mDisplayBrightnesses.valueAt(i); 2021 pw.println(" Display Id=" + displayId); 2022 pw.println(" Display State=" + Display.stateToString(displayState)); 2023 pw.println(" Display Brightness=" + brightnessPair.brightness); 2024 pw.println(" Display SdrBrightness=" + brightnessPair.sdrBrightness); 2025 } 2026 2027 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 2028 ipw.increaseIndent(); 2029 2030 pw.println(); 2031 pw.println("Display Adapters: size=" + mDisplayAdapters.size()); 2032 for (DisplayAdapter adapter : mDisplayAdapters) { 2033 pw.println(" " + adapter.getName()); 2034 adapter.dumpLocked(ipw); 2035 } 2036 2037 pw.println(); 2038 pw.println("Display Devices: size=" + mDisplayDeviceRepo.sizeLocked()); 2039 mDisplayDeviceRepo.forEachLocked(device -> { 2040 pw.println(" " + device.getDisplayDeviceInfoLocked()); 2041 device.dumpLocked(ipw); 2042 }); 2043 2044 pw.println(); 2045 mLogicalDisplayMapper.dumpLocked(pw); 2046 2047 final int callbackCount = mCallbacks.size(); 2048 pw.println(); 2049 pw.println("Callbacks: size=" + callbackCount); 2050 for (int i = 0; i < callbackCount; i++) { 2051 CallbackRecord callback = mCallbacks.valueAt(i); 2052 pw.println(" " + i + ": mPid=" + callback.mPid 2053 + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested); 2054 } 2055 2056 final int displayPowerControllerCount = mDisplayPowerControllers.size(); 2057 pw.println(); 2058 pw.println("Display Power Controllers: size=" + displayPowerControllerCount); 2059 for (int i = 0; i < displayPowerControllerCount; i++) { 2060 mDisplayPowerControllers.valueAt(i).dump(pw); 2061 } 2062 if (mBrightnessTracker != null) { 2063 pw.println(); 2064 mBrightnessTracker.dump(pw); 2065 } 2066 pw.println(); 2067 mPersistentDataStore.dump(pw); 2068 } 2069 pw.println(); 2070 mDisplayModeDirector.dump(pw); 2071 } 2072 2073 private static float[] getFloatArray(TypedArray array) { 2074 int length = array.length(); 2075 float[] floatArray = new float[length]; 2076 for (int i = 0; i < length; i++) { 2077 floatArray[i] = array.getFloat(i, Float.NaN); 2078 } 2079 array.recycle(); 2080 return floatArray; 2081 } 2082 2083 /** 2084 * This is the object that everything in the display manager locks on. 2085 * We make it an inner class within the {@link DisplayManagerService} to so that it is 2086 * clear that the object belongs to the display manager service and that it is 2087 * a unique object with a special purpose. 2088 */ 2089 public static final class SyncRoot { 2090 } 2091 2092 @VisibleForTesting 2093 static class Injector { 2094 VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot, Context context, 2095 Handler handler, DisplayAdapter.Listener displayAdapterListener) { 2096 return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener); 2097 } 2098 2099 long getDefaultDisplayDelayTimeout() { 2100 return WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT; 2101 } 2102 2103 boolean getAllowNonNativeRefreshRateOverride() { 2104 return DisplayProperties 2105 .debug_allow_non_native_refresh_rate_override().orElse(false); 2106 } 2107 } 2108 2109 @VisibleForTesting 2110 DisplayDeviceInfo getDisplayDeviceInfoInternal(int displayId) { 2111 synchronized (mSyncRoot) { 2112 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 2113 if (display != null) { 2114 final DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked(); 2115 return displayDevice.getDisplayDeviceInfoLocked(); 2116 } 2117 return null; 2118 } 2119 } 2120 2121 @VisibleForTesting 2122 int getDisplayIdToMirrorInternal(int displayId) { 2123 synchronized (mSyncRoot) { 2124 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 2125 if (display != null) { 2126 final DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked(); 2127 return displayDevice.getDisplayIdToMirrorLocked(); 2128 } 2129 return Display.INVALID_DISPLAY; 2130 } 2131 } 2132 2133 @VisibleForTesting 2134 Surface getVirtualDisplaySurfaceInternal(IBinder appToken) { 2135 synchronized (mSyncRoot) { 2136 if (mVirtualDisplayAdapter == null) { 2137 return null; 2138 } 2139 return mVirtualDisplayAdapter.getVirtualDisplaySurfaceLocked(appToken); 2140 } 2141 } 2142 2143 private void initializeDisplayPowerControllersLocked() { 2144 mLogicalDisplayMapper.forEachLocked(this::addDisplayPowerControllerLocked); 2145 } 2146 2147 private void addDisplayPowerControllerLocked(LogicalDisplay display) { 2148 if (mPowerHandler == null) { 2149 // initPowerManagement has not yet been called. 2150 return; 2151 } 2152 if (mBrightnessTracker == null) { 2153 mBrightnessTracker = new BrightnessTracker(mContext, null); 2154 } 2155 2156 final BrightnessSetting brightnessSetting = new BrightnessSetting(mPersistentDataStore, 2157 display, mSyncRoot); 2158 final DisplayPowerController displayPowerController = new DisplayPowerController( 2159 mContext, mDisplayPowerCallbacks, mPowerHandler, mSensorManager, 2160 mDisplayBlanker, display, mBrightnessTracker, brightnessSetting, 2161 () -> handleBrightnessChange(display)); 2162 mDisplayPowerControllers.append(display.getDisplayIdLocked(), displayPowerController); 2163 } 2164 2165 private void handleBrightnessChange(LogicalDisplay display) { 2166 sendDisplayEventLocked(display.getDisplayIdLocked(), 2167 DisplayManagerGlobal.EVENT_DISPLAY_BRIGHTNESS_CHANGED); 2168 } 2169 2170 private DisplayDevice getDeviceForDisplayLocked(int displayId) { 2171 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 2172 return display == null ? null : display.getPrimaryDisplayDeviceLocked(); 2173 } 2174 2175 private BrightnessConfiguration getBrightnessConfigForDisplayWithPdsFallbackLocked( 2176 String uniqueId, int userSerial) { 2177 BrightnessConfiguration config = 2178 mPersistentDataStore.getBrightnessConfigurationForDisplayLocked( 2179 uniqueId, userSerial); 2180 if (config == null) { 2181 // Get from global configurations 2182 config = mPersistentDataStore.getBrightnessConfiguration(userSerial); 2183 } 2184 return config; 2185 } 2186 2187 private final class DisplayManagerHandler extends Handler { 2188 public DisplayManagerHandler(Looper looper) { 2189 super(looper, null, true /*async*/); 2190 } 2191 2192 @Override 2193 public void handleMessage(Message msg) { 2194 switch (msg.what) { 2195 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS: 2196 registerDefaultDisplayAdapters(); 2197 break; 2198 2199 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS: 2200 registerAdditionalDisplayAdapters(); 2201 break; 2202 2203 case MSG_DELIVER_DISPLAY_EVENT: 2204 deliverDisplayEvent(msg.arg1, null, msg.arg2); 2205 break; 2206 2207 case MSG_REQUEST_TRAVERSAL: 2208 mWindowManagerInternal.requestTraversalFromDisplayManager(); 2209 break; 2210 2211 case MSG_UPDATE_VIEWPORT: { 2212 final boolean changed; 2213 synchronized (mSyncRoot) { 2214 changed = !mTempViewports.equals(mViewports); 2215 if (changed) { 2216 mTempViewports.clear(); 2217 for (DisplayViewport d : mViewports) { 2218 mTempViewports.add(d.makeCopy()); 2219 } 2220 } 2221 } 2222 if (changed) { 2223 mInputManagerInternal.setDisplayViewports(mTempViewports); 2224 } 2225 break; 2226 } 2227 2228 case MSG_LOAD_BRIGHTNESS_CONFIGURATIONS: 2229 loadBrightnessConfigurations(); 2230 break; 2231 2232 case MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE: 2233 ArraySet<Integer> uids; 2234 synchronized (mSyncRoot) { 2235 int displayId = msg.arg1; 2236 final LogicalDisplay display = 2237 mLogicalDisplayMapper.getDisplayLocked(displayId); 2238 if (display == null) { 2239 break; 2240 } 2241 uids = display.getPendingFrameRateOverrideUids(); 2242 display.clearPendingFrameRateOverrideUids(); 2243 } 2244 deliverDisplayEvent(msg.arg1, uids, msg.arg2); 2245 break; 2246 2247 case MSG_DELIVER_DISPLAY_GROUP_EVENT: 2248 deliverDisplayGroupEvent(msg.arg1, msg.arg2); 2249 break; 2250 2251 } 2252 } 2253 } 2254 2255 private final class LogicalDisplayListener implements LogicalDisplayMapper.Listener { 2256 @Override 2257 public void onLogicalDisplayEventLocked(LogicalDisplay display, int event) { 2258 switch (event) { 2259 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_ADDED: 2260 handleLogicalDisplayAddedLocked(display); 2261 break; 2262 2263 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_CHANGED: 2264 handleLogicalDisplayChangedLocked(display); 2265 break; 2266 2267 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REMOVED: 2268 handleLogicalDisplayRemovedLocked(display); 2269 break; 2270 2271 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_SWAPPED: 2272 handleLogicalDisplaySwappedLocked(display); 2273 break; 2274 2275 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED: 2276 handleLogicalDisplayFrameRateOverridesChangedLocked(display); 2277 break; 2278 2279 case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION: 2280 handleLogicalDisplayDeviceStateTransitionLocked(display); 2281 break; 2282 } 2283 } 2284 2285 @Override 2286 public void onDisplayGroupEventLocked(int groupId, int event) { 2287 sendDisplayGroupEvent(groupId, event); 2288 } 2289 2290 @Override 2291 public void onTraversalRequested() { 2292 synchronized (mSyncRoot) { 2293 scheduleTraversalLocked(false); 2294 } 2295 } 2296 } 2297 2298 private final class CallbackRecord implements DeathRecipient { 2299 public final int mPid; 2300 public final int mUid; 2301 private final IDisplayManagerCallback mCallback; 2302 private @EventsMask AtomicLong mEventsMask; 2303 2304 public boolean mWifiDisplayScanRequested; 2305 2306 CallbackRecord(int pid, int uid, IDisplayManagerCallback callback, 2307 @EventsMask long eventsMask) { 2308 mPid = pid; 2309 mUid = uid; 2310 mCallback = callback; 2311 mEventsMask = new AtomicLong(eventsMask); 2312 } 2313 2314 public void updateEventsMask(@EventsMask long eventsMask) { 2315 mEventsMask.set(eventsMask); 2316 } 2317 2318 @Override 2319 public void binderDied() { 2320 if (DEBUG) { 2321 Slog.d(TAG, "Display listener for pid " + mPid + " died."); 2322 } 2323 onCallbackDied(this); 2324 } 2325 2326 public void notifyDisplayEventAsync(int displayId, @DisplayEvent int event) { 2327 if (!shouldSendEvent(event)) { 2328 return; 2329 } 2330 2331 try { 2332 mCallback.onDisplayEvent(displayId, event); 2333 } catch (RemoteException ex) { 2334 Slog.w(TAG, "Failed to notify process " 2335 + mPid + " that displays changed, assuming it died.", ex); 2336 binderDied(); 2337 } 2338 } 2339 2340 private boolean shouldSendEvent(@DisplayEvent int event) { 2341 final long mask = mEventsMask.get(); 2342 switch (event) { 2343 case DisplayManagerGlobal.EVENT_DISPLAY_ADDED: 2344 return (mask & DisplayManager.EVENT_FLAG_DISPLAY_ADDED) != 0; 2345 case DisplayManagerGlobal.EVENT_DISPLAY_CHANGED: 2346 return (mask & DisplayManager.EVENT_FLAG_DISPLAY_CHANGED) != 0; 2347 case DisplayManagerGlobal.EVENT_DISPLAY_BRIGHTNESS_CHANGED: 2348 return (mask & DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS) != 0; 2349 case DisplayManagerGlobal.EVENT_DISPLAY_REMOVED: 2350 return (mask & DisplayManager.EVENT_FLAG_DISPLAY_REMOVED) != 0; 2351 default: 2352 // This should never happen. 2353 Slog.e(TAG, "Unknown display event " + event); 2354 return true; 2355 } 2356 } 2357 } 2358 2359 @VisibleForTesting 2360 final class BinderService extends IDisplayManager.Stub { 2361 /** 2362 * Returns information about the specified logical display. 2363 * 2364 * @param displayId The logical display id. 2365 * @return The logical display info, return {@code null} if the display does not exist or 2366 * the calling UID isn't present on the display. The returned object must be treated as 2367 * immutable. 2368 */ 2369 @Override // Binder call 2370 public DisplayInfo getDisplayInfo(int displayId) { 2371 final int callingUid = Binder.getCallingUid(); 2372 final long token = Binder.clearCallingIdentity(); 2373 try { 2374 return getDisplayInfoInternal(displayId, callingUid); 2375 } finally { 2376 Binder.restoreCallingIdentity(token); 2377 } 2378 } 2379 2380 /** 2381 * Returns the list of all display ids. 2382 */ 2383 @Override // Binder call 2384 public int[] getDisplayIds() { 2385 final int callingUid = Binder.getCallingUid(); 2386 final long token = Binder.clearCallingIdentity(); 2387 try { 2388 synchronized (mSyncRoot) { 2389 return mLogicalDisplayMapper.getDisplayIdsLocked(callingUid); 2390 } 2391 } finally { 2392 Binder.restoreCallingIdentity(token); 2393 } 2394 } 2395 2396 @Override // Binder call 2397 public boolean isUidPresentOnDisplay(int uid, int displayId) { 2398 final long token = Binder.clearCallingIdentity(); 2399 try { 2400 return isUidPresentOnDisplayInternal(uid, displayId); 2401 } finally { 2402 Binder.restoreCallingIdentity(token); 2403 } 2404 } 2405 2406 /** 2407 * Returns the stable device display size, in pixels. 2408 */ 2409 @Override // Binder call 2410 public Point getStableDisplaySize() { 2411 final long token = Binder.clearCallingIdentity(); 2412 try { 2413 return getStableDisplaySizeInternal(); 2414 } finally { 2415 Binder.restoreCallingIdentity(token); 2416 } 2417 } 2418 2419 @Override // Binder call 2420 public void registerCallback(IDisplayManagerCallback callback) { 2421 registerCallbackWithEventMask(callback, DisplayManager.EVENT_FLAG_DISPLAY_ADDED 2422 | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED 2423 | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED); 2424 } 2425 2426 @Override // Binder call 2427 public void registerCallbackWithEventMask(IDisplayManagerCallback callback, 2428 @EventsMask long eventsMask) { 2429 if (callback == null) { 2430 throw new IllegalArgumentException("listener must not be null"); 2431 } 2432 2433 final int callingPid = Binder.getCallingPid(); 2434 final int callingUid = Binder.getCallingUid(); 2435 final long token = Binder.clearCallingIdentity(); 2436 try { 2437 registerCallbackInternal(callback, callingPid, callingUid, eventsMask); 2438 } finally { 2439 Binder.restoreCallingIdentity(token); 2440 } 2441 } 2442 2443 @Override // Binder call 2444 public void startWifiDisplayScan() { 2445 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 2446 "Permission required to start wifi display scans"); 2447 2448 final int callingPid = Binder.getCallingPid(); 2449 final long token = Binder.clearCallingIdentity(); 2450 try { 2451 startWifiDisplayScanInternal(callingPid); 2452 } finally { 2453 Binder.restoreCallingIdentity(token); 2454 } 2455 } 2456 2457 @Override // Binder call 2458 public void stopWifiDisplayScan() { 2459 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 2460 "Permission required to stop wifi display scans"); 2461 2462 final int callingPid = Binder.getCallingPid(); 2463 final long token = Binder.clearCallingIdentity(); 2464 try { 2465 stopWifiDisplayScanInternal(callingPid); 2466 } finally { 2467 Binder.restoreCallingIdentity(token); 2468 } 2469 } 2470 2471 @Override // Binder call 2472 public void connectWifiDisplay(String address) { 2473 if (address == null) { 2474 throw new IllegalArgumentException("address must not be null"); 2475 } 2476 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 2477 "Permission required to connect to a wifi display"); 2478 2479 final long token = Binder.clearCallingIdentity(); 2480 try { 2481 connectWifiDisplayInternal(address); 2482 } finally { 2483 Binder.restoreCallingIdentity(token); 2484 } 2485 } 2486 2487 @Override // Binder call 2488 public void disconnectWifiDisplay() { 2489 // This request does not require special permissions. 2490 // Any app can request disconnection from the currently active wifi display. 2491 // This exception should no longer be needed once wifi display control moves 2492 // to the media router service. 2493 2494 final long token = Binder.clearCallingIdentity(); 2495 try { 2496 disconnectWifiDisplayInternal(); 2497 } finally { 2498 Binder.restoreCallingIdentity(token); 2499 } 2500 } 2501 2502 @Override // Binder call 2503 public void renameWifiDisplay(String address, String alias) { 2504 if (address == null) { 2505 throw new IllegalArgumentException("address must not be null"); 2506 } 2507 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 2508 "Permission required to rename to a wifi display"); 2509 2510 final long token = Binder.clearCallingIdentity(); 2511 try { 2512 renameWifiDisplayInternal(address, alias); 2513 } finally { 2514 Binder.restoreCallingIdentity(token); 2515 } 2516 } 2517 2518 @Override // Binder call 2519 public void forgetWifiDisplay(String address) { 2520 if (address == null) { 2521 throw new IllegalArgumentException("address must not be null"); 2522 } 2523 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 2524 "Permission required to forget to a wifi display"); 2525 2526 final long token = Binder.clearCallingIdentity(); 2527 try { 2528 forgetWifiDisplayInternal(address); 2529 } finally { 2530 Binder.restoreCallingIdentity(token); 2531 } 2532 } 2533 2534 @Override // Binder call 2535 public void pauseWifiDisplay() { 2536 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 2537 "Permission required to pause a wifi display session"); 2538 2539 final long token = Binder.clearCallingIdentity(); 2540 try { 2541 pauseWifiDisplayInternal(); 2542 } finally { 2543 Binder.restoreCallingIdentity(token); 2544 } 2545 } 2546 2547 @Override // Binder call 2548 public void resumeWifiDisplay() { 2549 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 2550 "Permission required to resume a wifi display session"); 2551 2552 final long token = Binder.clearCallingIdentity(); 2553 try { 2554 resumeWifiDisplayInternal(); 2555 } finally { 2556 Binder.restoreCallingIdentity(token); 2557 } 2558 } 2559 2560 @Override // Binder call 2561 public WifiDisplayStatus getWifiDisplayStatus() { 2562 // This request does not require special permissions. 2563 // Any app can get information about available wifi displays. 2564 2565 final long token = Binder.clearCallingIdentity(); 2566 try { 2567 return getWifiDisplayStatusInternal(); 2568 } finally { 2569 Binder.restoreCallingIdentity(token); 2570 } 2571 } 2572 2573 @Override // Binder call 2574 public void setUserDisabledHdrTypes(int[] userDisabledFormats) { 2575 mContext.enforceCallingOrSelfPermission( 2576 Manifest.permission.WRITE_SECURE_SETTINGS, 2577 "Permission required to write the user settings."); 2578 2579 final long token = Binder.clearCallingIdentity(); 2580 try { 2581 setUserDisabledHdrTypesInternal(userDisabledFormats); 2582 } finally { 2583 Binder.restoreCallingIdentity(token); 2584 } 2585 } 2586 2587 @Override // Binder call 2588 public void setAreUserDisabledHdrTypesAllowed(boolean areUserDisabledHdrTypesAllowed) { 2589 mContext.enforceCallingOrSelfPermission( 2590 Manifest.permission.WRITE_SECURE_SETTINGS, 2591 "Permission required to write the user settings."); 2592 final long token = Binder.clearCallingIdentity(); 2593 try { 2594 setAreUserDisabledHdrTypesAllowedInternal(areUserDisabledHdrTypesAllowed); 2595 } finally { 2596 Binder.restoreCallingIdentity(token); 2597 } 2598 } 2599 2600 @Override // Binder call 2601 public boolean areUserDisabledHdrTypesAllowed() { 2602 synchronized (mSyncRoot) { 2603 return mAreUserDisabledHdrTypesAllowed; 2604 } 2605 } 2606 2607 @Override // Binder call 2608 public int[] getUserDisabledHdrTypes() { 2609 return mUserDisabledHdrTypes; 2610 } 2611 2612 @Override // Binder call 2613 public void requestColorMode(int displayId, int colorMode) { 2614 mContext.enforceCallingOrSelfPermission( 2615 Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE, 2616 "Permission required to change the display color mode"); 2617 final long token = Binder.clearCallingIdentity(); 2618 try { 2619 requestColorModeInternal(displayId, colorMode); 2620 } finally { 2621 Binder.restoreCallingIdentity(token); 2622 } 2623 } 2624 2625 @Override // Binder call 2626 public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig, 2627 IVirtualDisplayCallback callback, IMediaProjection projection, String packageName) { 2628 final int callingUid = Binder.getCallingUid(); 2629 if (!validatePackageName(callingUid, packageName)) { 2630 throw new SecurityException("packageName must match the calling uid"); 2631 } 2632 if (callback == null) { 2633 throw new IllegalArgumentException("appToken must not be null"); 2634 } 2635 if (virtualDisplayConfig == null) { 2636 throw new IllegalArgumentException("virtualDisplayConfig must not be null"); 2637 } 2638 final Surface surface = virtualDisplayConfig.getSurface(); 2639 int flags = virtualDisplayConfig.getFlags(); 2640 2641 if (surface != null && surface.isSingleBuffered()) { 2642 throw new IllegalArgumentException("Surface can't be single-buffered"); 2643 } 2644 2645 if ((flags & VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) { 2646 flags |= VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; 2647 2648 // Public displays can't be allowed to show content when locked. 2649 if ((flags & VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) { 2650 throw new IllegalArgumentException( 2651 "Public display must not be marked as SHOW_WHEN_LOCKED_INSECURE"); 2652 } 2653 } 2654 if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) { 2655 flags &= ~VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; 2656 } 2657 if ((flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) { 2658 flags &= ~VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP; 2659 } 2660 2661 if (projection != null) { 2662 try { 2663 if (!getProjectionService().isValidMediaProjection(projection)) { 2664 throw new SecurityException("Invalid media projection"); 2665 } 2666 flags = projection.applyVirtualDisplayFlags(flags); 2667 } catch (RemoteException e) { 2668 throw new SecurityException("unable to validate media projection or flags"); 2669 } 2670 } 2671 2672 if (callingUid != Process.SYSTEM_UID && 2673 (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) { 2674 if (!canProjectVideo(projection)) { 2675 throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or " 2676 + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate " 2677 + "MediaProjection token in order to create a screen sharing virtual " 2678 + "display."); 2679 } 2680 } 2681 if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0) { 2682 if (!canProjectSecureVideo(projection)) { 2683 throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT " 2684 + "or an appropriate MediaProjection token to create a " 2685 + "secure virtual display."); 2686 } 2687 } 2688 2689 if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0) { 2690 if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) { 2691 EventLog.writeEvent(0x534e4554, "162627132", callingUid, 2692 "Attempt to create a trusted display without holding permission!"); 2693 throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to " 2694 + "create a trusted virtual display."); 2695 } 2696 } 2697 2698 if (callingUid != Process.SYSTEM_UID 2699 && (flags & VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP) != 0) { 2700 if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) { 2701 throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to " 2702 + "create a virtual display which is not in the default DisplayGroup."); 2703 } 2704 } 2705 2706 if ((flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) == 0) { 2707 flags &= ~VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; 2708 } 2709 2710 // Sometimes users can have sensitive information in system decoration windows. An app 2711 // could create a virtual display with system decorations support and read the user info 2712 // from the surface. 2713 // We should only allow adding flag VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS 2714 // to trusted virtual displays. 2715 final int trustedDisplayWithSysDecorFlag = 2716 (VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS 2717 | VIRTUAL_DISPLAY_FLAG_TRUSTED); 2718 if ((flags & trustedDisplayWithSysDecorFlag) 2719 == VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS 2720 && !checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "createVirtualDisplay()")) { 2721 throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); 2722 } 2723 2724 final long token = Binder.clearCallingIdentity(); 2725 try { 2726 return createVirtualDisplayInternal(callback, projection, callingUid, packageName, 2727 surface, flags, virtualDisplayConfig); 2728 } finally { 2729 Binder.restoreCallingIdentity(token); 2730 } 2731 } 2732 2733 @Override // Binder call 2734 public void resizeVirtualDisplay(IVirtualDisplayCallback callback, 2735 int width, int height, int densityDpi) { 2736 if (width <= 0 || height <= 0 || densityDpi <= 0) { 2737 throw new IllegalArgumentException("width, height, and densityDpi must be " 2738 + "greater than 0"); 2739 } 2740 final long token = Binder.clearCallingIdentity(); 2741 try { 2742 resizeVirtualDisplayInternal(callback.asBinder(), width, height, densityDpi); 2743 } finally { 2744 Binder.restoreCallingIdentity(token); 2745 } 2746 } 2747 2748 @Override // Binder call 2749 public void setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface) { 2750 if (surface != null && surface.isSingleBuffered()) { 2751 throw new IllegalArgumentException("Surface can't be single-buffered"); 2752 } 2753 final long token = Binder.clearCallingIdentity(); 2754 try { 2755 setVirtualDisplaySurfaceInternal(callback.asBinder(), surface); 2756 } finally { 2757 Binder.restoreCallingIdentity(token); 2758 } 2759 } 2760 2761 @Override // Binder call 2762 public void releaseVirtualDisplay(IVirtualDisplayCallback callback) { 2763 final long token = Binder.clearCallingIdentity(); 2764 try { 2765 releaseVirtualDisplayInternal(callback.asBinder()); 2766 } finally { 2767 Binder.restoreCallingIdentity(token); 2768 } 2769 } 2770 2771 @Override // Binder call 2772 public void setVirtualDisplayState(IVirtualDisplayCallback callback, boolean isOn) { 2773 final long token = Binder.clearCallingIdentity(); 2774 try { 2775 setVirtualDisplayStateInternal(callback.asBinder(), isOn); 2776 } finally { 2777 Binder.restoreCallingIdentity(token); 2778 } 2779 } 2780 2781 @Override // Binder call 2782 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 2783 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 2784 2785 final long token = Binder.clearCallingIdentity(); 2786 try { 2787 dumpInternal(pw); 2788 } finally { 2789 Binder.restoreCallingIdentity(token); 2790 } 2791 } 2792 2793 @Override // Binder call 2794 public ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents(String callingPackage) { 2795 mContext.enforceCallingOrSelfPermission( 2796 Manifest.permission.BRIGHTNESS_SLIDER_USAGE, 2797 "Permission to read brightness events."); 2798 2799 final int callingUid = Binder.getCallingUid(); 2800 AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class); 2801 final int mode = appOpsManager.noteOp(AppOpsManager.OP_GET_USAGE_STATS, 2802 callingUid, callingPackage); 2803 final boolean hasUsageStats; 2804 if (mode == AppOpsManager.MODE_DEFAULT) { 2805 // The default behavior here is to check if PackageManager has given the app 2806 // permission. 2807 hasUsageStats = mContext.checkCallingPermission( 2808 Manifest.permission.PACKAGE_USAGE_STATS) 2809 == PackageManager.PERMISSION_GRANTED; 2810 } else { 2811 hasUsageStats = mode == AppOpsManager.MODE_ALLOWED; 2812 } 2813 2814 final int userId = UserHandle.getUserId(callingUid); 2815 final long token = Binder.clearCallingIdentity(); 2816 try { 2817 synchronized (mSyncRoot) { 2818 return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY) 2819 .getBrightnessEvents(userId, hasUsageStats); 2820 } 2821 } finally { 2822 Binder.restoreCallingIdentity(token); 2823 } 2824 } 2825 2826 @Override // Binder call 2827 public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats() { 2828 mContext.enforceCallingOrSelfPermission( 2829 Manifest.permission.ACCESS_AMBIENT_LIGHT_STATS, 2830 "Permission required to to access ambient light stats."); 2831 final int callingUid = Binder.getCallingUid(); 2832 final int userId = UserHandle.getUserId(callingUid); 2833 final long token = Binder.clearCallingIdentity(); 2834 try { 2835 synchronized (mSyncRoot) { 2836 return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY) 2837 .getAmbientBrightnessStats(userId); 2838 } 2839 } finally { 2840 Binder.restoreCallingIdentity(token); 2841 } 2842 } 2843 2844 @Override // Binder call 2845 public void setBrightnessConfigurationForUser( 2846 BrightnessConfiguration c, @UserIdInt int userId, String packageName) { 2847 mContext.enforceCallingOrSelfPermission( 2848 Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS, 2849 "Permission required to change the display's brightness configuration"); 2850 if (userId != UserHandle.getCallingUserId()) { 2851 mContext.enforceCallingOrSelfPermission( 2852 Manifest.permission.INTERACT_ACROSS_USERS, 2853 "Permission required to change the display brightness" 2854 + " configuration of another user"); 2855 } 2856 final long token = Binder.clearCallingIdentity(); 2857 try { 2858 synchronized (mSyncRoot) { 2859 mLogicalDisplayMapper.forEachLocked(logicalDisplay -> { 2860 if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) { 2861 return; 2862 } 2863 final DisplayDevice displayDevice = 2864 logicalDisplay.getPrimaryDisplayDeviceLocked(); 2865 setBrightnessConfigurationForDisplayInternal(c, displayDevice.getUniqueId(), 2866 userId, packageName); 2867 }); 2868 } 2869 } finally { 2870 Binder.restoreCallingIdentity(token); 2871 } 2872 } 2873 2874 @Override // Binder call 2875 public void setBrightnessConfigurationForDisplay(BrightnessConfiguration c, 2876 String uniqueId, int userId, String packageName) { 2877 mContext.enforceCallingOrSelfPermission( 2878 Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS, 2879 "Permission required to change the display's brightness configuration"); 2880 if (userId != UserHandle.getCallingUserId()) { 2881 mContext.enforceCallingOrSelfPermission( 2882 Manifest.permission.INTERACT_ACROSS_USERS, 2883 "Permission required to change the display brightness" 2884 + " configuration of another user"); 2885 } 2886 final long token = Binder.clearCallingIdentity(); 2887 try { 2888 setBrightnessConfigurationForDisplayInternal(c, uniqueId, userId, packageName); 2889 } finally { 2890 Binder.restoreCallingIdentity(token); 2891 } 2892 } 2893 2894 @Override // Binder call 2895 public BrightnessConfiguration getBrightnessConfigurationForDisplay(String uniqueId, 2896 int userId) { 2897 mContext.enforceCallingOrSelfPermission( 2898 Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS, 2899 "Permission required to read the display's brightness configuration"); 2900 if (userId != UserHandle.getCallingUserId()) { 2901 mContext.enforceCallingOrSelfPermission( 2902 Manifest.permission.INTERACT_ACROSS_USERS, 2903 "Permission required to read the display brightness" 2904 + " configuration of another user"); 2905 } 2906 final long token = Binder.clearCallingIdentity(); 2907 final int userSerial = getUserManager().getUserSerialNumber(userId); 2908 try { 2909 synchronized (mSyncRoot) { 2910 // Get from per-display configurations 2911 BrightnessConfiguration config = 2912 getBrightnessConfigForDisplayWithPdsFallbackLocked( 2913 uniqueId, userSerial); 2914 if (config == null) { 2915 // Get default configuration 2916 DisplayPowerController dpc = getDpcFromUniqueIdLocked(uniqueId); 2917 if (dpc != null) { 2918 config = dpc.getDefaultBrightnessConfiguration(); 2919 } 2920 } 2921 return config; 2922 } 2923 } finally { 2924 Binder.restoreCallingIdentity(token); 2925 } 2926 } 2927 2928 2929 2930 @Override // Binder call 2931 public BrightnessConfiguration getBrightnessConfigurationForUser(int userId) { 2932 final String uniqueId; 2933 synchronized (mSyncRoot) { 2934 DisplayDevice displayDevice = mLogicalDisplayMapper.getDisplayLocked( 2935 Display.DEFAULT_DISPLAY).getPrimaryDisplayDeviceLocked(); 2936 uniqueId = displayDevice.getUniqueId(); 2937 } 2938 return getBrightnessConfigurationForDisplay(uniqueId, userId); 2939 2940 2941 } 2942 2943 @Override // Binder call 2944 public BrightnessConfiguration getDefaultBrightnessConfiguration() { 2945 mContext.enforceCallingOrSelfPermission( 2946 Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS, 2947 "Permission required to read the display's default brightness configuration"); 2948 final long token = Binder.clearCallingIdentity(); 2949 try { 2950 synchronized (mSyncRoot) { 2951 return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY) 2952 .getDefaultBrightnessConfiguration(); 2953 } 2954 } finally { 2955 Binder.restoreCallingIdentity(token); 2956 } 2957 } 2958 2959 @Override 2960 public BrightnessInfo getBrightnessInfo(int displayId) { 2961 mContext.enforceCallingOrSelfPermission( 2962 Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS, 2963 "Permission required to read the display's brightness info."); 2964 final long token = Binder.clearCallingIdentity(); 2965 try { 2966 synchronized (mSyncRoot) { 2967 DisplayPowerController dpc = mDisplayPowerControllers.get(displayId); 2968 if (dpc != null) { 2969 return dpc.getBrightnessInfo(); 2970 } 2971 } 2972 } finally { 2973 Binder.restoreCallingIdentity(token); 2974 } 2975 return null; 2976 } 2977 2978 @Override // Binder call 2979 public boolean isMinimalPostProcessingRequested(int displayId) { 2980 synchronized (mSyncRoot) { 2981 return mLogicalDisplayMapper.getDisplayLocked(displayId) 2982 .getRequestedMinimalPostProcessingLocked(); 2983 } 2984 } 2985 2986 @Override // Binder call 2987 public void setTemporaryBrightness(int displayId, float brightness) { 2988 mContext.enforceCallingOrSelfPermission( 2989 Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS, 2990 "Permission required to set the display's brightness"); 2991 final long token = Binder.clearCallingIdentity(); 2992 try { 2993 synchronized (mSyncRoot) { 2994 mDisplayPowerControllers.get(displayId) 2995 .setTemporaryBrightness(brightness); 2996 } 2997 } finally { 2998 Binder.restoreCallingIdentity(token); 2999 } 3000 } 3001 3002 @Override // Binder call 3003 public void setBrightness(int displayId, float brightness) { 3004 mContext.enforceCallingOrSelfPermission( 3005 Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS, 3006 "Permission required to set the display's brightness"); 3007 if (!isValidBrightness(brightness)) { 3008 Slog.w(TAG, "Attempted to set invalid brightness" + brightness); 3009 return; 3010 } 3011 final long token = Binder.clearCallingIdentity(); 3012 try { 3013 synchronized (mSyncRoot) { 3014 DisplayPowerController dpc = mDisplayPowerControllers.get(displayId); 3015 if (dpc != null) { 3016 dpc.putScreenBrightnessSetting(brightness); 3017 } 3018 mPersistentDataStore.saveIfNeeded(); 3019 } 3020 } finally { 3021 Binder.restoreCallingIdentity(token); 3022 } 3023 } 3024 3025 @Override // Binder call 3026 public float getBrightness(int displayId) { 3027 float brightness = PowerManager.BRIGHTNESS_INVALID_FLOAT; 3028 mContext.enforceCallingOrSelfPermission( 3029 Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS, 3030 "Permission required to set the display's brightness"); 3031 final long token = Binder.clearCallingIdentity(); 3032 try { 3033 synchronized (mSyncRoot) { 3034 DisplayPowerController dpc = mDisplayPowerControllers.get(displayId); 3035 if (dpc != null) { 3036 brightness = dpc.getScreenBrightnessSetting(); 3037 } 3038 } 3039 } finally { 3040 Binder.restoreCallingIdentity(token); 3041 } 3042 return brightness; 3043 } 3044 3045 @Override // Binder call 3046 public void setTemporaryAutoBrightnessAdjustment(float adjustment) { 3047 mContext.enforceCallingOrSelfPermission( 3048 Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS, 3049 "Permission required to set the display's auto brightness adjustment"); 3050 final long token = Binder.clearCallingIdentity(); 3051 try { 3052 synchronized (mSyncRoot) { 3053 mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY) 3054 .setTemporaryAutoBrightnessAdjustment(adjustment); 3055 } 3056 } finally { 3057 Binder.restoreCallingIdentity(token); 3058 } 3059 } 3060 3061 @Override // Binder call 3062 public void onShellCommand(FileDescriptor in, FileDescriptor out, 3063 FileDescriptor err, String[] args, ShellCallback callback, 3064 ResultReceiver resultReceiver) { 3065 new DisplayManagerShellCommand(DisplayManagerService.this).exec(this, in, out, err, 3066 args, callback, resultReceiver); 3067 } 3068 3069 @Override // Binder call 3070 public Curve getMinimumBrightnessCurve() { 3071 final long token = Binder.clearCallingIdentity(); 3072 try { 3073 return getMinimumBrightnessCurveInternal(); 3074 } finally { 3075 Binder.restoreCallingIdentity(token); 3076 } 3077 } 3078 3079 @Override // Binder call 3080 public int getPreferredWideGamutColorSpaceId() { 3081 final long token = Binder.clearCallingIdentity(); 3082 try { 3083 return getPreferredWideGamutColorSpaceIdInternal(); 3084 } finally { 3085 Binder.restoreCallingIdentity(token); 3086 } 3087 } 3088 3089 @Override // Binder call 3090 public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) { 3091 mContext.enforceCallingOrSelfPermission( 3092 Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS, 3093 "Permission required to override display mode requests."); 3094 final long token = Binder.clearCallingIdentity(); 3095 try { 3096 setShouldAlwaysRespectAppRequestedModeInternal(enabled); 3097 } finally { 3098 Binder.restoreCallingIdentity(token); 3099 } 3100 } 3101 3102 @Override // Binder call 3103 public boolean shouldAlwaysRespectAppRequestedMode() { 3104 mContext.enforceCallingOrSelfPermission( 3105 Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS, 3106 "Permission required to override display mode requests."); 3107 final long token = Binder.clearCallingIdentity(); 3108 try { 3109 return shouldAlwaysRespectAppRequestedModeInternal(); 3110 } finally { 3111 Binder.restoreCallingIdentity(token); 3112 } 3113 } 3114 3115 @Override // Binder call 3116 public void setRefreshRateSwitchingType(int newValue) { 3117 mContext.enforceCallingOrSelfPermission( 3118 Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE, 3119 "Permission required to modify refresh rate switching type."); 3120 final long token = Binder.clearCallingIdentity(); 3121 try { 3122 setRefreshRateSwitchingTypeInternal(newValue); 3123 } finally { 3124 Binder.restoreCallingIdentity(token); 3125 } 3126 } 3127 3128 @Override // Binder call 3129 public int getRefreshRateSwitchingType() { 3130 final long token = Binder.clearCallingIdentity(); 3131 try { 3132 return getRefreshRateSwitchingTypeInternal(); 3133 } finally { 3134 Binder.restoreCallingIdentity(token); 3135 } 3136 } 3137 3138 private boolean validatePackageName(int uid, String packageName) { 3139 if (packageName != null) { 3140 String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid); 3141 if (packageNames != null) { 3142 for (String n : packageNames) { 3143 if (n.equals(packageName)) { 3144 return true; 3145 } 3146 } 3147 } 3148 } 3149 return false; 3150 } 3151 3152 private boolean canProjectVideo(IMediaProjection projection) { 3153 if (projection != null) { 3154 try { 3155 if (projection.canProjectVideo()) { 3156 return true; 3157 } 3158 } catch (RemoteException e) { 3159 Slog.e(TAG, "Unable to query projection service for permissions", e); 3160 } 3161 } 3162 if (checkCallingPermission(CAPTURE_VIDEO_OUTPUT, "canProjectVideo()")) { 3163 return true; 3164 } 3165 return canProjectSecureVideo(projection); 3166 } 3167 3168 private boolean canProjectSecureVideo(IMediaProjection projection) { 3169 if (projection != null) { 3170 try { 3171 if (projection.canProjectSecureVideo()){ 3172 return true; 3173 } 3174 } catch (RemoteException e) { 3175 Slog.e(TAG, "Unable to query projection service for permissions", e); 3176 } 3177 } 3178 return checkCallingPermission(CAPTURE_SECURE_VIDEO_OUTPUT, "canProjectSecureVideo()"); 3179 } 3180 3181 private boolean checkCallingPermission(String permission, String func) { 3182 if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) { 3183 return true; 3184 } 3185 final String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid() 3186 + ", uid=" + Binder.getCallingUid() + " requires " + permission; 3187 Slog.w(TAG, msg); 3188 return false; 3189 } 3190 3191 } 3192 3193 private static boolean isValidBrightness(float brightness) { 3194 return !Float.isNaN(brightness) 3195 && (brightness >= PowerManager.BRIGHTNESS_MIN) 3196 && (brightness <= PowerManager.BRIGHTNESS_MAX); 3197 } 3198 3199 private final class LocalService extends DisplayManagerInternal { 3200 3201 @Override 3202 public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler, 3203 SensorManager sensorManager) { 3204 synchronized (mSyncRoot) { 3205 mDisplayPowerCallbacks = callbacks; 3206 mSensorManager = sensorManager; 3207 mPowerHandler = handler; 3208 initializeDisplayPowerControllersLocked(); 3209 } 3210 3211 mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATIONS); 3212 } 3213 3214 @Override 3215 public boolean requestPowerState(int groupId, DisplayPowerRequest request, 3216 boolean waitForNegativeProximity) { 3217 synchronized (mSyncRoot) { 3218 final DisplayGroup displayGroup = mLogicalDisplayMapper.getDisplayGroupLocked( 3219 groupId); 3220 if (displayGroup == null) { 3221 return true; 3222 } 3223 3224 final int size = displayGroup.getSizeLocked(); 3225 boolean ready = true; 3226 for (int i = 0; i < size; i++) { 3227 final int id = displayGroup.getIdLocked(i); 3228 final DisplayDevice displayDevice = mLogicalDisplayMapper.getDisplayLocked( 3229 id).getPrimaryDisplayDeviceLocked(); 3230 final int flags = displayDevice.getDisplayDeviceInfoLocked().flags; 3231 if ((flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) { 3232 final DisplayPowerController displayPowerController = 3233 mDisplayPowerControllers.get(id); 3234 ready &= displayPowerController.requestPowerState(request, 3235 waitForNegativeProximity); 3236 } 3237 } 3238 3239 return ready; 3240 } 3241 } 3242 3243 @Override 3244 public boolean isProximitySensorAvailable() { 3245 synchronized (mSyncRoot) { 3246 return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY) 3247 .isProximitySensorAvailable(); 3248 } 3249 } 3250 3251 @Override 3252 public void registerDisplayGroupListener(DisplayGroupListener listener) { 3253 mDisplayGroupListeners.add(listener); 3254 } 3255 3256 @Override 3257 public void unregisterDisplayGroupListener(DisplayGroupListener listener) { 3258 mDisplayGroupListeners.remove(listener); 3259 } 3260 3261 @Override 3262 public SurfaceControl.ScreenshotHardwareBuffer systemScreenshot(int displayId) { 3263 return systemScreenshotInternal(displayId); 3264 } 3265 3266 @Override 3267 public SurfaceControl.ScreenshotHardwareBuffer userScreenshot(int displayId) { 3268 return userScreenshotInternal(displayId); 3269 } 3270 3271 @Override 3272 public DisplayInfo getDisplayInfo(int displayId) { 3273 return getDisplayInfoInternal(displayId, Process.myUid()); 3274 } 3275 3276 @Override 3277 public Point getDisplayPosition(int displayId) { 3278 synchronized (mSyncRoot) { 3279 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 3280 if (display != null) { 3281 return display.getDisplayPosition(); 3282 } 3283 return null; 3284 } 3285 } 3286 3287 @Override 3288 public void registerDisplayTransactionListener(DisplayTransactionListener listener) { 3289 if (listener == null) { 3290 throw new IllegalArgumentException("listener must not be null"); 3291 } 3292 3293 registerDisplayTransactionListenerInternal(listener); 3294 } 3295 3296 @Override 3297 public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) { 3298 if (listener == null) { 3299 throw new IllegalArgumentException("listener must not be null"); 3300 } 3301 3302 unregisterDisplayTransactionListenerInternal(listener); 3303 } 3304 3305 @Override 3306 public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) { 3307 setDisplayInfoOverrideFromWindowManagerInternal(displayId, info); 3308 } 3309 3310 @Override 3311 public void getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo) { 3312 getNonOverrideDisplayInfoInternal(displayId, outInfo); 3313 } 3314 3315 @Override 3316 public void performTraversal(SurfaceControl.Transaction t) { 3317 performTraversalInternal(t); 3318 } 3319 3320 @Override 3321 public void setDisplayProperties(int displayId, boolean hasContent, 3322 float requestedRefreshRate, int requestedMode, float requestedMinRefreshRate, 3323 float requestedMaxRefreshRate, boolean requestedMinimalPostProcessing, 3324 boolean inTraversal) { 3325 setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate, 3326 requestedMode, requestedMinRefreshRate, requestedMaxRefreshRate, 3327 requestedMinimalPostProcessing, inTraversal); 3328 } 3329 3330 @Override 3331 public void setDisplayOffsets(int displayId, int x, int y) { 3332 setDisplayOffsetsInternal(displayId, x, y); 3333 } 3334 3335 @Override 3336 public void setDisplayScalingDisabled(int displayId, boolean disableScaling) { 3337 setDisplayScalingDisabledInternal(displayId, disableScaling); 3338 } 3339 3340 @Override 3341 public void setDisplayAccessUIDs(SparseArray<IntArray> newDisplayAccessUIDs) { 3342 setDisplayAccessUIDsInternal(newDisplayAccessUIDs); 3343 } 3344 3345 @Override 3346 public void persistBrightnessTrackerState() { 3347 synchronized (mSyncRoot) { 3348 mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY) 3349 .persistBrightnessTrackerState(); 3350 } 3351 } 3352 3353 @Override 3354 public void onOverlayChanged() { 3355 synchronized (mSyncRoot) { 3356 mDisplayDeviceRepo.forEachLocked(DisplayDevice::onOverlayChangedLocked); 3357 } 3358 } 3359 3360 @Override 3361 public DisplayedContentSamplingAttributes getDisplayedContentSamplingAttributes( 3362 int displayId) { 3363 return getDisplayedContentSamplingAttributesInternal(displayId); 3364 } 3365 3366 @Override 3367 public boolean setDisplayedContentSamplingEnabled( 3368 int displayId, boolean enable, int componentMask, int maxFrames) { 3369 return setDisplayedContentSamplingEnabledInternal( 3370 displayId, enable, componentMask, maxFrames); 3371 } 3372 3373 @Override 3374 public DisplayedContentSample getDisplayedContentSample(int displayId, 3375 long maxFrames, long timestamp) { 3376 return getDisplayedContentSampleInternal(displayId, maxFrames, timestamp); 3377 } 3378 3379 @Override 3380 public void ignoreProximitySensorUntilChanged() { 3381 mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY) 3382 .ignoreProximitySensorUntilChanged(); 3383 } 3384 3385 @Override 3386 public int getRefreshRateSwitchingType() { 3387 return getRefreshRateSwitchingTypeInternal(); 3388 } 3389 3390 @Override 3391 public RefreshRateRange getRefreshRateForDisplayAndSensor(int displayId, String sensorName, 3392 String sensorType) { 3393 final SensorManager sensorManager; 3394 synchronized (mSyncRoot) { 3395 sensorManager = mSensorManager; 3396 } 3397 if (sensorManager == null) { 3398 return null; 3399 } 3400 3401 // Verify that the specified sensor exists. 3402 final Sensor sensor = SensorUtils.findSensor(sensorManager, sensorType, sensorName, 3403 SensorUtils.NO_FALLBACK); 3404 if (sensor == null) { 3405 return null; 3406 } 3407 3408 synchronized (mSyncRoot) { 3409 final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); 3410 if (display == null) { 3411 return null; 3412 } 3413 final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); 3414 if (device == null) { 3415 return null; 3416 } 3417 final DisplayDeviceConfig config = device.getDisplayDeviceConfig(); 3418 SensorData sensorData = config.getProximitySensor(); 3419 if (sensorData.matches(sensorName, sensorType)) { 3420 return new RefreshRateRange(sensorData.minRefreshRate, 3421 sensorData.maxRefreshRate); 3422 } 3423 } 3424 return null; 3425 } 3426 3427 @Override 3428 public List<RefreshRateLimitation> getRefreshRateLimitations(int displayId) { 3429 final DisplayDeviceConfig config; 3430 synchronized (mSyncRoot) { 3431 final DisplayDevice device = getDeviceForDisplayLocked(displayId); 3432 if (device == null) { 3433 return null; 3434 } 3435 config = device.getDisplayDeviceConfig(); 3436 } 3437 return config.getRefreshRateLimitations(); 3438 } 3439 3440 @Override 3441 public IBinder getWindowTokenClientToMirror(int displayId) { 3442 final DisplayDevice device; 3443 synchronized (mSyncRoot) { 3444 device = getDeviceForDisplayLocked(displayId); 3445 if (device == null) { 3446 return null; 3447 } 3448 } 3449 return device.getWindowTokenClientToMirrorLocked(); 3450 } 3451 3452 @Override 3453 public void setWindowTokenClientToMirror(int displayId, IBinder windowToken) { 3454 synchronized (mSyncRoot) { 3455 final DisplayDevice device = getDeviceForDisplayLocked(displayId); 3456 if (device != null) { 3457 device.setWindowTokenClientToMirrorLocked(windowToken); 3458 } 3459 } 3460 } 3461 3462 @Override 3463 public Point getDisplaySurfaceDefaultSize(int displayId) { 3464 final DisplayDevice device; 3465 synchronized (mSyncRoot) { 3466 device = getDeviceForDisplayLocked(displayId); 3467 if (device == null) { 3468 return null; 3469 } 3470 } 3471 return device.getDisplaySurfaceDefaultSize(); 3472 } 3473 } 3474 3475 class DesiredDisplayModeSpecsObserver 3476 implements DisplayModeDirector.DesiredDisplayModeSpecsListener { 3477 3478 private final Consumer<LogicalDisplay> mSpecsChangedConsumer = display -> { 3479 int displayId = display.getDisplayIdLocked(); 3480 DisplayModeDirector.DesiredDisplayModeSpecs desiredDisplayModeSpecs = 3481 mDisplayModeDirector.getDesiredDisplayModeSpecs(displayId); 3482 DisplayModeDirector.DesiredDisplayModeSpecs existingDesiredDisplayModeSpecs = 3483 display.getDesiredDisplayModeSpecsLocked(); 3484 if (DEBUG) { 3485 Slog.i(TAG, 3486 "Comparing display specs: " + desiredDisplayModeSpecs 3487 + ", existing: " + existingDesiredDisplayModeSpecs); 3488 } 3489 if (!desiredDisplayModeSpecs.equals(existingDesiredDisplayModeSpecs)) { 3490 display.setDesiredDisplayModeSpecsLocked(desiredDisplayModeSpecs); 3491 mChanged = true; 3492 } 3493 }; 3494 3495 @GuardedBy("mSyncRoot") 3496 private boolean mChanged = false; 3497 3498 public void onDesiredDisplayModeSpecsChanged() { 3499 synchronized (mSyncRoot) { 3500 mChanged = false; 3501 mLogicalDisplayMapper.forEachLocked(mSpecsChangedConsumer); 3502 if (mChanged) { 3503 scheduleTraversalLocked(false); 3504 mChanged = false; 3505 } 3506 } 3507 } 3508 } 3509 3510 /** 3511 * Listens to changes in device state and reports the state to LogicalDisplayMapper. 3512 */ 3513 class DeviceStateListener implements DeviceStateManager.DeviceStateCallback { 3514 @Override 3515 public void onStateChanged(int deviceState) { 3516 synchronized (mSyncRoot) { 3517 mLogicalDisplayMapper.setDeviceStateLocked(deviceState); 3518 } 3519 } 3520 }; 3521 3522 private class BrightnessPair { 3523 public float brightness; 3524 public float sdrBrightness; 3525 3526 BrightnessPair(float brightness, float sdrBrightness) { 3527 this.brightness = brightness; 3528 this.sdrBrightness = sdrBrightness; 3529 } 3530 } 3531 3532 /** 3533 * Functional interface for providing time. 3534 * TODO(b/184781936): merge with PowerManagerService.Clock 3535 */ 3536 @VisibleForTesting 3537 public interface Clock { 3538 /** 3539 * Returns current time in milliseconds since boot, not counting time spent in deep sleep. 3540 */ 3541 long uptimeMillis(); 3542 } 3543 } 3544