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