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.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; 20 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY; 21 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC; 22 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE; 23 import static android.hardware.display.DisplayManager 24 .VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; 25 26 import com.android.internal.annotations.VisibleForTesting; 27 import com.android.internal.util.DumpUtils; 28 import com.android.internal.util.IndentingPrintWriter; 29 30 import android.Manifest; 31 import android.annotation.NonNull; 32 import android.annotation.Nullable; 33 import android.annotation.UserIdInt; 34 import android.app.AppOpsManager; 35 import android.content.Context; 36 import android.content.pm.PackageManager; 37 import android.content.pm.ParceledListSlice; 38 import android.content.res.Resources; 39 import android.content.res.TypedArray; 40 import android.graphics.Point; 41 import android.hardware.SensorManager; 42 import android.hardware.display.AmbientBrightnessDayStats; 43 import android.hardware.display.BrightnessChangeEvent; 44 import android.hardware.display.BrightnessConfiguration; 45 import android.hardware.display.Curve; 46 import android.hardware.display.DisplayManagerGlobal; 47 import android.hardware.display.DisplayManagerInternal; 48 import android.hardware.display.DisplayViewport; 49 import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener; 50 import android.hardware.display.IDisplayManager; 51 import android.hardware.display.IDisplayManagerCallback; 52 import android.hardware.display.IVirtualDisplayCallback; 53 import android.hardware.display.WifiDisplayStatus; 54 import android.hardware.input.InputManagerInternal; 55 import android.media.projection.IMediaProjection; 56 import android.media.projection.IMediaProjectionManager; 57 import android.os.Binder; 58 import android.os.Handler; 59 import android.os.IBinder; 60 import android.os.IBinder.DeathRecipient; 61 import android.os.Looper; 62 import android.os.Message; 63 import android.os.PowerManager; 64 import android.os.Process; 65 import android.os.RemoteException; 66 import android.os.ResultReceiver; 67 import android.os.ServiceManager; 68 import android.os.ShellCallback; 69 import android.os.SystemClock; 70 import android.os.SystemProperties; 71 import android.os.Trace; 72 import android.os.UserHandle; 73 import android.os.UserManager; 74 import android.provider.Settings; 75 import android.text.TextUtils; 76 import android.util.IntArray; 77 import android.util.Pair; 78 import android.util.Slog; 79 import android.util.SparseArray; 80 import android.util.Spline; 81 import android.view.Display; 82 import android.view.DisplayInfo; 83 import android.view.Surface; 84 import android.view.SurfaceControl; 85 86 import com.android.internal.util.Preconditions; 87 import com.android.server.AnimationThread; 88 import com.android.server.DisplayThread; 89 import com.android.server.LocalServices; 90 import com.android.server.SystemService; 91 import com.android.server.UiThread; 92 import com.android.server.wm.WindowManagerInternal; 93 import com.android.server.wm.SurfaceAnimationThread; 94 95 import java.io.FileDescriptor; 96 import java.io.PrintWriter; 97 import java.util.ArrayList; 98 import java.util.Arrays; 99 import java.util.List; 100 import java.util.concurrent.CopyOnWriteArrayList; 101 102 /** 103 * Manages attached displays. 104 * <p> 105 * The {@link DisplayManagerService} manages the global lifecycle of displays, 106 * decides how to configure logical displays based on the physical display devices currently 107 * attached, sends notifications to the system and to applications when the state 108 * changes, and so on. 109 * </p><p> 110 * The display manager service relies on a collection of {@link DisplayAdapter} components, 111 * for discovering and configuring physical display devices attached to the system. 112 * There are separate display adapters for each manner that devices are attached: 113 * one display adapter for built-in local displays, one for simulated non-functional 114 * displays when the system is headless, one for simulated overlay displays used for 115 * development, one for wifi displays, etc. 116 * </p><p> 117 * Display adapters are only weakly coupled to the display manager service. 118 * Display adapters communicate changes in display device state to the display manager 119 * service asynchronously via a {@link DisplayAdapter.Listener} registered 120 * by the display manager service. This separation of concerns is important for 121 * two main reasons. First, it neatly encapsulates the responsibilities of these 122 * two classes: display adapters handle individual display devices whereas 123 * the display manager service handles the global state. Second, it eliminates 124 * the potential for deadlocks resulting from asynchronous display device discovery. 125 * </p> 126 * 127 * <h3>Synchronization</h3> 128 * <p> 129 * Because the display manager may be accessed by multiple threads, the synchronization 130 * story gets a little complicated. In particular, the window manager may call into 131 * the display manager while holding a surface transaction with the expectation that 132 * it can apply changes immediately. Unfortunately, that means we can't just do 133 * everything asynchronously (*grump*). 134 * </p><p> 135 * To make this work, all of the objects that belong to the display manager must 136 * use the same lock. We call this lock the synchronization root and it has a unique 137 * type {@link DisplayManagerService.SyncRoot}. Methods that require this lock are 138 * named with the "Locked" suffix. 139 * </p><p> 140 * Where things get tricky is that the display manager is not allowed to make 141 * any potentially reentrant calls, especially into the window manager. We generally 142 * avoid this by making all potentially reentrant out-calls asynchronous. 143 * </p> 144 */ 145 public final class DisplayManagerService extends SystemService { 146 private static final String TAG = "DisplayManagerService"; 147 private static final boolean DEBUG = false; 148 149 // When this system property is set to 0, WFD is forcibly disabled on boot. 150 // When this system property is set to 1, WFD is forcibly enabled on boot. 151 // Otherwise WFD is enabled according to the value of config_enableWifiDisplay. 152 private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable"; 153 154 private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000; 155 156 private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1; 157 private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2; 158 private static final int MSG_DELIVER_DISPLAY_EVENT = 3; 159 private static final int MSG_REQUEST_TRAVERSAL = 4; 160 private static final int MSG_UPDATE_VIEWPORT = 5; 161 private static final int MSG_REGISTER_BRIGHTNESS_TRACKER = 6; 162 private static final int MSG_LOAD_BRIGHTNESS_CONFIGURATION = 7; 163 164 private final Context mContext; 165 private final DisplayManagerHandler mHandler; 166 private final Handler mUiHandler; 167 private final DisplayAdapterListener mDisplayAdapterListener; 168 private WindowManagerInternal mWindowManagerInternal; 169 private InputManagerInternal mInputManagerInternal; 170 private IMediaProjectionManager mProjectionService; 171 172 // The synchronization root for the display manager. 173 // This lock guards most of the display manager's state. 174 // NOTE: This is synchronized on while holding WindowManagerService.mWindowMap so never call 175 // into WindowManagerService methods that require mWindowMap while holding this unless you are 176 // very very sure that no deadlock can occur. 177 private final SyncRoot mSyncRoot = new SyncRoot(); 178 179 // True if in safe mode. 180 // This option may disable certain display adapters. 181 public boolean mSafeMode; 182 183 // True if we are in a special boot mode where only core applications and 184 // services should be started. This option may disable certain display adapters. 185 public boolean mOnlyCore; 186 187 // True if the display manager service should pretend there is only one display 188 // and only tell applications about the existence of the default logical display. 189 // The display manager can still mirror content to secondary displays but applications 190 // cannot present unique content on those displays. 191 // Used for demonstration purposes only. 192 private final boolean mSingleDisplayDemoMode; 193 194 // All callback records indexed by calling process id. 195 public final SparseArray<CallbackRecord> mCallbacks = 196 new SparseArray<CallbackRecord>(); 197 198 // List of all currently registered display adapters. 199 private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>(); 200 201 // List of all currently connected display devices. 202 private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>(); 203 204 // List of all logical displays indexed by logical display id. 205 private final SparseArray<LogicalDisplay> mLogicalDisplays = 206 new SparseArray<LogicalDisplay>(); 207 private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1; 208 209 // List of all display transaction listeners. 210 private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners = 211 new CopyOnWriteArrayList<DisplayTransactionListener>(); 212 213 // Display power controller. 214 private DisplayPowerController mDisplayPowerController; 215 216 // The overall display state, independent of changes that might influence one 217 // display or another in particular. 218 private int mGlobalDisplayState = Display.STATE_ON; 219 220 // The overall display brightness. 221 // For now, this only applies to the built-in display but we may split it up eventually. 222 private int mGlobalDisplayBrightness = PowerManager.BRIGHTNESS_DEFAULT; 223 224 // Set to true when there are pending display changes that have yet to be applied 225 // to the surface flinger state. 226 private boolean mPendingTraversal; 227 228 // The Wifi display adapter, or null if not registered. 229 private WifiDisplayAdapter mWifiDisplayAdapter; 230 231 // The number of active wifi display scan requests. 232 private int mWifiDisplayScanRequestCount; 233 234 // The virtual display adapter, or null if not registered. 235 private VirtualDisplayAdapter mVirtualDisplayAdapter; 236 237 // The User ID of the current user 238 private @UserIdInt int mCurrentUserId; 239 240 // The stable device screen height and width. These are not tied to a specific display, even 241 // the default display, because they need to be stable over the course of the device's entire 242 // life, even if the default display changes (e.g. a new monitor is plugged into a PC-like 243 // device). 244 private Point mStableDisplaySize = new Point(); 245 246 // Viewports of the default display and the display that should receive touch 247 // input from an external source. Used by the input system. 248 private final DisplayViewport mDefaultViewport = new DisplayViewport(); 249 private final DisplayViewport mExternalTouchViewport = new DisplayViewport(); 250 private final ArrayList<DisplayViewport> mVirtualTouchViewports = new ArrayList<>(); 251 252 // Persistent data store for all internal settings maintained by the display manager service. 253 private final PersistentDataStore mPersistentDataStore = new PersistentDataStore(); 254 255 // Temporary callback list, used when sending display events to applications. 256 // May be used outside of the lock but only on the handler thread. 257 private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>(); 258 259 // Temporary display info, used for comparing display configurations. 260 private final DisplayInfo mTempDisplayInfo = new DisplayInfo(); 261 262 // Temporary viewports, used when sending new viewport information to the 263 // input system. May be used outside of the lock but only on the handler thread. 264 private final DisplayViewport mTempDefaultViewport = new DisplayViewport(); 265 private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport(); 266 private final ArrayList<DisplayViewport> mTempVirtualTouchViewports = new ArrayList<>(); 267 268 // The default color mode for default displays. Overrides the usual 269 // Display.Display.COLOR_MODE_DEFAULT for displays with the 270 // DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY flag set. 271 private final int mDefaultDisplayDefaultColorMode; 272 273 // Temporary list of deferred work to perform when setting the display state. 274 // Only used by requestDisplayState. The field is self-synchronized and only 275 // intended for use inside of the requestGlobalDisplayStateInternal function. 276 private final ArrayList<Runnable> mTempDisplayStateWorkQueue = new ArrayList<Runnable>(); 277 278 // Lists of UIDs that are present on the displays. Maps displayId -> array of UIDs. 279 private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>(); 280 281 private final Injector mInjector; 282 283 // The minimum brightness curve, which guarantess that any brightness curve that dips below it 284 // is rejected by the system. 285 private final Curve mMinimumBrightnessCurve; 286 private final Spline mMinimumBrightnessSpline; 287 DisplayManagerService(Context context)288 public DisplayManagerService(Context context) { 289 this(context, new Injector()); 290 } 291 292 @VisibleForTesting DisplayManagerService(Context context, Injector injector)293 DisplayManagerService(Context context, Injector injector) { 294 super(context); 295 mInjector = injector; 296 mContext = context; 297 mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper()); 298 mUiHandler = UiThread.getHandler(); 299 mDisplayAdapterListener = new DisplayAdapterListener(); 300 mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false); 301 Resources resources = mContext.getResources(); 302 mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger( 303 com.android.internal.R.integer.config_defaultDisplayDefaultColorMode); 304 float[] lux = getFloatArray(resources.obtainTypedArray( 305 com.android.internal.R.array.config_minimumBrightnessCurveLux)); 306 float[] nits = getFloatArray(resources.obtainTypedArray( 307 com.android.internal.R.array.config_minimumBrightnessCurveNits)); 308 mMinimumBrightnessCurve = new Curve(lux, nits); 309 mMinimumBrightnessSpline = Spline.createSpline(lux, nits); 310 311 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 312 mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting(); 313 mCurrentUserId = UserHandle.USER_SYSTEM; 314 } 315 setupSchedulerPolicies()316 public void setupSchedulerPolicies() { 317 // android.display and android.anim is critical to user experience and we should make sure 318 // it is not in the default foregroup groups, add it to top-app to make sure it uses all 319 // the cores and scheduling settings for top-app when it runs. 320 Process.setThreadGroupAndCpuset(DisplayThread.get().getThreadId(), 321 Process.THREAD_GROUP_TOP_APP); 322 Process.setThreadGroupAndCpuset(AnimationThread.get().getThreadId(), 323 Process.THREAD_GROUP_TOP_APP); 324 Process.setThreadGroupAndCpuset(SurfaceAnimationThread.get().getThreadId(), 325 Process.THREAD_GROUP_TOP_APP); 326 } 327 328 @Override onStart()329 public void onStart() { 330 // We need to pre-load the persistent data store so it's ready before the default display 331 // adapter is up so that we have it's configuration. We could load it lazily, but since 332 // we're going to have to read it in eventually we may as well do it here rather than after 333 // we've waited for the display to register itself with us. 334 synchronized(mSyncRoot) { 335 mPersistentDataStore.loadIfNeeded(); 336 loadStableDisplayValuesLocked(); 337 } 338 mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS); 339 340 publishBinderService(Context.DISPLAY_SERVICE, new BinderService(), 341 true /*allowIsolated*/); 342 publishLocalService(DisplayManagerInternal.class, new LocalService()); 343 publishLocalService(DisplayTransformManager.class, new DisplayTransformManager()); 344 } 345 346 @Override onBootPhase(int phase)347 public void onBootPhase(int phase) { 348 if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) { 349 synchronized (mSyncRoot) { 350 long timeout = SystemClock.uptimeMillis() 351 + mInjector.getDefaultDisplayDelayTimeout(); 352 while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null || 353 mVirtualDisplayAdapter == null) { 354 long delay = timeout - SystemClock.uptimeMillis(); 355 if (delay <= 0) { 356 throw new RuntimeException("Timeout waiting for default display " 357 + "to be initialized. DefaultDisplay=" 358 + mLogicalDisplays.get(Display.DEFAULT_DISPLAY) 359 + ", mVirtualDisplayAdapter=" + mVirtualDisplayAdapter); 360 } 361 if (DEBUG) { 362 Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay); 363 } 364 try { 365 mSyncRoot.wait(delay); 366 } catch (InterruptedException ex) { 367 } 368 } 369 } 370 } 371 } 372 373 @Override onSwitchUser(@serIdInt int newUserId)374 public void onSwitchUser(@UserIdInt int newUserId) { 375 final int userSerial = getUserManager().getUserSerialNumber(newUserId); 376 synchronized (mSyncRoot) { 377 if (mCurrentUserId != newUserId) { 378 mCurrentUserId = newUserId; 379 BrightnessConfiguration config = 380 mPersistentDataStore.getBrightnessConfiguration(userSerial); 381 mDisplayPowerController.setBrightnessConfiguration(config); 382 } 383 mDisplayPowerController.onSwitchUser(newUserId); 384 } 385 } 386 387 // TODO: Use dependencies or a boot phase windowManagerAndInputReady()388 public void windowManagerAndInputReady() { 389 synchronized (mSyncRoot) { 390 mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); 391 mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); 392 scheduleTraversalLocked(false); 393 } 394 } 395 396 /** 397 * Called when the system is ready to go. 398 */ systemReady(boolean safeMode, boolean onlyCore)399 public void systemReady(boolean safeMode, boolean onlyCore) { 400 synchronized (mSyncRoot) { 401 mSafeMode = safeMode; 402 mOnlyCore = onlyCore; 403 } 404 405 mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS); 406 mHandler.sendEmptyMessage(MSG_REGISTER_BRIGHTNESS_TRACKER); 407 } 408 409 @VisibleForTesting getDisplayHandler()410 Handler getDisplayHandler() { 411 return mHandler; 412 } 413 loadStableDisplayValuesLocked()414 private void loadStableDisplayValuesLocked() { 415 final Point size = mPersistentDataStore.getStableDisplaySize(); 416 if (size.x > 0 && size.y > 0) { 417 // Just set these values directly so we don't write the display persistent data again 418 // unnecessarily 419 mStableDisplaySize.set(size.x, size.y); 420 } else { 421 final Resources res = mContext.getResources(); 422 final int width = res.getInteger( 423 com.android.internal.R.integer.config_stableDeviceDisplayWidth); 424 final int height = res.getInteger( 425 com.android.internal.R.integer.config_stableDeviceDisplayHeight); 426 if (width > 0 && height > 0) { 427 setStableDisplaySizeLocked(width, height); 428 } 429 } 430 } 431 getStableDisplaySizeInternal()432 private Point getStableDisplaySizeInternal() { 433 Point r = new Point(); 434 synchronized (mSyncRoot) { 435 if (mStableDisplaySize.x > 0 && mStableDisplaySize.y > 0) { 436 r.set(mStableDisplaySize.x, mStableDisplaySize.y); 437 } 438 } 439 return r; 440 } 441 registerDisplayTransactionListenerInternal( DisplayTransactionListener listener)442 private void registerDisplayTransactionListenerInternal( 443 DisplayTransactionListener listener) { 444 // List is self-synchronized copy-on-write. 445 mDisplayTransactionListeners.add(listener); 446 } 447 unregisterDisplayTransactionListenerInternal( DisplayTransactionListener listener)448 private void unregisterDisplayTransactionListenerInternal( 449 DisplayTransactionListener listener) { 450 // List is self-synchronized copy-on-write. 451 mDisplayTransactionListeners.remove(listener); 452 } 453 setDisplayInfoOverrideFromWindowManagerInternal( int displayId, DisplayInfo info)454 private void setDisplayInfoOverrideFromWindowManagerInternal( 455 int displayId, DisplayInfo info) { 456 synchronized (mSyncRoot) { 457 LogicalDisplay display = mLogicalDisplays.get(displayId); 458 if (display != null) { 459 if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) { 460 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); 461 scheduleTraversalLocked(false); 462 } 463 } 464 } 465 } 466 467 /** 468 * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo) 469 */ getNonOverrideDisplayInfoInternal(int displayId, DisplayInfo outInfo)470 private void getNonOverrideDisplayInfoInternal(int displayId, DisplayInfo outInfo) { 471 synchronized (mSyncRoot) { 472 final LogicalDisplay display = mLogicalDisplays.get(displayId); 473 if (display != null) { 474 display.getNonOverrideDisplayInfoLocked(outInfo); 475 } 476 } 477 } 478 479 @VisibleForTesting performTraversalInternal(SurfaceControl.Transaction t)480 void performTraversalInternal(SurfaceControl.Transaction t) { 481 synchronized (mSyncRoot) { 482 if (!mPendingTraversal) { 483 return; 484 } 485 mPendingTraversal = false; 486 487 performTraversalLocked(t); 488 } 489 490 // List is self-synchronized copy-on-write. 491 for (DisplayTransactionListener listener : mDisplayTransactionListeners) { 492 listener.onDisplayTransaction(); 493 } 494 } 495 requestGlobalDisplayStateInternal(int state, int brightness)496 private void requestGlobalDisplayStateInternal(int state, int brightness) { 497 if (state == Display.STATE_UNKNOWN) { 498 state = Display.STATE_ON; 499 } 500 if (state == Display.STATE_OFF) { 501 brightness = PowerManager.BRIGHTNESS_OFF; 502 } else if (brightness < 0) { 503 brightness = PowerManager.BRIGHTNESS_DEFAULT; 504 } else if (brightness > PowerManager.BRIGHTNESS_ON) { 505 brightness = PowerManager.BRIGHTNESS_ON; 506 } 507 508 synchronized (mTempDisplayStateWorkQueue) { 509 try { 510 // Update the display state within the lock. 511 // Note that we do not need to schedule traversals here although it 512 // may happen as a side-effect of displays changing state. 513 synchronized (mSyncRoot) { 514 if (mGlobalDisplayState == state 515 && mGlobalDisplayBrightness == brightness) { 516 return; // no change 517 } 518 519 Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestGlobalDisplayState(" 520 + Display.stateToString(state) 521 + ", brightness=" + brightness + ")"); 522 mGlobalDisplayState = state; 523 mGlobalDisplayBrightness = brightness; 524 applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue); 525 } 526 527 // Setting the display power state can take hundreds of milliseconds 528 // to complete so we defer the most expensive part of the work until 529 // after we have exited the critical section to avoid blocking other 530 // threads for a long time. 531 for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) { 532 mTempDisplayStateWorkQueue.get(i).run(); 533 } 534 Trace.traceEnd(Trace.TRACE_TAG_POWER); 535 } finally { 536 mTempDisplayStateWorkQueue.clear(); 537 } 538 } 539 } 540 getDisplayInfoInternal(int displayId, int callingUid)541 private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) { 542 synchronized (mSyncRoot) { 543 LogicalDisplay display = mLogicalDisplays.get(displayId); 544 if (display != null) { 545 DisplayInfo info = display.getDisplayInfoLocked(); 546 if (info.hasAccess(callingUid) 547 || isUidPresentOnDisplayInternal(callingUid, displayId)) { 548 return info; 549 } 550 } 551 return null; 552 } 553 } 554 getDisplayIdsInternal(int callingUid)555 private int[] getDisplayIdsInternal(int callingUid) { 556 synchronized (mSyncRoot) { 557 final int count = mLogicalDisplays.size(); 558 int[] displayIds = new int[count]; 559 int n = 0; 560 for (int i = 0; i < count; i++) { 561 LogicalDisplay display = mLogicalDisplays.valueAt(i); 562 DisplayInfo info = display.getDisplayInfoLocked(); 563 if (info.hasAccess(callingUid)) { 564 displayIds[n++] = mLogicalDisplays.keyAt(i); 565 } 566 } 567 if (n != count) { 568 displayIds = Arrays.copyOfRange(displayIds, 0, n); 569 } 570 return displayIds; 571 } 572 } 573 registerCallbackInternal(IDisplayManagerCallback callback, int callingPid)574 private void registerCallbackInternal(IDisplayManagerCallback callback, int callingPid) { 575 synchronized (mSyncRoot) { 576 if (mCallbacks.get(callingPid) != null) { 577 throw new SecurityException("The calling process has already " 578 + "registered an IDisplayManagerCallback."); 579 } 580 581 CallbackRecord record = new CallbackRecord(callingPid, callback); 582 try { 583 IBinder binder = callback.asBinder(); 584 binder.linkToDeath(record, 0); 585 } catch (RemoteException ex) { 586 // give up 587 throw new RuntimeException(ex); 588 } 589 590 mCallbacks.put(callingPid, record); 591 } 592 } 593 onCallbackDied(CallbackRecord record)594 private void onCallbackDied(CallbackRecord record) { 595 synchronized (mSyncRoot) { 596 mCallbacks.remove(record.mPid); 597 stopWifiDisplayScanLocked(record); 598 } 599 } 600 startWifiDisplayScanInternal(int callingPid)601 private void startWifiDisplayScanInternal(int callingPid) { 602 synchronized (mSyncRoot) { 603 CallbackRecord record = mCallbacks.get(callingPid); 604 if (record == null) { 605 throw new IllegalStateException("The calling process has not " 606 + "registered an IDisplayManagerCallback."); 607 } 608 startWifiDisplayScanLocked(record); 609 } 610 } 611 startWifiDisplayScanLocked(CallbackRecord record)612 private void startWifiDisplayScanLocked(CallbackRecord record) { 613 if (!record.mWifiDisplayScanRequested) { 614 record.mWifiDisplayScanRequested = true; 615 if (mWifiDisplayScanRequestCount++ == 0) { 616 if (mWifiDisplayAdapter != null) { 617 mWifiDisplayAdapter.requestStartScanLocked(); 618 } 619 } 620 } 621 } 622 stopWifiDisplayScanInternal(int callingPid)623 private void stopWifiDisplayScanInternal(int callingPid) { 624 synchronized (mSyncRoot) { 625 CallbackRecord record = mCallbacks.get(callingPid); 626 if (record == null) { 627 throw new IllegalStateException("The calling process has not " 628 + "registered an IDisplayManagerCallback."); 629 } 630 stopWifiDisplayScanLocked(record); 631 } 632 } 633 stopWifiDisplayScanLocked(CallbackRecord record)634 private void stopWifiDisplayScanLocked(CallbackRecord record) { 635 if (record.mWifiDisplayScanRequested) { 636 record.mWifiDisplayScanRequested = false; 637 if (--mWifiDisplayScanRequestCount == 0) { 638 if (mWifiDisplayAdapter != null) { 639 mWifiDisplayAdapter.requestStopScanLocked(); 640 } 641 } else if (mWifiDisplayScanRequestCount < 0) { 642 Slog.wtf(TAG, "mWifiDisplayScanRequestCount became negative: " 643 + mWifiDisplayScanRequestCount); 644 mWifiDisplayScanRequestCount = 0; 645 } 646 } 647 } 648 connectWifiDisplayInternal(String address)649 private void connectWifiDisplayInternal(String address) { 650 synchronized (mSyncRoot) { 651 if (mWifiDisplayAdapter != null) { 652 mWifiDisplayAdapter.requestConnectLocked(address); 653 } 654 } 655 } 656 pauseWifiDisplayInternal()657 private void pauseWifiDisplayInternal() { 658 synchronized (mSyncRoot) { 659 if (mWifiDisplayAdapter != null) { 660 mWifiDisplayAdapter.requestPauseLocked(); 661 } 662 } 663 } 664 resumeWifiDisplayInternal()665 private void resumeWifiDisplayInternal() { 666 synchronized (mSyncRoot) { 667 if (mWifiDisplayAdapter != null) { 668 mWifiDisplayAdapter.requestResumeLocked(); 669 } 670 } 671 } 672 disconnectWifiDisplayInternal()673 private void disconnectWifiDisplayInternal() { 674 synchronized (mSyncRoot) { 675 if (mWifiDisplayAdapter != null) { 676 mWifiDisplayAdapter.requestDisconnectLocked(); 677 } 678 } 679 } 680 renameWifiDisplayInternal(String address, String alias)681 private void renameWifiDisplayInternal(String address, String alias) { 682 synchronized (mSyncRoot) { 683 if (mWifiDisplayAdapter != null) { 684 mWifiDisplayAdapter.requestRenameLocked(address, alias); 685 } 686 } 687 } 688 forgetWifiDisplayInternal(String address)689 private void forgetWifiDisplayInternal(String address) { 690 synchronized (mSyncRoot) { 691 if (mWifiDisplayAdapter != null) { 692 mWifiDisplayAdapter.requestForgetLocked(address); 693 } 694 } 695 } 696 getWifiDisplayStatusInternal()697 private WifiDisplayStatus getWifiDisplayStatusInternal() { 698 synchronized (mSyncRoot) { 699 if (mWifiDisplayAdapter != null) { 700 return mWifiDisplayAdapter.getWifiDisplayStatusLocked(); 701 } 702 return new WifiDisplayStatus(); 703 } 704 } 705 requestColorModeInternal(int displayId, int colorMode)706 private void requestColorModeInternal(int displayId, int colorMode) { 707 synchronized (mSyncRoot) { 708 LogicalDisplay display = mLogicalDisplays.get(displayId); 709 if (display != null && 710 display.getRequestedColorModeLocked() != colorMode) { 711 display.setRequestedColorModeLocked(colorMode); 712 scheduleTraversalLocked(false); 713 } 714 } 715 } 716 setSaturationLevelInternal(float level)717 private void setSaturationLevelInternal(float level) { 718 if (level < 0 || level > 1) { 719 throw new IllegalArgumentException("Saturation level must be between 0 and 1"); 720 } 721 float[] matrix = (level == 1.0f ? null : computeSaturationMatrix(level)); 722 DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class); 723 dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_SATURATION, matrix); 724 } 725 computeSaturationMatrix(float saturation)726 private static float[] computeSaturationMatrix(float saturation) { 727 float desaturation = 1.0f - saturation; 728 float[] luminance = {0.231f * desaturation, 0.715f * desaturation, 0.072f * desaturation}; 729 float[] matrix = { 730 luminance[0] + saturation, luminance[0], luminance[0], 0, 731 luminance[1], luminance[1] + saturation, luminance[1], 0, 732 luminance[2], luminance[2], luminance[2] + saturation, 0, 733 0, 0, 0, 1 734 }; 735 return matrix; 736 } 737 createVirtualDisplayInternal(IVirtualDisplayCallback callback, IMediaProjection projection, int callingUid, String packageName, String name, int width, int height, int densityDpi, Surface surface, int flags, String uniqueId)738 private int createVirtualDisplayInternal(IVirtualDisplayCallback callback, 739 IMediaProjection projection, int callingUid, String packageName, String name, int width, 740 int height, int densityDpi, Surface surface, int flags, String uniqueId) { 741 synchronized (mSyncRoot) { 742 if (mVirtualDisplayAdapter == null) { 743 Slog.w(TAG, "Rejecting request to create private virtual display " 744 + "because the virtual display adapter is not available."); 745 return -1; 746 } 747 748 DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked( 749 callback, projection, callingUid, packageName, name, width, height, densityDpi, 750 surface, flags, uniqueId); 751 if (device == null) { 752 return -1; 753 } 754 755 handleDisplayDeviceAddedLocked(device); 756 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device); 757 if (display != null) { 758 return display.getDisplayIdLocked(); 759 } 760 761 // Something weird happened and the logical display was not created. 762 Slog.w(TAG, "Rejecting request to create virtual display " 763 + "because the logical display was not created."); 764 mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder()); 765 handleDisplayDeviceRemovedLocked(device); 766 } 767 return -1; 768 } 769 resizeVirtualDisplayInternal(IBinder appToken, int width, int height, int densityDpi)770 private void resizeVirtualDisplayInternal(IBinder appToken, 771 int width, int height, int densityDpi) { 772 synchronized (mSyncRoot) { 773 if (mVirtualDisplayAdapter == null) { 774 return; 775 } 776 777 mVirtualDisplayAdapter.resizeVirtualDisplayLocked(appToken, width, height, densityDpi); 778 } 779 } 780 setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface)781 private void setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface) { 782 synchronized (mSyncRoot) { 783 if (mVirtualDisplayAdapter == null) { 784 return; 785 } 786 787 mVirtualDisplayAdapter.setVirtualDisplaySurfaceLocked(appToken, surface); 788 } 789 } 790 releaseVirtualDisplayInternal(IBinder appToken)791 private void releaseVirtualDisplayInternal(IBinder appToken) { 792 synchronized (mSyncRoot) { 793 if (mVirtualDisplayAdapter == null) { 794 return; 795 } 796 797 DisplayDevice device = 798 mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken); 799 if (device != null) { 800 handleDisplayDeviceRemovedLocked(device); 801 } 802 } 803 } 804 registerDefaultDisplayAdapters()805 private void registerDefaultDisplayAdapters() { 806 // Register default display adapters. 807 synchronized (mSyncRoot) { 808 // main display adapter 809 registerDisplayAdapterLocked(new LocalDisplayAdapter( 810 mSyncRoot, mContext, mHandler, mDisplayAdapterListener)); 811 812 // Standalone VR devices rely on a virtual display as their primary display for 813 // 2D UI. We register virtual display adapter along side the main display adapter 814 // here so that it is ready by the time the system sends the home Intent for 815 // early apps like SetupWizard/Launcher. In particular, SUW is displayed using 816 // the virtual display inside VR before any VR-specific apps even run. 817 mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext, 818 mHandler, mDisplayAdapterListener); 819 if (mVirtualDisplayAdapter != null) { 820 registerDisplayAdapterLocked(mVirtualDisplayAdapter); 821 } 822 } 823 } 824 registerAdditionalDisplayAdapters()825 private void registerAdditionalDisplayAdapters() { 826 synchronized (mSyncRoot) { 827 if (shouldRegisterNonEssentialDisplayAdaptersLocked()) { 828 registerOverlayDisplayAdapterLocked(); 829 registerWifiDisplayAdapterLocked(); 830 } 831 } 832 } 833 registerOverlayDisplayAdapterLocked()834 private void registerOverlayDisplayAdapterLocked() { 835 registerDisplayAdapterLocked(new OverlayDisplayAdapter( 836 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler)); 837 } 838 registerWifiDisplayAdapterLocked()839 private void registerWifiDisplayAdapterLocked() { 840 if (mContext.getResources().getBoolean( 841 com.android.internal.R.bool.config_enableWifiDisplay) 842 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) { 843 mWifiDisplayAdapter = new WifiDisplayAdapter( 844 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, 845 mPersistentDataStore); 846 registerDisplayAdapterLocked(mWifiDisplayAdapter); 847 } 848 } 849 shouldRegisterNonEssentialDisplayAdaptersLocked()850 private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() { 851 // In safe mode, we disable non-essential display adapters to give the user 852 // an opportunity to fix broken settings or other problems that might affect 853 // system stability. 854 // In only-core mode, we disable non-essential display adapters to minimize 855 // the number of dependencies that are started while in this mode and to 856 // prevent problems that might occur due to the device being encrypted. 857 return !mSafeMode && !mOnlyCore; 858 } 859 registerDisplayAdapterLocked(DisplayAdapter adapter)860 private void registerDisplayAdapterLocked(DisplayAdapter adapter) { 861 mDisplayAdapters.add(adapter); 862 adapter.registerLocked(); 863 } 864 handleDisplayDeviceAdded(DisplayDevice device)865 private void handleDisplayDeviceAdded(DisplayDevice device) { 866 synchronized (mSyncRoot) { 867 handleDisplayDeviceAddedLocked(device); 868 } 869 } 870 handleDisplayDeviceAddedLocked(DisplayDevice device)871 private void handleDisplayDeviceAddedLocked(DisplayDevice device) { 872 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 873 if (mDisplayDevices.contains(device)) { 874 Slog.w(TAG, "Attempted to add already added display device: " + info); 875 return; 876 } 877 878 Slog.i(TAG, "Display device added: " + info); 879 device.mDebugLastLoggedDeviceInfo = info; 880 881 mDisplayDevices.add(device); 882 LogicalDisplay display = addLogicalDisplayLocked(device); 883 Runnable work = updateDisplayStateLocked(device); 884 if (work != null) { 885 work.run(); 886 } 887 scheduleTraversalLocked(false); 888 } 889 handleDisplayDeviceChanged(DisplayDevice device)890 private void handleDisplayDeviceChanged(DisplayDevice device) { 891 synchronized (mSyncRoot) { 892 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 893 if (!mDisplayDevices.contains(device)) { 894 Slog.w(TAG, "Attempted to change non-existent display device: " + info); 895 return; 896 } 897 898 int diff = device.mDebugLastLoggedDeviceInfo.diff(info); 899 if (diff == DisplayDeviceInfo.DIFF_STATE) { 900 Slog.i(TAG, "Display device changed state: \"" + info.name 901 + "\", " + Display.stateToString(info.state)); 902 } else if (diff != 0) { 903 Slog.i(TAG, "Display device changed: " + info); 904 } 905 if ((diff & DisplayDeviceInfo.DIFF_COLOR_MODE) != 0) { 906 try { 907 mPersistentDataStore.setColorMode(device, info.colorMode); 908 } finally { 909 mPersistentDataStore.saveIfNeeded(); 910 } 911 } 912 device.mDebugLastLoggedDeviceInfo = info; 913 914 device.applyPendingDisplayDeviceInfoChangesLocked(); 915 if (updateLogicalDisplaysLocked()) { 916 scheduleTraversalLocked(false); 917 } 918 } 919 } 920 handleDisplayDeviceRemoved(DisplayDevice device)921 private void handleDisplayDeviceRemoved(DisplayDevice device) { 922 synchronized (mSyncRoot) { 923 handleDisplayDeviceRemovedLocked(device); 924 } 925 } 926 handleDisplayDeviceRemovedLocked(DisplayDevice device)927 private void handleDisplayDeviceRemovedLocked(DisplayDevice device) { 928 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 929 if (!mDisplayDevices.remove(device)) { 930 Slog.w(TAG, "Attempted to remove non-existent display device: " + info); 931 return; 932 } 933 934 Slog.i(TAG, "Display device removed: " + info); 935 device.mDebugLastLoggedDeviceInfo = info; 936 937 updateLogicalDisplaysLocked(); 938 scheduleTraversalLocked(false); 939 } 940 applyGlobalDisplayStateLocked(List<Runnable> workQueue)941 private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) { 942 final int count = mDisplayDevices.size(); 943 for (int i = 0; i < count; i++) { 944 DisplayDevice device = mDisplayDevices.get(i); 945 Runnable runnable = updateDisplayStateLocked(device); 946 if (runnable != null) { 947 workQueue.add(runnable); 948 } 949 } 950 } 951 updateDisplayStateLocked(DisplayDevice device)952 private Runnable updateDisplayStateLocked(DisplayDevice device) { 953 // Blank or unblank the display immediately to match the state requested 954 // by the display power controller (if known). 955 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 956 if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) { 957 return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness); 958 } 959 return null; 960 } 961 962 // Adds a new logical display based on the given display device. 963 // Sends notifications if needed. addLogicalDisplayLocked(DisplayDevice device)964 private LogicalDisplay addLogicalDisplayLocked(DisplayDevice device) { 965 DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked(); 966 boolean isDefault = (deviceInfo.flags 967 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0; 968 if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) { 969 Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo); 970 isDefault = false; 971 } 972 973 if (!isDefault && mSingleDisplayDemoMode) { 974 Slog.i(TAG, "Not creating a logical display for a secondary display " 975 + " because single display demo mode is enabled: " + deviceInfo); 976 return null; 977 } 978 979 final int displayId = assignDisplayIdLocked(isDefault); 980 final int layerStack = assignLayerStackLocked(displayId); 981 982 LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device); 983 display.updateLocked(mDisplayDevices); 984 if (!display.isValidLocked()) { 985 // This should never happen currently. 986 Slog.w(TAG, "Ignoring display device because the logical display " 987 + "created from it was not considered valid: " + deviceInfo); 988 return null; 989 } 990 991 configureColorModeLocked(display, device); 992 if (isDefault) { 993 recordStableDisplayStatsIfNeededLocked(display); 994 } 995 996 mLogicalDisplays.put(displayId, display); 997 998 // Wake up waitForDefaultDisplay. 999 if (isDefault) { 1000 mSyncRoot.notifyAll(); 1001 } 1002 1003 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED); 1004 return display; 1005 } 1006 assignDisplayIdLocked(boolean isDefault)1007 private int assignDisplayIdLocked(boolean isDefault) { 1008 return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++; 1009 } 1010 assignLayerStackLocked(int displayId)1011 private int assignLayerStackLocked(int displayId) { 1012 // Currently layer stacks and display ids are the same. 1013 // This need not be the case. 1014 return displayId; 1015 } 1016 configureColorModeLocked(LogicalDisplay display, DisplayDevice device)1017 private void configureColorModeLocked(LogicalDisplay display, DisplayDevice device) { 1018 if (display.getPrimaryDisplayDeviceLocked() == device) { 1019 int colorMode = mPersistentDataStore.getColorMode(device); 1020 if (colorMode == Display.COLOR_MODE_INVALID) { 1021 if ((device.getDisplayDeviceInfoLocked().flags 1022 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) { 1023 colorMode = mDefaultDisplayDefaultColorMode; 1024 } else { 1025 colorMode = Display.COLOR_MODE_DEFAULT; 1026 } 1027 } 1028 display.setRequestedColorModeLocked(colorMode); 1029 } 1030 } 1031 1032 // If we've never recorded stable device stats for this device before and they aren't 1033 // explicitly configured, go ahead and record the stable device stats now based on the status 1034 // of the default display at first boot. recordStableDisplayStatsIfNeededLocked(LogicalDisplay d)1035 private void recordStableDisplayStatsIfNeededLocked(LogicalDisplay d) { 1036 if (mStableDisplaySize.x <= 0 && mStableDisplaySize.y <= 0) { 1037 DisplayInfo info = d.getDisplayInfoLocked(); 1038 setStableDisplaySizeLocked(info.getNaturalWidth(), info.getNaturalHeight()); 1039 } 1040 } 1041 setStableDisplaySizeLocked(int width, int height)1042 private void setStableDisplaySizeLocked(int width, int height) { 1043 mStableDisplaySize = new Point(width, height); 1044 try { 1045 mPersistentDataStore.setStableDisplaySize(mStableDisplaySize); 1046 } finally { 1047 mPersistentDataStore.saveIfNeeded(); 1048 } 1049 } 1050 1051 @VisibleForTesting getMinimumBrightnessCurveInternal()1052 Curve getMinimumBrightnessCurveInternal() { 1053 return mMinimumBrightnessCurve; 1054 } 1055 setBrightnessConfigurationForUserInternal( @ullable BrightnessConfiguration c, @UserIdInt int userId, @Nullable String packageName)1056 private void setBrightnessConfigurationForUserInternal( 1057 @Nullable BrightnessConfiguration c, @UserIdInt int userId, 1058 @Nullable String packageName) { 1059 validateBrightnessConfiguration(c); 1060 final int userSerial = getUserManager().getUserSerialNumber(userId); 1061 synchronized (mSyncRoot) { 1062 try { 1063 mPersistentDataStore.setBrightnessConfigurationForUser(c, userSerial, 1064 packageName); 1065 } finally { 1066 mPersistentDataStore.saveIfNeeded(); 1067 } 1068 if (userId == mCurrentUserId) { 1069 mDisplayPowerController.setBrightnessConfiguration(c); 1070 } 1071 } 1072 } 1073 1074 @VisibleForTesting validateBrightnessConfiguration(BrightnessConfiguration config)1075 void validateBrightnessConfiguration(BrightnessConfiguration config) { 1076 if (config == null) { 1077 return; 1078 } 1079 if (isBrightnessConfigurationTooDark(config)) { 1080 throw new IllegalArgumentException("brightness curve is too dark"); 1081 } 1082 } 1083 isBrightnessConfigurationTooDark(BrightnessConfiguration config)1084 private boolean isBrightnessConfigurationTooDark(BrightnessConfiguration config) { 1085 Pair<float[], float[]> curve = config.getCurve(); 1086 float[] lux = curve.first; 1087 float[] nits = curve.second; 1088 for (int i = 0; i < lux.length; i++) { 1089 if (nits[i] < mMinimumBrightnessSpline.interpolate(lux[i])) { 1090 return true; 1091 } 1092 } 1093 return false; 1094 } 1095 loadBrightnessConfiguration()1096 private void loadBrightnessConfiguration() { 1097 synchronized (mSyncRoot) { 1098 final int userSerial = getUserManager().getUserSerialNumber(mCurrentUserId); 1099 BrightnessConfiguration config = 1100 mPersistentDataStore.getBrightnessConfiguration(userSerial); 1101 mDisplayPowerController.setBrightnessConfiguration(config); 1102 } 1103 } 1104 1105 // Updates all existing logical displays given the current set of display devices. 1106 // Removes invalid logical displays. 1107 // Sends notifications if needed. updateLogicalDisplaysLocked()1108 private boolean updateLogicalDisplaysLocked() { 1109 boolean changed = false; 1110 for (int i = mLogicalDisplays.size(); i-- > 0; ) { 1111 final int displayId = mLogicalDisplays.keyAt(i); 1112 LogicalDisplay display = mLogicalDisplays.valueAt(i); 1113 1114 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked()); 1115 display.updateLocked(mDisplayDevices); 1116 if (!display.isValidLocked()) { 1117 mLogicalDisplays.removeAt(i); 1118 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED); 1119 changed = true; 1120 } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) { 1121 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); 1122 changed = true; 1123 } 1124 } 1125 return changed; 1126 } 1127 performTraversalLocked(SurfaceControl.Transaction t)1128 private void performTraversalLocked(SurfaceControl.Transaction t) { 1129 // Clear all viewports before configuring displays so that we can keep 1130 // track of which ones we have configured. 1131 clearViewportsLocked(); 1132 1133 // Configure each display device. 1134 final int count = mDisplayDevices.size(); 1135 for (int i = 0; i < count; i++) { 1136 DisplayDevice device = mDisplayDevices.get(i); 1137 configureDisplayLocked(t, device); 1138 device.performTraversalLocked(t); 1139 } 1140 1141 // Tell the input system about these new viewports. 1142 if (mInputManagerInternal != null) { 1143 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT); 1144 } 1145 } 1146 setDisplayPropertiesInternal(int displayId, boolean hasContent, float requestedRefreshRate, int requestedModeId, boolean inTraversal)1147 private void setDisplayPropertiesInternal(int displayId, boolean hasContent, 1148 float requestedRefreshRate, int requestedModeId, boolean inTraversal) { 1149 synchronized (mSyncRoot) { 1150 LogicalDisplay display = mLogicalDisplays.get(displayId); 1151 if (display == null) { 1152 return; 1153 } 1154 if (display.hasContentLocked() != hasContent) { 1155 if (DEBUG) { 1156 Slog.d(TAG, "Display " + displayId + " hasContent flag changed: " 1157 + "hasContent=" + hasContent + ", inTraversal=" + inTraversal); 1158 } 1159 1160 display.setHasContentLocked(hasContent); 1161 scheduleTraversalLocked(inTraversal); 1162 } 1163 if (requestedModeId == 0 && requestedRefreshRate != 0) { 1164 // Scan supported modes returned by display.getInfo() to find a mode with the same 1165 // size as the default display mode but with the specified refresh rate instead. 1166 requestedModeId = display.getDisplayInfoLocked().findDefaultModeByRefreshRate( 1167 requestedRefreshRate); 1168 } 1169 if (display.getRequestedModeIdLocked() != requestedModeId) { 1170 if (DEBUG) { 1171 Slog.d(TAG, "Display " + displayId + " switching to mode " + requestedModeId); 1172 } 1173 display.setRequestedModeIdLocked(requestedModeId); 1174 scheduleTraversalLocked(inTraversal); 1175 } 1176 } 1177 } 1178 setDisplayOffsetsInternal(int displayId, int x, int y)1179 private void setDisplayOffsetsInternal(int displayId, int x, int y) { 1180 synchronized (mSyncRoot) { 1181 LogicalDisplay display = mLogicalDisplays.get(displayId); 1182 if (display == null) { 1183 return; 1184 } 1185 if (display.getDisplayOffsetXLocked() != x 1186 || display.getDisplayOffsetYLocked() != y) { 1187 if (DEBUG) { 1188 Slog.d(TAG, "Display " + displayId + " burn-in offset set to (" 1189 + x + ", " + y + ")"); 1190 } 1191 display.setDisplayOffsetsLocked(x, y); 1192 scheduleTraversalLocked(false); 1193 } 1194 } 1195 } 1196 1197 // Updates the lists of UIDs that are present on displays. setDisplayAccessUIDsInternal(SparseArray<IntArray> newDisplayAccessUIDs)1198 private void setDisplayAccessUIDsInternal(SparseArray<IntArray> newDisplayAccessUIDs) { 1199 synchronized (mSyncRoot) { 1200 mDisplayAccessUIDs.clear(); 1201 for (int i = newDisplayAccessUIDs.size() - 1; i >= 0; i--) { 1202 mDisplayAccessUIDs.append(newDisplayAccessUIDs.keyAt(i), 1203 newDisplayAccessUIDs.valueAt(i)); 1204 } 1205 } 1206 } 1207 1208 // Checks if provided UID's content is present on the display and UID has access to it. isUidPresentOnDisplayInternal(int uid, int displayId)1209 private boolean isUidPresentOnDisplayInternal(int uid, int displayId) { 1210 synchronized (mSyncRoot) { 1211 final IntArray displayUIDs = mDisplayAccessUIDs.get(displayId); 1212 return displayUIDs != null && displayUIDs.indexOf(uid) != -1; 1213 } 1214 } 1215 clearViewportsLocked()1216 private void clearViewportsLocked() { 1217 mDefaultViewport.valid = false; 1218 mExternalTouchViewport.valid = false; 1219 mVirtualTouchViewports.clear(); 1220 } 1221 configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device)1222 private void configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device) { 1223 final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 1224 final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0; 1225 1226 // Find the logical display that the display device is showing. 1227 // Certain displays only ever show their own content. 1228 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device); 1229 if (!ownContent) { 1230 if (display != null && !display.hasContentLocked()) { 1231 // If the display does not have any content of its own, then 1232 // automatically mirror the default logical display contents. 1233 display = null; 1234 } 1235 if (display == null) { 1236 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY); 1237 } 1238 } 1239 1240 // Apply the logical display configuration to the display device. 1241 if (display == null) { 1242 // TODO: no logical display for the device, blank it 1243 Slog.w(TAG, "Missing logical display to use for physical display device: " 1244 + device.getDisplayDeviceInfoLocked()); 1245 return; 1246 } 1247 display.configureDisplayLocked(t, device, info.state == Display.STATE_OFF); 1248 1249 // Update the viewports if needed. 1250 if (!mDefaultViewport.valid 1251 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) { 1252 setViewportLocked(mDefaultViewport, display, device); 1253 } 1254 if (!mExternalTouchViewport.valid 1255 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) { 1256 setViewportLocked(mExternalTouchViewport, display, device); 1257 } 1258 1259 if (info.touch == DisplayDeviceInfo.TOUCH_VIRTUAL && !TextUtils.isEmpty(info.uniqueId)) { 1260 final DisplayViewport viewport = getVirtualTouchViewportLocked(info.uniqueId); 1261 setViewportLocked(viewport, display, device); 1262 } 1263 } 1264 1265 /** Gets the virtual device viewport or creates it if not yet created. */ getVirtualTouchViewportLocked(@onNull String uniqueId)1266 private DisplayViewport getVirtualTouchViewportLocked(@NonNull String uniqueId) { 1267 DisplayViewport viewport; 1268 final int count = mVirtualTouchViewports.size(); 1269 for (int i = 0; i < count; i++) { 1270 viewport = mVirtualTouchViewports.get(i); 1271 if (uniqueId.equals(viewport.uniqueId)) { 1272 return viewport; 1273 } 1274 } 1275 1276 viewport = new DisplayViewport(); 1277 viewport.uniqueId = uniqueId; 1278 mVirtualTouchViewports.add(viewport); 1279 return viewport; 1280 } 1281 setViewportLocked(DisplayViewport viewport, LogicalDisplay display, DisplayDevice device)1282 private static void setViewportLocked(DisplayViewport viewport, 1283 LogicalDisplay display, DisplayDevice device) { 1284 viewport.valid = true; 1285 viewport.displayId = display.getDisplayIdLocked(); 1286 device.populateViewportLocked(viewport); 1287 } 1288 findLogicalDisplayForDeviceLocked(DisplayDevice device)1289 private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) { 1290 final int count = mLogicalDisplays.size(); 1291 for (int i = 0; i < count; i++) { 1292 LogicalDisplay display = mLogicalDisplays.valueAt(i); 1293 if (display.getPrimaryDisplayDeviceLocked() == device) { 1294 return display; 1295 } 1296 } 1297 return null; 1298 } 1299 sendDisplayEventLocked(int displayId, int event)1300 private void sendDisplayEventLocked(int displayId, int event) { 1301 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event); 1302 mHandler.sendMessage(msg); 1303 } 1304 1305 // Requests that performTraversals be called at a 1306 // later time to apply changes to surfaces and displays. scheduleTraversalLocked(boolean inTraversal)1307 private void scheduleTraversalLocked(boolean inTraversal) { 1308 if (!mPendingTraversal && mWindowManagerInternal != null) { 1309 mPendingTraversal = true; 1310 if (!inTraversal) { 1311 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL); 1312 } 1313 } 1314 } 1315 1316 // Runs on Handler thread. 1317 // Delivers display event notifications to callbacks. deliverDisplayEvent(int displayId, int event)1318 private void deliverDisplayEvent(int displayId, int event) { 1319 if (DEBUG) { 1320 Slog.d(TAG, "Delivering display event: displayId=" 1321 + displayId + ", event=" + event); 1322 } 1323 1324 // Grab the lock and copy the callbacks. 1325 final int count; 1326 synchronized (mSyncRoot) { 1327 count = mCallbacks.size(); 1328 mTempCallbacks.clear(); 1329 for (int i = 0; i < count; i++) { 1330 mTempCallbacks.add(mCallbacks.valueAt(i)); 1331 } 1332 } 1333 1334 // After releasing the lock, send the notifications out. 1335 for (int i = 0; i < count; i++) { 1336 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event); 1337 } 1338 mTempCallbacks.clear(); 1339 } 1340 getProjectionService()1341 private IMediaProjectionManager getProjectionService() { 1342 if (mProjectionService == null) { 1343 IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE); 1344 mProjectionService = IMediaProjectionManager.Stub.asInterface(b); 1345 } 1346 return mProjectionService; 1347 } 1348 getUserManager()1349 private UserManager getUserManager() { 1350 return mContext.getSystemService(UserManager.class); 1351 } 1352 dumpInternal(PrintWriter pw)1353 private void dumpInternal(PrintWriter pw) { 1354 pw.println("DISPLAY MANAGER (dumpsys display)"); 1355 1356 synchronized (mSyncRoot) { 1357 pw.println(" mOnlyCode=" + mOnlyCore); 1358 pw.println(" mSafeMode=" + mSafeMode); 1359 pw.println(" mPendingTraversal=" + mPendingTraversal); 1360 pw.println(" mGlobalDisplayState=" + Display.stateToString(mGlobalDisplayState)); 1361 pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId); 1362 pw.println(" mDefaultViewport=" + mDefaultViewport); 1363 pw.println(" mExternalTouchViewport=" + mExternalTouchViewport); 1364 pw.println(" mVirtualTouchViewports=" + mVirtualTouchViewports); 1365 pw.println(" mDefaultDisplayDefaultColorMode=" + mDefaultDisplayDefaultColorMode); 1366 pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode); 1367 pw.println(" mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount); 1368 pw.println(" mStableDisplaySize=" + mStableDisplaySize); 1369 1370 1371 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 1372 ipw.increaseIndent(); 1373 1374 pw.println(); 1375 pw.println("Display Adapters: size=" + mDisplayAdapters.size()); 1376 for (DisplayAdapter adapter : mDisplayAdapters) { 1377 pw.println(" " + adapter.getName()); 1378 adapter.dumpLocked(ipw); 1379 } 1380 1381 pw.println(); 1382 pw.println("Display Devices: size=" + mDisplayDevices.size()); 1383 for (DisplayDevice device : mDisplayDevices) { 1384 pw.println(" " + device.getDisplayDeviceInfoLocked()); 1385 device.dumpLocked(ipw); 1386 } 1387 1388 final int logicalDisplayCount = mLogicalDisplays.size(); 1389 pw.println(); 1390 pw.println("Logical Displays: size=" + logicalDisplayCount); 1391 for (int i = 0; i < logicalDisplayCount; i++) { 1392 int displayId = mLogicalDisplays.keyAt(i); 1393 LogicalDisplay display = mLogicalDisplays.valueAt(i); 1394 pw.println(" Display " + displayId + ":"); 1395 display.dumpLocked(ipw); 1396 } 1397 1398 final int callbackCount = mCallbacks.size(); 1399 pw.println(); 1400 pw.println("Callbacks: size=" + callbackCount); 1401 for (int i = 0; i < callbackCount; i++) { 1402 CallbackRecord callback = mCallbacks.valueAt(i); 1403 pw.println(" " + i + ": mPid=" + callback.mPid 1404 + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested); 1405 } 1406 1407 if (mDisplayPowerController != null) { 1408 mDisplayPowerController.dump(pw); 1409 } 1410 1411 pw.println(); 1412 mPersistentDataStore.dump(pw); 1413 } 1414 } 1415 getFloatArray(TypedArray array)1416 private static float[] getFloatArray(TypedArray array) { 1417 int length = array.length(); 1418 float[] floatArray = new float[length]; 1419 for (int i = 0; i < length; i++) { 1420 floatArray[i] = array.getFloat(i, Float.NaN); 1421 } 1422 array.recycle(); 1423 return floatArray; 1424 } 1425 1426 /** 1427 * This is the object that everything in the display manager locks on. 1428 * We make it an inner class within the {@link DisplayManagerService} to so that it is 1429 * clear that the object belongs to the display manager service and that it is 1430 * a unique object with a special purpose. 1431 */ 1432 public static final class SyncRoot { 1433 } 1434 1435 @VisibleForTesting 1436 static class Injector { getVirtualDisplayAdapter(SyncRoot syncRoot, Context context, Handler handler, DisplayAdapter.Listener displayAdapterListener)1437 VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot, Context context, 1438 Handler handler, DisplayAdapter.Listener displayAdapterListener) { 1439 return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener); 1440 } 1441 getDefaultDisplayDelayTimeout()1442 long getDefaultDisplayDelayTimeout() { 1443 return WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT; 1444 } 1445 } 1446 1447 @VisibleForTesting getDisplayDeviceInfoInternal(int displayId)1448 DisplayDeviceInfo getDisplayDeviceInfoInternal(int displayId) { 1449 synchronized (mSyncRoot) { 1450 LogicalDisplay display = mLogicalDisplays.get(displayId); 1451 if (display != null) { 1452 DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked(); 1453 return displayDevice.getDisplayDeviceInfoLocked(); 1454 } 1455 return null; 1456 } 1457 } 1458 1459 private final class DisplayManagerHandler extends Handler { DisplayManagerHandler(Looper looper)1460 public DisplayManagerHandler(Looper looper) { 1461 super(looper, null, true /*async*/); 1462 } 1463 1464 @Override handleMessage(Message msg)1465 public void handleMessage(Message msg) { 1466 switch (msg.what) { 1467 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS: 1468 registerDefaultDisplayAdapters(); 1469 break; 1470 1471 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS: 1472 registerAdditionalDisplayAdapters(); 1473 break; 1474 1475 case MSG_DELIVER_DISPLAY_EVENT: 1476 deliverDisplayEvent(msg.arg1, msg.arg2); 1477 break; 1478 1479 case MSG_REQUEST_TRAVERSAL: 1480 mWindowManagerInternal.requestTraversalFromDisplayManager(); 1481 break; 1482 1483 case MSG_UPDATE_VIEWPORT: { 1484 synchronized (mSyncRoot) { 1485 mTempDefaultViewport.copyFrom(mDefaultViewport); 1486 mTempExternalTouchViewport.copyFrom(mExternalTouchViewport); 1487 if (!mTempVirtualTouchViewports.equals(mVirtualTouchViewports)) { 1488 mTempVirtualTouchViewports.clear(); 1489 for (DisplayViewport d : mVirtualTouchViewports) { 1490 mTempVirtualTouchViewports.add(d.makeCopy()); 1491 } 1492 } 1493 } 1494 mInputManagerInternal.setDisplayViewports(mTempDefaultViewport, 1495 mTempExternalTouchViewport, mTempVirtualTouchViewports); 1496 break; 1497 } 1498 1499 case MSG_LOAD_BRIGHTNESS_CONFIGURATION: 1500 loadBrightnessConfiguration(); 1501 break; 1502 } 1503 } 1504 } 1505 1506 private final class DisplayAdapterListener implements DisplayAdapter.Listener { 1507 @Override onDisplayDeviceEvent(DisplayDevice device, int event)1508 public void onDisplayDeviceEvent(DisplayDevice device, int event) { 1509 switch (event) { 1510 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED: 1511 handleDisplayDeviceAdded(device); 1512 break; 1513 1514 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED: 1515 handleDisplayDeviceChanged(device); 1516 break; 1517 1518 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED: 1519 handleDisplayDeviceRemoved(device); 1520 break; 1521 } 1522 } 1523 1524 @Override onTraversalRequested()1525 public void onTraversalRequested() { 1526 synchronized (mSyncRoot) { 1527 scheduleTraversalLocked(false); 1528 } 1529 } 1530 } 1531 1532 private final class CallbackRecord implements DeathRecipient { 1533 public final int mPid; 1534 private final IDisplayManagerCallback mCallback; 1535 1536 public boolean mWifiDisplayScanRequested; 1537 CallbackRecord(int pid, IDisplayManagerCallback callback)1538 public CallbackRecord(int pid, IDisplayManagerCallback callback) { 1539 mPid = pid; 1540 mCallback = callback; 1541 } 1542 1543 @Override binderDied()1544 public void binderDied() { 1545 if (DEBUG) { 1546 Slog.d(TAG, "Display listener for pid " + mPid + " died."); 1547 } 1548 onCallbackDied(this); 1549 } 1550 notifyDisplayEventAsync(int displayId, int event)1551 public void notifyDisplayEventAsync(int displayId, int event) { 1552 try { 1553 mCallback.onDisplayEvent(displayId, event); 1554 } catch (RemoteException ex) { 1555 Slog.w(TAG, "Failed to notify process " 1556 + mPid + " that displays changed, assuming it died.", ex); 1557 binderDied(); 1558 } 1559 } 1560 } 1561 1562 @VisibleForTesting 1563 final class BinderService extends IDisplayManager.Stub { 1564 /** 1565 * Returns information about the specified logical display. 1566 * 1567 * @param displayId The logical display id. 1568 * @return The logical display info, or null if the display does not exist. The 1569 * returned object must be treated as immutable. 1570 */ 1571 @Override // Binder call getDisplayInfo(int displayId)1572 public DisplayInfo getDisplayInfo(int displayId) { 1573 final int callingUid = Binder.getCallingUid(); 1574 final long token = Binder.clearCallingIdentity(); 1575 try { 1576 return getDisplayInfoInternal(displayId, callingUid); 1577 } finally { 1578 Binder.restoreCallingIdentity(token); 1579 } 1580 } 1581 1582 /** 1583 * Returns the list of all display ids. 1584 */ 1585 @Override // Binder call getDisplayIds()1586 public int[] getDisplayIds() { 1587 final int callingUid = Binder.getCallingUid(); 1588 final long token = Binder.clearCallingIdentity(); 1589 try { 1590 return getDisplayIdsInternal(callingUid); 1591 } finally { 1592 Binder.restoreCallingIdentity(token); 1593 } 1594 } 1595 1596 /** 1597 * Returns the stable device display size, in pixels. 1598 */ 1599 @Override // Binder call getStableDisplaySize()1600 public Point getStableDisplaySize() { 1601 final long token = Binder.clearCallingIdentity(); 1602 try { 1603 return getStableDisplaySizeInternal(); 1604 } finally { 1605 Binder.restoreCallingIdentity(token); 1606 } 1607 } 1608 1609 @Override // Binder call registerCallback(IDisplayManagerCallback callback)1610 public void registerCallback(IDisplayManagerCallback callback) { 1611 if (callback == null) { 1612 throw new IllegalArgumentException("listener must not be null"); 1613 } 1614 1615 final int callingPid = Binder.getCallingPid(); 1616 final long token = Binder.clearCallingIdentity(); 1617 try { 1618 registerCallbackInternal(callback, callingPid); 1619 } finally { 1620 Binder.restoreCallingIdentity(token); 1621 } 1622 } 1623 1624 @Override // Binder call startWifiDisplayScan()1625 public void startWifiDisplayScan() { 1626 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1627 "Permission required to start wifi display scans"); 1628 1629 final int callingPid = Binder.getCallingPid(); 1630 final long token = Binder.clearCallingIdentity(); 1631 try { 1632 startWifiDisplayScanInternal(callingPid); 1633 } finally { 1634 Binder.restoreCallingIdentity(token); 1635 } 1636 } 1637 1638 @Override // Binder call stopWifiDisplayScan()1639 public void stopWifiDisplayScan() { 1640 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1641 "Permission required to stop wifi display scans"); 1642 1643 final int callingPid = Binder.getCallingPid(); 1644 final long token = Binder.clearCallingIdentity(); 1645 try { 1646 stopWifiDisplayScanInternal(callingPid); 1647 } finally { 1648 Binder.restoreCallingIdentity(token); 1649 } 1650 } 1651 1652 @Override // Binder call connectWifiDisplay(String address)1653 public void connectWifiDisplay(String address) { 1654 if (address == null) { 1655 throw new IllegalArgumentException("address must not be null"); 1656 } 1657 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1658 "Permission required to connect to a wifi display"); 1659 1660 final long token = Binder.clearCallingIdentity(); 1661 try { 1662 connectWifiDisplayInternal(address); 1663 } finally { 1664 Binder.restoreCallingIdentity(token); 1665 } 1666 } 1667 1668 @Override // Binder call disconnectWifiDisplay()1669 public void disconnectWifiDisplay() { 1670 // This request does not require special permissions. 1671 // Any app can request disconnection from the currently active wifi display. 1672 // This exception should no longer be needed once wifi display control moves 1673 // to the media router service. 1674 1675 final long token = Binder.clearCallingIdentity(); 1676 try { 1677 disconnectWifiDisplayInternal(); 1678 } finally { 1679 Binder.restoreCallingIdentity(token); 1680 } 1681 } 1682 1683 @Override // Binder call renameWifiDisplay(String address, String alias)1684 public void renameWifiDisplay(String address, String alias) { 1685 if (address == null) { 1686 throw new IllegalArgumentException("address must not be null"); 1687 } 1688 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1689 "Permission required to rename to a wifi display"); 1690 1691 final long token = Binder.clearCallingIdentity(); 1692 try { 1693 renameWifiDisplayInternal(address, alias); 1694 } finally { 1695 Binder.restoreCallingIdentity(token); 1696 } 1697 } 1698 1699 @Override // Binder call forgetWifiDisplay(String address)1700 public void forgetWifiDisplay(String address) { 1701 if (address == null) { 1702 throw new IllegalArgumentException("address must not be null"); 1703 } 1704 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1705 "Permission required to forget to a wifi display"); 1706 1707 final long token = Binder.clearCallingIdentity(); 1708 try { 1709 forgetWifiDisplayInternal(address); 1710 } finally { 1711 Binder.restoreCallingIdentity(token); 1712 } 1713 } 1714 1715 @Override // Binder call pauseWifiDisplay()1716 public void pauseWifiDisplay() { 1717 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1718 "Permission required to pause a wifi display session"); 1719 1720 final long token = Binder.clearCallingIdentity(); 1721 try { 1722 pauseWifiDisplayInternal(); 1723 } finally { 1724 Binder.restoreCallingIdentity(token); 1725 } 1726 } 1727 1728 @Override // Binder call resumeWifiDisplay()1729 public void resumeWifiDisplay() { 1730 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1731 "Permission required to resume a wifi display session"); 1732 1733 final long token = Binder.clearCallingIdentity(); 1734 try { 1735 resumeWifiDisplayInternal(); 1736 } finally { 1737 Binder.restoreCallingIdentity(token); 1738 } 1739 } 1740 1741 @Override // Binder call getWifiDisplayStatus()1742 public WifiDisplayStatus getWifiDisplayStatus() { 1743 // This request does not require special permissions. 1744 // Any app can get information about available wifi displays. 1745 1746 final long token = Binder.clearCallingIdentity(); 1747 try { 1748 return getWifiDisplayStatusInternal(); 1749 } finally { 1750 Binder.restoreCallingIdentity(token); 1751 } 1752 } 1753 1754 @Override // Binder call requestColorMode(int displayId, int colorMode)1755 public void requestColorMode(int displayId, int colorMode) { 1756 mContext.enforceCallingOrSelfPermission( 1757 Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE, 1758 "Permission required to change the display color mode"); 1759 final long token = Binder.clearCallingIdentity(); 1760 try { 1761 requestColorModeInternal(displayId, colorMode); 1762 } finally { 1763 Binder.restoreCallingIdentity(token); 1764 } 1765 } 1766 1767 @Override // Binder call setSaturationLevel(float level)1768 public void setSaturationLevel(float level) { 1769 mContext.enforceCallingOrSelfPermission( 1770 Manifest.permission.CONTROL_DISPLAY_SATURATION, 1771 "Permission required to set display saturation level"); 1772 final long token = Binder.clearCallingIdentity(); 1773 try { 1774 setSaturationLevelInternal(level); 1775 } finally { 1776 Binder.restoreCallingIdentity(token); 1777 } 1778 } 1779 1780 @Override // Binder call createVirtualDisplay(IVirtualDisplayCallback callback, IMediaProjection projection, String packageName, String name, int width, int height, int densityDpi, Surface surface, int flags, String uniqueId)1781 public int createVirtualDisplay(IVirtualDisplayCallback callback, 1782 IMediaProjection projection, String packageName, String name, 1783 int width, int height, int densityDpi, Surface surface, int flags, 1784 String uniqueId) { 1785 final int callingUid = Binder.getCallingUid(); 1786 if (!validatePackageName(callingUid, packageName)) { 1787 throw new SecurityException("packageName must match the calling uid"); 1788 } 1789 if (callback == null) { 1790 throw new IllegalArgumentException("appToken must not be null"); 1791 } 1792 if (TextUtils.isEmpty(name)) { 1793 throw new IllegalArgumentException("name must be non-null and non-empty"); 1794 } 1795 if (width <= 0 || height <= 0 || densityDpi <= 0) { 1796 throw new IllegalArgumentException("width, height, and densityDpi must be " 1797 + "greater than 0"); 1798 } 1799 if (surface != null && surface.isSingleBuffered()) { 1800 throw new IllegalArgumentException("Surface can't be single-buffered"); 1801 } 1802 1803 if ((flags & VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) { 1804 flags |= VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; 1805 1806 // Public displays can't be allowed to show content when locked. 1807 if ((flags & VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) { 1808 throw new IllegalArgumentException( 1809 "Public display must not be marked as SHOW_WHEN_LOCKED_INSECURE"); 1810 } 1811 } 1812 if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) { 1813 flags &= ~VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; 1814 } 1815 1816 if (projection != null) { 1817 try { 1818 if (!getProjectionService().isValidMediaProjection(projection)) { 1819 throw new SecurityException("Invalid media projection"); 1820 } 1821 flags = projection.applyVirtualDisplayFlags(flags); 1822 } catch (RemoteException e) { 1823 throw new SecurityException("unable to validate media projection or flags"); 1824 } 1825 } 1826 1827 if (callingUid != Process.SYSTEM_UID && 1828 (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) { 1829 if (!canProjectVideo(projection)) { 1830 throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or " 1831 + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate " 1832 + "MediaProjection token in order to create a screen sharing virtual " 1833 + "display."); 1834 } 1835 } 1836 if ((flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0) { 1837 if (!canProjectSecureVideo(projection)) { 1838 throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT " 1839 + "or an appropriate MediaProjection token to create a " 1840 + "secure virtual display."); 1841 } 1842 } 1843 1844 final long token = Binder.clearCallingIdentity(); 1845 try { 1846 return createVirtualDisplayInternal(callback, projection, callingUid, packageName, 1847 name, width, height, densityDpi, surface, flags, uniqueId); 1848 } finally { 1849 Binder.restoreCallingIdentity(token); 1850 } 1851 } 1852 1853 @Override // Binder call resizeVirtualDisplay(IVirtualDisplayCallback callback, int width, int height, int densityDpi)1854 public void resizeVirtualDisplay(IVirtualDisplayCallback callback, 1855 int width, int height, int densityDpi) { 1856 final long token = Binder.clearCallingIdentity(); 1857 try { 1858 resizeVirtualDisplayInternal(callback.asBinder(), width, height, densityDpi); 1859 } finally { 1860 Binder.restoreCallingIdentity(token); 1861 } 1862 } 1863 1864 @Override // Binder call setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface)1865 public void setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface) { 1866 if (surface != null && surface.isSingleBuffered()) { 1867 throw new IllegalArgumentException("Surface can't be single-buffered"); 1868 } 1869 final long token = Binder.clearCallingIdentity(); 1870 try { 1871 setVirtualDisplaySurfaceInternal(callback.asBinder(), surface); 1872 } finally { 1873 Binder.restoreCallingIdentity(token); 1874 } 1875 } 1876 1877 @Override // Binder call releaseVirtualDisplay(IVirtualDisplayCallback callback)1878 public void releaseVirtualDisplay(IVirtualDisplayCallback callback) { 1879 final long token = Binder.clearCallingIdentity(); 1880 try { 1881 releaseVirtualDisplayInternal(callback.asBinder()); 1882 } finally { 1883 Binder.restoreCallingIdentity(token); 1884 } 1885 } 1886 1887 @Override // Binder call dump(FileDescriptor fd, final PrintWriter pw, String[] args)1888 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 1889 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 1890 1891 final long token = Binder.clearCallingIdentity(); 1892 try { 1893 dumpInternal(pw); 1894 } finally { 1895 Binder.restoreCallingIdentity(token); 1896 } 1897 } 1898 1899 @Override // Binder call getBrightnessEvents(String callingPackage)1900 public ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents(String callingPackage) { 1901 mContext.enforceCallingOrSelfPermission( 1902 Manifest.permission.BRIGHTNESS_SLIDER_USAGE, 1903 "Permission to read brightness events."); 1904 1905 final int callingUid = Binder.getCallingUid(); 1906 AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class); 1907 final int mode = appOpsManager.noteOp(AppOpsManager.OP_GET_USAGE_STATS, 1908 callingUid, callingPackage); 1909 final boolean hasUsageStats; 1910 if (mode == AppOpsManager.MODE_DEFAULT) { 1911 // The default behavior here is to check if PackageManager has given the app 1912 // permission. 1913 hasUsageStats = mContext.checkCallingPermission( 1914 Manifest.permission.PACKAGE_USAGE_STATS) 1915 == PackageManager.PERMISSION_GRANTED; 1916 } else { 1917 hasUsageStats = mode == AppOpsManager.MODE_ALLOWED; 1918 } 1919 1920 final int userId = UserHandle.getUserId(callingUid); 1921 final long token = Binder.clearCallingIdentity(); 1922 try { 1923 synchronized (mSyncRoot) { 1924 return mDisplayPowerController.getBrightnessEvents(userId, hasUsageStats); 1925 } 1926 } finally { 1927 Binder.restoreCallingIdentity(token); 1928 } 1929 } 1930 1931 @Override // Binder call getAmbientBrightnessStats()1932 public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats() { 1933 mContext.enforceCallingOrSelfPermission( 1934 Manifest.permission.ACCESS_AMBIENT_LIGHT_STATS, 1935 "Permission required to to access ambient light stats."); 1936 final int callingUid = Binder.getCallingUid(); 1937 final int userId = UserHandle.getUserId(callingUid); 1938 final long token = Binder.clearCallingIdentity(); 1939 try { 1940 synchronized (mSyncRoot) { 1941 return mDisplayPowerController.getAmbientBrightnessStats(userId); 1942 } 1943 } finally { 1944 Binder.restoreCallingIdentity(token); 1945 } 1946 } 1947 1948 @Override // Binder call setBrightnessConfigurationForUser( BrightnessConfiguration c, @UserIdInt int userId, String packageName)1949 public void setBrightnessConfigurationForUser( 1950 BrightnessConfiguration c, @UserIdInt int userId, String packageName) { 1951 mContext.enforceCallingOrSelfPermission( 1952 Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS, 1953 "Permission required to change the display's brightness configuration"); 1954 if (userId != UserHandle.getCallingUserId()) { 1955 mContext.enforceCallingOrSelfPermission( 1956 Manifest.permission.INTERACT_ACROSS_USERS, 1957 "Permission required to change the display brightness" 1958 + " configuration of another user"); 1959 } 1960 if (packageName != null && !validatePackageName(getCallingUid(), packageName)) { 1961 packageName = null; 1962 } 1963 final long token = Binder.clearCallingIdentity(); 1964 try { 1965 setBrightnessConfigurationForUserInternal(c, userId, packageName); 1966 } finally { 1967 Binder.restoreCallingIdentity(token); 1968 } 1969 } 1970 1971 @Override // Binder call getBrightnessConfigurationForUser(int userId)1972 public BrightnessConfiguration getBrightnessConfigurationForUser(int userId) { 1973 mContext.enforceCallingOrSelfPermission( 1974 Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS, 1975 "Permission required to read the display's brightness configuration"); 1976 if (userId != UserHandle.getCallingUserId()) { 1977 mContext.enforceCallingOrSelfPermission( 1978 Manifest.permission.INTERACT_ACROSS_USERS, 1979 "Permission required to read the display brightness" 1980 + " configuration of another user"); 1981 } 1982 final long token = Binder.clearCallingIdentity(); 1983 try { 1984 final int userSerial = getUserManager().getUserSerialNumber(userId); 1985 synchronized (mSyncRoot) { 1986 BrightnessConfiguration config = 1987 mPersistentDataStore.getBrightnessConfiguration(userSerial); 1988 if (config == null) { 1989 config = mDisplayPowerController.getDefaultBrightnessConfiguration(); 1990 } 1991 return config; 1992 } 1993 } finally { 1994 Binder.restoreCallingIdentity(token); 1995 } 1996 } 1997 1998 @Override // Binder call getDefaultBrightnessConfiguration()1999 public BrightnessConfiguration getDefaultBrightnessConfiguration() { 2000 mContext.enforceCallingOrSelfPermission( 2001 Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS, 2002 "Permission required to read the display's default brightness configuration"); 2003 final long token = Binder.clearCallingIdentity(); 2004 try { 2005 synchronized (mSyncRoot) { 2006 return mDisplayPowerController.getDefaultBrightnessConfiguration(); 2007 } 2008 } finally { 2009 Binder.restoreCallingIdentity(token); 2010 } 2011 } 2012 2013 @Override // Binder call setTemporaryBrightness(int brightness)2014 public void setTemporaryBrightness(int brightness) { 2015 mContext.enforceCallingOrSelfPermission( 2016 Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS, 2017 "Permission required to set the display's brightness"); 2018 final long token = Binder.clearCallingIdentity(); 2019 try { 2020 synchronized (mSyncRoot) { 2021 mDisplayPowerController.setTemporaryBrightness(brightness); 2022 } 2023 } finally { 2024 Binder.restoreCallingIdentity(token); 2025 } 2026 } 2027 2028 @Override // Binder call setTemporaryAutoBrightnessAdjustment(float adjustment)2029 public void setTemporaryAutoBrightnessAdjustment(float adjustment) { 2030 mContext.enforceCallingOrSelfPermission( 2031 Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS, 2032 "Permission required to set the display's auto brightness adjustment"); 2033 final long token = Binder.clearCallingIdentity(); 2034 try { 2035 synchronized (mSyncRoot) { 2036 mDisplayPowerController.setTemporaryAutoBrightnessAdjustment(adjustment); 2037 } 2038 } finally { 2039 Binder.restoreCallingIdentity(token); 2040 } 2041 } 2042 2043 @Override // Binder call onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)2044 public void onShellCommand(FileDescriptor in, FileDescriptor out, 2045 FileDescriptor err, String[] args, ShellCallback callback, 2046 ResultReceiver resultReceiver) { 2047 final long token = Binder.clearCallingIdentity(); 2048 try { 2049 DisplayManagerShellCommand command = new DisplayManagerShellCommand(this); 2050 command.exec(this, in, out, err, args, callback, resultReceiver); 2051 } finally { 2052 Binder.restoreCallingIdentity(token); 2053 } 2054 } 2055 2056 @Override // Binder call getMinimumBrightnessCurve()2057 public Curve getMinimumBrightnessCurve() { 2058 final long token = Binder.clearCallingIdentity(); 2059 try { 2060 return getMinimumBrightnessCurveInternal(); 2061 } finally { 2062 Binder.restoreCallingIdentity(token); 2063 } 2064 } 2065 setBrightness(int brightness)2066 void setBrightness(int brightness) { 2067 Settings.System.putIntForUser(mContext.getContentResolver(), 2068 Settings.System.SCREEN_BRIGHTNESS, brightness, UserHandle.USER_CURRENT); 2069 } 2070 resetBrightnessConfiguration()2071 void resetBrightnessConfiguration() { 2072 setBrightnessConfigurationForUserInternal(null, mContext.getUserId(), 2073 mContext.getPackageName()); 2074 } 2075 validatePackageName(int uid, String packageName)2076 private boolean validatePackageName(int uid, String packageName) { 2077 if (packageName != null) { 2078 String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid); 2079 if (packageNames != null) { 2080 for (String n : packageNames) { 2081 if (n.equals(packageName)) { 2082 return true; 2083 } 2084 } 2085 } 2086 } 2087 return false; 2088 } 2089 canProjectVideo(IMediaProjection projection)2090 private boolean canProjectVideo(IMediaProjection projection) { 2091 if (projection != null) { 2092 try { 2093 if (projection.canProjectVideo()) { 2094 return true; 2095 } 2096 } catch (RemoteException e) { 2097 Slog.e(TAG, "Unable to query projection service for permissions", e); 2098 } 2099 } 2100 if (mContext.checkCallingPermission( 2101 android.Manifest.permission.CAPTURE_VIDEO_OUTPUT) 2102 == PackageManager.PERMISSION_GRANTED) { 2103 return true; 2104 } 2105 return canProjectSecureVideo(projection); 2106 } 2107 canProjectSecureVideo(IMediaProjection projection)2108 private boolean canProjectSecureVideo(IMediaProjection projection) { 2109 if (projection != null) { 2110 try { 2111 if (projection.canProjectSecureVideo()){ 2112 return true; 2113 } 2114 } catch (RemoteException e) { 2115 Slog.e(TAG, "Unable to query projection service for permissions", e); 2116 } 2117 } 2118 return mContext.checkCallingPermission( 2119 android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT) 2120 == PackageManager.PERMISSION_GRANTED; 2121 } 2122 } 2123 2124 private final class LocalService extends DisplayManagerInternal { 2125 @Override initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler, SensorManager sensorManager)2126 public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler, 2127 SensorManager sensorManager) { 2128 synchronized (mSyncRoot) { 2129 DisplayBlanker blanker = new DisplayBlanker() { 2130 @Override 2131 public void requestDisplayState(int state, int brightness) { 2132 // The order of operations is important for legacy reasons. 2133 if (state == Display.STATE_OFF) { 2134 requestGlobalDisplayStateInternal(state, brightness); 2135 } 2136 2137 callbacks.onDisplayStateChange(state); 2138 2139 if (state != Display.STATE_OFF) { 2140 requestGlobalDisplayStateInternal(state, brightness); 2141 } 2142 } 2143 }; 2144 mDisplayPowerController = new DisplayPowerController( 2145 mContext, callbacks, handler, sensorManager, blanker); 2146 } 2147 2148 mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATION); 2149 } 2150 2151 @Override requestPowerState(DisplayPowerRequest request, boolean waitForNegativeProximity)2152 public boolean requestPowerState(DisplayPowerRequest request, 2153 boolean waitForNegativeProximity) { 2154 synchronized (mSyncRoot) { 2155 return mDisplayPowerController.requestPowerState(request, 2156 waitForNegativeProximity); 2157 } 2158 } 2159 2160 @Override isProximitySensorAvailable()2161 public boolean isProximitySensorAvailable() { 2162 synchronized (mSyncRoot) { 2163 return mDisplayPowerController.isProximitySensorAvailable(); 2164 } 2165 } 2166 2167 @Override getDisplayInfo(int displayId)2168 public DisplayInfo getDisplayInfo(int displayId) { 2169 return getDisplayInfoInternal(displayId, Process.myUid()); 2170 } 2171 2172 @Override registerDisplayTransactionListener(DisplayTransactionListener listener)2173 public void registerDisplayTransactionListener(DisplayTransactionListener listener) { 2174 if (listener == null) { 2175 throw new IllegalArgumentException("listener must not be null"); 2176 } 2177 2178 registerDisplayTransactionListenerInternal(listener); 2179 } 2180 2181 @Override unregisterDisplayTransactionListener(DisplayTransactionListener listener)2182 public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) { 2183 if (listener == null) { 2184 throw new IllegalArgumentException("listener must not be null"); 2185 } 2186 2187 unregisterDisplayTransactionListenerInternal(listener); 2188 } 2189 2190 @Override setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info)2191 public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) { 2192 setDisplayInfoOverrideFromWindowManagerInternal(displayId, info); 2193 } 2194 2195 @Override getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo)2196 public void getNonOverrideDisplayInfo(int displayId, DisplayInfo outInfo) { 2197 getNonOverrideDisplayInfoInternal(displayId, outInfo); 2198 } 2199 2200 @Override performTraversal(SurfaceControl.Transaction t)2201 public void performTraversal(SurfaceControl.Transaction t) { 2202 performTraversalInternal(t); 2203 } 2204 2205 @Override setDisplayProperties(int displayId, boolean hasContent, float requestedRefreshRate, int requestedMode, boolean inTraversal)2206 public void setDisplayProperties(int displayId, boolean hasContent, 2207 float requestedRefreshRate, int requestedMode, boolean inTraversal) { 2208 setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate, 2209 requestedMode, inTraversal); 2210 } 2211 2212 @Override setDisplayOffsets(int displayId, int x, int y)2213 public void setDisplayOffsets(int displayId, int x, int y) { 2214 setDisplayOffsetsInternal(displayId, x, y); 2215 } 2216 2217 @Override setDisplayAccessUIDs(SparseArray<IntArray> newDisplayAccessUIDs)2218 public void setDisplayAccessUIDs(SparseArray<IntArray> newDisplayAccessUIDs) { 2219 setDisplayAccessUIDsInternal(newDisplayAccessUIDs); 2220 } 2221 2222 @Override isUidPresentOnDisplay(int uid, int displayId)2223 public boolean isUidPresentOnDisplay(int uid, int displayId) { 2224 return isUidPresentOnDisplayInternal(uid, displayId); 2225 } 2226 2227 @Override persistBrightnessTrackerState()2228 public void persistBrightnessTrackerState() { 2229 synchronized (mSyncRoot) { 2230 mDisplayPowerController.persistBrightnessTrackerState(); 2231 } 2232 } 2233 2234 @Override onOverlayChanged()2235 public void onOverlayChanged() { 2236 synchronized (mSyncRoot) { 2237 for (int i = 0; i < mDisplayDevices.size(); i++) { 2238 mDisplayDevices.get(i).onOverlayChangedLocked(); 2239 } 2240 } 2241 } 2242 } 2243 } 2244