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