DisplayManagerService.java revision bd6e1500aedc5461e832f69e76341bff0e55fa2b
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.os.Binder; 28import android.os.Handler; 29import android.os.IBinder; 30import android.os.Looper; 31import android.os.Message; 32import android.os.RemoteException; 33import android.os.SystemClock; 34import android.os.SystemProperties; 35import android.util.Slog; 36import android.util.SparseArray; 37import android.view.Display; 38import android.view.DisplayInfo; 39import android.view.Surface; 40 41import java.io.FileDescriptor; 42import java.io.PrintWriter; 43import java.io.StringWriter; 44import java.util.ArrayList; 45 46/** 47 * Manages attached displays. 48 * <p> 49 * The {@link DisplayManagerService} manages the global lifecycle of displays, 50 * decides how to configure logical displays based on the physical display devices currently 51 * attached, sends notifications to the system and to applications when the state 52 * changes, and so on. 53 * </p><p> 54 * The display manager service relies on a collection of {@link DisplayAdapter} components, 55 * for discovering and configuring physical display devices attached to the system. 56 * There are separate display adapters for each manner that devices are attached: 57 * one display adapter for built-in local displays, one for simulated non-functional 58 * displays when the system is headless, one for simulated overlay displays used for 59 * development, one for wifi displays, etc. 60 * </p><p> 61 * Display adapters are only weakly coupled to the display manager service. 62 * Display adapters communicate changes in display device state to the display manager 63 * service asynchronously via a {@link DisplayAdapter.DisplayAdapterListener} registered 64 * by the display manager service. This separation of concerns is important for 65 * two main reasons. First, it neatly encapsulates the responsibilities of these 66 * two classes: display adapters handle individual display devices whereas 67 * the display manager service handles the global state. Second, it eliminates 68 * the potential for deadlocks resulting from asynchronous display device discovery. 69 * </p><p> 70 * To keep things simple, display adapters and display devices are single-threaded 71 * and are only accessed on the display manager's handler thread. Of course, the 72 * display manager must be accessible by multiple thread (especially for 73 * incoming binder calls) so all of the display manager's state is synchronized 74 * and guarded by a lock. 75 * </p> 76 */ 77public final class DisplayManagerService extends IDisplayManager.Stub { 78 private static final String TAG = "DisplayManagerService"; 79 private static final boolean DEBUG = false; 80 81 private static final String SYSTEM_HEADLESS = "ro.config.headless"; 82 private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000; 83 84 private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER = 1; 85 private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2; 86 private static final int MSG_DELIVER_DISPLAY_EVENT = 3; 87 88 private final Object mLock = new Object(); 89 90 private final Context mContext; 91 private final boolean mHeadless; 92 93 private final DisplayManagerHandler mHandler; 94 private final DisplayAdapterListener mDisplayAdapterListener = new DisplayAdapterListener(); 95 private final SparseArray<CallbackRecord> mCallbacks = 96 new SparseArray<CallbackRecord>(); 97 98 // List of all currently registered display adapters. 99 private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>(); 100 101 // List of all currently connected display devices. 102 private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>(); 103 104 // List of all logical displays, indexed by logical display id. 105 private final SparseArray<LogicalDisplay> mLogicalDisplays = new SparseArray<LogicalDisplay>(); 106 private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1; 107 108 // True if in safe mode. 109 // This option may disable certain display adapters. 110 private boolean mSafeMode; 111 112 // True if we are in a special boot mode where only core applications and 113 // services should be started. This option may disable certain display adapters. 114 private boolean mOnlyCore; 115 116 // Temporary callback list, used when sending display events to applications. 117 private ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>(); 118 119 public DisplayManagerService(Context context, Handler uiHandler) { 120 mContext = context; 121 mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1"); 122 123 mHandler = new DisplayManagerHandler(uiHandler.getLooper()); 124 mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER); 125 } 126 127 /** 128 * Pauses the boot process to wait for the first display to be initialized. 129 */ 130 public boolean waitForDefaultDisplay() { 131 synchronized (mLock) { 132 long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT; 133 while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) { 134 long delay = timeout - SystemClock.uptimeMillis(); 135 if (delay <= 0) { 136 return false; 137 } 138 if (DEBUG) { 139 Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay); 140 } 141 try { 142 mLock.wait(delay); 143 } catch (InterruptedException ex) { 144 } 145 } 146 } 147 return true; 148 } 149 150 /** 151 * Called when the system is ready to go. 152 */ 153 public void systemReady(boolean safeMode, boolean onlyCore) { 154 synchronized (mLock) { 155 mSafeMode = safeMode; 156 mOnlyCore = onlyCore; 157 } 158 mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS); 159 } 160 161 // Runs on handler. 162 private void registerDefaultDisplayAdapter() { 163 // Register default display adapter. 164 if (mHeadless) { 165 registerDisplayAdapter(new HeadlessDisplayAdapter(mContext)); 166 } else { 167 registerDisplayAdapter(new LocalDisplayAdapter(mContext)); 168 } 169 } 170 171 // Runs on handler. 172 private void registerAdditionalDisplayAdapters() { 173 if (shouldRegisterNonEssentialDisplayAdapters()) { 174 registerDisplayAdapter(new OverlayDisplayAdapter(mContext)); 175 } 176 } 177 178 private boolean shouldRegisterNonEssentialDisplayAdapters() { 179 // In safe mode, we disable non-essential display adapters to give the user 180 // an opportunity to fix broken settings or other problems that might affect 181 // system stability. 182 // In only-core mode, we disable non-essential display adapters to minimize 183 // the number of dependencies that are started while in this mode and to 184 // prevent problems that might occur due to the device being encrypted. 185 synchronized (mLock) { 186 return !mSafeMode && !mOnlyCore; 187 } 188 } 189 190 // Runs on handler. 191 private void registerDisplayAdapter(DisplayAdapter adapter) { 192 synchronized (mLock) { 193 mDisplayAdapters.add(adapter); 194 } 195 196 adapter.register(mDisplayAdapterListener); 197 } 198 199 // FIXME: this isn't the right API for the long term 200 public void getDefaultExternalDisplayDeviceInfo(DisplayDeviceInfo info) { 201 // hardcoded assuming 720p touch screen plugged into HDMI and USB 202 // need to redesign this 203 info.width = 1280; 204 info.height = 720; 205 } 206 207 /** 208 * Returns true if the device is headless. 209 * 210 * @return True if the device is headless. 211 */ 212 public boolean isHeadless() { 213 return mHeadless; 214 } 215 216 /** 217 * Sets the new logical display orientation. 218 * 219 * @param displayId The logical display id. 220 * @param orientation One of the Surface.ROTATION_* constants. 221 */ 222 public void setDisplayOrientation(int displayId, int orientation) { 223 synchronized (mLock) { 224 // TODO: update mirror transforms 225 LogicalDisplay display = mLogicalDisplays.get(displayId); 226 if (display != null && display.mPrimaryDisplayDevice != null) { 227 IBinder displayToken = display.mPrimaryDisplayDevice.getDisplayToken(); 228 if (displayToken != null) { 229 Surface.openTransaction(); 230 try { 231 Surface.setDisplayOrientation(displayToken, orientation); 232 } finally { 233 Surface.closeTransaction(); 234 } 235 } 236 237 display.mBaseDisplayInfo.rotation = orientation; 238 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); 239 } 240 } 241 } 242 243 /** 244 * Overrides the display information of a particular logical display. 245 * This is used by the window manager to control the size and characteristics 246 * of the default display. 247 * 248 * @param displayId The logical display id. 249 * @param info The new data to be stored. 250 */ 251 public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) { 252 synchronized (mLock) { 253 LogicalDisplay display = mLogicalDisplays.get(displayId); 254 if (display != null) { 255 if (info != null) { 256 if (display.mOverrideDisplayInfo == null) { 257 display.mOverrideDisplayInfo = new DisplayInfo(); 258 } 259 display.mOverrideDisplayInfo.copyFrom(info); 260 } else { 261 display.mOverrideDisplayInfo = null; 262 } 263 264 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); 265 } 266 } 267 } 268 269 /** 270 * Returns information about the specified logical display. 271 * 272 * @param displayId The logical display id. 273 * @param The logical display info, or null if the display does not exist. 274 */ 275 @Override // Binder call 276 public DisplayInfo getDisplayInfo(int displayId) { 277 synchronized (mLock) { 278 LogicalDisplay display = mLogicalDisplays.get(displayId); 279 if (display != null) { 280 if (display.mOverrideDisplayInfo != null) { 281 return new DisplayInfo(display.mOverrideDisplayInfo); 282 } 283 return new DisplayInfo(display.mBaseDisplayInfo); 284 } 285 return null; 286 } 287 } 288 289 @Override // Binder call 290 public int[] getDisplayIds() { 291 synchronized (mLock) { 292 final int count = mLogicalDisplays.size(); 293 int[] displayIds = new int[count]; 294 for (int i = 0; i > count; i++) { 295 displayIds[i] = mLogicalDisplays.keyAt(i); 296 } 297 return displayIds; 298 } 299 } 300 301 @Override // Binder call 302 public void registerCallback(IDisplayManagerCallback callback) { 303 if (callback == null) { 304 throw new IllegalArgumentException("listener must not be null"); 305 } 306 307 synchronized (mLock) { 308 int callingPid = Binder.getCallingPid(); 309 if (mCallbacks.get(callingPid) != null) { 310 throw new SecurityException("The calling process has already " 311 + "registered an IDisplayManagerCallback."); 312 } 313 314 CallbackRecord record = new CallbackRecord(callingPid, callback); 315 try { 316 IBinder binder = callback.asBinder(); 317 binder.linkToDeath(record, 0); 318 } catch (RemoteException ex) { 319 // give up 320 throw new RuntimeException(ex); 321 } 322 323 mCallbacks.put(callingPid, record); 324 } 325 } 326 327 private void onCallbackDied(int pid) { 328 synchronized (mLock) { 329 mCallbacks.remove(pid); 330 } 331 } 332 333 // Runs on handler. 334 private void handleDisplayDeviceAdded(DisplayDevice device) { 335 synchronized (mLock) { 336 if (mDisplayDevices.contains(device)) { 337 Slog.w(TAG, "Attempted to add already added display device: " + device); 338 return; 339 } 340 341 mDisplayDevices.add(device); 342 343 LogicalDisplay display = new LogicalDisplay(device); 344 display.updateFromPrimaryDisplayDevice(); 345 346 boolean isDefault = (display.mPrimaryDisplayDeviceInfo.flags 347 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0; 348 if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) { 349 Slog.w(TAG, "Attempted to add a second default device: " + device); 350 isDefault = false; 351 } 352 353 int displayId = isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++; 354 mLogicalDisplays.put(displayId, display); 355 356 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED); 357 358 // Wake up waitForDefaultDisplay. 359 if (isDefault) { 360 mLock.notifyAll(); 361 } 362 } 363 } 364 365 // Runs on handler. 366 private void handleDisplayDeviceChanged(DisplayDevice device) { 367 synchronized (mLock) { 368 if (!mDisplayDevices.contains(device)) { 369 Slog.w(TAG, "Attempted to change non-existent display device: " + device); 370 return; 371 } 372 373 for (int i = mLogicalDisplays.size(); i-- > 0; ) { 374 LogicalDisplay display = mLogicalDisplays.valueAt(i); 375 if (display.mPrimaryDisplayDevice == device) { 376 final int displayId = mLogicalDisplays.keyAt(i); 377 display.updateFromPrimaryDisplayDevice(); 378 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED); 379 } 380 } 381 } 382 } 383 384 // Runs on handler. 385 private void handleDisplayDeviceRemoved(DisplayDevice device) { 386 synchronized (mLock) { 387 if (!mDisplayDevices.remove(device)) { 388 Slog.w(TAG, "Attempted to remove non-existent display device: " + device); 389 return; 390 } 391 392 for (int i = mLogicalDisplays.size(); i-- > 0; ) { 393 LogicalDisplay display = mLogicalDisplays.valueAt(i); 394 if (display.mPrimaryDisplayDevice == device) { 395 final int displayId = mLogicalDisplays.keyAt(i); 396 mLogicalDisplays.removeAt(i); 397 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED); 398 } 399 } 400 } 401 } 402 403 // Posts a message to send a display event at the next opportunity. 404 private void sendDisplayEventLocked(int displayId, int event) { 405 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event); 406 mHandler.sendMessage(msg); 407 } 408 409 // Runs on handler. 410 // This method actually sends display event notifications. 411 // Note that it must be very careful not to be holding the lock while sending 412 // is in progress. 413 private void deliverDisplayEvent(int displayId, int event) { 414 if (DEBUG) { 415 Slog.d(TAG, "Delivering display event: displayId=" + displayId + ", event=" + event); 416 } 417 418 final int count; 419 synchronized (mLock) { 420 count = mCallbacks.size(); 421 mTempCallbacks.clear(); 422 for (int i = 0; i < count; i++) { 423 mTempCallbacks.add(mCallbacks.valueAt(i)); 424 } 425 } 426 427 for (int i = 0; i < count; i++) { 428 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event); 429 } 430 mTempCallbacks.clear(); 431 } 432 433 @Override // Binder call 434 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 435 if (mContext == null 436 || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) 437 != PackageManager.PERMISSION_GRANTED) { 438 pw.println("Permission Denial: can't dump DisplayManager from from pid=" 439 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 440 return; 441 } 442 443 pw.println("DISPLAY MANAGER (dumpsys display)"); 444 pw.println(" mHeadless=" + mHeadless); 445 446 mHandler.runWithScissors(new Runnable() { 447 @Override 448 public void run() { 449 dumpLocal(pw); 450 } 451 }); 452 } 453 454 // Runs on handler. 455 private void dumpLocal(PrintWriter pw) { 456 synchronized (mLock) { 457 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 458 459 pw.println(); 460 pw.println("Display Adapters: size=" + mDisplayAdapters.size()); 461 for (DisplayAdapter adapter : mDisplayAdapters) { 462 pw.println(" " + adapter.getName()); 463 adapter.dump(ipw); 464 } 465 466 pw.println(); 467 pw.println("Display Devices: size=" + mDisplayDevices.size()); 468 for (DisplayDevice device : mDisplayDevices) { 469 pw.println(" " + device); 470 } 471 472 final int logicalDisplayCount = mLogicalDisplays.size(); 473 pw.println(); 474 pw.println("Logical Displays: size=" + logicalDisplayCount); 475 for (int i = 0; i < logicalDisplayCount; i++) { 476 int displayId = mLogicalDisplays.keyAt(i); 477 LogicalDisplay display = mLogicalDisplays.valueAt(i); 478 pw.println(" Display " + displayId + ":"); 479 pw.println(" mPrimaryDisplayDevice=" + display.mPrimaryDisplayDevice); 480 pw.println(" mBaseDisplayInfo=" + display.mBaseDisplayInfo); 481 pw.println(" mOverrideDisplayInfo=" 482 + display.mOverrideDisplayInfo); 483 } 484 } 485 } 486 487 private final class DisplayManagerHandler extends Handler { 488 public DisplayManagerHandler(Looper looper) { 489 super(looper, null, true /*async*/); 490 } 491 492 @Override 493 public void handleMessage(Message msg) { 494 switch (msg.what) { 495 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER: 496 registerDefaultDisplayAdapter(); 497 break; 498 499 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS: 500 registerAdditionalDisplayAdapters(); 501 break; 502 503 case MSG_DELIVER_DISPLAY_EVENT: 504 deliverDisplayEvent(msg.arg1, msg.arg2); 505 break; 506 } 507 } 508 } 509 510 private final class DisplayAdapterListener implements DisplayAdapter.Listener { 511 @Override 512 public void onDisplayDeviceEvent(DisplayDevice device, int event) { 513 switch (event) { 514 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED: 515 handleDisplayDeviceAdded(device); 516 break; 517 518 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED: 519 handleDisplayDeviceChanged(device); 520 break; 521 522 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED: 523 handleDisplayDeviceRemoved(device); 524 break; 525 } 526 } 527 } 528 529 private final class CallbackRecord implements DeathRecipient { 530 private final int mPid; 531 private final IDisplayManagerCallback mCallback; 532 533 public CallbackRecord(int pid, IDisplayManagerCallback callback) { 534 mPid = pid; 535 mCallback = callback; 536 } 537 538 @Override 539 public void binderDied() { 540 if (DEBUG) { 541 Slog.d(TAG, "Display listener for pid " + mPid + " died."); 542 } 543 onCallbackDied(mPid); 544 } 545 546 public void notifyDisplayEventAsync(int displayId, int event) { 547 try { 548 mCallback.onDisplayEvent(displayId, event); 549 } catch (RemoteException ex) { 550 Slog.w(TAG, "Failed to notify process " 551 + mPid + " that displays changed, assuming it died.", ex); 552 binderDied(); 553 } 554 } 555 } 556 557 /** 558 * Each logical display is primarily associated with one display device. 559 * The primary display device is nominally responsible for the basic properties 560 * of the logical display such as its size, refresh rate, and dpi. 561 * 562 * A logical display may be mirrored onto other display devices besides its 563 * primary display device, but it always remains bound to its primary. 564 * Note that the contents of a logical display may not always be visible, even 565 * on its primary display device, such as in the case where the logical display's 566 * primary display device is currently mirroring content from a different logical display. 567 */ 568 private final static class LogicalDisplay { 569 public final DisplayInfo mBaseDisplayInfo = new DisplayInfo(); 570 public DisplayInfo mOverrideDisplayInfo; // set by the window manager 571 572 public final DisplayDevice mPrimaryDisplayDevice; 573 public final DisplayDeviceInfo mPrimaryDisplayDeviceInfo = new DisplayDeviceInfo(); 574 575 public LogicalDisplay(DisplayDevice primaryDisplayDevice) { 576 mPrimaryDisplayDevice = primaryDisplayDevice; 577 } 578 579 public void updateFromPrimaryDisplayDevice() { 580 // Bootstrap the logical display using its associated primary physical display. 581 mPrimaryDisplayDevice.getInfo(mPrimaryDisplayDeviceInfo); 582 583 mBaseDisplayInfo.appWidth = mPrimaryDisplayDeviceInfo.width; 584 mBaseDisplayInfo.appHeight = mPrimaryDisplayDeviceInfo.height; 585 mBaseDisplayInfo.logicalWidth = mPrimaryDisplayDeviceInfo.width; 586 mBaseDisplayInfo.logicalHeight = mPrimaryDisplayDeviceInfo.height; 587 mBaseDisplayInfo.rotation = Surface.ROTATION_0; 588 mBaseDisplayInfo.refreshRate = mPrimaryDisplayDeviceInfo.refreshRate; 589 mBaseDisplayInfo.logicalDensityDpi = mPrimaryDisplayDeviceInfo.densityDpi; 590 mBaseDisplayInfo.physicalXDpi = mPrimaryDisplayDeviceInfo.xDpi; 591 mBaseDisplayInfo.physicalYDpi = mPrimaryDisplayDeviceInfo.yDpi; 592 mBaseDisplayInfo.smallestNominalAppWidth = mPrimaryDisplayDeviceInfo.width; 593 mBaseDisplayInfo.smallestNominalAppHeight = mPrimaryDisplayDeviceInfo.height; 594 mBaseDisplayInfo.largestNominalAppWidth = mPrimaryDisplayDeviceInfo.width; 595 mBaseDisplayInfo.largestNominalAppHeight = mPrimaryDisplayDeviceInfo.height; 596 } 597 } 598} 599