DisplayManagerService.java revision bc335457462a12434a9df6955de1dd693cdccac7
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 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(); 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(); 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(); 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 */ 672 public void setDisplayHasContent(int displayId, boolean hasContent) { 673 synchronized (mSyncRoot) { 674 LogicalDisplay display = mLogicalDisplays.get(displayId); 675 if (display != null && display.hasContentLocked() != hasContent) { 676 display.setHasContentLocked(hasContent); 677 scheduleTraversalLocked(); 678 } 679 } 680 } 681 682 private void clearViewportsLocked() { 683 mDefaultViewport.valid = false; 684 mExternalTouchViewport.valid = false; 685 } 686 687 private void configureDisplayInTransactionLocked(DisplayDevice device) { 688 // Find the logical display that the display device is showing. 689 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device); 690 if (display != null && !display.hasContentLocked()) { 691 display = null; 692 } 693 if (display == null) { 694 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY); 695 } 696 697 // Apply the logical display configuration to the display device. 698 if (display == null) { 699 // TODO: no logical display for the device, blank it 700 Slog.w(TAG, "Missing logical display to use for physical display device: " 701 + device.getDisplayDeviceInfoLocked()); 702 return; 703 } else { 704 display.configureDisplayInTransactionLocked(device); 705 } 706 707 // Update the viewports if needed. 708 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); 709 if (!mDefaultViewport.valid 710 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) { 711 setViewportLocked(mDefaultViewport, display, device); 712 } 713 if (!mExternalTouchViewport.valid 714 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) { 715 setViewportLocked(mExternalTouchViewport, display, device); 716 } 717 } 718 719 private static void setViewportLocked(DisplayViewport viewport, 720 LogicalDisplay display, DisplayDevice device) { 721 viewport.valid = true; 722 viewport.displayId = display.getDisplayIdLocked(); 723 device.populateViewportLocked(viewport); 724 } 725 726 private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) { 727 final int count = mLogicalDisplays.size(); 728 for (int i = 0; i < count; i++) { 729 LogicalDisplay display = mLogicalDisplays.valueAt(i); 730 if (display.getPrimaryDisplayDeviceLocked() == device) { 731 return display; 732 } 733 } 734 return null; 735 } 736 737 private void sendDisplayEventLocked(int displayId, int event) { 738 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event); 739 mHandler.sendMessage(msg); 740 } 741 742 // Requests that performTraversalsInTransactionFromWindowManager be called at a 743 // later time to apply changes to surfaces and displays. 744 private void scheduleTraversalLocked() { 745 if (!mPendingTraversal && mWindowManagerFuncs != null) { 746 mPendingTraversal = true; 747 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL); 748 } 749 } 750 751 // Runs on Handler thread. 752 // Delivers display event notifications to callbacks. 753 private void deliverDisplayEvent(int displayId, int event) { 754 if (DEBUG) { 755 Slog.d(TAG, "Delivering display event: displayId=" 756 + displayId + ", event=" + event); 757 } 758 759 // Grab the lock and copy the callbacks. 760 final int count; 761 synchronized (mSyncRoot) { 762 count = mCallbacks.size(); 763 mTempCallbacks.clear(); 764 for (int i = 0; i < count; i++) { 765 mTempCallbacks.add(mCallbacks.valueAt(i)); 766 } 767 } 768 769 // After releasing the lock, send the notifications out. 770 for (int i = 0; i < count; i++) { 771 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event); 772 } 773 mTempCallbacks.clear(); 774 } 775 776 @Override // Binder call 777 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 778 if (mContext == null 779 || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) 780 != PackageManager.PERMISSION_GRANTED) { 781 pw.println("Permission Denial: can't dump DisplayManager from from pid=" 782 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 783 return; 784 } 785 786 pw.println("DISPLAY MANAGER (dumpsys display)"); 787 pw.println(" mHeadless=" + mHeadless); 788 789 synchronized (mSyncRoot) { 790 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 791 ipw.increaseIndent(); 792 793 pw.println(); 794 pw.println("Display Adapters: size=" + mDisplayAdapters.size()); 795 for (DisplayAdapter adapter : mDisplayAdapters) { 796 pw.println(" " + adapter.getName()); 797 adapter.dumpLocked(ipw); 798 } 799 800 pw.println(); 801 pw.println("Display Devices: size=" + mDisplayDevices.size()); 802 for (DisplayDevice device : mDisplayDevices) { 803 pw.println(" " + device.getDisplayDeviceInfoLocked()); 804 device.dumpLocked(ipw); 805 } 806 807 final int logicalDisplayCount = mLogicalDisplays.size(); 808 pw.println(); 809 pw.println("Logical Displays: size=" + logicalDisplayCount); 810 for (int i = 0; i < logicalDisplayCount; i++) { 811 int displayId = mLogicalDisplays.keyAt(i); 812 LogicalDisplay display = mLogicalDisplays.valueAt(i); 813 pw.println(" Display " + displayId + ":"); 814 display.dumpLocked(ipw); 815 } 816 817 pw.println(); 818 pw.println("Default viewport: " + mDefaultViewport); 819 pw.println("External touch viewport: " + mExternalTouchViewport); 820 } 821 } 822 823 /** 824 * This is the object that everything in the display manager locks on. 825 * We make it an inner class within the {@link DisplayManagerService} to so that it is 826 * clear that the object belongs to the display manager service and that it is 827 * a unique object with a special purpose. 828 */ 829 public static final class SyncRoot { 830 } 831 832 /** 833 * Private interface to the window manager. 834 */ 835 public interface WindowManagerFuncs { 836 /** 837 * Request that the window manager call 838 * {@link #performTraversalInTransactionFromWindowManager} within a surface 839 * transaction at a later time. 840 */ 841 void requestTraversal(); 842 } 843 844 /** 845 * Private interface to the input manager. 846 */ 847 public interface InputManagerFuncs { 848 /** 849 * Sets information about the displays as needed by the input system. 850 * The input system should copy this information if required. 851 */ 852 void setDisplayViewports(DisplayViewport defaultViewport, 853 DisplayViewport externalTouchViewport); 854 } 855 856 private final class DisplayManagerHandler extends Handler { 857 public DisplayManagerHandler(Looper looper) { 858 super(looper, null, true /*async*/); 859 } 860 861 @Override 862 public void handleMessage(Message msg) { 863 switch (msg.what) { 864 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER: 865 registerDefaultDisplayAdapter(); 866 break; 867 868 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS: 869 registerAdditionalDisplayAdapters(); 870 break; 871 872 case MSG_DELIVER_DISPLAY_EVENT: 873 deliverDisplayEvent(msg.arg1, msg.arg2); 874 break; 875 876 case MSG_REQUEST_TRAVERSAL: 877 mWindowManagerFuncs.requestTraversal(); 878 break; 879 880 case MSG_UPDATE_VIEWPORT: { 881 synchronized (mSyncRoot) { 882 mTempDefaultViewport.copyFrom(mDefaultViewport); 883 mTempExternalTouchViewport.copyFrom(mExternalTouchViewport); 884 } 885 mInputManagerFuncs.setDisplayViewports( 886 mTempDefaultViewport, mTempExternalTouchViewport); 887 break; 888 } 889 } 890 } 891 } 892 893 private final class DisplayAdapterListener implements DisplayAdapter.Listener { 894 @Override 895 public void onDisplayDeviceEvent(DisplayDevice device, int event) { 896 switch (event) { 897 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED: 898 handleDisplayDeviceAdded(device); 899 break; 900 901 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED: 902 handleDisplayDeviceChanged(device); 903 break; 904 905 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED: 906 handleDisplayDeviceRemoved(device); 907 break; 908 } 909 } 910 911 @Override 912 public void onTraversalRequested() { 913 synchronized (mSyncRoot) { 914 scheduleTraversalLocked(); 915 } 916 } 917 } 918 919 private final class CallbackRecord implements DeathRecipient { 920 private final int mPid; 921 private final IDisplayManagerCallback mCallback; 922 923 public CallbackRecord(int pid, IDisplayManagerCallback callback) { 924 mPid = pid; 925 mCallback = callback; 926 } 927 928 @Override 929 public void binderDied() { 930 if (DEBUG) { 931 Slog.d(TAG, "Display listener for pid " + mPid + " died."); 932 } 933 onCallbackDied(mPid); 934 } 935 936 public void notifyDisplayEventAsync(int displayId, int event) { 937 try { 938 mCallback.onDisplayEvent(displayId, event); 939 } catch (RemoteException ex) { 940 Slog.w(TAG, "Failed to notify process " 941 + mPid + " that displays changed, assuming it died.", ex); 942 binderDied(); 943 } 944 } 945 } 946} 947