DisplayManagerService.java revision 0ccc2b0a4466f12fb1d753b58314854674b01b3c
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 setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface) { 527 synchronized (mSyncRoot) { 528 if (mVirtualDisplayAdapter == null) { 529 return; 530 } 531 532 mVirtualDisplayAdapter.setVirtualDisplaySurfaceLocked(appToken, surface); 533 } 534 } 535 536 private void releaseVirtualDisplayInternal(IBinder appToken) { 537 synchronized (mSyncRoot) { 538 if (mVirtualDisplayAdapter == null) { 539 return; 540 } 541 542 DisplayDevice device = 543 mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken); 544 if (device != null) { 545 handleDisplayDeviceRemovedLocked(device); 546 } 547 } 548 } 549 550 private void registerDefaultDisplayAdapter() { 551 // Register default display adapter. 552 synchronized (mSyncRoot) { 553 registerDisplayAdapterLocked(new LocalDisplayAdapter( 554 mSyncRoot, mContext, mHandler, mDisplayAdapterListener)); 555 } 556 } 557 558 private void registerAdditionalDisplayAdapters() { 559 synchronized (mSyncRoot) { 560 if (shouldRegisterNonEssentialDisplayAdaptersLocked()) { 561 registerOverlayDisplayAdapterLocked(); 562 registerWifiDisplayAdapterLocked(); 563 registerVirtualDisplayAdapterLocked(); 564 } 565 } 566 } 567 568 private void registerOverlayDisplayAdapterLocked() { 569 registerDisplayAdapterLocked(new OverlayDisplayAdapter( 570 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler)); 571 } 572 573 private void registerWifiDisplayAdapterLocked() { 574 if (mContext.getResources().getBoolean( 575 com.android.internal.R.bool.config_enableWifiDisplay) 576 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) { 577 mWifiDisplayAdapter = new WifiDisplayAdapter( 578 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, 579 mPersistentDataStore); 580 registerDisplayAdapterLocked(mWifiDisplayAdapter); 581 } 582 } 583 584 private void registerVirtualDisplayAdapterLocked() { 585 mVirtualDisplayAdapter = new VirtualDisplayAdapter( 586 mSyncRoot, mContext, mHandler, mDisplayAdapterListener); 587 registerDisplayAdapterLocked(mVirtualDisplayAdapter); 588 } 589 590 private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() { 591 // In safe mode, we disable non-essential display adapters to give the user 592 // an opportunity to fix broken settings or other problems that might affect 593 // system stability. 594 // In only-core mode, we disable non-essential display adapters to minimize 595 // the number of dependencies that are started while in this mode and to 596 // prevent problems that might occur due to the device being encrypted. 597 return !mSafeMode && !mOnlyCore; 598 } 599 600 private void registerDisplayAdapterLocked(DisplayAdapter adapter) { 601 mDisplayAdapters.add(adapter); 602 adapter.registerLocked(); 603 } 604 605 private void handleDisplayDeviceAdded(DisplayDevice device) { 606 synchronized (mSyncRoot) { 607 handleDisplayDeviceAddedLocked(device); 608 } 609 } 610 611 private void handleDisplayDeviceAddedLocked(DisplayDevice device) { 612 if (mDisplayDevices.contains(device)) { 613 Slog.w(TAG, "Attempted to add already added display device: " 614 + device.getDisplayDeviceInfoLocked()); 615 return; 616 } 617 618 Slog.i(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked()); 619 620 mDisplayDevices.add(device); 621 addLogicalDisplayLocked(device); 622 updateDisplayStateLocked(device); 623 scheduleTraversalLocked(false); 624 } 625 626 private void handleDisplayDeviceChanged(DisplayDevice device) { 627 synchronized (mSyncRoot) { 628 if (!mDisplayDevices.contains(device)) { 629 Slog.w(TAG, "Attempted to change non-existent display device: " 630 + device.getDisplayDeviceInfoLocked()); 631 return; 632 } 633 634 Slog.i(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked()); 635 636 device.applyPendingDisplayDeviceInfoChangesLocked(); 637 if (updateLogicalDisplaysLocked()) { 638 scheduleTraversalLocked(false); 639 } 640 } 641 } 642 643 private void handleDisplayDeviceRemoved(DisplayDevice device) { 644 synchronized (mSyncRoot) { 645 handleDisplayDeviceRemovedLocked(device); 646 } 647 } 648 private void handleDisplayDeviceRemovedLocked(DisplayDevice device) { 649 if (!mDisplayDevices.remove(device)) { 650 Slog.w(TAG, "Attempted to remove non-existent display device: " 651 + device.getDisplayDeviceInfoLocked()); 652 return; 653 } 654 655 Slog.i(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked()); 656 657 updateLogicalDisplaysLocked(); 658 scheduleTraversalLocked(false); 659 } 660 661 private void updateGlobalDisplayStateLocked() { 662 final int count = mDisplayDevices.size(); 663 for (int i = 0; i < count; i++) { 664 DisplayDevice device = mDisplayDevices.get(i); 665 updateDisplayStateLocked(device); 666 } 667 } 668 669 private void updateDisplayStateLocked(DisplayDevice device) { 670 // Blank or unblank the display immediately to match the state requested 671 // by the display power controller (if known). 672 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 673 if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) { 674 device.requestDisplayStateLocked(mGlobalDisplayState); 675 } 676 } 677 678 // Adds a new logical display based on the given display device. 679 // Sends notifications if needed. 680 private void addLogicalDisplayLocked(DisplayDevice device) { 681 DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked(); 682 boolean isDefault = (deviceInfo.flags 683 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0; 684 if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) { 685 Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo); 686 isDefault = false; 687 } 688 689 if (!isDefault && mSingleDisplayDemoMode) { 690 Slog.i(TAG, "Not creating a logical display for a secondary display " 691 + " because single display demo mode is enabled: " + deviceInfo); 692 return; 693 } 694 695 final int displayId = assignDisplayIdLocked(isDefault); 696 final int layerStack = assignLayerStackLocked(displayId); 697 698 LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device); 699 display.updateLocked(mDisplayDevices); 700 if (!display.isValidLocked()) { 701 // This should never happen currently. 702 Slog.w(TAG, "Ignoring display device because the logical display " 703 + "created from it was not considered valid: " + deviceInfo); 704 return; 705 } 706 707 mLogicalDisplays.put(displayId, display); 708 709 // Wake up waitForDefaultDisplay. 710 if (isDefault) { 711 mSyncRoot.notifyAll(); 712 } 713 714 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED); 715 } 716 717 private int assignDisplayIdLocked(boolean isDefault) { 718 return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++; 719 } 720 721 private int assignLayerStackLocked(int displayId) { 722 // Currently layer stacks and display ids are the same. 723 // This need not be the case. 724 return displayId; 725 } 726 727 // Updates all existing logical displays given the current set of display devices. 728 // Removes invalid logical displays. 729 // Sends notifications if needed. 730 private boolean updateLogicalDisplaysLocked() { 731 boolean changed = false; 732 for (int i = mLogicalDisplays.size(); i-- > 0; ) { 733 final int displayId = mLogicalDisplays.keyAt(i); 734 LogicalDisplay display = mLogicalDisplays.valueAt(i); 735 736 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked()); 737 display.updateLocked(mDisplayDevices); 738 if (!display.isValidLocked()) { 739 mLogicalDisplays.removeAt(i); 740 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED); 741 changed = true; 742 } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) { 743 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); 744 changed = true; 745 } 746 } 747 return changed; 748 } 749 750 private void performTraversalInTransactionLocked() { 751 // Clear all viewports before configuring displays so that we can keep 752 // track of which ones we have configured. 753 clearViewportsLocked(); 754 755 // Configure each display device. 756 final int count = mDisplayDevices.size(); 757 for (int i = 0; i < count; i++) { 758 DisplayDevice device = mDisplayDevices.get(i); 759 configureDisplayInTransactionLocked(device); 760 device.performTraversalInTransactionLocked(); 761 } 762 763 // Tell the input system about these new viewports. 764 if (mInputManagerInternal != null) { 765 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT); 766 } 767 } 768 769 private void setDisplayHasContentInternal(int displayId, boolean hasContent, 770 boolean inTraversal) { 771 synchronized (mSyncRoot) { 772 LogicalDisplay display = mLogicalDisplays.get(displayId); 773 if (display != null && display.hasContentLocked() != hasContent) { 774 if (DEBUG) { 775 Slog.d(TAG, "Display " + displayId + " hasContent flag changed: " 776 + "hasContent=" + hasContent + ", inTraversal=" + inTraversal); 777 } 778 779 display.setHasContentLocked(hasContent); 780 scheduleTraversalLocked(inTraversal); 781 } 782 } 783 } 784 785 private void clearViewportsLocked() { 786 mDefaultViewport.valid = false; 787 mExternalTouchViewport.valid = false; 788 } 789 790 private void configureDisplayInTransactionLocked(DisplayDevice device) { 791 final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 792 final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0; 793 794 // Find the logical display that the display device is showing. 795 // Certain displays only ever show their own content. 796 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device); 797 if (!ownContent) { 798 if (display != null && !display.hasContentLocked()) { 799 // If the display does not have any content of its own, then 800 // automatically mirror the default logical display contents. 801 display = null; 802 } 803 if (display == null) { 804 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY); 805 } 806 } 807 808 // Apply the logical display configuration to the display device. 809 if (display == null) { 810 // TODO: no logical display for the device, blank it 811 Slog.w(TAG, "Missing logical display to use for physical display device: " 812 + device.getDisplayDeviceInfoLocked()); 813 return; 814 } 815 display.configureDisplayInTransactionLocked(device, info.state == Display.STATE_OFF); 816 817 // Update the viewports if needed. 818 if (!mDefaultViewport.valid 819 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) { 820 setViewportLocked(mDefaultViewport, display, device); 821 } 822 if (!mExternalTouchViewport.valid 823 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) { 824 setViewportLocked(mExternalTouchViewport, display, device); 825 } 826 } 827 828 private static void setViewportLocked(DisplayViewport viewport, 829 LogicalDisplay display, DisplayDevice device) { 830 viewport.valid = true; 831 viewport.displayId = display.getDisplayIdLocked(); 832 device.populateViewportLocked(viewport); 833 } 834 835 private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) { 836 final int count = mLogicalDisplays.size(); 837 for (int i = 0; i < count; i++) { 838 LogicalDisplay display = mLogicalDisplays.valueAt(i); 839 if (display.getPrimaryDisplayDeviceLocked() == device) { 840 return display; 841 } 842 } 843 return null; 844 } 845 846 private void sendDisplayEventLocked(int displayId, int event) { 847 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event); 848 mHandler.sendMessage(msg); 849 } 850 851 // Requests that performTraversalsInTransactionFromWindowManager be called at a 852 // later time to apply changes to surfaces and displays. 853 private void scheduleTraversalLocked(boolean inTraversal) { 854 if (!mPendingTraversal && mWindowManagerInternal != null) { 855 mPendingTraversal = true; 856 if (!inTraversal) { 857 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL); 858 } 859 } 860 } 861 862 // Runs on Handler thread. 863 // Delivers display event notifications to callbacks. 864 private void deliverDisplayEvent(int displayId, int event) { 865 if (DEBUG) { 866 Slog.d(TAG, "Delivering display event: displayId=" 867 + displayId + ", event=" + event); 868 } 869 870 // Grab the lock and copy the callbacks. 871 final int count; 872 synchronized (mSyncRoot) { 873 count = mCallbacks.size(); 874 mTempCallbacks.clear(); 875 for (int i = 0; i < count; i++) { 876 mTempCallbacks.add(mCallbacks.valueAt(i)); 877 } 878 } 879 880 // After releasing the lock, send the notifications out. 881 for (int i = 0; i < count; i++) { 882 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event); 883 } 884 mTempCallbacks.clear(); 885 } 886 887 private IMediaProjectionManager getProjectionService() { 888 if (mProjectionService == null) { 889 IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE); 890 mProjectionService = IMediaProjectionManager.Stub.asInterface(b); 891 } 892 return mProjectionService; 893 } 894 895 private void dumpInternal(PrintWriter pw) { 896 pw.println("DISPLAY MANAGER (dumpsys display)"); 897 898 synchronized (mSyncRoot) { 899 pw.println(" mOnlyCode=" + mOnlyCore); 900 pw.println(" mSafeMode=" + mSafeMode); 901 pw.println(" mPendingTraversal=" + mPendingTraversal); 902 pw.println(" mGlobalDisplayState=" + Display.stateToString(mGlobalDisplayState)); 903 pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId); 904 pw.println(" mDefaultViewport=" + mDefaultViewport); 905 pw.println(" mExternalTouchViewport=" + mExternalTouchViewport); 906 pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode); 907 pw.println(" mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount); 908 909 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 910 ipw.increaseIndent(); 911 912 pw.println(); 913 pw.println("Display Adapters: size=" + mDisplayAdapters.size()); 914 for (DisplayAdapter adapter : mDisplayAdapters) { 915 pw.println(" " + adapter.getName()); 916 adapter.dumpLocked(ipw); 917 } 918 919 pw.println(); 920 pw.println("Display Devices: size=" + mDisplayDevices.size()); 921 for (DisplayDevice device : mDisplayDevices) { 922 pw.println(" " + device.getDisplayDeviceInfoLocked()); 923 device.dumpLocked(ipw); 924 } 925 926 final int logicalDisplayCount = mLogicalDisplays.size(); 927 pw.println(); 928 pw.println("Logical Displays: size=" + logicalDisplayCount); 929 for (int i = 0; i < logicalDisplayCount; i++) { 930 int displayId = mLogicalDisplays.keyAt(i); 931 LogicalDisplay display = mLogicalDisplays.valueAt(i); 932 pw.println(" Display " + displayId + ":"); 933 display.dumpLocked(ipw); 934 } 935 936 final int callbackCount = mCallbacks.size(); 937 pw.println(); 938 pw.println("Callbacks: size=" + callbackCount); 939 for (int i = 0; i < callbackCount; i++) { 940 CallbackRecord callback = mCallbacks.valueAt(i); 941 pw.println(" " + i + ": mPid=" + callback.mPid 942 + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested); 943 } 944 945 if (mDisplayPowerController != null) { 946 mDisplayPowerController.dump(pw); 947 } 948 } 949 } 950 951 /** 952 * This is the object that everything in the display manager locks on. 953 * We make it an inner class within the {@link DisplayManagerService} to so that it is 954 * clear that the object belongs to the display manager service and that it is 955 * a unique object with a special purpose. 956 */ 957 public static final class SyncRoot { 958 } 959 960 private final class DisplayManagerHandler extends Handler { 961 public DisplayManagerHandler(Looper looper) { 962 super(looper, null, true /*async*/); 963 } 964 965 @Override 966 public void handleMessage(Message msg) { 967 switch (msg.what) { 968 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER: 969 registerDefaultDisplayAdapter(); 970 break; 971 972 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS: 973 registerAdditionalDisplayAdapters(); 974 break; 975 976 case MSG_DELIVER_DISPLAY_EVENT: 977 deliverDisplayEvent(msg.arg1, msg.arg2); 978 break; 979 980 case MSG_REQUEST_TRAVERSAL: 981 mWindowManagerInternal.requestTraversalFromDisplayManager(); 982 break; 983 984 case MSG_UPDATE_VIEWPORT: { 985 synchronized (mSyncRoot) { 986 mTempDefaultViewport.copyFrom(mDefaultViewport); 987 mTempExternalTouchViewport.copyFrom(mExternalTouchViewport); 988 } 989 mInputManagerInternal.setDisplayViewports( 990 mTempDefaultViewport, mTempExternalTouchViewport); 991 break; 992 } 993 } 994 } 995 } 996 997 private final class DisplayAdapterListener implements DisplayAdapter.Listener { 998 @Override 999 public void onDisplayDeviceEvent(DisplayDevice device, int event) { 1000 switch (event) { 1001 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED: 1002 handleDisplayDeviceAdded(device); 1003 break; 1004 1005 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED: 1006 handleDisplayDeviceChanged(device); 1007 break; 1008 1009 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED: 1010 handleDisplayDeviceRemoved(device); 1011 break; 1012 } 1013 } 1014 1015 @Override 1016 public void onTraversalRequested() { 1017 synchronized (mSyncRoot) { 1018 scheduleTraversalLocked(false); 1019 } 1020 } 1021 } 1022 1023 private final class CallbackRecord implements DeathRecipient { 1024 public final int mPid; 1025 private final IDisplayManagerCallback mCallback; 1026 1027 public boolean mWifiDisplayScanRequested; 1028 1029 public CallbackRecord(int pid, IDisplayManagerCallback callback) { 1030 mPid = pid; 1031 mCallback = callback; 1032 } 1033 1034 @Override 1035 public void binderDied() { 1036 if (DEBUG) { 1037 Slog.d(TAG, "Display listener for pid " + mPid + " died."); 1038 } 1039 onCallbackDied(this); 1040 } 1041 1042 public void notifyDisplayEventAsync(int displayId, int event) { 1043 try { 1044 mCallback.onDisplayEvent(displayId, event); 1045 } catch (RemoteException ex) { 1046 Slog.w(TAG, "Failed to notify process " 1047 + mPid + " that displays changed, assuming it died.", ex); 1048 binderDied(); 1049 } 1050 } 1051 } 1052 1053 private final class BinderService extends IDisplayManager.Stub { 1054 /** 1055 * Returns information about the specified logical display. 1056 * 1057 * @param displayId The logical display id. 1058 * @return The logical display info, or null if the display does not exist. The 1059 * returned object must be treated as immutable. 1060 */ 1061 @Override // Binder call 1062 public DisplayInfo getDisplayInfo(int displayId) { 1063 final int callingUid = Binder.getCallingUid(); 1064 final long token = Binder.clearCallingIdentity(); 1065 try { 1066 return getDisplayInfoInternal(displayId, callingUid); 1067 } finally { 1068 Binder.restoreCallingIdentity(token); 1069 } 1070 } 1071 1072 /** 1073 * Returns the list of all display ids. 1074 */ 1075 @Override // Binder call 1076 public int[] getDisplayIds() { 1077 final int callingUid = Binder.getCallingUid(); 1078 final long token = Binder.clearCallingIdentity(); 1079 try { 1080 return getDisplayIdsInternal(callingUid); 1081 } finally { 1082 Binder.restoreCallingIdentity(token); 1083 } 1084 } 1085 1086 @Override // Binder call 1087 public void registerCallback(IDisplayManagerCallback callback) { 1088 if (callback == null) { 1089 throw new IllegalArgumentException("listener must not be null"); 1090 } 1091 1092 final int callingPid = Binder.getCallingPid(); 1093 final long token = Binder.clearCallingIdentity(); 1094 try { 1095 registerCallbackInternal(callback, callingPid); 1096 } finally { 1097 Binder.restoreCallingIdentity(token); 1098 } 1099 } 1100 1101 @Override // Binder call 1102 public void startWifiDisplayScan() { 1103 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1104 "Permission required to start wifi display scans"); 1105 1106 final int callingPid = Binder.getCallingPid(); 1107 final long token = Binder.clearCallingIdentity(); 1108 try { 1109 startWifiDisplayScanInternal(callingPid); 1110 } finally { 1111 Binder.restoreCallingIdentity(token); 1112 } 1113 } 1114 1115 @Override // Binder call 1116 public void stopWifiDisplayScan() { 1117 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1118 "Permission required to stop wifi display scans"); 1119 1120 final int callingPid = Binder.getCallingPid(); 1121 final long token = Binder.clearCallingIdentity(); 1122 try { 1123 stopWifiDisplayScanInternal(callingPid); 1124 } finally { 1125 Binder.restoreCallingIdentity(token); 1126 } 1127 } 1128 1129 @Override // Binder call 1130 public void connectWifiDisplay(String address) { 1131 if (address == null) { 1132 throw new IllegalArgumentException("address must not be null"); 1133 } 1134 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1135 "Permission required to connect to a wifi display"); 1136 1137 final long token = Binder.clearCallingIdentity(); 1138 try { 1139 connectWifiDisplayInternal(address); 1140 } finally { 1141 Binder.restoreCallingIdentity(token); 1142 } 1143 } 1144 1145 @Override // Binder call 1146 public void disconnectWifiDisplay() { 1147 // This request does not require special permissions. 1148 // Any app can request disconnection from the currently active wifi display. 1149 // This exception should no longer be needed once wifi display control moves 1150 // to the media router service. 1151 1152 final long token = Binder.clearCallingIdentity(); 1153 try { 1154 disconnectWifiDisplayInternal(); 1155 } finally { 1156 Binder.restoreCallingIdentity(token); 1157 } 1158 } 1159 1160 @Override // Binder call 1161 public void renameWifiDisplay(String address, String alias) { 1162 if (address == null) { 1163 throw new IllegalArgumentException("address must not be null"); 1164 } 1165 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1166 "Permission required to rename to a wifi display"); 1167 1168 final long token = Binder.clearCallingIdentity(); 1169 try { 1170 renameWifiDisplayInternal(address, alias); 1171 } finally { 1172 Binder.restoreCallingIdentity(token); 1173 } 1174 } 1175 1176 @Override // Binder call 1177 public void forgetWifiDisplay(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 forget to a wifi display"); 1183 1184 final long token = Binder.clearCallingIdentity(); 1185 try { 1186 forgetWifiDisplayInternal(address); 1187 } finally { 1188 Binder.restoreCallingIdentity(token); 1189 } 1190 } 1191 1192 @Override // Binder call 1193 public void pauseWifiDisplay() { 1194 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1195 "Permission required to pause a wifi display session"); 1196 1197 final long token = Binder.clearCallingIdentity(); 1198 try { 1199 pauseWifiDisplayInternal(); 1200 } finally { 1201 Binder.restoreCallingIdentity(token); 1202 } 1203 } 1204 1205 @Override // Binder call 1206 public void resumeWifiDisplay() { 1207 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1208 "Permission required to resume a wifi display session"); 1209 1210 final long token = Binder.clearCallingIdentity(); 1211 try { 1212 resumeWifiDisplayInternal(); 1213 } finally { 1214 Binder.restoreCallingIdentity(token); 1215 } 1216 } 1217 1218 @Override // Binder call 1219 public WifiDisplayStatus getWifiDisplayStatus() { 1220 // This request does not require special permissions. 1221 // Any app can get information about available wifi displays. 1222 1223 final long token = Binder.clearCallingIdentity(); 1224 try { 1225 return getWifiDisplayStatusInternal(); 1226 } finally { 1227 Binder.restoreCallingIdentity(token); 1228 } 1229 } 1230 1231 @Override // Binder call 1232 public int createVirtualDisplay(IVirtualDisplayCallbacks callbacks, 1233 IMediaProjection projection, String packageName, String name, 1234 int width, int height, int densityDpi, Surface surface, int flags) { 1235 final int callingUid = Binder.getCallingUid(); 1236 if (!validatePackageName(callingUid, packageName)) { 1237 throw new SecurityException("packageName must match the calling uid"); 1238 } 1239 if (callbacks == null) { 1240 throw new IllegalArgumentException("appToken must not be null"); 1241 } 1242 if (TextUtils.isEmpty(name)) { 1243 throw new IllegalArgumentException("name must be non-null and non-empty"); 1244 } 1245 if (width <= 0 || height <= 0 || densityDpi <= 0) { 1246 throw new IllegalArgumentException("width, height, and densityDpi must be " 1247 + "greater than 0"); 1248 } 1249 1250 if (projection != null) { 1251 try { 1252 if (!getProjectionService().isValidMediaProjection(projection)) { 1253 throw new SecurityException("Invalid media projection"); 1254 } 1255 } catch (RemoteException e) { 1256 throw new SecurityException("unable to validate media projection"); 1257 } 1258 flags &= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE; 1259 try { 1260 flags |= projection.getVirtualDisplayFlags(); 1261 } catch (RemoteException e) { 1262 throw new RuntimeException("unable to retrieve media projection flags"); 1263 } 1264 } 1265 1266 if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SCREEN_SHARE) != 0) { 1267 if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0 || 1268 (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION) != 0) { 1269 throw new IllegalArgumentException("screen sharing virtual displays must not " 1270 + "be public or presentation displays"); 1271 } 1272 if (!canProjectVideo(projection)) { 1273 throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or " 1274 + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate " 1275 + "MediaProjection token in order to create a screen sharing virtual " 1276 + "display."); 1277 } 1278 } 1279 1280 1281 if (callingUid != Process.SYSTEM_UID && 1282 (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) { 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 to create a public virtual display."); 1287 } 1288 } 1289 if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) { 1290 if (!canProjectSecureVideo(projection)) { 1291 throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT " 1292 + "or an appropriate MediaProjection token to create a " 1293 + "secure virtual display."); 1294 } 1295 } 1296 1297 final long token = Binder.clearCallingIdentity(); 1298 try { 1299 return createVirtualDisplayInternal(callbacks, projection, callingUid, 1300 packageName, name, width, height, densityDpi, surface, flags); 1301 } finally { 1302 Binder.restoreCallingIdentity(token); 1303 } 1304 } 1305 1306 @Override // Binder call 1307 public void setVirtualDisplaySurface(IVirtualDisplayCallbacks callbacks, Surface surface) { 1308 final long token = Binder.clearCallingIdentity(); 1309 try { 1310 setVirtualDisplaySurfaceInternal(callbacks.asBinder(), surface); 1311 } finally { 1312 Binder.restoreCallingIdentity(token); 1313 } 1314 } 1315 1316 @Override // Binder call 1317 public void releaseVirtualDisplay(IVirtualDisplayCallbacks callbacks) { 1318 final long token = Binder.clearCallingIdentity(); 1319 try { 1320 releaseVirtualDisplayInternal(callbacks.asBinder()); 1321 } finally { 1322 Binder.restoreCallingIdentity(token); 1323 } 1324 } 1325 1326 @Override // Binder call 1327 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 1328 if (mContext == null 1329 || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) 1330 != PackageManager.PERMISSION_GRANTED) { 1331 pw.println("Permission Denial: can't dump DisplayManager from from pid=" 1332 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 1333 return; 1334 } 1335 1336 final long token = Binder.clearCallingIdentity(); 1337 try { 1338 dumpInternal(pw); 1339 } finally { 1340 Binder.restoreCallingIdentity(token); 1341 } 1342 } 1343 1344 private boolean validatePackageName(int uid, String packageName) { 1345 if (packageName != null) { 1346 String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid); 1347 if (packageNames != null) { 1348 for (String n : packageNames) { 1349 if (n.equals(packageName)) { 1350 return true; 1351 } 1352 } 1353 } 1354 } 1355 return false; 1356 } 1357 1358 private boolean canProjectVideo(IMediaProjection projection) { 1359 if (projection != null) { 1360 try { 1361 if (projection.canProjectVideo()) { 1362 return true; 1363 } 1364 } catch (RemoteException e) { 1365 Slog.e(TAG, "Unable to query projection service for permissions", e); 1366 } 1367 } 1368 if (mContext.checkCallingPermission( 1369 android.Manifest.permission.CAPTURE_VIDEO_OUTPUT) 1370 == PackageManager.PERMISSION_GRANTED) { 1371 return true; 1372 } 1373 return canProjectSecureVideo(projection); 1374 } 1375 1376 private boolean canProjectSecureVideo(IMediaProjection projection) { 1377 if (projection != null) { 1378 try { 1379 if (projection.canProjectSecureVideo()){ 1380 return true; 1381 } 1382 } catch (RemoteException e) { 1383 Slog.e(TAG, "Unable to query projection service for permissions", e); 1384 } 1385 } 1386 return mContext.checkCallingPermission( 1387 android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT) 1388 == PackageManager.PERMISSION_GRANTED; 1389 } 1390 } 1391 1392 private final class LocalService extends DisplayManagerInternal { 1393 @Override 1394 public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler, 1395 SensorManager sensorManager) { 1396 synchronized (mSyncRoot) { 1397 DisplayBlanker blanker = new DisplayBlanker() { 1398 @Override 1399 public void requestDisplayState(int state) { 1400 // The order of operations is important for legacy reasons. 1401 if (state == Display.STATE_OFF) { 1402 requestGlobalDisplayStateInternal(state); 1403 } 1404 1405 callbacks.onDisplayStateChange(state); 1406 1407 if (state != Display.STATE_OFF) { 1408 requestGlobalDisplayStateInternal(state); 1409 } 1410 } 1411 }; 1412 mDisplayPowerController = new DisplayPowerController( 1413 mContext, callbacks, handler, sensorManager, blanker); 1414 } 1415 } 1416 1417 @Override 1418 public boolean requestPowerState(DisplayPowerRequest request, 1419 boolean waitForNegativeProximity) { 1420 return mDisplayPowerController.requestPowerState(request, 1421 waitForNegativeProximity); 1422 } 1423 1424 @Override 1425 public boolean isProximitySensorAvailable() { 1426 return mDisplayPowerController.isProximitySensorAvailable(); 1427 } 1428 1429 @Override 1430 public DisplayInfo getDisplayInfo(int displayId) { 1431 return getDisplayInfoInternal(displayId, Process.myUid()); 1432 } 1433 1434 @Override 1435 public void registerDisplayTransactionListener(DisplayTransactionListener listener) { 1436 if (listener == null) { 1437 throw new IllegalArgumentException("listener must not be null"); 1438 } 1439 1440 registerDisplayTransactionListenerInternal(listener); 1441 } 1442 1443 @Override 1444 public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) { 1445 if (listener == null) { 1446 throw new IllegalArgumentException("listener must not be null"); 1447 } 1448 1449 unregisterDisplayTransactionListenerInternal(listener); 1450 } 1451 1452 @Override 1453 public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) { 1454 setDisplayInfoOverrideFromWindowManagerInternal(displayId, info); 1455 } 1456 1457 @Override 1458 public void performTraversalInTransactionFromWindowManager() { 1459 performTraversalInTransactionFromWindowManagerInternal(); 1460 } 1461 1462 @Override 1463 public void setDisplayHasContent(int displayId, boolean hasContent, boolean inTraversal) { 1464 setDisplayHasContentInternal(displayId, hasContent, inTraversal); 1465 } 1466 } 1467} 1468