DisplayManagerService.java revision 3f145a2f958320766ae9240c7a57debc20d578aa
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 setDisplayPropertiesInternal(int displayId, boolean hasContent, 781 float requestedRefreshRate, boolean inTraversal) { 782 synchronized (mSyncRoot) { 783 LogicalDisplay display = mLogicalDisplays.get(displayId); 784 if (display == null) { 785 return; 786 } 787 if (display.hasContentLocked() != hasContent) { 788 if (DEBUG) { 789 Slog.d(TAG, "Display " + displayId + " hasContent flag changed: " 790 + "hasContent=" + hasContent + ", inTraversal=" + inTraversal); 791 } 792 793 display.setHasContentLocked(hasContent); 794 scheduleTraversalLocked(inTraversal); 795 } 796 if (display.getRequestedRefreshRateLocked() != requestedRefreshRate) { 797 if (DEBUG) { 798 Slog.d(TAG, "Display " + displayId + " has requested a new refresh rate: " 799 + requestedRefreshRate + "fps"); 800 } 801 display.setRequestedRefreshRateLocked(requestedRefreshRate); 802 scheduleTraversalLocked(inTraversal); 803 } 804 } 805 } 806 807 private void clearViewportsLocked() { 808 mDefaultViewport.valid = false; 809 mExternalTouchViewport.valid = false; 810 } 811 812 private void configureDisplayInTransactionLocked(DisplayDevice device) { 813 final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 814 final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0; 815 816 // Find the logical display that the display device is showing. 817 // Certain displays only ever show their own content. 818 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device); 819 if (!ownContent) { 820 if (display != null && !display.hasContentLocked()) { 821 // If the display does not have any content of its own, then 822 // automatically mirror the default logical display contents. 823 display = null; 824 } 825 if (display == null) { 826 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY); 827 } 828 } 829 830 // Apply the logical display configuration to the display device. 831 if (display == null) { 832 // TODO: no logical display for the device, blank it 833 Slog.w(TAG, "Missing logical display to use for physical display device: " 834 + device.getDisplayDeviceInfoLocked()); 835 return; 836 } 837 display.configureDisplayInTransactionLocked(device, info.state == Display.STATE_OFF); 838 839 // Update the viewports if needed. 840 if (!mDefaultViewport.valid 841 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) { 842 setViewportLocked(mDefaultViewport, display, device); 843 } 844 if (!mExternalTouchViewport.valid 845 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) { 846 setViewportLocked(mExternalTouchViewport, display, device); 847 } 848 } 849 850 private static void setViewportLocked(DisplayViewport viewport, 851 LogicalDisplay display, DisplayDevice device) { 852 viewport.valid = true; 853 viewport.displayId = display.getDisplayIdLocked(); 854 device.populateViewportLocked(viewport); 855 } 856 857 private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) { 858 final int count = mLogicalDisplays.size(); 859 for (int i = 0; i < count; i++) { 860 LogicalDisplay display = mLogicalDisplays.valueAt(i); 861 if (display.getPrimaryDisplayDeviceLocked() == device) { 862 return display; 863 } 864 } 865 return null; 866 } 867 868 private void sendDisplayEventLocked(int displayId, int event) { 869 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event); 870 mHandler.sendMessage(msg); 871 } 872 873 // Requests that performTraversalsInTransactionFromWindowManager be called at a 874 // later time to apply changes to surfaces and displays. 875 private void scheduleTraversalLocked(boolean inTraversal) { 876 if (!mPendingTraversal && mWindowManagerInternal != null) { 877 mPendingTraversal = true; 878 if (!inTraversal) { 879 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL); 880 } 881 } 882 } 883 884 // Runs on Handler thread. 885 // Delivers display event notifications to callbacks. 886 private void deliverDisplayEvent(int displayId, int event) { 887 if (DEBUG) { 888 Slog.d(TAG, "Delivering display event: displayId=" 889 + displayId + ", event=" + event); 890 } 891 892 // Grab the lock and copy the callbacks. 893 final int count; 894 synchronized (mSyncRoot) { 895 count = mCallbacks.size(); 896 mTempCallbacks.clear(); 897 for (int i = 0; i < count; i++) { 898 mTempCallbacks.add(mCallbacks.valueAt(i)); 899 } 900 } 901 902 // After releasing the lock, send the notifications out. 903 for (int i = 0; i < count; i++) { 904 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event); 905 } 906 mTempCallbacks.clear(); 907 } 908 909 private IMediaProjectionManager getProjectionService() { 910 if (mProjectionService == null) { 911 IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE); 912 mProjectionService = IMediaProjectionManager.Stub.asInterface(b); 913 } 914 return mProjectionService; 915 } 916 917 private void dumpInternal(PrintWriter pw) { 918 pw.println("DISPLAY MANAGER (dumpsys display)"); 919 920 synchronized (mSyncRoot) { 921 pw.println(" mOnlyCode=" + mOnlyCore); 922 pw.println(" mSafeMode=" + mSafeMode); 923 pw.println(" mPendingTraversal=" + mPendingTraversal); 924 pw.println(" mGlobalDisplayState=" + Display.stateToString(mGlobalDisplayState)); 925 pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId); 926 pw.println(" mDefaultViewport=" + mDefaultViewport); 927 pw.println(" mExternalTouchViewport=" + mExternalTouchViewport); 928 pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode); 929 pw.println(" mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount); 930 931 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 932 ipw.increaseIndent(); 933 934 pw.println(); 935 pw.println("Display Adapters: size=" + mDisplayAdapters.size()); 936 for (DisplayAdapter adapter : mDisplayAdapters) { 937 pw.println(" " + adapter.getName()); 938 adapter.dumpLocked(ipw); 939 } 940 941 pw.println(); 942 pw.println("Display Devices: size=" + mDisplayDevices.size()); 943 for (DisplayDevice device : mDisplayDevices) { 944 pw.println(" " + device.getDisplayDeviceInfoLocked()); 945 device.dumpLocked(ipw); 946 } 947 948 final int logicalDisplayCount = mLogicalDisplays.size(); 949 pw.println(); 950 pw.println("Logical Displays: size=" + logicalDisplayCount); 951 for (int i = 0; i < logicalDisplayCount; i++) { 952 int displayId = mLogicalDisplays.keyAt(i); 953 LogicalDisplay display = mLogicalDisplays.valueAt(i); 954 pw.println(" Display " + displayId + ":"); 955 display.dumpLocked(ipw); 956 } 957 958 final int callbackCount = mCallbacks.size(); 959 pw.println(); 960 pw.println("Callbacks: size=" + callbackCount); 961 for (int i = 0; i < callbackCount; i++) { 962 CallbackRecord callback = mCallbacks.valueAt(i); 963 pw.println(" " + i + ": mPid=" + callback.mPid 964 + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested); 965 } 966 967 if (mDisplayPowerController != null) { 968 mDisplayPowerController.dump(pw); 969 } 970 } 971 } 972 973 /** 974 * This is the object that everything in the display manager locks on. 975 * We make it an inner class within the {@link DisplayManagerService} to so that it is 976 * clear that the object belongs to the display manager service and that it is 977 * a unique object with a special purpose. 978 */ 979 public static final class SyncRoot { 980 } 981 982 private final class DisplayManagerHandler extends Handler { 983 public DisplayManagerHandler(Looper looper) { 984 super(looper, null, true /*async*/); 985 } 986 987 @Override 988 public void handleMessage(Message msg) { 989 switch (msg.what) { 990 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER: 991 registerDefaultDisplayAdapter(); 992 break; 993 994 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS: 995 registerAdditionalDisplayAdapters(); 996 break; 997 998 case MSG_DELIVER_DISPLAY_EVENT: 999 deliverDisplayEvent(msg.arg1, msg.arg2); 1000 break; 1001 1002 case MSG_REQUEST_TRAVERSAL: 1003 mWindowManagerInternal.requestTraversalFromDisplayManager(); 1004 break; 1005 1006 case MSG_UPDATE_VIEWPORT: { 1007 synchronized (mSyncRoot) { 1008 mTempDefaultViewport.copyFrom(mDefaultViewport); 1009 mTempExternalTouchViewport.copyFrom(mExternalTouchViewport); 1010 } 1011 mInputManagerInternal.setDisplayViewports( 1012 mTempDefaultViewport, mTempExternalTouchViewport); 1013 break; 1014 } 1015 } 1016 } 1017 } 1018 1019 private final class DisplayAdapterListener implements DisplayAdapter.Listener { 1020 @Override 1021 public void onDisplayDeviceEvent(DisplayDevice device, int event) { 1022 switch (event) { 1023 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED: 1024 handleDisplayDeviceAdded(device); 1025 break; 1026 1027 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED: 1028 handleDisplayDeviceChanged(device); 1029 break; 1030 1031 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED: 1032 handleDisplayDeviceRemoved(device); 1033 break; 1034 } 1035 } 1036 1037 @Override 1038 public void onTraversalRequested() { 1039 synchronized (mSyncRoot) { 1040 scheduleTraversalLocked(false); 1041 } 1042 } 1043 } 1044 1045 private final class CallbackRecord implements DeathRecipient { 1046 public final int mPid; 1047 private final IDisplayManagerCallback mCallback; 1048 1049 public boolean mWifiDisplayScanRequested; 1050 1051 public CallbackRecord(int pid, IDisplayManagerCallback callback) { 1052 mPid = pid; 1053 mCallback = callback; 1054 } 1055 1056 @Override 1057 public void binderDied() { 1058 if (DEBUG) { 1059 Slog.d(TAG, "Display listener for pid " + mPid + " died."); 1060 } 1061 onCallbackDied(this); 1062 } 1063 1064 public void notifyDisplayEventAsync(int displayId, int event) { 1065 try { 1066 mCallback.onDisplayEvent(displayId, event); 1067 } catch (RemoteException ex) { 1068 Slog.w(TAG, "Failed to notify process " 1069 + mPid + " that displays changed, assuming it died.", ex); 1070 binderDied(); 1071 } 1072 } 1073 } 1074 1075 private final class BinderService extends IDisplayManager.Stub { 1076 /** 1077 * Returns information about the specified logical display. 1078 * 1079 * @param displayId The logical display id. 1080 * @return The logical display info, or null if the display does not exist. The 1081 * returned object must be treated as immutable. 1082 */ 1083 @Override // Binder call 1084 public DisplayInfo getDisplayInfo(int displayId) { 1085 final int callingUid = Binder.getCallingUid(); 1086 final long token = Binder.clearCallingIdentity(); 1087 try { 1088 return getDisplayInfoInternal(displayId, callingUid); 1089 } finally { 1090 Binder.restoreCallingIdentity(token); 1091 } 1092 } 1093 1094 /** 1095 * Returns the list of all display ids. 1096 */ 1097 @Override // Binder call 1098 public int[] getDisplayIds() { 1099 final int callingUid = Binder.getCallingUid(); 1100 final long token = Binder.clearCallingIdentity(); 1101 try { 1102 return getDisplayIdsInternal(callingUid); 1103 } finally { 1104 Binder.restoreCallingIdentity(token); 1105 } 1106 } 1107 1108 @Override // Binder call 1109 public void registerCallback(IDisplayManagerCallback callback) { 1110 if (callback == null) { 1111 throw new IllegalArgumentException("listener must not be null"); 1112 } 1113 1114 final int callingPid = Binder.getCallingPid(); 1115 final long token = Binder.clearCallingIdentity(); 1116 try { 1117 registerCallbackInternal(callback, callingPid); 1118 } finally { 1119 Binder.restoreCallingIdentity(token); 1120 } 1121 } 1122 1123 @Override // Binder call 1124 public void startWifiDisplayScan() { 1125 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1126 "Permission required to start wifi display scans"); 1127 1128 final int callingPid = Binder.getCallingPid(); 1129 final long token = Binder.clearCallingIdentity(); 1130 try { 1131 startWifiDisplayScanInternal(callingPid); 1132 } finally { 1133 Binder.restoreCallingIdentity(token); 1134 } 1135 } 1136 1137 @Override // Binder call 1138 public void stopWifiDisplayScan() { 1139 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1140 "Permission required to stop wifi display scans"); 1141 1142 final int callingPid = Binder.getCallingPid(); 1143 final long token = Binder.clearCallingIdentity(); 1144 try { 1145 stopWifiDisplayScanInternal(callingPid); 1146 } finally { 1147 Binder.restoreCallingIdentity(token); 1148 } 1149 } 1150 1151 @Override // Binder call 1152 public void connectWifiDisplay(String address) { 1153 if (address == null) { 1154 throw new IllegalArgumentException("address must not be null"); 1155 } 1156 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1157 "Permission required to connect to a wifi display"); 1158 1159 final long token = Binder.clearCallingIdentity(); 1160 try { 1161 connectWifiDisplayInternal(address); 1162 } finally { 1163 Binder.restoreCallingIdentity(token); 1164 } 1165 } 1166 1167 @Override // Binder call 1168 public void disconnectWifiDisplay() { 1169 // This request does not require special permissions. 1170 // Any app can request disconnection from the currently active wifi display. 1171 // This exception should no longer be needed once wifi display control moves 1172 // to the media router service. 1173 1174 final long token = Binder.clearCallingIdentity(); 1175 try { 1176 disconnectWifiDisplayInternal(); 1177 } finally { 1178 Binder.restoreCallingIdentity(token); 1179 } 1180 } 1181 1182 @Override // Binder call 1183 public void renameWifiDisplay(String address, String alias) { 1184 if (address == null) { 1185 throw new IllegalArgumentException("address must not be null"); 1186 } 1187 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1188 "Permission required to rename to a wifi display"); 1189 1190 final long token = Binder.clearCallingIdentity(); 1191 try { 1192 renameWifiDisplayInternal(address, alias); 1193 } finally { 1194 Binder.restoreCallingIdentity(token); 1195 } 1196 } 1197 1198 @Override // Binder call 1199 public void forgetWifiDisplay(String address) { 1200 if (address == null) { 1201 throw new IllegalArgumentException("address must not be null"); 1202 } 1203 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1204 "Permission required to forget to a wifi display"); 1205 1206 final long token = Binder.clearCallingIdentity(); 1207 try { 1208 forgetWifiDisplayInternal(address); 1209 } finally { 1210 Binder.restoreCallingIdentity(token); 1211 } 1212 } 1213 1214 @Override // Binder call 1215 public void pauseWifiDisplay() { 1216 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1217 "Permission required to pause a wifi display session"); 1218 1219 final long token = Binder.clearCallingIdentity(); 1220 try { 1221 pauseWifiDisplayInternal(); 1222 } finally { 1223 Binder.restoreCallingIdentity(token); 1224 } 1225 } 1226 1227 @Override // Binder call 1228 public void resumeWifiDisplay() { 1229 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, 1230 "Permission required to resume a wifi display session"); 1231 1232 final long token = Binder.clearCallingIdentity(); 1233 try { 1234 resumeWifiDisplayInternal(); 1235 } finally { 1236 Binder.restoreCallingIdentity(token); 1237 } 1238 } 1239 1240 @Override // Binder call 1241 public WifiDisplayStatus getWifiDisplayStatus() { 1242 // This request does not require special permissions. 1243 // Any app can get information about available wifi displays. 1244 1245 final long token = Binder.clearCallingIdentity(); 1246 try { 1247 return getWifiDisplayStatusInternal(); 1248 } finally { 1249 Binder.restoreCallingIdentity(token); 1250 } 1251 } 1252 1253 @Override // Binder call 1254 public int createVirtualDisplay(IVirtualDisplayCallbacks callbacks, 1255 IMediaProjection projection, String packageName, String name, 1256 int width, int height, int densityDpi, Surface surface, int flags) { 1257 final int callingUid = Binder.getCallingUid(); 1258 if (!validatePackageName(callingUid, packageName)) { 1259 throw new SecurityException("packageName must match the calling uid"); 1260 } 1261 if (callbacks == null) { 1262 throw new IllegalArgumentException("appToken must not be null"); 1263 } 1264 if (TextUtils.isEmpty(name)) { 1265 throw new IllegalArgumentException("name must be non-null and non-empty"); 1266 } 1267 if (width <= 0 || height <= 0 || densityDpi <= 0) { 1268 throw new IllegalArgumentException("width, height, and densityDpi must be " 1269 + "greater than 0"); 1270 } 1271 1272 if (projection != null) { 1273 try { 1274 if (!getProjectionService().isValidMediaProjection(projection)) { 1275 throw new SecurityException("Invalid media projection"); 1276 } 1277 } catch (RemoteException e) { 1278 throw new SecurityException("unable to validate media projection"); 1279 } 1280 flags &= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE; 1281 try { 1282 flags |= projection.getVirtualDisplayFlags(); 1283 } catch (RemoteException e) { 1284 throw new RuntimeException("unable to retrieve media projection flags"); 1285 } 1286 } 1287 1288 if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SCREEN_SHARE) != 0) { 1289 if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0 || 1290 (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION) != 0) { 1291 throw new IllegalArgumentException("screen sharing virtual displays must not " 1292 + "be public or presentation displays"); 1293 } 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 in order to create a screen sharing virtual " 1298 + "display."); 1299 } 1300 } 1301 1302 1303 if (callingUid != Process.SYSTEM_UID && 1304 (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) { 1305 if (!canProjectVideo(projection)) { 1306 throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or " 1307 + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate " 1308 + "MediaProjection token to create a public virtual display."); 1309 } 1310 } 1311 if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) { 1312 if (!canProjectSecureVideo(projection)) { 1313 throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT " 1314 + "or an appropriate MediaProjection token to create a " 1315 + "secure virtual display."); 1316 } 1317 } 1318 1319 final long token = Binder.clearCallingIdentity(); 1320 try { 1321 return createVirtualDisplayInternal(callbacks, projection, callingUid, 1322 packageName, name, width, height, densityDpi, surface, flags); 1323 } finally { 1324 Binder.restoreCallingIdentity(token); 1325 } 1326 } 1327 1328 @Override // Binder call 1329 public void resizeVirtualDisplay(IVirtualDisplayCallbacks callbacks, 1330 int width, int height, int densityDpi) { 1331 final long token = Binder.clearCallingIdentity(); 1332 try { 1333 resizeVirtualDisplayInternal(callbacks.asBinder(), width, height, densityDpi); 1334 } finally { 1335 Binder.restoreCallingIdentity(token); 1336 } 1337 } 1338 1339 @Override // Binder call 1340 public void setVirtualDisplaySurface(IVirtualDisplayCallbacks callbacks, Surface surface) { 1341 final long token = Binder.clearCallingIdentity(); 1342 try { 1343 setVirtualDisplaySurfaceInternal(callbacks.asBinder(), surface); 1344 } finally { 1345 Binder.restoreCallingIdentity(token); 1346 } 1347 } 1348 1349 @Override // Binder call 1350 public void releaseVirtualDisplay(IVirtualDisplayCallbacks callbacks) { 1351 final long token = Binder.clearCallingIdentity(); 1352 try { 1353 releaseVirtualDisplayInternal(callbacks.asBinder()); 1354 } finally { 1355 Binder.restoreCallingIdentity(token); 1356 } 1357 } 1358 1359 @Override // Binder call 1360 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 1361 if (mContext == null 1362 || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) 1363 != PackageManager.PERMISSION_GRANTED) { 1364 pw.println("Permission Denial: can't dump DisplayManager from from pid=" 1365 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 1366 return; 1367 } 1368 1369 final long token = Binder.clearCallingIdentity(); 1370 try { 1371 dumpInternal(pw); 1372 } finally { 1373 Binder.restoreCallingIdentity(token); 1374 } 1375 } 1376 1377 private boolean validatePackageName(int uid, String packageName) { 1378 if (packageName != null) { 1379 String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid); 1380 if (packageNames != null) { 1381 for (String n : packageNames) { 1382 if (n.equals(packageName)) { 1383 return true; 1384 } 1385 } 1386 } 1387 } 1388 return false; 1389 } 1390 1391 private boolean canProjectVideo(IMediaProjection projection) { 1392 if (projection != null) { 1393 try { 1394 if (projection.canProjectVideo()) { 1395 return true; 1396 } 1397 } catch (RemoteException e) { 1398 Slog.e(TAG, "Unable to query projection service for permissions", e); 1399 } 1400 } 1401 if (mContext.checkCallingPermission( 1402 android.Manifest.permission.CAPTURE_VIDEO_OUTPUT) 1403 == PackageManager.PERMISSION_GRANTED) { 1404 return true; 1405 } 1406 return canProjectSecureVideo(projection); 1407 } 1408 1409 private boolean canProjectSecureVideo(IMediaProjection projection) { 1410 if (projection != null) { 1411 try { 1412 if (projection.canProjectSecureVideo()){ 1413 return true; 1414 } 1415 } catch (RemoteException e) { 1416 Slog.e(TAG, "Unable to query projection service for permissions", e); 1417 } 1418 } 1419 return mContext.checkCallingPermission( 1420 android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT) 1421 == PackageManager.PERMISSION_GRANTED; 1422 } 1423 } 1424 1425 private final class LocalService extends DisplayManagerInternal { 1426 @Override 1427 public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler, 1428 SensorManager sensorManager) { 1429 synchronized (mSyncRoot) { 1430 DisplayBlanker blanker = new DisplayBlanker() { 1431 @Override 1432 public void requestDisplayState(int state) { 1433 // The order of operations is important for legacy reasons. 1434 if (state == Display.STATE_OFF) { 1435 requestGlobalDisplayStateInternal(state); 1436 } 1437 1438 callbacks.onDisplayStateChange(state); 1439 1440 if (state != Display.STATE_OFF) { 1441 requestGlobalDisplayStateInternal(state); 1442 } 1443 } 1444 }; 1445 mDisplayPowerController = new DisplayPowerController( 1446 mContext, callbacks, handler, sensorManager, blanker); 1447 } 1448 } 1449 1450 @Override 1451 public boolean requestPowerState(DisplayPowerRequest request, 1452 boolean waitForNegativeProximity) { 1453 return mDisplayPowerController.requestPowerState(request, 1454 waitForNegativeProximity); 1455 } 1456 1457 @Override 1458 public boolean isProximitySensorAvailable() { 1459 return mDisplayPowerController.isProximitySensorAvailable(); 1460 } 1461 1462 @Override 1463 public DisplayInfo getDisplayInfo(int displayId) { 1464 return getDisplayInfoInternal(displayId, Process.myUid()); 1465 } 1466 1467 @Override 1468 public void registerDisplayTransactionListener(DisplayTransactionListener listener) { 1469 if (listener == null) { 1470 throw new IllegalArgumentException("listener must not be null"); 1471 } 1472 1473 registerDisplayTransactionListenerInternal(listener); 1474 } 1475 1476 @Override 1477 public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) { 1478 if (listener == null) { 1479 throw new IllegalArgumentException("listener must not be null"); 1480 } 1481 1482 unregisterDisplayTransactionListenerInternal(listener); 1483 } 1484 1485 @Override 1486 public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) { 1487 setDisplayInfoOverrideFromWindowManagerInternal(displayId, info); 1488 } 1489 1490 @Override 1491 public void performTraversalInTransactionFromWindowManager() { 1492 performTraversalInTransactionFromWindowManagerInternal(); 1493 } 1494 1495 @Override 1496 public void setDisplayProperties(int displayId, boolean hasContent, 1497 float requestedRefreshRate, boolean inTraversal) { 1498 setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate, inTraversal); 1499 } 1500 } 1501} 1502