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