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.display.DisplayManagerGlobal; 25 import android.hardware.display.IDisplayManager; 26 import android.hardware.display.IDisplayManagerCallback; 27 import android.hardware.display.WifiDisplayStatus; 28 import android.os.Binder; 29 import android.os.Handler; 30 import android.os.IBinder; 31 import android.os.Looper; 32 import android.os.Message; 33 import android.os.RemoteException; 34 import android.os.SystemClock; 35 import android.os.SystemProperties; 36 import android.util.Slog; 37 import android.util.SparseArray; 38 import android.view.Display; 39 import android.view.DisplayInfo; 40 41 import java.io.FileDescriptor; 42 import java.io.PrintWriter; 43 import java.util.ArrayList; 44 import java.util.concurrent.CopyOnWriteArrayList; 45 46 /** 47 * Manages attached displays. 48 * <p> 49 * The {@link DisplayManagerService} manages the global lifecycle of displays, 50 * decides how to configure logical displays based on the physical display devices currently 51 * attached, sends notifications to the system and to applications when the state 52 * changes, and so on. 53 * </p><p> 54 * The display manager service relies on a collection of {@link DisplayAdapter} components, 55 * for discovering and configuring physical display devices attached to the system. 56 * There are separate display adapters for each manner that devices are attached: 57 * one display adapter for built-in local displays, one for simulated non-functional 58 * displays when the system is headless, one for simulated overlay displays used for 59 * development, one for wifi displays, etc. 60 * </p><p> 61 * Display adapters are only weakly coupled to the display manager service. 62 * Display adapters communicate changes in display device state to the display manager 63 * service asynchronously via a {@link DisplayAdapter.Listener} registered 64 * by the display manager service. This separation of concerns is important for 65 * two main reasons. First, it neatly encapsulates the responsibilities of these 66 * two classes: display adapters handle individual display devices whereas 67 * the display manager service handles the global state. Second, it eliminates 68 * the potential for deadlocks resulting from asynchronous display device discovery. 69 * </p> 70 * 71 * <h3>Synchronization</h3> 72 * <p> 73 * Because the display manager may be accessed by multiple threads, the synchronization 74 * story gets a little complicated. In particular, the window manager may call into 75 * the display manager while holding a surface transaction with the expectation that 76 * it can apply changes immediately. Unfortunately, that means we can't just do 77 * everything asynchronously (*grump*). 78 * </p><p> 79 * To make this work, all of the objects that belong to the display manager must 80 * use the same lock. We call this lock the synchronization root and it has a unique 81 * type {@link DisplayManagerService.SyncRoot}. Methods that require this lock are 82 * named with the "Locked" suffix. 83 * </p><p> 84 * Where things get tricky is that the display manager is not allowed to make 85 * any potentially reentrant calls, especially into the window manager. We generally 86 * avoid this by making all potentially reentrant out-calls asynchronous. 87 * </p> 88 */ 89 public final class DisplayManagerService extends IDisplayManager.Stub { 90 private static final String TAG = "DisplayManagerService"; 91 private static final boolean DEBUG = false; 92 93 // When this system property is set to 0, WFD is forcibly disabled on boot. 94 // When this system property is set to 1, WFD is forcibly enabled on boot. 95 // Otherwise WFD is enabled according to the value of config_enableWifiDisplay. 96 private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable"; 97 98 private static final String SYSTEM_HEADLESS = "ro.config.headless"; 99 private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000; 100 101 private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER = 1; 102 private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2; 103 private static final int MSG_DELIVER_DISPLAY_EVENT = 3; 104 private static final int MSG_REQUEST_TRAVERSAL = 4; 105 private static final int MSG_UPDATE_VIEWPORT = 5; 106 107 private static final int DISPLAY_BLANK_STATE_UNKNOWN = 0; 108 private static final int DISPLAY_BLANK_STATE_BLANKED = 1; 109 private static final int DISPLAY_BLANK_STATE_UNBLANKED = 2; 110 111 private final Context mContext; 112 private final boolean mHeadless; 113 private final DisplayManagerHandler mHandler; 114 private final Handler mUiHandler; 115 private final DisplayAdapterListener mDisplayAdapterListener; 116 private WindowManagerFuncs mWindowManagerFuncs; 117 private InputManagerFuncs mInputManagerFuncs; 118 119 // The synchronization root for the display manager. 120 // This lock guards most of the display manager's state. 121 // NOTE: This is synchronized on while holding WindowManagerService.mWindowMap so never call 122 // into WindowManagerService methods that require mWindowMap while holding this unless you are 123 // very very sure that no deadlock can occur. 124 private final SyncRoot mSyncRoot = new SyncRoot(); 125 126 // True if in safe mode. 127 // This option may disable certain display adapters. 128 public boolean mSafeMode; 129 130 // True if we are in a special boot mode where only core applications and 131 // services should be started. This option may disable certain display adapters. 132 public boolean mOnlyCore; 133 134 // True if the display manager service should pretend there is only one display 135 // and only tell applications about the existence of the default logical display. 136 // The display manager can still mirror content to secondary displays but applications 137 // cannot present unique content on those displays. 138 // Used for demonstration purposes only. 139 private final boolean mSingleDisplayDemoMode; 140 141 // All callback records indexed by calling process id. 142 public final SparseArray<CallbackRecord> mCallbacks = 143 new SparseArray<CallbackRecord>(); 144 145 // List of all currently registered display adapters. 146 private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>(); 147 148 // List of all currently connected display devices. 149 private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>(); 150 151 // List of all removed display devices. 152 private final ArrayList<DisplayDevice> mRemovedDisplayDevices = new ArrayList<DisplayDevice>(); 153 154 // List of all logical displays indexed by logical display id. 155 private final SparseArray<LogicalDisplay> mLogicalDisplays = 156 new SparseArray<LogicalDisplay>(); 157 private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1; 158 159 // List of all display transaction listeners. 160 private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners = 161 new CopyOnWriteArrayList<DisplayTransactionListener>(); 162 163 // Set to true if all displays have been blanked by the power manager. 164 private int mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNKNOWN; 165 166 // Set to true when there are pending display changes that have yet to be applied 167 // to the surface flinger state. 168 private boolean mPendingTraversal; 169 170 // The Wifi display adapter, or null if not registered. 171 private WifiDisplayAdapter mWifiDisplayAdapter; 172 173 // Viewports of the default display and the display that should receive touch 174 // input from an external source. Used by the input system. 175 private final DisplayViewport mDefaultViewport = new DisplayViewport(); 176 private final DisplayViewport mExternalTouchViewport = new DisplayViewport(); 177 178 // Persistent data store for all internal settings maintained by the display manager service. 179 private final PersistentDataStore mPersistentDataStore = new PersistentDataStore(); 180 181 // Temporary callback list, used when sending display events to applications. 182 // May be used outside of the lock but only on the handler thread. 183 private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>(); 184 185 // Temporary display info, used for comparing display configurations. 186 private final DisplayInfo mTempDisplayInfo = new DisplayInfo(); 187 188 // Temporary viewports, used when sending new viewport information to the 189 // input system. May be used outside of the lock but only on the handler thread. 190 private final DisplayViewport mTempDefaultViewport = new DisplayViewport(); 191 private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport(); 192 193 public DisplayManagerService(Context context, Handler mainHandler, Handler uiHandler) { 194 mContext = context; 195 mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1"); 196 197 mHandler = new DisplayManagerHandler(mainHandler.getLooper()); 198 mUiHandler = uiHandler; 199 mDisplayAdapterListener = new DisplayAdapterListener(); 200 mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false); 201 202 mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER); 203 } 204 205 /** 206 * Pauses the boot process to wait for the first display to be initialized. 207 */ 208 public boolean waitForDefaultDisplay() { 209 synchronized (mSyncRoot) { 210 long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT; 211 while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) { 212 long delay = timeout - SystemClock.uptimeMillis(); 213 if (delay <= 0) { 214 return false; 215 } 216 if (DEBUG) { 217 Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay); 218 } 219 try { 220 mSyncRoot.wait(delay); 221 } catch (InterruptedException ex) { 222 } 223 } 224 } 225 return true; 226 } 227 228 /** 229 * Called during initialization to associate the display manager with the 230 * window manager. 231 */ 232 public void setWindowManager(WindowManagerFuncs windowManagerFuncs) { 233 synchronized (mSyncRoot) { 234 mWindowManagerFuncs = windowManagerFuncs; 235 scheduleTraversalLocked(false); 236 } 237 } 238 239 /** 240 * Called during initialization to associate the display manager with the 241 * input manager. 242 */ 243 public void setInputManager(InputManagerFuncs inputManagerFuncs) { 244 synchronized (mSyncRoot) { 245 mInputManagerFuncs = inputManagerFuncs; 246 scheduleTraversalLocked(false); 247 } 248 } 249 250 /** 251 * Called when the system is ready to go. 252 */ 253 public void systemReady(boolean safeMode, boolean onlyCore) { 254 synchronized (mSyncRoot) { 255 mSafeMode = safeMode; 256 mOnlyCore = onlyCore; 257 } 258 259 mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS); 260 } 261 262 /** 263 * Returns true if the device is headless. 264 * 265 * @return True if the device is headless. 266 */ 267 public boolean isHeadless() { 268 return mHeadless; 269 } 270 271 /** 272 * Registers a display transaction listener to provide the client a chance to 273 * update its surfaces within the same transaction as any display layout updates. 274 * 275 * @param listener The listener to register. 276 */ 277 public void registerDisplayTransactionListener(DisplayTransactionListener listener) { 278 if (listener == null) { 279 throw new IllegalArgumentException("listener must not be null"); 280 } 281 282 // List is self-synchronized copy-on-write. 283 mDisplayTransactionListeners.add(listener); 284 } 285 286 /** 287 * Unregisters a display transaction listener to provide the client a chance to 288 * update its surfaces within the same transaction as any display layout updates. 289 * 290 * @param listener The listener to unregister. 291 */ 292 public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) { 293 if (listener == null) { 294 throw new IllegalArgumentException("listener must not be null"); 295 } 296 297 // List is self-synchronized copy-on-write. 298 mDisplayTransactionListeners.remove(listener); 299 } 300 301 /** 302 * Overrides the display information of a particular logical display. 303 * This is used by the window manager to control the size and characteristics 304 * of the default display. It is expected to apply the requested change 305 * to the display information synchronously so that applications will immediately 306 * observe the new state. 307 * 308 * @param displayId The logical display id. 309 * @param info The new data to be stored. 310 */ 311 public void setDisplayInfoOverrideFromWindowManager( 312 int displayId, DisplayInfo info) { 313 synchronized (mSyncRoot) { 314 LogicalDisplay display = mLogicalDisplays.get(displayId); 315 if (display != null) { 316 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked()); 317 display.setDisplayInfoOverrideFromWindowManagerLocked(info); 318 if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) { 319 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); 320 scheduleTraversalLocked(false); 321 } 322 } 323 } 324 } 325 326 /** 327 * Sets the overscan insets for a particular display. 328 */ 329 public void setOverscan(int displayId, int left, int top, int right, int bottom) { 330 synchronized (mSyncRoot) { 331 LogicalDisplay display = mLogicalDisplays.get(displayId); 332 if (display != null) { 333 display.setOverscan(left, top, right, bottom); 334 } 335 } 336 } 337 338 /** 339 * Called by the window manager to perform traversals while holding a 340 * surface flinger transaction. 341 */ 342 public void performTraversalInTransactionFromWindowManager() { 343 synchronized (mSyncRoot) { 344 if (!mPendingTraversal) { 345 return; 346 } 347 mPendingTraversal = false; 348 349 performTraversalInTransactionLocked(); 350 } 351 352 // List is self-synchronized copy-on-write. 353 for (DisplayTransactionListener listener : mDisplayTransactionListeners) { 354 listener.onDisplayTransaction(); 355 } 356 } 357 358 /** 359 * Called by the power manager to blank all displays. 360 */ 361 public void blankAllDisplaysFromPowerManager() { 362 synchronized (mSyncRoot) { 363 if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_BLANKED) { 364 mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_BLANKED; 365 366 final int count = mDisplayDevices.size(); 367 for (int i = 0; i < count; i++) { 368 DisplayDevice device = mDisplayDevices.get(i); 369 device.blankLocked(); 370 } 371 372 scheduleTraversalLocked(false); 373 } 374 } 375 } 376 377 /** 378 * Called by the power manager to unblank all displays. 379 */ 380 public void unblankAllDisplaysFromPowerManager() { 381 synchronized (mSyncRoot) { 382 if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_UNBLANKED) { 383 mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNBLANKED; 384 385 final int count = mDisplayDevices.size(); 386 for (int i = 0; i < count; i++) { 387 DisplayDevice device = mDisplayDevices.get(i); 388 device.unblankLocked(); 389 } 390 391 scheduleTraversalLocked(false); 392 } 393 } 394 } 395 396 /** 397 * Returns information about the specified logical display. 398 * 399 * @param displayId The logical display id. 400 * @return The logical display info, or null if the display does not exist. The 401 * returned object must be treated as immutable. 402 */ 403 @Override // Binder call 404 public DisplayInfo getDisplayInfo(int displayId) { 405 synchronized (mSyncRoot) { 406 LogicalDisplay display = mLogicalDisplays.get(displayId); 407 if (display != null) { 408 return display.getDisplayInfoLocked(); 409 } 410 return null; 411 } 412 } 413 414 /** 415 * Returns the list of all display ids. 416 */ 417 @Override // Binder call 418 public int[] getDisplayIds() { 419 synchronized (mSyncRoot) { 420 final int count = mLogicalDisplays.size(); 421 int[] displayIds = new int[count]; 422 for (int i = 0; i < count; i++) { 423 displayIds[i] = mLogicalDisplays.keyAt(i); 424 } 425 return displayIds; 426 } 427 } 428 429 @Override // Binder call 430 public void registerCallback(IDisplayManagerCallback callback) { 431 if (callback == null) { 432 throw new IllegalArgumentException("listener must not be null"); 433 } 434 435 synchronized (mSyncRoot) { 436 int callingPid = Binder.getCallingPid(); 437 if (mCallbacks.get(callingPid) != null) { 438 throw new SecurityException("The calling process has already " 439 + "registered an IDisplayManagerCallback."); 440 } 441 442 CallbackRecord record = new CallbackRecord(callingPid, callback); 443 try { 444 IBinder binder = callback.asBinder(); 445 binder.linkToDeath(record, 0); 446 } catch (RemoteException ex) { 447 // give up 448 throw new RuntimeException(ex); 449 } 450 451 mCallbacks.put(callingPid, record); 452 } 453 } 454 455 private void onCallbackDied(int pid) { 456 synchronized (mSyncRoot) { 457 mCallbacks.remove(pid); 458 } 459 } 460 461 @Override // Binder call 462 public void scanWifiDisplays() { 463 final long token = Binder.clearCallingIdentity(); 464 try { 465 synchronized (mSyncRoot) { 466 if (mWifiDisplayAdapter != null) { 467 mWifiDisplayAdapter.requestScanLocked(); 468 } 469 } 470 } finally { 471 Binder.restoreCallingIdentity(token); 472 } 473 } 474 475 @Override // Binder call 476 public void connectWifiDisplay(String address) { 477 if (address == null) { 478 throw new IllegalArgumentException("address must not be null"); 479 } 480 481 final boolean trusted = canCallerConfigureWifiDisplay(); 482 final long token = Binder.clearCallingIdentity(); 483 try { 484 synchronized (mSyncRoot) { 485 if (mWifiDisplayAdapter != null) { 486 mWifiDisplayAdapter.requestConnectLocked(address, trusted); 487 } 488 } 489 } finally { 490 Binder.restoreCallingIdentity(token); 491 } 492 } 493 494 @Override // Binder call 495 public void disconnectWifiDisplay() { 496 final long token = Binder.clearCallingIdentity(); 497 try { 498 synchronized (mSyncRoot) { 499 if (mWifiDisplayAdapter != null) { 500 mWifiDisplayAdapter.requestDisconnectLocked(); 501 } 502 } 503 } finally { 504 Binder.restoreCallingIdentity(token); 505 } 506 } 507 508 @Override // Binder call 509 public void renameWifiDisplay(String address, String alias) { 510 if (address == null) { 511 throw new IllegalArgumentException("address must not be null"); 512 } 513 if (!canCallerConfigureWifiDisplay()) { 514 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to " 515 + "rename a wifi display."); 516 } 517 518 final long token = Binder.clearCallingIdentity(); 519 try { 520 synchronized (mSyncRoot) { 521 if (mWifiDisplayAdapter != null) { 522 mWifiDisplayAdapter.requestRenameLocked(address, alias); 523 } 524 } 525 } finally { 526 Binder.restoreCallingIdentity(token); 527 } 528 } 529 530 @Override // Binder call 531 public void forgetWifiDisplay(String address) { 532 if (address == null) { 533 throw new IllegalArgumentException("address must not be null"); 534 } 535 if (!canCallerConfigureWifiDisplay()) { 536 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to " 537 + "forget a wifi display."); 538 } 539 540 final long token = Binder.clearCallingIdentity(); 541 try { 542 synchronized (mSyncRoot) { 543 if (mWifiDisplayAdapter != null) { 544 mWifiDisplayAdapter.requestForgetLocked(address); 545 } 546 } 547 } finally { 548 Binder.restoreCallingIdentity(token); 549 } 550 } 551 552 @Override // Binder call 553 public WifiDisplayStatus getWifiDisplayStatus() { 554 final long token = Binder.clearCallingIdentity(); 555 try { 556 synchronized (mSyncRoot) { 557 if (mWifiDisplayAdapter != null) { 558 return mWifiDisplayAdapter.getWifiDisplayStatusLocked(); 559 } 560 return new WifiDisplayStatus(); 561 } 562 } finally { 563 Binder.restoreCallingIdentity(token); 564 } 565 } 566 567 private boolean canCallerConfigureWifiDisplay() { 568 return mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) 569 == PackageManager.PERMISSION_GRANTED; 570 } 571 572 private void registerDefaultDisplayAdapter() { 573 // Register default display adapter. 574 synchronized (mSyncRoot) { 575 if (mHeadless) { 576 registerDisplayAdapterLocked(new HeadlessDisplayAdapter( 577 mSyncRoot, mContext, mHandler, mDisplayAdapterListener)); 578 } else { 579 registerDisplayAdapterLocked(new LocalDisplayAdapter( 580 mSyncRoot, mContext, mHandler, mDisplayAdapterListener)); 581 } 582 } 583 } 584 585 private void registerAdditionalDisplayAdapters() { 586 synchronized (mSyncRoot) { 587 if (shouldRegisterNonEssentialDisplayAdaptersLocked()) { 588 registerOverlayDisplayAdapterLocked(); 589 registerWifiDisplayAdapterLocked(); 590 } 591 } 592 } 593 594 private void registerOverlayDisplayAdapterLocked() { 595 registerDisplayAdapterLocked(new OverlayDisplayAdapter( 596 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler)); 597 } 598 599 private void registerWifiDisplayAdapterLocked() { 600 if (mContext.getResources().getBoolean( 601 com.android.internal.R.bool.config_enableWifiDisplay) 602 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) { 603 mWifiDisplayAdapter = new WifiDisplayAdapter( 604 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, 605 mPersistentDataStore); 606 registerDisplayAdapterLocked(mWifiDisplayAdapter); 607 } 608 } 609 610 private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() { 611 // In safe mode, we disable non-essential display adapters to give the user 612 // an opportunity to fix broken settings or other problems that might affect 613 // system stability. 614 // In only-core mode, we disable non-essential display adapters to minimize 615 // the number of dependencies that are started while in this mode and to 616 // prevent problems that might occur due to the device being encrypted. 617 return !mSafeMode && !mOnlyCore; 618 } 619 620 private void registerDisplayAdapterLocked(DisplayAdapter adapter) { 621 mDisplayAdapters.add(adapter); 622 adapter.registerLocked(); 623 } 624 625 private void handleDisplayDeviceAdded(DisplayDevice device) { 626 synchronized (mSyncRoot) { 627 if (mDisplayDevices.contains(device)) { 628 Slog.w(TAG, "Attempted to add already added display device: " 629 + device.getDisplayDeviceInfoLocked()); 630 return; 631 } 632 633 Slog.i(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked()); 634 635 mDisplayDevices.add(device); 636 addLogicalDisplayLocked(device); 637 scheduleTraversalLocked(false); 638 639 // Blank or unblank the display immediately to match the state requested 640 // by the power manager (if known). 641 switch (mAllDisplayBlankStateFromPowerManager) { 642 case DISPLAY_BLANK_STATE_BLANKED: 643 device.blankLocked(); 644 break; 645 case DISPLAY_BLANK_STATE_UNBLANKED: 646 device.unblankLocked(); 647 break; 648 } 649 } 650 } 651 652 private void handleDisplayDeviceChanged(DisplayDevice device) { 653 synchronized (mSyncRoot) { 654 if (!mDisplayDevices.contains(device)) { 655 Slog.w(TAG, "Attempted to change non-existent display device: " 656 + device.getDisplayDeviceInfoLocked()); 657 return; 658 } 659 660 Slog.i(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked()); 661 662 device.applyPendingDisplayDeviceInfoChangesLocked(); 663 if (updateLogicalDisplaysLocked()) { 664 scheduleTraversalLocked(false); 665 } 666 } 667 } 668 669 private void handleDisplayDeviceRemoved(DisplayDevice device) { 670 synchronized (mSyncRoot) { 671 if (!mDisplayDevices.remove(device)) { 672 Slog.w(TAG, "Attempted to remove non-existent display device: " 673 + device.getDisplayDeviceInfoLocked()); 674 return; 675 } 676 677 Slog.i(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked()); 678 679 mRemovedDisplayDevices.add(device); 680 updateLogicalDisplaysLocked(); 681 scheduleTraversalLocked(false); 682 } 683 } 684 685 // Adds a new logical display based on the given display device. 686 // Sends notifications if needed. 687 private void addLogicalDisplayLocked(DisplayDevice device) { 688 DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked(); 689 boolean isDefault = (deviceInfo.flags 690 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0; 691 if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) { 692 Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo); 693 isDefault = false; 694 } 695 696 if (!isDefault && mSingleDisplayDemoMode) { 697 Slog.i(TAG, "Not creating a logical display for a secondary display " 698 + " because single display demo mode is enabled: " + deviceInfo); 699 return; 700 } 701 702 final int displayId = assignDisplayIdLocked(isDefault); 703 final int layerStack = assignLayerStackLocked(displayId); 704 705 LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device); 706 display.updateLocked(mDisplayDevices); 707 if (!display.isValidLocked()) { 708 // This should never happen currently. 709 Slog.w(TAG, "Ignoring display device because the logical display " 710 + "created from it was not considered valid: " + deviceInfo); 711 return; 712 } 713 714 mLogicalDisplays.put(displayId, display); 715 716 // Wake up waitForDefaultDisplay. 717 if (isDefault) { 718 mSyncRoot.notifyAll(); 719 } 720 721 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED); 722 } 723 724 private int assignDisplayIdLocked(boolean isDefault) { 725 return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++; 726 } 727 728 private int assignLayerStackLocked(int displayId) { 729 // Currently layer stacks and display ids are the same. 730 // This need not be the case. 731 return displayId; 732 } 733 734 // Updates all existing logical displays given the current set of display devices. 735 // Removes invalid logical displays. 736 // Sends notifications if needed. 737 private boolean updateLogicalDisplaysLocked() { 738 boolean changed = false; 739 for (int i = mLogicalDisplays.size(); i-- > 0; ) { 740 final int displayId = mLogicalDisplays.keyAt(i); 741 LogicalDisplay display = mLogicalDisplays.valueAt(i); 742 743 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked()); 744 display.updateLocked(mDisplayDevices); 745 if (!display.isValidLocked()) { 746 mLogicalDisplays.removeAt(i); 747 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED); 748 changed = true; 749 } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) { 750 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); 751 changed = true; 752 } 753 } 754 return changed; 755 } 756 757 private void performTraversalInTransactionLocked() { 758 // Perform one last traversal for each removed display device. 759 final int removedCount = mRemovedDisplayDevices.size(); 760 for (int i = 0; i < removedCount; i++) { 761 DisplayDevice device = mRemovedDisplayDevices.get(i); 762 device.performTraversalInTransactionLocked(); 763 } 764 mRemovedDisplayDevices.clear(); 765 766 // Clear all viewports before configuring displays so that we can keep 767 // track of which ones we have configured. 768 clearViewportsLocked(); 769 770 // Configure each display device. 771 final int count = mDisplayDevices.size(); 772 for (int i = 0; i < count; i++) { 773 DisplayDevice device = mDisplayDevices.get(i); 774 configureDisplayInTransactionLocked(device); 775 device.performTraversalInTransactionLocked(); 776 } 777 778 // Tell the input system about these new viewports. 779 if (mInputManagerFuncs != null) { 780 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT); 781 } 782 } 783 784 /** 785 * Tells the display manager whether there is interesting unique content on the 786 * specified logical display. This is used to control automatic mirroring. 787 * <p> 788 * If the display has unique content, then the display manager arranges for it 789 * to be presented on a physical display if appropriate. Otherwise, the display manager 790 * may choose to make the physical display mirror some other logical display. 791 * </p> 792 * 793 * @param displayId The logical display id to update. 794 * @param hasContent True if the logical display has content. 795 * @param inTraversal True if called from WindowManagerService during a window traversal prior 796 * to call to performTraversalInTransactionFromWindowManager. 797 */ 798 public void setDisplayHasContent(int displayId, boolean hasContent, boolean inTraversal) { 799 synchronized (mSyncRoot) { 800 LogicalDisplay display = mLogicalDisplays.get(displayId); 801 if (display != null && display.hasContentLocked() != hasContent) { 802 display.setHasContentLocked(hasContent); 803 scheduleTraversalLocked(inTraversal); 804 } 805 } 806 } 807 808 private void clearViewportsLocked() { 809 mDefaultViewport.valid = false; 810 mExternalTouchViewport.valid = false; 811 } 812 813 private void configureDisplayInTransactionLocked(DisplayDevice device) { 814 // Find the logical display that the display device is showing. 815 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device); 816 if (display != null && !display.hasContentLocked()) { 817 display = null; 818 } 819 if (display == null) { 820 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY); 821 } 822 823 // Apply the logical display configuration to the display device. 824 if (display == null) { 825 // TODO: no logical display for the device, blank it 826 Slog.w(TAG, "Missing logical display to use for physical display device: " 827 + device.getDisplayDeviceInfoLocked()); 828 return; 829 } 830 boolean isBlanked = (mAllDisplayBlankStateFromPowerManager == DISPLAY_BLANK_STATE_BLANKED); 831 display.configureDisplayInTransactionLocked(device, isBlanked); 832 833 // Update the viewports if needed. 834 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 835 if (!mDefaultViewport.valid 836 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) { 837 setViewportLocked(mDefaultViewport, display, device); 838 } 839 if (!mExternalTouchViewport.valid 840 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) { 841 setViewportLocked(mExternalTouchViewport, display, device); 842 } 843 } 844 845 private static void setViewportLocked(DisplayViewport viewport, 846 LogicalDisplay display, DisplayDevice device) { 847 viewport.valid = true; 848 viewport.displayId = display.getDisplayIdLocked(); 849 device.populateViewportLocked(viewport); 850 } 851 852 private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) { 853 final int count = mLogicalDisplays.size(); 854 for (int i = 0; i < count; i++) { 855 LogicalDisplay display = mLogicalDisplays.valueAt(i); 856 if (display.getPrimaryDisplayDeviceLocked() == device) { 857 return display; 858 } 859 } 860 return null; 861 } 862 863 private void sendDisplayEventLocked(int displayId, int event) { 864 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event); 865 mHandler.sendMessage(msg); 866 } 867 868 // Requests that performTraversalsInTransactionFromWindowManager be called at a 869 // later time to apply changes to surfaces and displays. 870 private void scheduleTraversalLocked(boolean inTraversal) { 871 if (!mPendingTraversal && mWindowManagerFuncs != null) { 872 mPendingTraversal = true; 873 if (!inTraversal) { 874 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL); 875 } 876 } 877 } 878 879 // Runs on Handler thread. 880 // Delivers display event notifications to callbacks. 881 private void deliverDisplayEvent(int displayId, int event) { 882 if (DEBUG) { 883 Slog.d(TAG, "Delivering display event: displayId=" 884 + displayId + ", event=" + event); 885 } 886 887 // Grab the lock and copy the callbacks. 888 final int count; 889 synchronized (mSyncRoot) { 890 count = mCallbacks.size(); 891 mTempCallbacks.clear(); 892 for (int i = 0; i < count; i++) { 893 mTempCallbacks.add(mCallbacks.valueAt(i)); 894 } 895 } 896 897 // After releasing the lock, send the notifications out. 898 for (int i = 0; i < count; i++) { 899 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event); 900 } 901 mTempCallbacks.clear(); 902 } 903 904 @Override // Binder call 905 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 906 if (mContext == null 907 || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) 908 != PackageManager.PERMISSION_GRANTED) { 909 pw.println("Permission Denial: can't dump DisplayManager from from pid=" 910 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 911 return; 912 } 913 914 pw.println("DISPLAY MANAGER (dumpsys display)"); 915 916 synchronized (mSyncRoot) { 917 pw.println(" mHeadless=" + mHeadless); 918 pw.println(" mOnlyCode=" + mOnlyCore); 919 pw.println(" mSafeMode=" + mSafeMode); 920 pw.println(" mPendingTraversal=" + mPendingTraversal); 921 pw.println(" mAllDisplayBlankStateFromPowerManager=" 922 + mAllDisplayBlankStateFromPowerManager); 923 pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId); 924 pw.println(" mDefaultViewport=" + mDefaultViewport); 925 pw.println(" mExternalTouchViewport=" + mExternalTouchViewport); 926 pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode); 927 928 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 929 ipw.increaseIndent(); 930 931 pw.println(); 932 pw.println("Display Adapters: size=" + mDisplayAdapters.size()); 933 for (DisplayAdapter adapter : mDisplayAdapters) { 934 pw.println(" " + adapter.getName()); 935 adapter.dumpLocked(ipw); 936 } 937 938 pw.println(); 939 pw.println("Display Devices: size=" + mDisplayDevices.size()); 940 for (DisplayDevice device : mDisplayDevices) { 941 pw.println(" " + device.getDisplayDeviceInfoLocked()); 942 device.dumpLocked(ipw); 943 } 944 945 final int logicalDisplayCount = mLogicalDisplays.size(); 946 pw.println(); 947 pw.println("Logical Displays: size=" + logicalDisplayCount); 948 for (int i = 0; i < logicalDisplayCount; i++) { 949 int displayId = mLogicalDisplays.keyAt(i); 950 LogicalDisplay display = mLogicalDisplays.valueAt(i); 951 pw.println(" Display " + displayId + ":"); 952 display.dumpLocked(ipw); 953 } 954 } 955 } 956 957 /** 958 * This is the object that everything in the display manager locks on. 959 * We make it an inner class within the {@link DisplayManagerService} to so that it is 960 * clear that the object belongs to the display manager service and that it is 961 * a unique object with a special purpose. 962 */ 963 public static final class SyncRoot { 964 } 965 966 /** 967 * Private interface to the window manager. 968 */ 969 public interface WindowManagerFuncs { 970 /** 971 * Request that the window manager call 972 * {@link #performTraversalInTransactionFromWindowManager} within a surface 973 * transaction at a later time. 974 */ 975 void requestTraversal(); 976 } 977 978 /** 979 * Private interface to the input manager. 980 */ 981 public interface InputManagerFuncs { 982 /** 983 * Sets information about the displays as needed by the input system. 984 * The input system should copy this information if required. 985 */ 986 void setDisplayViewports(DisplayViewport defaultViewport, 987 DisplayViewport externalTouchViewport); 988 } 989 990 private final class DisplayManagerHandler extends Handler { 991 public DisplayManagerHandler(Looper looper) { 992 super(looper, null, true /*async*/); 993 } 994 995 @Override 996 public void handleMessage(Message msg) { 997 switch (msg.what) { 998 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER: 999 registerDefaultDisplayAdapter(); 1000 break; 1001 1002 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS: 1003 registerAdditionalDisplayAdapters(); 1004 break; 1005 1006 case MSG_DELIVER_DISPLAY_EVENT: 1007 deliverDisplayEvent(msg.arg1, msg.arg2); 1008 break; 1009 1010 case MSG_REQUEST_TRAVERSAL: 1011 mWindowManagerFuncs.requestTraversal(); 1012 break; 1013 1014 case MSG_UPDATE_VIEWPORT: { 1015 synchronized (mSyncRoot) { 1016 mTempDefaultViewport.copyFrom(mDefaultViewport); 1017 mTempExternalTouchViewport.copyFrom(mExternalTouchViewport); 1018 } 1019 mInputManagerFuncs.setDisplayViewports( 1020 mTempDefaultViewport, mTempExternalTouchViewport); 1021 break; 1022 } 1023 } 1024 } 1025 } 1026 1027 private final class DisplayAdapterListener implements DisplayAdapter.Listener { 1028 @Override 1029 public void onDisplayDeviceEvent(DisplayDevice device, int event) { 1030 switch (event) { 1031 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED: 1032 handleDisplayDeviceAdded(device); 1033 break; 1034 1035 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED: 1036 handleDisplayDeviceChanged(device); 1037 break; 1038 1039 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED: 1040 handleDisplayDeviceRemoved(device); 1041 break; 1042 } 1043 } 1044 1045 @Override 1046 public void onTraversalRequested() { 1047 synchronized (mSyncRoot) { 1048 scheduleTraversalLocked(false); 1049 } 1050 } 1051 } 1052 1053 private final class CallbackRecord implements DeathRecipient { 1054 private final int mPid; 1055 private final IDisplayManagerCallback mCallback; 1056 1057 public CallbackRecord(int pid, IDisplayManagerCallback callback) { 1058 mPid = pid; 1059 mCallback = callback; 1060 } 1061 1062 @Override 1063 public void binderDied() { 1064 if (DEBUG) { 1065 Slog.d(TAG, "Display listener for pid " + mPid + " died."); 1066 } 1067 onCallbackDied(mPid); 1068 } 1069 1070 public void notifyDisplayEventAsync(int displayId, int event) { 1071 try { 1072 mCallback.onDisplayEvent(displayId, event); 1073 } catch (RemoteException ex) { 1074 Slog.w(TAG, "Failed to notify process " 1075 + mPid + " that displays changed, assuming it died.", ex); 1076 binderDied(); 1077 } 1078 } 1079 } 1080 } 1081