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