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