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