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 com.android.internal.util.IndentingPrintWriter; 20 21 import android.Manifest; 22 import android.content.Context; 23 import android.content.pm.PackageManager; 24 import android.hardware.SensorManager; 25 import android.hardware.display.DisplayManager; 26 import android.hardware.display.DisplayManagerGlobal; 27 import android.hardware.display.DisplayManagerInternal; 28 import android.hardware.display.DisplayViewport; 29 import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener; 30 import android.hardware.display.IDisplayManager; 31 import android.hardware.display.IDisplayManagerCallback; 32 import android.hardware.display.IVirtualDisplayCallback; 33 import android.hardware.display.WifiDisplayStatus; 34 import android.hardware.input.InputManagerInternal; 35 import android.media.projection.IMediaProjection; 36 import android.media.projection.IMediaProjectionManager; 37 import android.os.Binder; 38 import android.os.Handler; 39 import android.os.IBinder; 40 import android.os.IBinder.DeathRecipient; 41 import android.os.Looper; 42 import android.os.Message; 43 import android.os.PowerManager; 44 import android.os.Process; 45 import android.os.RemoteException; 46 import android.os.ServiceManager; 47 import android.os.SystemClock; 48 import android.os.SystemProperties; 49 import android.os.Trace; 50 import android.text.TextUtils; 51 import android.util.Slog; 52 import android.util.SparseArray; 53 import android.view.Display; 54 import android.view.DisplayInfo; 55 import android.view.Surface; 56 import android.view.WindowManagerInternal; 57 58 import com.android.server.DisplayThread; 59 import com.android.server.LocalServices; 60 import com.android.server.SystemService; 61 import com.android.server.UiThread; 62 63 import java.io.FileDescriptor; 64 import java.io.PrintWriter; 65 import java.util.ArrayList; 66 import java.util.Arrays; 67 import java.util.List; 68 import java.util.concurrent.CopyOnWriteArrayList; 69 70 /** 71 * Manages attached displays. 72 * <p> 73 * The {@link DisplayManagerService} manages the global lifecycle of displays, 74 * decides how to configure logical displays based on the physical display devices currently 75 * attached, sends notifications to the system and to applications when the state 76 * changes, and so on. 77 * </p><p> 78 * The display manager service relies on a collection of {@link DisplayAdapter} components, 79 * for discovering and configuring physical display devices attached to the system. 80 * There are separate display adapters for each manner that devices are attached: 81 * one display adapter for built-in local displays, one for simulated non-functional 82 * displays when the system is headless, one for simulated overlay displays used for 83 * development, one for wifi displays, etc. 84 * </p><p> 85 * Display adapters are only weakly coupled to the display manager service. 86 * Display adapters communicate changes in display device state to the display manager 87 * service asynchronously via a {@link DisplayAdapter.Listener} registered 88 * by the display manager service. This separation of concerns is important for 89 * two main reasons. First, it neatly encapsulates the responsibilities of these 90 * two classes: display adapters handle individual display devices whereas 91 * the display manager service handles the global state. Second, it eliminates 92 * the potential for deadlocks resulting from asynchronous display device discovery. 93 * </p> 94 * 95 * <h3>Synchronization</h3> 96 * <p> 97 * Because the display manager may be accessed by multiple threads, the synchronization 98 * story gets a little complicated. In particular, the window manager may call into 99 * the display manager while holding a surface transaction with the expectation that 100 * it can apply changes immediately. Unfortunately, that means we can't just do 101 * everything asynchronously (*grump*). 102 * </p><p> 103 * To make this work, all of the objects that belong to the display manager must 104 * use the same lock. We call this lock the synchronization root and it has a unique 105 * type {@link DisplayManagerService.SyncRoot}. Methods that require this lock are 106 * named with the "Locked" suffix. 107 * </p><p> 108 * Where things get tricky is that the display manager is not allowed to make 109 * any potentially reentrant calls, especially into the window manager. We generally 110 * avoid this by making all potentially reentrant out-calls asynchronous. 111 * </p> 112 */ 113 public final class DisplayManagerService extends SystemService { 114 private static final String TAG = "DisplayManagerService"; 115 private static final boolean DEBUG = false; 116 117 // When this system property is set to 0, WFD is forcibly disabled on boot. 118 // When this system property is set to 1, WFD is forcibly enabled on boot. 119 // Otherwise WFD is enabled according to the value of config_enableWifiDisplay. 120 private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable"; 121 122 private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000; 123 124 private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER = 1; 125 private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2; 126 private static final int MSG_DELIVER_DISPLAY_EVENT = 3; 127 private static final int MSG_REQUEST_TRAVERSAL = 4; 128 private static final int MSG_UPDATE_VIEWPORT = 5; 129 130 private final Context mContext; 131 private final DisplayManagerHandler mHandler; 132 private final Handler mUiHandler; 133 private final DisplayAdapterListener mDisplayAdapterListener; 134 private WindowManagerInternal mWindowManagerInternal; 135 private InputManagerInternal mInputManagerInternal; 136 private IMediaProjectionManager mProjectionService; 137 138 // The synchronization root for the display manager. 139 // This lock guards most of the display manager's state. 140 // NOTE: This is synchronized on while holding WindowManagerService.mWindowMap so never call 141 // into WindowManagerService methods that require mWindowMap while holding this unless you are 142 // very very sure that no deadlock can occur. 143 private final SyncRoot mSyncRoot = new SyncRoot(); 144 145 // True if in safe mode. 146 // This option may disable certain display adapters. 147 public boolean mSafeMode; 148 149 // True if we are in a special boot mode where only core applications and 150 // services should be started. This option may disable certain display adapters. 151 public boolean mOnlyCore; 152 153 // True if the display manager service should pretend there is only one display 154 // and only tell applications about the existence of the default logical display. 155 // The display manager can still mirror content to secondary displays but applications 156 // cannot present unique content on those displays. 157 // Used for demonstration purposes only. 158 private final boolean mSingleDisplayDemoMode; 159 160 // All callback records indexed by calling process id. 161 public final SparseArray<CallbackRecord> mCallbacks = 162 new SparseArray<CallbackRecord>(); 163 164 // List of all currently registered display adapters. 165 private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>(); 166 167 // List of all currently connected display devices. 168 private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>(); 169 170 // List of all logical displays indexed by logical display id. 171 private final SparseArray<LogicalDisplay> mLogicalDisplays = 172 new SparseArray<LogicalDisplay>(); 173 private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1; 174 175 // List of all display transaction listeners. 176 private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners = 177 new CopyOnWriteArrayList<DisplayTransactionListener>(); 178 179 // Display power controller. 180 private DisplayPowerController mDisplayPowerController; 181 182 // The overall display state, independent of changes that might influence one 183 // display or another in particular. 184 private int mGlobalDisplayState = Display.STATE_ON; 185 186 // The overall display brightness. 187 // For now, this only applies to the built-in display but we may split it up eventually. 188 private int mGlobalDisplayBrightness = PowerManager.BRIGHTNESS_DEFAULT; 189 190 // Set to true when there are pending display changes that have yet to be applied 191 // to the surface flinger state. 192 private boolean mPendingTraversal; 193 194 // The Wifi display adapter, or null if not registered. 195 private WifiDisplayAdapter mWifiDisplayAdapter; 196 197 // The number of active wifi display scan requests. 198 private int mWifiDisplayScanRequestCount; 199 200 // The virtual display adapter, or null if not registered. 201 private VirtualDisplayAdapter mVirtualDisplayAdapter; 202 203 // Viewports of the default display and the display that should receive touch 204 // input from an external source. Used by the input system. 205 private final DisplayViewport mDefaultViewport = new DisplayViewport(); 206 private final DisplayViewport mExternalTouchViewport = new DisplayViewport(); 207 208 // Persistent data store for all internal settings maintained by the display manager service. 209 private final PersistentDataStore mPersistentDataStore = new PersistentDataStore(); 210 211 // Temporary callback list, used when sending display events to applications. 212 // May be used outside of the lock but only on the handler thread. 213 private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>(); 214 215 // Temporary display info, used for comparing display configurations. 216 private final DisplayInfo mTempDisplayInfo = new DisplayInfo(); 217 218 // Temporary viewports, used when sending new viewport information to the 219 // input system. May be used outside of the lock but only on the handler thread. 220 private final DisplayViewport mTempDefaultViewport = new DisplayViewport(); 221 private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport(); 222 223 // Temporary list of deferred work to perform when setting the display state. 224 // Only used by requestDisplayState. The field is self-synchronized and only 225 // intended for use inside of the requestGlobalDisplayStateInternal function. 226 private final ArrayList<Runnable> mTempDisplayStateWorkQueue = new ArrayList<Runnable>(); 227 DisplayManagerService(Context context)228 public DisplayManagerService(Context context) { 229 super(context); 230 mContext = context; 231 mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper()); 232 mUiHandler = UiThread.getHandler(); 233 mDisplayAdapterListener = new DisplayAdapterListener(); 234 mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false); 235 236 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 237 mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting(); 238 } 239 240 @Override onStart()241 public void onStart() { 242 // We need to pre-load the persistent data store so it's ready before the default display 243 // adapter is up so that we have it's configuration. We could load it lazily, but since 244 // we're going to have to read it in eventually we may as well do it here rather than after 245 // we've waited for the diplay to register itself with us. 246 mPersistentDataStore.loadIfNeeded(); 247 mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER); 248 249 publishBinderService(Context.DISPLAY_SERVICE, new BinderService(), 250 true /*allowIsolated*/); 251 publishLocalService(DisplayManagerInternal.class, new LocalService()); 252 publishLocalService(DisplayTransformManager.class, new DisplayTransformManager()); 253 } 254 255 @Override onBootPhase(int phase)256 public void onBootPhase(int phase) { 257 if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) { 258 synchronized (mSyncRoot) { 259 long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT; 260 while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) { 261 long delay = timeout - SystemClock.uptimeMillis(); 262 if (delay <= 0) { 263 throw new RuntimeException("Timeout waiting for default display " 264 + "to be initialized."); 265 } 266 if (DEBUG) { 267 Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay); 268 } 269 try { 270 mSyncRoot.wait(delay); 271 } catch (InterruptedException ex) { 272 } 273 } 274 } 275 } 276 } 277 278 // TODO: Use dependencies or a boot phase windowManagerAndInputReady()279 public void windowManagerAndInputReady() { 280 synchronized (mSyncRoot) { 281 mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); 282 mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); 283 scheduleTraversalLocked(false); 284 } 285 } 286 287 /** 288 * Called when the system is ready to go. 289 */ systemReady(boolean safeMode, boolean onlyCore)290 public void systemReady(boolean safeMode, boolean onlyCore) { 291 synchronized (mSyncRoot) { 292 mSafeMode = safeMode; 293 mOnlyCore = onlyCore; 294 } 295 296 mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS); 297 } 298 registerDisplayTransactionListenerInternal( DisplayTransactionListener listener)299 private void registerDisplayTransactionListenerInternal( 300 DisplayTransactionListener listener) { 301 // List is self-synchronized copy-on-write. 302 mDisplayTransactionListeners.add(listener); 303 } 304 unregisterDisplayTransactionListenerInternal( DisplayTransactionListener listener)305 private void unregisterDisplayTransactionListenerInternal( 306 DisplayTransactionListener listener) { 307 // List is self-synchronized copy-on-write. 308 mDisplayTransactionListeners.remove(listener); 309 } 310 setDisplayInfoOverrideFromWindowManagerInternal( int displayId, DisplayInfo info)311 private void setDisplayInfoOverrideFromWindowManagerInternal( 312 int displayId, DisplayInfo info) { 313 synchronized (mSyncRoot) { 314 LogicalDisplay display = mLogicalDisplays.get(displayId); 315 if (display != null) { 316 if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) { 317 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); 318 scheduleTraversalLocked(false); 319 } 320 } 321 } 322 } 323 performTraversalInTransactionFromWindowManagerInternal()324 private void performTraversalInTransactionFromWindowManagerInternal() { 325 synchronized (mSyncRoot) { 326 if (!mPendingTraversal) { 327 return; 328 } 329 mPendingTraversal = false; 330 331 performTraversalInTransactionLocked(); 332 } 333 334 // List is self-synchronized copy-on-write. 335 for (DisplayTransactionListener listener : mDisplayTransactionListeners) { 336 listener.onDisplayTransaction(); 337 } 338 } 339 requestGlobalDisplayStateInternal(int state, int brightness)340 private void requestGlobalDisplayStateInternal(int state, int brightness) { 341 if (state == Display.STATE_UNKNOWN) { 342 state = Display.STATE_ON; 343 } 344 if (state == Display.STATE_OFF) { 345 brightness = PowerManager.BRIGHTNESS_OFF; 346 } else if (brightness < 0) { 347 brightness = PowerManager.BRIGHTNESS_DEFAULT; 348 } else if (brightness > PowerManager.BRIGHTNESS_ON) { 349 brightness = PowerManager.BRIGHTNESS_ON; 350 } 351 352 synchronized (mTempDisplayStateWorkQueue) { 353 try { 354 // Update the display state within the lock. 355 // Note that we do not need to schedule traversals here although it 356 // may happen as a side-effect of displays changing state. 357 synchronized (mSyncRoot) { 358 if (mGlobalDisplayState == state 359 && mGlobalDisplayBrightness == brightness) { 360 return; // no change 361 } 362 363 Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestGlobalDisplayState(" 364 + Display.stateToString(state) 365 + ", brightness=" + brightness + ")"); 366 mGlobalDisplayState = state; 367 mGlobalDisplayBrightness = brightness; 368 applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue); 369 } 370 371 // Setting the display power state can take hundreds of milliseconds 372 // to complete so we defer the most expensive part of the work until 373 // after we have exited the critical section to avoid blocking other 374 // threads for a long time. 375 for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) { 376 mTempDisplayStateWorkQueue.get(i).run(); 377 } 378 Trace.traceEnd(Trace.TRACE_TAG_POWER); 379 } finally { 380 mTempDisplayStateWorkQueue.clear(); 381 } 382 } 383 } 384 getDisplayInfoInternal(int displayId, int callingUid)385 private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) { 386 synchronized (mSyncRoot) { 387 LogicalDisplay display = mLogicalDisplays.get(displayId); 388 if (display != null) { 389 DisplayInfo info = display.getDisplayInfoLocked(); 390 if (info.hasAccess(callingUid)) { 391 return info; 392 } 393 } 394 return null; 395 } 396 } 397 getDisplayIdsInternal(int callingUid)398 private int[] getDisplayIdsInternal(int callingUid) { 399 synchronized (mSyncRoot) { 400 final int count = mLogicalDisplays.size(); 401 int[] displayIds = new int[count]; 402 int n = 0; 403 for (int i = 0; i < count; i++) { 404 LogicalDisplay display = mLogicalDisplays.valueAt(i); 405 DisplayInfo info = display.getDisplayInfoLocked(); 406 if (info.hasAccess(callingUid)) { 407 displayIds[n++] = mLogicalDisplays.keyAt(i); 408 } 409 } 410 if (n != count) { 411 displayIds = Arrays.copyOfRange(displayIds, 0, n); 412 } 413 return displayIds; 414 } 415 } 416 registerCallbackInternal(IDisplayManagerCallback callback, int callingPid)417 private void registerCallbackInternal(IDisplayManagerCallback callback, int callingPid) { 418 synchronized (mSyncRoot) { 419 if (mCallbacks.get(callingPid) != null) { 420 throw new SecurityException("The calling process has already " 421 + "registered an IDisplayManagerCallback."); 422 } 423 424 CallbackRecord record = new CallbackRecord(callingPid, callback); 425 try { 426 IBinder binder = callback.asBinder(); 427 binder.linkToDeath(record, 0); 428 } catch (RemoteException ex) { 429 // give up 430 throw new RuntimeException(ex); 431 } 432 433 mCallbacks.put(callingPid, record); 434 } 435 } 436 onCallbackDied(CallbackRecord record)437 private void onCallbackDied(CallbackRecord record) { 438 synchronized (mSyncRoot) { 439 mCallbacks.remove(record.mPid); 440 stopWifiDisplayScanLocked(record); 441 } 442 } 443 startWifiDisplayScanInternal(int callingPid)444 private void startWifiDisplayScanInternal(int callingPid) { 445 synchronized (mSyncRoot) { 446 CallbackRecord record = mCallbacks.get(callingPid); 447 if (record == null) { 448 throw new IllegalStateException("The calling process has not " 449 + "registered an IDisplayManagerCallback."); 450 } 451 startWifiDisplayScanLocked(record); 452 } 453 } 454 startWifiDisplayScanLocked(CallbackRecord record)455 private void startWifiDisplayScanLocked(CallbackRecord record) { 456 if (!record.mWifiDisplayScanRequested) { 457 record.mWifiDisplayScanRequested = true; 458 if (mWifiDisplayScanRequestCount++ == 0) { 459 if (mWifiDisplayAdapter != null) { 460 mWifiDisplayAdapter.requestStartScanLocked(); 461 } 462 } 463 } 464 } 465 stopWifiDisplayScanInternal(int callingPid)466 private void stopWifiDisplayScanInternal(int callingPid) { 467 synchronized (mSyncRoot) { 468 CallbackRecord record = mCallbacks.get(callingPid); 469 if (record == null) { 470 throw new IllegalStateException("The calling process has not " 471 + "registered an IDisplayManagerCallback."); 472 } 473 stopWifiDisplayScanLocked(record); 474 } 475 } 476 stopWifiDisplayScanLocked(CallbackRecord record)477 private void stopWifiDisplayScanLocked(CallbackRecord record) { 478 if (record.mWifiDisplayScanRequested) { 479 record.mWifiDisplayScanRequested = false; 480 if (--mWifiDisplayScanRequestCount == 0) { 481 if (mWifiDisplayAdapter != null) { 482 mWifiDisplayAdapter.requestStopScanLocked(); 483 } 484 } else if (mWifiDisplayScanRequestCount < 0) { 485 Slog.wtf(TAG, "mWifiDisplayScanRequestCount became negative: " 486 + mWifiDisplayScanRequestCount); 487 mWifiDisplayScanRequestCount = 0; 488 } 489 } 490 } 491 connectWifiDisplayInternal(String address)492 private void connectWifiDisplayInternal(String address) { 493 synchronized (mSyncRoot) { 494 if (mWifiDisplayAdapter != null) { 495 mWifiDisplayAdapter.requestConnectLocked(address); 496 } 497 } 498 } 499 pauseWifiDisplayInternal()500 private void pauseWifiDisplayInternal() { 501 synchronized (mSyncRoot) { 502 if (mWifiDisplayAdapter != null) { 503 mWifiDisplayAdapter.requestPauseLocked(); 504 } 505 } 506 } 507 resumeWifiDisplayInternal()508 private void resumeWifiDisplayInternal() { 509 synchronized (mSyncRoot) { 510 if (mWifiDisplayAdapter != null) { 511 mWifiDisplayAdapter.requestResumeLocked(); 512 } 513 } 514 } 515 disconnectWifiDisplayInternal()516 private void disconnectWifiDisplayInternal() { 517 synchronized (mSyncRoot) { 518 if (mWifiDisplayAdapter != null) { 519 mWifiDisplayAdapter.requestDisconnectLocked(); 520 } 521 } 522 } 523 renameWifiDisplayInternal(String address, String alias)524 private void renameWifiDisplayInternal(String address, String alias) { 525 synchronized (mSyncRoot) { 526 if (mWifiDisplayAdapter != null) { 527 mWifiDisplayAdapter.requestRenameLocked(address, alias); 528 } 529 } 530 } 531 forgetWifiDisplayInternal(String address)532 private void forgetWifiDisplayInternal(String address) { 533 synchronized (mSyncRoot) { 534 if (mWifiDisplayAdapter != null) { 535 mWifiDisplayAdapter.requestForgetLocked(address); 536 } 537 } 538 } 539 getWifiDisplayStatusInternal()540 private WifiDisplayStatus getWifiDisplayStatusInternal() { 541 synchronized (mSyncRoot) { 542 if (mWifiDisplayAdapter != null) { 543 return mWifiDisplayAdapter.getWifiDisplayStatusLocked(); 544 } 545 return new WifiDisplayStatus(); 546 } 547 } 548 requestColorModeInternal(int displayId, int colorMode)549 private void requestColorModeInternal(int displayId, int colorMode) { 550 synchronized (mSyncRoot) { 551 LogicalDisplay display = mLogicalDisplays.get(displayId); 552 if (display != null && 553 display.getRequestedColorModeLocked() != colorMode) { 554 display.setRequestedColorModeLocked(colorMode); 555 scheduleTraversalLocked(false); 556 } 557 } 558 } 559 createVirtualDisplayInternal(IVirtualDisplayCallback callback, IMediaProjection projection, int callingUid, String packageName, String name, int width, int height, int densityDpi, Surface surface, int flags)560 private int createVirtualDisplayInternal(IVirtualDisplayCallback callback, 561 IMediaProjection projection, int callingUid, String packageName, 562 String name, int width, int height, int densityDpi, Surface surface, int flags) { 563 synchronized (mSyncRoot) { 564 if (mVirtualDisplayAdapter == null) { 565 Slog.w(TAG, "Rejecting request to create private virtual display " 566 + "because the virtual display adapter is not available."); 567 return -1; 568 } 569 570 DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked( 571 callback, projection, callingUid, packageName, 572 name, width, height, densityDpi, surface, flags); 573 if (device == null) { 574 return -1; 575 } 576 577 handleDisplayDeviceAddedLocked(device); 578 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device); 579 if (display != null) { 580 return display.getDisplayIdLocked(); 581 } 582 583 // Something weird happened and the logical display was not created. 584 Slog.w(TAG, "Rejecting request to create virtual display " 585 + "because the logical display was not created."); 586 mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder()); 587 handleDisplayDeviceRemovedLocked(device); 588 } 589 return -1; 590 } 591 resizeVirtualDisplayInternal(IBinder appToken, int width, int height, int densityDpi)592 private void resizeVirtualDisplayInternal(IBinder appToken, 593 int width, int height, int densityDpi) { 594 synchronized (mSyncRoot) { 595 if (mVirtualDisplayAdapter == null) { 596 return; 597 } 598 599 mVirtualDisplayAdapter.resizeVirtualDisplayLocked(appToken, width, height, densityDpi); 600 } 601 } 602 setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface)603 private void setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface) { 604 synchronized (mSyncRoot) { 605 if (mVirtualDisplayAdapter == null) { 606 return; 607 } 608 609 mVirtualDisplayAdapter.setVirtualDisplaySurfaceLocked(appToken, surface); 610 } 611 } 612 releaseVirtualDisplayInternal(IBinder appToken)613 private void releaseVirtualDisplayInternal(IBinder appToken) { 614 synchronized (mSyncRoot) { 615 if (mVirtualDisplayAdapter == null) { 616 return; 617 } 618 619 DisplayDevice device = 620 mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken); 621 if (device != null) { 622 handleDisplayDeviceRemovedLocked(device); 623 } 624 } 625 } 626 registerDefaultDisplayAdapter()627 private void registerDefaultDisplayAdapter() { 628 // Register default display adapter. 629 synchronized (mSyncRoot) { 630 registerDisplayAdapterLocked(new LocalDisplayAdapter( 631 mSyncRoot, mContext, mHandler, mDisplayAdapterListener)); 632 } 633 } 634 registerAdditionalDisplayAdapters()635 private void registerAdditionalDisplayAdapters() { 636 synchronized (mSyncRoot) { 637 if (shouldRegisterNonEssentialDisplayAdaptersLocked()) { 638 registerOverlayDisplayAdapterLocked(); 639 registerWifiDisplayAdapterLocked(); 640 registerVirtualDisplayAdapterLocked(); 641 } 642 } 643 } 644 registerOverlayDisplayAdapterLocked()645 private void registerOverlayDisplayAdapterLocked() { 646 registerDisplayAdapterLocked(new OverlayDisplayAdapter( 647 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler)); 648 } 649 registerWifiDisplayAdapterLocked()650 private void registerWifiDisplayAdapterLocked() { 651 if (mContext.getResources().getBoolean( 652 com.android.internal.R.bool.config_enableWifiDisplay) 653 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) { 654 mWifiDisplayAdapter = new WifiDisplayAdapter( 655 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, 656 mPersistentDataStore); 657 registerDisplayAdapterLocked(mWifiDisplayAdapter); 658 } 659 } 660 registerVirtualDisplayAdapterLocked()661 private void registerVirtualDisplayAdapterLocked() { 662 mVirtualDisplayAdapter = new VirtualDisplayAdapter( 663 mSyncRoot, mContext, mHandler, mDisplayAdapterListener); 664 registerDisplayAdapterLocked(mVirtualDisplayAdapter); 665 } 666 shouldRegisterNonEssentialDisplayAdaptersLocked()667 private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() { 668 // In safe mode, we disable non-essential display adapters to give the user 669 // an opportunity to fix broken settings or other problems that might affect 670 // system stability. 671 // In only-core mode, we disable non-essential display adapters to minimize 672 // the number of dependencies that are started while in this mode and to 673 // prevent problems that might occur due to the device being encrypted. 674 return !mSafeMode && !mOnlyCore; 675 } 676 registerDisplayAdapterLocked(DisplayAdapter adapter)677 private void registerDisplayAdapterLocked(DisplayAdapter adapter) { 678 mDisplayAdapters.add(adapter); 679 adapter.registerLocked(); 680 } 681 handleDisplayDeviceAdded(DisplayDevice device)682 private void handleDisplayDeviceAdded(DisplayDevice device) { 683 synchronized (mSyncRoot) { 684 handleDisplayDeviceAddedLocked(device); 685 } 686 } 687 handleDisplayDeviceAddedLocked(DisplayDevice device)688 private void handleDisplayDeviceAddedLocked(DisplayDevice device) { 689 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 690 if (mDisplayDevices.contains(device)) { 691 Slog.w(TAG, "Attempted to add already added display device: " + info); 692 return; 693 } 694 695 Slog.i(TAG, "Display device added: " + info); 696 device.mDebugLastLoggedDeviceInfo = info; 697 698 mDisplayDevices.add(device); 699 LogicalDisplay display = addLogicalDisplayLocked(device); 700 Runnable work = updateDisplayStateLocked(device); 701 if (work != null) { 702 work.run(); 703 } 704 if (display != null && display.getPrimaryDisplayDeviceLocked() == device) { 705 int colorMode = mPersistentDataStore.getColorMode(device); 706 display.setRequestedColorModeLocked(colorMode); 707 } 708 scheduleTraversalLocked(false); 709 } 710 handleDisplayDeviceChanged(DisplayDevice device)711 private void handleDisplayDeviceChanged(DisplayDevice device) { 712 synchronized (mSyncRoot) { 713 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 714 if (!mDisplayDevices.contains(device)) { 715 Slog.w(TAG, "Attempted to change non-existent display device: " + info); 716 return; 717 } 718 719 int diff = device.mDebugLastLoggedDeviceInfo.diff(info); 720 if (diff == DisplayDeviceInfo.DIFF_STATE) { 721 Slog.i(TAG, "Display device changed state: \"" + info.name 722 + "\", " + Display.stateToString(info.state)); 723 } else if (diff != 0) { 724 Slog.i(TAG, "Display device changed: " + info); 725 } 726 if ((diff & DisplayDeviceInfo.DIFF_COLOR_MODE) != 0) { 727 try { 728 mPersistentDataStore.setColorMode(device, info.colorMode); 729 } finally { 730 mPersistentDataStore.saveIfNeeded(); 731 } 732 } 733 device.mDebugLastLoggedDeviceInfo = info; 734 735 device.applyPendingDisplayDeviceInfoChangesLocked(); 736 if (updateLogicalDisplaysLocked()) { 737 scheduleTraversalLocked(false); 738 } 739 } 740 } 741 handleDisplayDeviceRemoved(DisplayDevice device)742 private void handleDisplayDeviceRemoved(DisplayDevice device) { 743 synchronized (mSyncRoot) { 744 handleDisplayDeviceRemovedLocked(device); 745 } 746 } 747 handleDisplayDeviceRemovedLocked(DisplayDevice device)748 private void handleDisplayDeviceRemovedLocked(DisplayDevice device) { 749 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 750 if (!mDisplayDevices.remove(device)) { 751 Slog.w(TAG, "Attempted to remove non-existent display device: " + info); 752 return; 753 } 754 755 Slog.i(TAG, "Display device removed: " + info); 756 device.mDebugLastLoggedDeviceInfo = info; 757 758 updateLogicalDisplaysLocked(); 759 scheduleTraversalLocked(false); 760 } 761 applyGlobalDisplayStateLocked(List<Runnable> workQueue)762 private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) { 763 final int count = mDisplayDevices.size(); 764 for (int i = 0; i < count; i++) { 765 DisplayDevice device = mDisplayDevices.get(i); 766 Runnable runnable = updateDisplayStateLocked(device); 767 if (runnable != null) { 768 workQueue.add(runnable); 769 } 770 } 771 } 772 updateDisplayStateLocked(DisplayDevice device)773 private Runnable updateDisplayStateLocked(DisplayDevice device) { 774 // Blank or unblank the display immediately to match the state requested 775 // by the display power controller (if known). 776 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 777 if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) { 778 return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness); 779 } 780 return null; 781 } 782 783 // Adds a new logical display based on the given display device. 784 // Sends notifications if needed. addLogicalDisplayLocked(DisplayDevice device)785 private LogicalDisplay addLogicalDisplayLocked(DisplayDevice device) { 786 DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked(); 787 boolean isDefault = (deviceInfo.flags 788 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0; 789 if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) { 790 Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo); 791 isDefault = false; 792 } 793 794 if (!isDefault && mSingleDisplayDemoMode) { 795 Slog.i(TAG, "Not creating a logical display for a secondary display " 796 + " because single display demo mode is enabled: " + deviceInfo); 797 return null; 798 } 799 800 final int displayId = assignDisplayIdLocked(isDefault); 801 final int layerStack = assignLayerStackLocked(displayId); 802 803 LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device); 804 display.updateLocked(mDisplayDevices); 805 if (!display.isValidLocked()) { 806 // This should never happen currently. 807 Slog.w(TAG, "Ignoring display device because the logical display " 808 + "created from it was not considered valid: " + deviceInfo); 809 return null; 810 } 811 812 mLogicalDisplays.put(displayId, display); 813 814 // Wake up waitForDefaultDisplay. 815 if (isDefault) { 816 mSyncRoot.notifyAll(); 817 } 818 819 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED); 820 return display; 821 } 822 assignDisplayIdLocked(boolean isDefault)823 private int assignDisplayIdLocked(boolean isDefault) { 824 return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++; 825 } 826 assignLayerStackLocked(int displayId)827 private int assignLayerStackLocked(int displayId) { 828 // Currently layer stacks and display ids are the same. 829 // This need not be the case. 830 return displayId; 831 } 832 833 // Updates all existing logical displays given the current set of display devices. 834 // Removes invalid logical displays. 835 // Sends notifications if needed. updateLogicalDisplaysLocked()836 private boolean updateLogicalDisplaysLocked() { 837 boolean changed = false; 838 for (int i = mLogicalDisplays.size(); i-- > 0; ) { 839 final int displayId = mLogicalDisplays.keyAt(i); 840 LogicalDisplay display = mLogicalDisplays.valueAt(i); 841 842 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked()); 843 display.updateLocked(mDisplayDevices); 844 if (!display.isValidLocked()) { 845 mLogicalDisplays.removeAt(i); 846 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED); 847 changed = true; 848 } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) { 849 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); 850 changed = true; 851 } 852 } 853 return changed; 854 } 855 performTraversalInTransactionLocked()856 private void performTraversalInTransactionLocked() { 857 // Clear all viewports before configuring displays so that we can keep 858 // track of which ones we have configured. 859 clearViewportsLocked(); 860 861 // Configure each display device. 862 final int count = mDisplayDevices.size(); 863 for (int i = 0; i < count; i++) { 864 DisplayDevice device = mDisplayDevices.get(i); 865 configureDisplayInTransactionLocked(device); 866 device.performTraversalInTransactionLocked(); 867 } 868 869 // Tell the input system about these new viewports. 870 if (mInputManagerInternal != null) { 871 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT); 872 } 873 } 874 setDisplayPropertiesInternal(int displayId, boolean hasContent, float requestedRefreshRate, int requestedModeId, boolean inTraversal)875 private void setDisplayPropertiesInternal(int displayId, boolean hasContent, 876 float requestedRefreshRate, int requestedModeId, boolean inTraversal) { 877 synchronized (mSyncRoot) { 878 LogicalDisplay display = mLogicalDisplays.get(displayId); 879 if (display == null) { 880 return; 881 } 882 if (display.hasContentLocked() != hasContent) { 883 if (DEBUG) { 884 Slog.d(TAG, "Display " + displayId + " hasContent flag changed: " 885 + "hasContent=" + hasContent + ", inTraversal=" + inTraversal); 886 } 887 888 display.setHasContentLocked(hasContent); 889 scheduleTraversalLocked(inTraversal); 890 } 891 if (requestedModeId == 0 && requestedRefreshRate != 0) { 892 // Scan supported modes returned by display.getInfo() to find a mode with the same 893 // size as the default display mode but with the specified refresh rate instead. 894 requestedModeId = display.getDisplayInfoLocked().findDefaultModeByRefreshRate( 895 requestedRefreshRate); 896 } 897 if (display.getRequestedModeIdLocked() != requestedModeId) { 898 if (DEBUG) { 899 Slog.d(TAG, "Display " + displayId + " switching to mode " + requestedModeId); 900 } 901 display.setRequestedModeIdLocked(requestedModeId); 902 scheduleTraversalLocked(inTraversal); 903 } 904 } 905 } 906 setDisplayOffsetsInternal(int displayId, int x, int y)907 private void setDisplayOffsetsInternal(int displayId, int x, int y) { 908 synchronized (mSyncRoot) { 909 LogicalDisplay display = mLogicalDisplays.get(displayId); 910 if (display == null) { 911 return; 912 } 913 if (display.getDisplayOffsetXLocked() != x 914 || display.getDisplayOffsetYLocked() != y) { 915 if (DEBUG) { 916 Slog.d(TAG, "Display " + displayId + " burn-in offset set to (" 917 + x + ", " + y + ")"); 918 } 919 display.setDisplayOffsetsLocked(x, y); 920 scheduleTraversalLocked(false); 921 } 922 } 923 } 924 clearViewportsLocked()925 private void clearViewportsLocked() { 926 mDefaultViewport.valid = false; 927 mExternalTouchViewport.valid = false; 928 } 929 configureDisplayInTransactionLocked(DisplayDevice device)930 private void configureDisplayInTransactionLocked(DisplayDevice device) { 931 final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 932 final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0; 933 934 // Find the logical display that the display device is showing. 935 // Certain displays only ever show their own content. 936 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device); 937 if (!ownContent) { 938 if (display != null && !display.hasContentLocked()) { 939 // If the display does not have any content of its own, then 940 // automatically mirror the default logical display contents. 941 display = null; 942 } 943 if (display == null) { 944 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY); 945 } 946 } 947 948 // Apply the logical display configuration to the display device. 949 if (display == null) { 950 // TODO: no logical display for the device, blank it 951 Slog.w(TAG, "Missing logical display to use for physical display device: " 952 + device.getDisplayDeviceInfoLocked()); 953 return; 954 } 955 display.configureDisplayInTransactionLocked(device, info.state == Display.STATE_OFF); 956 957 // Update the viewports if needed. 958 if (!mDefaultViewport.valid 959 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) { 960 setViewportLocked(mDefaultViewport, display, device); 961 } 962 if (!mExternalTouchViewport.valid 963 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) { 964 setViewportLocked(mExternalTouchViewport, display, device); 965 } 966 } 967 setViewportLocked(DisplayViewport viewport, LogicalDisplay display, DisplayDevice device)968 private static void setViewportLocked(DisplayViewport viewport, 969 LogicalDisplay display, DisplayDevice device) { 970 viewport.valid = true; 971 viewport.displayId = display.getDisplayIdLocked(); 972 device.populateViewportLocked(viewport); 973 } 974 findLogicalDisplayForDeviceLocked(DisplayDevice device)975 private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) { 976 final int count = mLogicalDisplays.size(); 977 for (int i = 0; i < count; i++) { 978 LogicalDisplay display = mLogicalDisplays.valueAt(i); 979 if (display.getPrimaryDisplayDeviceLocked() == device) { 980 return display; 981 } 982 } 983 return null; 984 } 985 sendDisplayEventLocked(int displayId, int event)986 private void sendDisplayEventLocked(int displayId, int event) { 987 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event); 988 mHandler.sendMessage(msg); 989 } 990 991 // Requests that performTraversalsInTransactionFromWindowManager be called at a 992 // later time to apply changes to surfaces and displays. scheduleTraversalLocked(boolean inTraversal)993 private void scheduleTraversalLocked(boolean inTraversal) { 994 if (!mPendingTraversal && mWindowManagerInternal != null) { 995 mPendingTraversal = true; 996 if (!inTraversal) { 997 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL); 998 } 999 } 1000 } 1001 1002 // Runs on Handler thread. 1003 // Delivers display event notifications to callbacks. deliverDisplayEvent(int displayId, int event)1004 private void deliverDisplayEvent(int displayId, int event) { 1005 if (DEBUG) { 1006 Slog.d(TAG, "Delivering display event: displayId=" 1007 + displayId + ", event=" + event); 1008 } 1009 1010 // Grab the lock and copy the callbacks. 1011 final int count; 1012 synchronized (mSyncRoot) { 1013 count = mCallbacks.size(); 1014 mTempCallbacks.clear(); 1015 for (int i = 0; i < count; i++) { 1016 mTempCallbacks.add(mCallbacks.valueAt(i)); 1017 } 1018 } 1019 1020 // After releasing the lock, send the notifications out. 1021 for (int i = 0; i < count; i++) { 1022 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event); 1023 } 1024 mTempCallbacks.clear(); 1025 } 1026 getProjectionService()1027 private IMediaProjectionManager getProjectionService() { 1028 if (mProjectionService == null) { 1029 IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE); 1030 mProjectionService = IMediaProjectionManager.Stub.asInterface(b); 1031 } 1032 return mProjectionService; 1033 } 1034 dumpInternal(PrintWriter pw)1035 private void dumpInternal(PrintWriter pw) { 1036 pw.println("DISPLAY MANAGER (dumpsys display)"); 1037 1038 synchronized (mSyncRoot) { 1039 pw.println(" mOnlyCode=" + mOnlyCore); 1040 pw.println(" mSafeMode=" + mSafeMode); 1041 pw.println(" mPendingTraversal=" + mPendingTraversal); 1042 pw.println(" mGlobalDisplayState=" + Display.stateToString(mGlobalDisplayState)); 1043 pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId); 1044 pw.println(" mDefaultViewport=" + mDefaultViewport); 1045 pw.println(" mExternalTouchViewport=" + mExternalTouchViewport); 1046 pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode); 1047 pw.println(" mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount); 1048 1049 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 1050 ipw.increaseIndent(); 1051 1052 pw.println(); 1053 pw.println("Display Adapters: size=" + mDisplayAdapters.size()); 1054 for (DisplayAdapter adapter : mDisplayAdapters) { 1055 pw.println(" " + adapter.getName()); 1056 adapter.dumpLocked(ipw); 1057 } 1058 1059 pw.println(); 1060 pw.println("Display Devices: size=" + mDisplayDevices.size()); 1061 for (DisplayDevice device : mDisplayDevices) { 1062 pw.println(" " + device.getDisplayDeviceInfoLocked()); 1063 device.dumpLocked(ipw); 1064 } 1065 1066 final int logicalDisplayCount = mLogicalDisplays.size(); 1067 pw.println(); 1068 pw.println("Logical Displays: size=" + logicalDisplayCount); 1069 for (int i = 0; i < logicalDisplayCount; i++) { 1070 int displayId = mLogicalDisplays.keyAt(i); 1071 LogicalDisplay display = mLogicalDisplays.valueAt(i); 1072 pw.println(" Display " + displayId + ":"); 1073 display.dumpLocked(ipw); 1074 } 1075 1076 final int callbackCount = mCallbacks.size(); 1077 pw.println(); 1078 pw.println("Callbacks: size=" + callbackCount); 1079 for (int i = 0; i < callbackCount; i++) { 1080 CallbackRecord callback = mCallbacks.valueAt(i); 1081 pw.println(" " + i + ": mPid=" + callback.mPid 1082 + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested); 1083 } 1084 1085 if (mDisplayPowerController != null) { 1086 mDisplayPowerController.dump(pw); 1087 } 1088 1089 pw.println(); 1090 mPersistentDataStore.dump(pw); 1091 } 1092 } 1093 1094 /** 1095 * This is the object that everything in the display manager locks on. 1096 * We make it an inner class within the {@link DisplayManagerService} to so that it is 1097 * clear that the object belongs to the display manager service and that it is 1098 * a unique object with a special purpose. 1099 */ 1100 public static final class SyncRoot { 1101 } 1102 1103 private final class DisplayManagerHandler extends Handler { DisplayManagerHandler(Looper looper)1104 public DisplayManagerHandler(Looper looper) { 1105 super(looper, null, true /*async*/); 1106 } 1107 1108 @Override handleMessage(Message msg)1109 public void handleMessage(Message msg) { 1110 switch (msg.what) { 1111 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER: 1112 registerDefaultDisplayAdapter(); 1113 break; 1114 1115 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS: 1116 registerAdditionalDisplayAdapters(); 1117 break; 1118 1119 case MSG_DELIVER_DISPLAY_EVENT: 1120 deliverDisplayEvent(msg.arg1, msg.arg2); 1121 break; 1122 1123 case MSG_REQUEST_TRAVERSAL: 1124 mWindowManagerInternal.requestTraversalFromDisplayManager(); 1125 break; 1126 1127 case MSG_UPDATE_VIEWPORT: { 1128 synchronized (mSyncRoot) { 1129 mTempDefaultViewport.copyFrom(mDefaultViewport); 1130 mTempExternalTouchViewport.copyFrom(mExternalTouchViewport); 1131 } 1132 mInputManagerInternal.setDisplayViewports( 1133 mTempDefaultViewport, mTempExternalTouchViewport); 1134 break; 1135 } 1136 } 1137 } 1138 } 1139 1140 private final class DisplayAdapterListener implements DisplayAdapter.Listener { 1141 @Override onDisplayDeviceEvent(DisplayDevice device, int event)1142 public void onDisplayDeviceEvent(DisplayDevice device, int event) { 1143 switch (event) { 1144 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED: 1145 handleDisplayDeviceAdded(device); 1146 break; 1147 1148 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED: 1149 handleDisplayDeviceChanged(device); 1150 break; 1151 1152 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED: 1153 handleDisplayDeviceRemoved(device); 1154 break; 1155 } 1156 } 1157 1158 @Override onTraversalRequested()1159 public void onTraversalRequested() { 1160 synchronized (mSyncRoot) { 1161 scheduleTraversalLocked(false); 1162 } 1163 } 1164 } 1165 1166 private final class CallbackRecord implements DeathRecipient { 1167 public final int mPid; 1168 private final IDisplayManagerCallback mCallback; 1169 1170 public boolean mWifiDisplayScanRequested; 1171 CallbackRecord(int pid, IDisplayManagerCallback callback)1172 public CallbackRecord(int pid, IDisplayManagerCallback callback) { 1173 mPid = pid; 1174 mCallback = callback; 1175 } 1176 1177 @Override binderDied()1178 public void binderDied() { 1179 if (DEBUG) { 1180 Slog.d(TAG, "Display listener for pid " + mPid + " died."); 1181 } 1182 onCallbackDied(this); 1183 } 1184 notifyDisplayEventAsync(int displayId, int event)1185 public void notifyDisplayEventAsync(int displayId, int event) { 1186 try { 1187 mCallback.onDisplayEvent(displayId, event); 1188 } catch (RemoteException ex) { 1189 Slog.w(TAG, "Failed to notify process " 1190 + mPid + " that displays changed, assuming it died.", ex); 1191 binderDied(); 1192 } 1193 } 1194 } 1195 1196 private final class BinderService extends IDisplayManager.Stub { 1197 /** 1198 * Returns information about the specified logical display. 1199 * 1200 * @param displayId The logical display id. 1201 * @return The logical display info, or null if the display does not exist. The 1202 * returned object must be treated as immutable. 1203 */ 1204 @Override // Binder call getDisplayInfo(int displayId)1205 public DisplayInfo getDisplayInfo(int displayId) { 1206 final int callingUid = Binder.getCallingUid(); 1207 final long token = Binder.clearCallingIdentity(); 1208 try { 1209 return getDisplayInfoInternal(displayId, callingUid); 1210 } finally { 1211 Binder.restoreCallingIdentity(token); 1212 } 1213 } 1214 1215 /** 1216 * Returns the list of all display ids. 1217 */ 1218 @Override // Binder call getDisplayIds()1219 public int[] getDisplayIds() { 1220 final int callingUid = Binder.getCallingUid(); 1221 final long token = Binder.clearCallingIdentity(); 1222 try { 1223 return getDisplayIdsInternal(callingUid); 1224 } finally { 1225 Binder.restoreCallingIdentity(token); 1226 } 1227 } 1228 1229 @Override // Binder call registerCallback(IDisplayManagerCallback callback)1230 public void registerCallback(IDisplayManagerCallback callback) { 1231 if (callback == null) { 1232 throw new IllegalArgumentException("listener must not be null"); 1233 } 1234 1235 final int callingPid = Binder.getCallingPid(); 1236 final long token = Binder.clearCallingIdentity(); 1237 try { 1238 registerCallbackInternal(callback, callingPid); 1239 } finally { 1240 Binder.restoreCallingIdentity(token); 1241 } 1242 } 1243 1244 @Override // Binder call startWifiDisplayScan()1245 public void startWifiDisplayScan() { 1246 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1247 "Permission required to start wifi display scans"); 1248 1249 final int callingPid = Binder.getCallingPid(); 1250 final long token = Binder.clearCallingIdentity(); 1251 try { 1252 startWifiDisplayScanInternal(callingPid); 1253 } finally { 1254 Binder.restoreCallingIdentity(token); 1255 } 1256 } 1257 1258 @Override // Binder call stopWifiDisplayScan()1259 public void stopWifiDisplayScan() { 1260 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1261 "Permission required to stop wifi display scans"); 1262 1263 final int callingPid = Binder.getCallingPid(); 1264 final long token = Binder.clearCallingIdentity(); 1265 try { 1266 stopWifiDisplayScanInternal(callingPid); 1267 } finally { 1268 Binder.restoreCallingIdentity(token); 1269 } 1270 } 1271 1272 @Override // Binder call connectWifiDisplay(String address)1273 public void connectWifiDisplay(String address) { 1274 if (address == null) { 1275 throw new IllegalArgumentException("address must not be null"); 1276 } 1277 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1278 "Permission required to connect to a wifi display"); 1279 1280 final long token = Binder.clearCallingIdentity(); 1281 try { 1282 connectWifiDisplayInternal(address); 1283 } finally { 1284 Binder.restoreCallingIdentity(token); 1285 } 1286 } 1287 1288 @Override // Binder call disconnectWifiDisplay()1289 public void disconnectWifiDisplay() { 1290 // This request does not require special permissions. 1291 // Any app can request disconnection from the currently active wifi display. 1292 // This exception should no longer be needed once wifi display control moves 1293 // to the media router service. 1294 1295 final long token = Binder.clearCallingIdentity(); 1296 try { 1297 disconnectWifiDisplayInternal(); 1298 } finally { 1299 Binder.restoreCallingIdentity(token); 1300 } 1301 } 1302 1303 @Override // Binder call renameWifiDisplay(String address, String alias)1304 public void renameWifiDisplay(String address, String alias) { 1305 if (address == null) { 1306 throw new IllegalArgumentException("address must not be null"); 1307 } 1308 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1309 "Permission required to rename to a wifi display"); 1310 1311 final long token = Binder.clearCallingIdentity(); 1312 try { 1313 renameWifiDisplayInternal(address, alias); 1314 } finally { 1315 Binder.restoreCallingIdentity(token); 1316 } 1317 } 1318 1319 @Override // Binder call forgetWifiDisplay(String address)1320 public void forgetWifiDisplay(String address) { 1321 if (address == null) { 1322 throw new IllegalArgumentException("address must not be null"); 1323 } 1324 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1325 "Permission required to forget to a wifi display"); 1326 1327 final long token = Binder.clearCallingIdentity(); 1328 try { 1329 forgetWifiDisplayInternal(address); 1330 } finally { 1331 Binder.restoreCallingIdentity(token); 1332 } 1333 } 1334 1335 @Override // Binder call pauseWifiDisplay()1336 public void pauseWifiDisplay() { 1337 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1338 "Permission required to pause a wifi display session"); 1339 1340 final long token = Binder.clearCallingIdentity(); 1341 try { 1342 pauseWifiDisplayInternal(); 1343 } finally { 1344 Binder.restoreCallingIdentity(token); 1345 } 1346 } 1347 1348 @Override // Binder call resumeWifiDisplay()1349 public void resumeWifiDisplay() { 1350 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1351 "Permission required to resume a wifi display session"); 1352 1353 final long token = Binder.clearCallingIdentity(); 1354 try { 1355 resumeWifiDisplayInternal(); 1356 } finally { 1357 Binder.restoreCallingIdentity(token); 1358 } 1359 } 1360 1361 @Override // Binder call getWifiDisplayStatus()1362 public WifiDisplayStatus getWifiDisplayStatus() { 1363 // This request does not require special permissions. 1364 // Any app can get information about available wifi displays. 1365 1366 final long token = Binder.clearCallingIdentity(); 1367 try { 1368 return getWifiDisplayStatusInternal(); 1369 } finally { 1370 Binder.restoreCallingIdentity(token); 1371 } 1372 } 1373 1374 @Override // Binder call requestColorMode(int displayId, int colorMode)1375 public void requestColorMode(int displayId, int colorMode) { 1376 mContext.enforceCallingOrSelfPermission( 1377 Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE, 1378 "Permission required to change the display color mode"); 1379 final long token = Binder.clearCallingIdentity(); 1380 try { 1381 requestColorModeInternal(displayId, colorMode); 1382 } finally { 1383 Binder.restoreCallingIdentity(token); 1384 } 1385 } 1386 1387 @Override // Binder call createVirtualDisplay(IVirtualDisplayCallback callback, IMediaProjection projection, String packageName, String name, int width, int height, int densityDpi, Surface surface, int flags)1388 public int createVirtualDisplay(IVirtualDisplayCallback callback, 1389 IMediaProjection projection, String packageName, String name, 1390 int width, int height, int densityDpi, Surface surface, int flags) { 1391 final int callingUid = Binder.getCallingUid(); 1392 if (!validatePackageName(callingUid, packageName)) { 1393 throw new SecurityException("packageName must match the calling uid"); 1394 } 1395 if (callback == null) { 1396 throw new IllegalArgumentException("appToken must not be null"); 1397 } 1398 if (TextUtils.isEmpty(name)) { 1399 throw new IllegalArgumentException("name must be non-null and non-empty"); 1400 } 1401 if (width <= 0 || height <= 0 || densityDpi <= 0) { 1402 throw new IllegalArgumentException("width, height, and densityDpi must be " 1403 + "greater than 0"); 1404 } 1405 1406 if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) { 1407 flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; 1408 } 1409 if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) { 1410 flags &= ~DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; 1411 } 1412 1413 if (projection != null) { 1414 try { 1415 if (!getProjectionService().isValidMediaProjection(projection)) { 1416 throw new SecurityException("Invalid media projection"); 1417 } 1418 flags = projection.applyVirtualDisplayFlags(flags); 1419 } catch (RemoteException e) { 1420 throw new SecurityException("unable to validate media projection or flags"); 1421 } 1422 } 1423 1424 if (callingUid != Process.SYSTEM_UID && 1425 (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) { 1426 if (!canProjectVideo(projection)) { 1427 throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or " 1428 + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate " 1429 + "MediaProjection token in order to create a screen sharing virtual " 1430 + "display."); 1431 } 1432 } 1433 if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) { 1434 if (!canProjectSecureVideo(projection)) { 1435 throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT " 1436 + "or an appropriate MediaProjection token to create a " 1437 + "secure virtual display."); 1438 } 1439 } 1440 1441 final long token = Binder.clearCallingIdentity(); 1442 try { 1443 return createVirtualDisplayInternal(callback, projection, callingUid, 1444 packageName, name, width, height, densityDpi, surface, flags); 1445 } finally { 1446 Binder.restoreCallingIdentity(token); 1447 } 1448 } 1449 1450 @Override // Binder call resizeVirtualDisplay(IVirtualDisplayCallback callback, int width, int height, int densityDpi)1451 public void resizeVirtualDisplay(IVirtualDisplayCallback callback, 1452 int width, int height, int densityDpi) { 1453 final long token = Binder.clearCallingIdentity(); 1454 try { 1455 resizeVirtualDisplayInternal(callback.asBinder(), width, height, densityDpi); 1456 } finally { 1457 Binder.restoreCallingIdentity(token); 1458 } 1459 } 1460 1461 @Override // Binder call setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface)1462 public void setVirtualDisplaySurface(IVirtualDisplayCallback callback, Surface surface) { 1463 final long token = Binder.clearCallingIdentity(); 1464 try { 1465 setVirtualDisplaySurfaceInternal(callback.asBinder(), surface); 1466 } finally { 1467 Binder.restoreCallingIdentity(token); 1468 } 1469 } 1470 1471 @Override // Binder call releaseVirtualDisplay(IVirtualDisplayCallback callback)1472 public void releaseVirtualDisplay(IVirtualDisplayCallback callback) { 1473 final long token = Binder.clearCallingIdentity(); 1474 try { 1475 releaseVirtualDisplayInternal(callback.asBinder()); 1476 } finally { 1477 Binder.restoreCallingIdentity(token); 1478 } 1479 } 1480 1481 @Override // Binder call dump(FileDescriptor fd, final PrintWriter pw, String[] args)1482 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 1483 if (mContext == null 1484 || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) 1485 != PackageManager.PERMISSION_GRANTED) { 1486 pw.println("Permission Denial: can't dump DisplayManager from from pid=" 1487 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 1488 return; 1489 } 1490 1491 final long token = Binder.clearCallingIdentity(); 1492 try { 1493 dumpInternal(pw); 1494 } finally { 1495 Binder.restoreCallingIdentity(token); 1496 } 1497 } 1498 validatePackageName(int uid, String packageName)1499 private boolean validatePackageName(int uid, String packageName) { 1500 if (packageName != null) { 1501 String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid); 1502 if (packageNames != null) { 1503 for (String n : packageNames) { 1504 if (n.equals(packageName)) { 1505 return true; 1506 } 1507 } 1508 } 1509 } 1510 return false; 1511 } 1512 canProjectVideo(IMediaProjection projection)1513 private boolean canProjectVideo(IMediaProjection projection) { 1514 if (projection != null) { 1515 try { 1516 if (projection.canProjectVideo()) { 1517 return true; 1518 } 1519 } catch (RemoteException e) { 1520 Slog.e(TAG, "Unable to query projection service for permissions", e); 1521 } 1522 } 1523 if (mContext.checkCallingPermission( 1524 android.Manifest.permission.CAPTURE_VIDEO_OUTPUT) 1525 == PackageManager.PERMISSION_GRANTED) { 1526 return true; 1527 } 1528 return canProjectSecureVideo(projection); 1529 } 1530 canProjectSecureVideo(IMediaProjection projection)1531 private boolean canProjectSecureVideo(IMediaProjection projection) { 1532 if (projection != null) { 1533 try { 1534 if (projection.canProjectSecureVideo()){ 1535 return true; 1536 } 1537 } catch (RemoteException e) { 1538 Slog.e(TAG, "Unable to query projection service for permissions", e); 1539 } 1540 } 1541 return mContext.checkCallingPermission( 1542 android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT) 1543 == PackageManager.PERMISSION_GRANTED; 1544 } 1545 } 1546 1547 private final class LocalService extends DisplayManagerInternal { 1548 @Override initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler, SensorManager sensorManager)1549 public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler, 1550 SensorManager sensorManager) { 1551 synchronized (mSyncRoot) { 1552 DisplayBlanker blanker = new DisplayBlanker() { 1553 @Override 1554 public void requestDisplayState(int state, int brightness) { 1555 // The order of operations is important for legacy reasons. 1556 if (state == Display.STATE_OFF) { 1557 requestGlobalDisplayStateInternal(state, brightness); 1558 } 1559 1560 callbacks.onDisplayStateChange(state); 1561 1562 if (state != Display.STATE_OFF) { 1563 requestGlobalDisplayStateInternal(state, brightness); 1564 } 1565 } 1566 }; 1567 mDisplayPowerController = new DisplayPowerController( 1568 mContext, callbacks, handler, sensorManager, blanker); 1569 } 1570 } 1571 1572 @Override requestPowerState(DisplayPowerRequest request, boolean waitForNegativeProximity)1573 public boolean requestPowerState(DisplayPowerRequest request, 1574 boolean waitForNegativeProximity) { 1575 return mDisplayPowerController.requestPowerState(request, 1576 waitForNegativeProximity); 1577 } 1578 1579 @Override isProximitySensorAvailable()1580 public boolean isProximitySensorAvailable() { 1581 return mDisplayPowerController.isProximitySensorAvailable(); 1582 } 1583 1584 @Override getDisplayInfo(int displayId)1585 public DisplayInfo getDisplayInfo(int displayId) { 1586 return getDisplayInfoInternal(displayId, Process.myUid()); 1587 } 1588 1589 @Override registerDisplayTransactionListener(DisplayTransactionListener listener)1590 public void registerDisplayTransactionListener(DisplayTransactionListener listener) { 1591 if (listener == null) { 1592 throw new IllegalArgumentException("listener must not be null"); 1593 } 1594 1595 registerDisplayTransactionListenerInternal(listener); 1596 } 1597 1598 @Override unregisterDisplayTransactionListener(DisplayTransactionListener listener)1599 public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) { 1600 if (listener == null) { 1601 throw new IllegalArgumentException("listener must not be null"); 1602 } 1603 1604 unregisterDisplayTransactionListenerInternal(listener); 1605 } 1606 1607 @Override setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info)1608 public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) { 1609 setDisplayInfoOverrideFromWindowManagerInternal(displayId, info); 1610 } 1611 1612 @Override performTraversalInTransactionFromWindowManager()1613 public void performTraversalInTransactionFromWindowManager() { 1614 performTraversalInTransactionFromWindowManagerInternal(); 1615 } 1616 1617 @Override setDisplayProperties(int displayId, boolean hasContent, float requestedRefreshRate, int requestedMode, boolean inTraversal)1618 public void setDisplayProperties(int displayId, boolean hasContent, 1619 float requestedRefreshRate, int requestedMode, boolean inTraversal) { 1620 setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate, 1621 requestedMode, inTraversal); 1622 } 1623 1624 @Override setDisplayOffsets(int displayId, int x, int y)1625 public void setDisplayOffsets(int displayId, int x, int y) { 1626 setDisplayOffsetsInternal(displayId, x, y); 1627 } 1628 } 1629 } 1630