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