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