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