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