DisplayManagerService.java revision 65d11b3eeff395011a2c6b56eb117fd3c4881c1a
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(false); 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(false); 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(false); 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 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 (address == null) { 370 throw new IllegalArgumentException("address must not be null"); 371 } 372 373 final boolean trusted = canCallerConfigureWifiDisplay(); 374 final long token = Binder.clearCallingIdentity(); 375 try { 376 synchronized (mSyncRoot) { 377 if (mWifiDisplayAdapter != null) { 378 mWifiDisplayAdapter.requestConnectLocked(address, trusted); 379 } 380 } 381 } finally { 382 Binder.restoreCallingIdentity(token); 383 } 384 } 385 386 @Override // Binder call 387 public void disconnectWifiDisplay() { 388 final long token = Binder.clearCallingIdentity(); 389 try { 390 synchronized (mSyncRoot) { 391 if (mWifiDisplayAdapter != null) { 392 mWifiDisplayAdapter.requestDisconnectLocked(); 393 } 394 } 395 } finally { 396 Binder.restoreCallingIdentity(token); 397 } 398 } 399 400 @Override // Binder call 401 public void renameWifiDisplay(String address, String alias) { 402 if (address == null) { 403 throw new IllegalArgumentException("address must not be null"); 404 } 405 if (!canCallerConfigureWifiDisplay()) { 406 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to " 407 + "rename a wifi display."); 408 } 409 410 final long token = Binder.clearCallingIdentity(); 411 try { 412 synchronized (mSyncRoot) { 413 if (mWifiDisplayAdapter != null) { 414 mWifiDisplayAdapter.requestRenameLocked(address, alias); 415 } 416 } 417 } finally { 418 Binder.restoreCallingIdentity(token); 419 } 420 } 421 422 @Override // Binder call 423 public void forgetWifiDisplay(String address) { 424 if (address == null) { 425 throw new IllegalArgumentException("address must not be null"); 426 } 427 if (!canCallerConfigureWifiDisplay()) { 428 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to " 429 + "forget a wifi display."); 430 } 431 432 final long token = Binder.clearCallingIdentity(); 433 try { 434 synchronized (mSyncRoot) { 435 if (mWifiDisplayAdapter != null) { 436 mWifiDisplayAdapter.requestForgetLocked(address); 437 } 438 } 439 } finally { 440 Binder.restoreCallingIdentity(token); 441 } 442 } 443 444 @Override // Binder call 445 public WifiDisplayStatus getWifiDisplayStatus() { 446 final long token = Binder.clearCallingIdentity(); 447 try { 448 synchronized (mSyncRoot) { 449 if (mWifiDisplayAdapter != null) { 450 return mWifiDisplayAdapter.getWifiDisplayStatusLocked(); 451 } else { 452 return new WifiDisplayStatus(); 453 } 454 } 455 } finally { 456 Binder.restoreCallingIdentity(token); 457 } 458 } 459 460 private boolean canCallerConfigureWifiDisplay() { 461 return mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) 462 == PackageManager.PERMISSION_GRANTED; 463 } 464 465 private void registerDefaultDisplayAdapter() { 466 // Register default display adapter. 467 synchronized (mSyncRoot) { 468 if (mHeadless) { 469 registerDisplayAdapterLocked(new HeadlessDisplayAdapter( 470 mSyncRoot, mContext, mHandler, mDisplayAdapterListener)); 471 } else { 472 registerDisplayAdapterLocked(new LocalDisplayAdapter( 473 mSyncRoot, mContext, mHandler, mDisplayAdapterListener)); 474 } 475 } 476 } 477 478 private void registerAdditionalDisplayAdapters() { 479 synchronized (mSyncRoot) { 480 if (shouldRegisterNonEssentialDisplayAdaptersLocked()) { 481 registerOverlayDisplayAdapterLocked(); 482 registerWifiDisplayAdapterLocked(); 483 } 484 } 485 } 486 487 private void registerOverlayDisplayAdapterLocked() { 488 registerDisplayAdapterLocked(new OverlayDisplayAdapter( 489 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler)); 490 } 491 492 private void registerWifiDisplayAdapterLocked() { 493 if (mContext.getResources().getBoolean( 494 com.android.internal.R.bool.config_enableWifiDisplay) 495 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) { 496 mWifiDisplayAdapter = new WifiDisplayAdapter( 497 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, 498 mPersistentDataStore); 499 registerDisplayAdapterLocked(mWifiDisplayAdapter); 500 } 501 } 502 503 private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() { 504 // In safe mode, we disable non-essential display adapters to give the user 505 // an opportunity to fix broken settings or other problems that might affect 506 // system stability. 507 // In only-core mode, we disable non-essential display adapters to minimize 508 // the number of dependencies that are started while in this mode and to 509 // prevent problems that might occur due to the device being encrypted. 510 return !mSafeMode && !mOnlyCore; 511 } 512 513 private void registerDisplayAdapterLocked(DisplayAdapter adapter) { 514 mDisplayAdapters.add(adapter); 515 adapter.registerLocked(); 516 } 517 518 private void handleDisplayDeviceAdded(DisplayDevice device) { 519 synchronized (mSyncRoot) { 520 if (mDisplayDevices.contains(device)) { 521 Slog.w(TAG, "Attempted to add already added display device: " 522 + device.getDisplayDeviceInfoLocked()); 523 return; 524 } 525 526 Slog.i(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked()); 527 528 mDisplayDevices.add(device); 529 addLogicalDisplayLocked(device); 530 scheduleTraversalLocked(false); 531 } 532 } 533 534 private void handleDisplayDeviceChanged(DisplayDevice device) { 535 synchronized (mSyncRoot) { 536 if (!mDisplayDevices.contains(device)) { 537 Slog.w(TAG, "Attempted to change non-existent display device: " 538 + device.getDisplayDeviceInfoLocked()); 539 return; 540 } 541 542 Slog.i(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked()); 543 544 device.applyPendingDisplayDeviceInfoChangesLocked(); 545 if (updateLogicalDisplaysLocked()) { 546 scheduleTraversalLocked(false); 547 } 548 } 549 } 550 551 private void handleDisplayDeviceRemoved(DisplayDevice device) { 552 synchronized (mSyncRoot) { 553 if (!mDisplayDevices.remove(device)) { 554 Slog.w(TAG, "Attempted to remove non-existent display device: " 555 + device.getDisplayDeviceInfoLocked()); 556 return; 557 } 558 559 Slog.i(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked()); 560 561 mRemovedDisplayDevices.add(device); 562 updateLogicalDisplaysLocked(); 563 scheduleTraversalLocked(false); 564 } 565 } 566 567 // Adds a new logical display based on the given display device. 568 // Sends notifications if needed. 569 private void addLogicalDisplayLocked(DisplayDevice device) { 570 DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked(); 571 boolean isDefault = (deviceInfo.flags 572 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0; 573 if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) { 574 Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo); 575 isDefault = false; 576 } 577 578 final int displayId = assignDisplayIdLocked(isDefault); 579 final int layerStack = assignLayerStackLocked(displayId); 580 581 LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device); 582 display.updateLocked(mDisplayDevices); 583 if (!display.isValidLocked()) { 584 // This should never happen currently. 585 Slog.w(TAG, "Ignoring display device because the logical display " 586 + "created from it was not considered valid: " + deviceInfo); 587 return; 588 } 589 590 mLogicalDisplays.put(displayId, display); 591 592 // Wake up waitForDefaultDisplay. 593 if (isDefault) { 594 mSyncRoot.notifyAll(); 595 } 596 597 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED); 598 } 599 600 private int assignDisplayIdLocked(boolean isDefault) { 601 return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++; 602 } 603 604 private int assignLayerStackLocked(int displayId) { 605 // Currently layer stacks and display ids are the same. 606 // This need not be the case. 607 return displayId; 608 } 609 610 // Updates all existing logical displays given the current set of display devices. 611 // Removes invalid logical displays. 612 // Sends notifications if needed. 613 private boolean updateLogicalDisplaysLocked() { 614 boolean changed = false; 615 for (int i = mLogicalDisplays.size(); i-- > 0; ) { 616 final int displayId = mLogicalDisplays.keyAt(i); 617 LogicalDisplay display = mLogicalDisplays.valueAt(i); 618 619 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked()); 620 display.updateLocked(mDisplayDevices); 621 if (!display.isValidLocked()) { 622 mLogicalDisplays.removeAt(i); 623 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED); 624 changed = true; 625 } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) { 626 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); 627 changed = true; 628 } 629 } 630 return changed; 631 } 632 633 private void performTraversalInTransactionLocked() { 634 // Perform one last traversal for each removed display device. 635 final int removedCount = mRemovedDisplayDevices.size(); 636 for (int i = 0; i < removedCount; i++) { 637 DisplayDevice device = mRemovedDisplayDevices.get(i); 638 device.performTraversalInTransactionLocked(); 639 } 640 mRemovedDisplayDevices.clear(); 641 642 // Clear all viewports before configuring displays so that we can keep 643 // track of which ones we have configured. 644 clearViewportsLocked(); 645 646 // Configure each display device. 647 final int count = mDisplayDevices.size(); 648 for (int i = 0; i < count; i++) { 649 DisplayDevice device = mDisplayDevices.get(i); 650 configureDisplayInTransactionLocked(device); 651 device.performTraversalInTransactionLocked(); 652 } 653 654 // Tell the input system about these new viewports. 655 if (mInputManagerFuncs != null) { 656 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT); 657 } 658 } 659 660 /** 661 * Tells the display manager whether there is interesting unique content on the 662 * specified logical display. This is used to control automatic mirroring. 663 * <p> 664 * If the display has unique content, then the display manager arranges for it 665 * to be presented on a physical display if appropriate. Otherwise, the display manager 666 * may choose to make the physical display mirror some other logical display. 667 * </p> 668 * 669 * @param displayId The logical display id to update. 670 * @param hasContent True if the logical display has content. 671 * @param inTraversal True if called from WindowManagerService during a window traversal prior 672 * to call to performTraversalInTransactionFromWindowManager. 673 */ 674 public void setDisplayHasContent(int displayId, boolean hasContent, boolean inTraversal) { 675 synchronized (mSyncRoot) { 676 LogicalDisplay display = mLogicalDisplays.get(displayId); 677 if (display != null && display.hasContentLocked() != hasContent) { 678 display.setHasContentLocked(hasContent); 679 scheduleTraversalLocked(inTraversal); 680 } 681 } 682 } 683 684 private void clearViewportsLocked() { 685 mDefaultViewport.valid = false; 686 mExternalTouchViewport.valid = false; 687 } 688 689 private void configureDisplayInTransactionLocked(DisplayDevice device) { 690 // Find the logical display that the display device is showing. 691 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device); 692 if (display != null && !display.hasContentLocked()) { 693 display = null; 694 } 695 if (display == null) { 696 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY); 697 } 698 699 // Apply the logical display configuration to the display device. 700 if (display == null) { 701 // TODO: no logical display for the device, blank it 702 Slog.w(TAG, "Missing logical display to use for physical display device: " 703 + device.getDisplayDeviceInfoLocked()); 704 return; 705 } else { 706 display.configureDisplayInTransactionLocked(device); 707 } 708 709 // Update the viewports if needed. 710 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 711 if (!mDefaultViewport.valid 712 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) { 713 setViewportLocked(mDefaultViewport, display, device); 714 } 715 if (!mExternalTouchViewport.valid 716 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) { 717 setViewportLocked(mExternalTouchViewport, display, device); 718 } 719 } 720 721 private static void setViewportLocked(DisplayViewport viewport, 722 LogicalDisplay display, DisplayDevice device) { 723 viewport.valid = true; 724 viewport.displayId = display.getDisplayIdLocked(); 725 device.populateViewportLocked(viewport); 726 } 727 728 private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) { 729 final int count = mLogicalDisplays.size(); 730 for (int i = 0; i < count; i++) { 731 LogicalDisplay display = mLogicalDisplays.valueAt(i); 732 if (display.getPrimaryDisplayDeviceLocked() == device) { 733 return display; 734 } 735 } 736 return null; 737 } 738 739 private void sendDisplayEventLocked(int displayId, int event) { 740 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event); 741 mHandler.sendMessage(msg); 742 } 743 744 // Requests that performTraversalsInTransactionFromWindowManager be called at a 745 // later time to apply changes to surfaces and displays. 746 private void scheduleTraversalLocked(boolean inTraversal) { 747 if (!mPendingTraversal && mWindowManagerFuncs != null) { 748 mPendingTraversal = true; 749 if (!inTraversal) { 750 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL); 751 } 752 } 753 } 754 755 // Runs on Handler thread. 756 // Delivers display event notifications to callbacks. 757 private void deliverDisplayEvent(int displayId, int event) { 758 if (DEBUG) { 759 Slog.d(TAG, "Delivering display event: displayId=" 760 + displayId + ", event=" + event); 761 } 762 763 // Grab the lock and copy the callbacks. 764 final int count; 765 synchronized (mSyncRoot) { 766 count = mCallbacks.size(); 767 mTempCallbacks.clear(); 768 for (int i = 0; i < count; i++) { 769 mTempCallbacks.add(mCallbacks.valueAt(i)); 770 } 771 } 772 773 // After releasing the lock, send the notifications out. 774 for (int i = 0; i < count; i++) { 775 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event); 776 } 777 mTempCallbacks.clear(); 778 } 779 780 @Override // Binder call 781 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 782 if (mContext == null 783 || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) 784 != PackageManager.PERMISSION_GRANTED) { 785 pw.println("Permission Denial: can't dump DisplayManager from from pid=" 786 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 787 return; 788 } 789 790 pw.println("DISPLAY MANAGER (dumpsys display)"); 791 pw.println(" mHeadless=" + mHeadless); 792 793 synchronized (mSyncRoot) { 794 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 795 ipw.increaseIndent(); 796 797 pw.println(); 798 pw.println("Display Adapters: size=" + mDisplayAdapters.size()); 799 for (DisplayAdapter adapter : mDisplayAdapters) { 800 pw.println(" " + adapter.getName()); 801 adapter.dumpLocked(ipw); 802 } 803 804 pw.println(); 805 pw.println("Display Devices: size=" + mDisplayDevices.size()); 806 for (DisplayDevice device : mDisplayDevices) { 807 pw.println(" " + device.getDisplayDeviceInfoLocked()); 808 device.dumpLocked(ipw); 809 } 810 811 final int logicalDisplayCount = mLogicalDisplays.size(); 812 pw.println(); 813 pw.println("Logical Displays: size=" + logicalDisplayCount); 814 for (int i = 0; i < logicalDisplayCount; i++) { 815 int displayId = mLogicalDisplays.keyAt(i); 816 LogicalDisplay display = mLogicalDisplays.valueAt(i); 817 pw.println(" Display " + displayId + ":"); 818 display.dumpLocked(ipw); 819 } 820 821 pw.println(); 822 pw.println("Default viewport: " + mDefaultViewport); 823 pw.println("External touch viewport: " + mExternalTouchViewport); 824 } 825 } 826 827 /** 828 * This is the object that everything in the display manager locks on. 829 * We make it an inner class within the {@link DisplayManagerService} to so that it is 830 * clear that the object belongs to the display manager service and that it is 831 * a unique object with a special purpose. 832 */ 833 public static final class SyncRoot { 834 } 835 836 /** 837 * Private interface to the window manager. 838 */ 839 public interface WindowManagerFuncs { 840 /** 841 * Request that the window manager call 842 * {@link #performTraversalInTransactionFromWindowManager} within a surface 843 * transaction at a later time. 844 */ 845 void requestTraversal(); 846 } 847 848 /** 849 * Private interface to the input manager. 850 */ 851 public interface InputManagerFuncs { 852 /** 853 * Sets information about the displays as needed by the input system. 854 * The input system should copy this information if required. 855 */ 856 void setDisplayViewports(DisplayViewport defaultViewport, 857 DisplayViewport externalTouchViewport); 858 } 859 860 private final class DisplayManagerHandler extends Handler { 861 public DisplayManagerHandler(Looper looper) { 862 super(looper, null, true /*async*/); 863 } 864 865 @Override 866 public void handleMessage(Message msg) { 867 switch (msg.what) { 868 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER: 869 registerDefaultDisplayAdapter(); 870 break; 871 872 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS: 873 registerAdditionalDisplayAdapters(); 874 break; 875 876 case MSG_DELIVER_DISPLAY_EVENT: 877 deliverDisplayEvent(msg.arg1, msg.arg2); 878 break; 879 880 case MSG_REQUEST_TRAVERSAL: 881 mWindowManagerFuncs.requestTraversal(); 882 break; 883 884 case MSG_UPDATE_VIEWPORT: { 885 synchronized (mSyncRoot) { 886 mTempDefaultViewport.copyFrom(mDefaultViewport); 887 mTempExternalTouchViewport.copyFrom(mExternalTouchViewport); 888 } 889 mInputManagerFuncs.setDisplayViewports( 890 mTempDefaultViewport, mTempExternalTouchViewport); 891 break; 892 } 893 } 894 } 895 } 896 897 private final class DisplayAdapterListener implements DisplayAdapter.Listener { 898 @Override 899 public void onDisplayDeviceEvent(DisplayDevice device, int event) { 900 switch (event) { 901 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED: 902 handleDisplayDeviceAdded(device); 903 break; 904 905 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED: 906 handleDisplayDeviceChanged(device); 907 break; 908 909 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED: 910 handleDisplayDeviceRemoved(device); 911 break; 912 } 913 } 914 915 @Override 916 public void onTraversalRequested() { 917 synchronized (mSyncRoot) { 918 scheduleTraversalLocked(false); 919 } 920 } 921 } 922 923 private final class CallbackRecord implements DeathRecipient { 924 private final int mPid; 925 private final IDisplayManagerCallback mCallback; 926 927 public CallbackRecord(int pid, IDisplayManagerCallback callback) { 928 mPid = pid; 929 mCallback = callback; 930 } 931 932 @Override 933 public void binderDied() { 934 if (DEBUG) { 935 Slog.d(TAG, "Display listener for pid " + mPid + " died."); 936 } 937 onCallbackDied(mPid); 938 } 939 940 public void notifyDisplayEventAsync(int displayId, int event) { 941 try { 942 mCallback.onDisplayEvent(displayId, event); 943 } catch (RemoteException ex) { 944 Slog.w(TAG, "Failed to notify process " 945 + mPid + " that displays changed, assuming it died.", ex); 946 binderDied(); 947 } 948 } 949 } 950} 951