blob: e11d454756686b65d51967642aaf54a8c0ec3406 [file] [log] [blame]
Jeff Brownfa25bf52012-07-23 19:26:30 -07001/*
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
Jeff Brownbd6e1502012-08-28 03:27:37 -070019import com.android.internal.util.IndentingPrintWriter;
20
Jeff Brownfa25bf52012-07-23 19:26:30 -070021import android.Manifest;
22import android.content.Context;
23import android.content.pm.PackageManager;
Jeff Brownbd6e1502012-08-28 03:27:37 -070024import android.hardware.display.DisplayManagerGlobal;
Jeff Brownfa25bf52012-07-23 19:26:30 -070025import android.hardware.display.IDisplayManager;
Jeff Brownbd6e1502012-08-28 03:27:37 -070026import android.hardware.display.IDisplayManagerCallback;
Jeff Browne08ae382012-09-07 20:36:36 -070027import android.hardware.display.WifiDisplayStatus;
Jeff Brownfa25bf52012-07-23 19:26:30 -070028import android.os.Binder;
Jeff Brownbd6e1502012-08-28 03:27:37 -070029import android.os.Handler;
Jeff Brown64a55af2012-08-26 02:47:39 -070030import android.os.IBinder;
Jeff Brownbd6e1502012-08-28 03:27:37 -070031import android.os.Looper;
32import android.os.Message;
33import android.os.RemoteException;
34import android.os.SystemClock;
Jeff Brownfa25bf52012-07-23 19:26:30 -070035import android.os.SystemProperties;
Jeff Brownbd6e1502012-08-28 03:27:37 -070036import android.util.Slog;
37import android.util.SparseArray;
Jeff Brownfa25bf52012-07-23 19:26:30 -070038import android.view.Display;
39import android.view.DisplayInfo;
Jeff Brownfa25bf52012-07-23 19:26:30 -070040
41import java.io.FileDescriptor;
42import java.io.PrintWriter;
43import java.util.ArrayList;
44
45/**
Jeff Brownbd6e1502012-08-28 03:27:37 -070046 * Manages attached displays.
Jeff Brownfa25bf52012-07-23 19:26:30 -070047 * <p>
Jeff Brownbd6e1502012-08-28 03:27:37 -070048 * 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
Craig Mautner722285e2012-09-07 13:55:58 -070062 * service asynchronously via a {@link DisplayAdapter.Listener} registered
Jeff Brownbd6e1502012-08-28 03:27:37 -070063 * 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.
Jeff Brown4ed8fe72012-08-30 18:18:29 -070068 * </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*).
Jeff Brownbd6e1502012-08-28 03:27:37 -070077 * </p><p>
Jeff Brown4ed8fe72012-08-30 18:18:29 -070078 * 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.
Jeff Brownfa25bf52012-07-23 19:26:30 -070086 * </p>
87 */
88public final class DisplayManagerService extends IDisplayManager.Stub {
89 private static final String TAG = "DisplayManagerService";
Jeff Brownbd6e1502012-08-28 03:27:37 -070090 private static final boolean DEBUG = false;
Jeff Brownfa25bf52012-07-23 19:26:30 -070091
92 private static final String SYSTEM_HEADLESS = "ro.config.headless";
Jeff Brownbd6e1502012-08-28 03:27:37 -070093 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;
Jeff Brown4ed8fe72012-08-30 18:18:29 -070098 private static final int MSG_REQUEST_TRAVERSAL = 4;
Jeff Brownd728bf52012-09-08 18:05:28 -070099 private static final int MSG_UPDATE_VIEWPORT = 5;
Jeff Brownfa25bf52012-07-23 19:26:30 -0700100
Jeff Brown848c2dc2012-08-19 20:18:08 -0700101 private final Context mContext;
Jeff Brownfa25bf52012-07-23 19:26:30 -0700102 private final boolean mHeadless;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700103 private final DisplayManagerHandler mHandler;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700104 private final Handler mUiHandler;
105 private final DisplayAdapterListener mDisplayAdapterListener;
106 private WindowManagerFuncs mWindowManagerFuncs;
Jeff Brownd728bf52012-09-08 18:05:28 -0700107 private InputManagerFuncs mInputManagerFuncs;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700108
109 // The synchronization root for the display manager.
110 // This lock guards most of the display manager's state.
111 private final SyncRoot mSyncRoot = new SyncRoot();
112
113 // True if in safe mode.
114 // This option may disable certain display adapters.
115 public boolean mSafeMode;
116
117 // True if we are in a special boot mode where only core applications and
118 // services should be started. This option may disable certain display adapters.
119 public boolean mOnlyCore;
120
121 // All callback records indexed by calling process id.
122 public final SparseArray<CallbackRecord> mCallbacks =
Jeff Brownbd6e1502012-08-28 03:27:37 -0700123 new SparseArray<CallbackRecord>();
Jeff Brownfa25bf52012-07-23 19:26:30 -0700124
Jeff Brownbd6e1502012-08-28 03:27:37 -0700125 // List of all currently registered display adapters.
126 private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
127
128 // List of all currently connected display devices.
129 private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>();
130
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700131 // List of all removed display devices.
132 private final ArrayList<DisplayDevice> mRemovedDisplayDevices = new ArrayList<DisplayDevice>();
133
134 // List of all logical displays indexed by logical display id.
135 private final SparseArray<LogicalDisplay> mLogicalDisplays =
136 new SparseArray<LogicalDisplay>();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700137 private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
138
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700139 // Set to true when there are pending display changes that have yet to be applied
140 // to the surface flinger state.
141 private boolean mPendingTraversal;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700142
Jeff Browne08ae382012-09-07 20:36:36 -0700143 // The Wifi display adapter, or null if not registered.
144 private WifiDisplayAdapter mWifiDisplayAdapter;
145
Jeff Brownd728bf52012-09-08 18:05:28 -0700146 // Viewports of the default display and the display that should receive touch
147 // input from an external source. Used by the input system.
148 private final DisplayViewport mDefaultViewport = new DisplayViewport();
149 private final DisplayViewport mExternalTouchViewport = new DisplayViewport();
150
Jeff Brownbd6e1502012-08-28 03:27:37 -0700151 // Temporary callback list, used when sending display events to applications.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700152 // May be used outside of the lock but only on the handler thread.
153 private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700154
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700155 // Temporary display info, used for comparing display configurations.
156 private final DisplayInfo mTempDisplayInfo = new DisplayInfo();
157
Jeff Brownd728bf52012-09-08 18:05:28 -0700158 // Temporary viewports, used when sending new viewport information to the
159 // input system. May be used outside of the lock but only on the handler thread.
160 private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
161 private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
162
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700163 public DisplayManagerService(Context context, Handler mainHandler, Handler uiHandler) {
Jeff Brown848c2dc2012-08-19 20:18:08 -0700164 mContext = context;
Jeff Brownfa25bf52012-07-23 19:26:30 -0700165 mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1");
Jeff Brown848c2dc2012-08-19 20:18:08 -0700166
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700167 mHandler = new DisplayManagerHandler(mainHandler.getLooper());
168 mUiHandler = uiHandler;
169 mDisplayAdapterListener = new DisplayAdapterListener();
170
Jeff Brownbd6e1502012-08-28 03:27:37 -0700171 mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
Craig Mautner4f67ba62012-08-02 11:23:00 -0700172 }
173
Jeff Brownbd6e1502012-08-28 03:27:37 -0700174 /**
175 * Pauses the boot process to wait for the first display to be initialized.
176 */
177 public boolean waitForDefaultDisplay() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700178 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700179 long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
180 while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) {
181 long delay = timeout - SystemClock.uptimeMillis();
182 if (delay <= 0) {
183 return false;
184 }
185 if (DEBUG) {
186 Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
187 }
188 try {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700189 mSyncRoot.wait(delay);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700190 } catch (InterruptedException ex) {
191 }
192 }
193 }
194 return true;
195 }
196
197 /**
Jeff Brownd728bf52012-09-08 18:05:28 -0700198 * Called during initialization to associate the display manager with the
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700199 * window manager.
200 */
201 public void setWindowManager(WindowManagerFuncs windowManagerFuncs) {
202 synchronized (mSyncRoot) {
203 mWindowManagerFuncs = windowManagerFuncs;
204 scheduleTraversalLocked();
205 }
206 }
207
208 /**
Jeff Brownd728bf52012-09-08 18:05:28 -0700209 * Called during initialization to associate the display manager with the
210 * input manager.
211 */
212 public void setInputManager(InputManagerFuncs inputManagerFuncs) {
213 synchronized (mSyncRoot) {
214 mInputManagerFuncs = inputManagerFuncs;
215 scheduleTraversalLocked();
216 }
217 }
218
219 /**
Jeff Brownbd6e1502012-08-28 03:27:37 -0700220 * Called when the system is ready to go.
221 */
222 public void systemReady(boolean safeMode, boolean onlyCore) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700223 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700224 mSafeMode = safeMode;
225 mOnlyCore = onlyCore;
226 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700227
Jeff Brownbd6e1502012-08-28 03:27:37 -0700228 mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
229 }
230
Jeff Brown848c2dc2012-08-19 20:18:08 -0700231 /**
232 * Returns true if the device is headless.
233 *
234 * @return True if the device is headless.
235 */
Jeff Brownfa25bf52012-07-23 19:26:30 -0700236 public boolean isHeadless() {
237 return mHeadless;
238 }
239
Craig Mautner4f67ba62012-08-02 11:23:00 -0700240 /**
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700241 * Overrides the display information of a particular logical display.
242 * This is used by the window manager to control the size and characteristics
243 * of the default display. It is expected to apply the requested change
244 * to the display information synchronously so that applications will immediately
245 * observe the new state.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700246 *
Jeff Brown64a55af2012-08-26 02:47:39 -0700247 * @param displayId The logical display id.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700248 * @param info The new data to be stored.
Jeff Brown64a55af2012-08-26 02:47:39 -0700249 */
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700250 public void setDisplayInfoOverrideFromWindowManager(
251 int displayId, DisplayInfo info) {
252 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700253 LogicalDisplay display = mLogicalDisplays.get(displayId);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700254 if (display != null) {
255 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
256 display.setDisplayInfoOverrideFromWindowManagerLocked(info);
257 if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
258 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
259 scheduleTraversalLocked();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700260 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700261 }
262 }
263 }
264
265 /**
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700266 * Called by the window manager to perform traversals while holding a
267 * surface flinger transaction.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700268 */
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700269 public void performTraversalInTransactionFromWindowManager() {
270 synchronized (mSyncRoot) {
271 if (!mPendingTraversal) {
272 return;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700273 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700274 mPendingTraversal = false;
275
276 performTraversalInTransactionLocked();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700277 }
278 }
279
280 /**
281 * Returns information about the specified logical display.
282 *
283 * @param displayId The logical display id.
Craig Mautner722285e2012-09-07 13:55:58 -0700284 * @return The logical display info, or null if the display does not exist. The
285 * returned object must be treated as immutable.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700286 */
287 @Override // Binder call
288 public DisplayInfo getDisplayInfo(int displayId) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700289 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700290 LogicalDisplay display = mLogicalDisplays.get(displayId);
291 if (display != null) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700292 return display.getDisplayInfoLocked();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700293 }
294 return null;
295 }
296 }
297
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700298 /**
299 * Returns the list of all display ids.
300 */
Jeff Brownbd6e1502012-08-28 03:27:37 -0700301 @Override // Binder call
302 public int[] getDisplayIds() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700303 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700304 final int count = mLogicalDisplays.size();
305 int[] displayIds = new int[count];
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700306 for (int i = 0; i < count; i++) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700307 displayIds[i] = mLogicalDisplays.keyAt(i);
308 }
309 return displayIds;
310 }
311 }
312
313 @Override // Binder call
314 public void registerCallback(IDisplayManagerCallback callback) {
315 if (callback == null) {
316 throw new IllegalArgumentException("listener must not be null");
317 }
318
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700319 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700320 int callingPid = Binder.getCallingPid();
321 if (mCallbacks.get(callingPid) != null) {
322 throw new SecurityException("The calling process has already "
323 + "registered an IDisplayManagerCallback.");
Jeff Brown64a55af2012-08-26 02:47:39 -0700324 }
325
Jeff Brownbd6e1502012-08-28 03:27:37 -0700326 CallbackRecord record = new CallbackRecord(callingPid, callback);
327 try {
328 IBinder binder = callback.asBinder();
329 binder.linkToDeath(record, 0);
330 } catch (RemoteException ex) {
331 // give up
332 throw new RuntimeException(ex);
333 }
334
335 mCallbacks.put(callingPid, record);
336 }
337 }
338
339 private void onCallbackDied(int pid) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700340 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700341 mCallbacks.remove(pid);
342 }
343 }
344
Jeff Browne08ae382012-09-07 20:36:36 -0700345 @Override // Binder call
346 public void scanWifiDisplays() {
347 if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
348 != PackageManager.PERMISSION_GRANTED) {
349 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission");
350 }
351
352 final long token = Binder.clearCallingIdentity();
353 try {
354 synchronized (mSyncRoot) {
355 mWifiDisplayAdapter.requestScanLocked();
356 }
357 } finally {
358 Binder.restoreCallingIdentity(token);
359 }
360 }
361
362 @Override // Binder call
363 public void connectWifiDisplay(String address) {
364 if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
365 != PackageManager.PERMISSION_GRANTED) {
366 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission");
367 }
368 if (address == null) {
369 throw new IllegalArgumentException("address must not be null");
370 }
371
372 final long token = Binder.clearCallingIdentity();
373 try {
374 synchronized (mSyncRoot) {
375 mWifiDisplayAdapter.requestConnectLocked(address);
376 }
377 } finally {
378 Binder.restoreCallingIdentity(token);
379 }
380 }
381
382 @Override // Binder call
383 public void disconnectWifiDisplay() {
384 if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
385 != PackageManager.PERMISSION_GRANTED) {
386 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission");
387 }
388
389 final long token = Binder.clearCallingIdentity();
390 try {
391 synchronized (mSyncRoot) {
392 mWifiDisplayAdapter.requestDisconnectLocked();
393 }
394 } finally {
395 Binder.restoreCallingIdentity(token);
396 }
397 }
398
399 @Override // Binder call
400 public WifiDisplayStatus getWifiDisplayStatus() {
401 if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
402 != PackageManager.PERMISSION_GRANTED) {
403 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission");
404 }
405
406 final long token = Binder.clearCallingIdentity();
407 try {
408 synchronized (mSyncRoot) {
409 return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
410 }
411 } finally {
412 Binder.restoreCallingIdentity(token);
413 }
414 }
415
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700416 private void registerDefaultDisplayAdapter() {
417 // Register default display adapter.
418 synchronized (mSyncRoot) {
419 if (mHeadless) {
420 registerDisplayAdapterLocked(new HeadlessDisplayAdapter(
421 mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
422 } else {
423 registerDisplayAdapterLocked(new LocalDisplayAdapter(
424 mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
425 }
426 }
427 }
428
429 private void registerAdditionalDisplayAdapters() {
430 synchronized (mSyncRoot) {
431 if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
432 registerDisplayAdapterLocked(new OverlayDisplayAdapter(
433 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
Jeff Browne08ae382012-09-07 20:36:36 -0700434 mWifiDisplayAdapter = new WifiDisplayAdapter(
435 mSyncRoot, mContext, mHandler, mDisplayAdapterListener);
436 registerDisplayAdapterLocked(mWifiDisplayAdapter);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700437 }
438 }
439 }
440
441 private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
442 // In safe mode, we disable non-essential display adapters to give the user
443 // an opportunity to fix broken settings or other problems that might affect
444 // system stability.
445 // In only-core mode, we disable non-essential display adapters to minimize
446 // the number of dependencies that are started while in this mode and to
447 // prevent problems that might occur due to the device being encrypted.
448 return !mSafeMode && !mOnlyCore;
449 }
450
451 private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
452 mDisplayAdapters.add(adapter);
453 adapter.registerLocked();
454 }
455
Jeff Brownbd6e1502012-08-28 03:27:37 -0700456 private void handleDisplayDeviceAdded(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700457 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700458 if (mDisplayDevices.contains(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700459 Slog.w(TAG, "Attempted to add already added display device: "
460 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700461 return;
462 }
463
464 mDisplayDevices.add(device);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700465 addLogicalDisplayLocked(device);
466 scheduleTraversalLocked();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700467 }
468 }
469
Jeff Brownbd6e1502012-08-28 03:27:37 -0700470 private void handleDisplayDeviceChanged(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700471 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700472 if (!mDisplayDevices.contains(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700473 Slog.w(TAG, "Attempted to change non-existent display device: "
474 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700475 return;
476 }
477
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700478 device.applyPendingDisplayDeviceInfoChangesLocked();
479 if (updateLogicalDisplaysLocked()) {
480 scheduleTraversalLocked();
Jeff Brown64a55af2012-08-26 02:47:39 -0700481 }
482 }
483 }
484
Jeff Brownbd6e1502012-08-28 03:27:37 -0700485 private void handleDisplayDeviceRemoved(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700486 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700487 if (!mDisplayDevices.remove(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700488 Slog.w(TAG, "Attempted to remove non-existent display device: "
489 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700490 return;
Craig Mautner4f67ba62012-08-02 11:23:00 -0700491 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700492
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700493 mRemovedDisplayDevices.add(device);
494 updateLogicalDisplaysLocked();
495 scheduleTraversalLocked();
Craig Mautner4f67ba62012-08-02 11:23:00 -0700496 }
497 }
498
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700499 // Adds a new logical display based on the given display device.
500 // Sends notifications if needed.
501 private void addLogicalDisplayLocked(DisplayDevice device) {
502 DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
503 boolean isDefault = (deviceInfo.flags
504 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
505 if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
506 Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo);
507 isDefault = false;
508 }
509
510 final int displayId = assignDisplayIdLocked(isDefault);
511 final int layerStack = assignLayerStackLocked(displayId);
512
Jeff Brownd728bf52012-09-08 18:05:28 -0700513 LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700514 display.updateLocked(mDisplayDevices);
515 if (!display.isValidLocked()) {
516 // This should never happen currently.
517 Slog.w(TAG, "Ignoring display device because the logical display "
518 + "created from it was not considered valid: " + deviceInfo);
519 return;
520 }
521
522 mLogicalDisplays.put(displayId, display);
523
524 // Wake up waitForDefaultDisplay.
525 if (isDefault) {
526 mSyncRoot.notifyAll();
527 }
528
529 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
530 }
531
532 private int assignDisplayIdLocked(boolean isDefault) {
533 return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
534 }
535
536 private int assignLayerStackLocked(int displayId) {
537 // Currently layer stacks and display ids are the same.
538 // This need not be the case.
539 return displayId;
540 }
541
542 // Updates all existing logical displays given the current set of display devices.
543 // Removes invalid logical displays.
544 // Sends notifications if needed.
545 private boolean updateLogicalDisplaysLocked() {
546 boolean changed = false;
547 for (int i = mLogicalDisplays.size(); i-- > 0; ) {
548 final int displayId = mLogicalDisplays.keyAt(i);
549 LogicalDisplay display = mLogicalDisplays.valueAt(i);
550
551 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
552 display.updateLocked(mDisplayDevices);
553 if (!display.isValidLocked()) {
554 mLogicalDisplays.removeAt(i);
555 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
556 changed = true;
557 } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
558 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
559 changed = true;
560 }
561 }
562 return changed;
563 }
564
565 private void performTraversalInTransactionLocked() {
566 // Perform one last traversal for each removed display device.
567 final int removedCount = mRemovedDisplayDevices.size();
568 for (int i = 0; i < removedCount; i++) {
569 DisplayDevice device = mRemovedDisplayDevices.get(i);
570 device.performTraversalInTransactionLocked();
571 }
572 mRemovedDisplayDevices.clear();
573
Jeff Brownd728bf52012-09-08 18:05:28 -0700574 // Clear all viewports before configuring displays so that we can keep
575 // track of which ones we have configured.
576 clearViewportsLocked();
577
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700578 // Configure each display device.
579 final int count = mDisplayDevices.size();
580 for (int i = 0; i < count; i++) {
581 DisplayDevice device = mDisplayDevices.get(i);
582 configureDisplayInTransactionLocked(device);
583 device.performTraversalInTransactionLocked();
584 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700585
586 // Tell the input system about these new viewports.
587 if (mInputManagerFuncs != null) {
588 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
589 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700590 }
591
Craig Mautner722285e2012-09-07 13:55:58 -0700592 /**
593 * Tells the display manager whether there is interesting unique content on the
594 * specified logical display. This is used to control automatic mirroring.
595 * <p>
596 * If the display has unique content, then the display manager arranges for it
597 * to be presented on a physical display if appropriate. Otherwise, the display manager
598 * may choose to make the physical display mirror some other logical display.
599 * </p>
600 *
601 * @param displayId The logical display id to update.
602 * @param hasContent True if the logical display has content.
603 */
604 public void setDisplayHasContent(int displayId, boolean hasContent) {
605 synchronized (mSyncRoot) {
606 LogicalDisplay display = mLogicalDisplays.get(displayId);
607 if (display != null && display.hasContentLocked() != hasContent) {
608 display.setHasContentLocked(hasContent);
609 scheduleTraversalLocked();
610 }
611 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700612 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700613
Jeff Brownd728bf52012-09-08 18:05:28 -0700614 private void clearViewportsLocked() {
615 mDefaultViewport.valid = false;
616 mExternalTouchViewport.valid = false;
Craig Mautner722285e2012-09-07 13:55:58 -0700617 }
618
619 private void configureDisplayInTransactionLocked(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700620 // Find the logical display that the display device is showing.
Craig Mautner722285e2012-09-07 13:55:58 -0700621 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
622 if (display != null && !display.hasContentLocked()) {
623 display = null;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700624 }
625 if (display == null) {
626 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
627 }
628
629 // Apply the logical display configuration to the display device.
630 if (display == null) {
631 // TODO: no logical display for the device, blank it
Jeff Brownd728bf52012-09-08 18:05:28 -0700632 Slog.w(TAG, "Missing logical display to use for physical display device: "
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700633 + device.getDisplayDeviceInfoLocked());
Jeff Brownd728bf52012-09-08 18:05:28 -0700634 return;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700635 } else {
636 display.configureDisplayInTransactionLocked(device);
637 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700638
639 // Update the viewports if needed.
640 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
641 if (!mDefaultViewport.valid
642 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
643 setViewportLocked(mDefaultViewport, display, device);
644 }
645 if (!mExternalTouchViewport.valid
646 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
647 setViewportLocked(mExternalTouchViewport, display, device);
648 }
649 }
650
651 private static void setViewportLocked(DisplayViewport viewport,
652 LogicalDisplay display, DisplayDevice device) {
653 viewport.valid = true;
654 viewport.displayId = display.getDisplayIdLocked();
655 device.populateViewportLocked(viewport);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700656 }
657
658 private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) {
659 final int count = mLogicalDisplays.size();
660 for (int i = 0; i < count; i++) {
661 LogicalDisplay display = mLogicalDisplays.valueAt(i);
662 if (display.getPrimaryDisplayDeviceLocked() == device) {
663 return display;
664 }
665 }
666 return null;
667 }
668
Jeff Brownbd6e1502012-08-28 03:27:37 -0700669 private void sendDisplayEventLocked(int displayId, int event) {
670 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
671 mHandler.sendMessage(msg);
672 }
673
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700674 // Requests that performTraversalsInTransactionFromWindowManager be called at a
675 // later time to apply changes to surfaces and displays.
676 private void scheduleTraversalLocked() {
677 if (!mPendingTraversal && mWindowManagerFuncs != null) {
678 mPendingTraversal = true;
679 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
680 }
681 }
682
683 // Runs on Handler thread.
684 // Delivers display event notifications to callbacks.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700685 private void deliverDisplayEvent(int displayId, int event) {
686 if (DEBUG) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700687 Slog.d(TAG, "Delivering display event: displayId="
688 + displayId + ", event=" + event);
Jeff Brownfa25bf52012-07-23 19:26:30 -0700689 }
Jeff Brownfa25bf52012-07-23 19:26:30 -0700690
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700691 // Grab the lock and copy the callbacks.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700692 final int count;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700693 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700694 count = mCallbacks.size();
695 mTempCallbacks.clear();
696 for (int i = 0; i < count; i++) {
697 mTempCallbacks.add(mCallbacks.valueAt(i));
Craig Mautner4f67ba62012-08-02 11:23:00 -0700698 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700699 }
Craig Mautner4f67ba62012-08-02 11:23:00 -0700700
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700701 // After releasing the lock, send the notifications out.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700702 for (int i = 0; i < count; i++) {
703 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
704 }
705 mTempCallbacks.clear();
Craig Mautner4f67ba62012-08-02 11:23:00 -0700706 }
707
Jeff Brownfa25bf52012-07-23 19:26:30 -0700708 @Override // Binder call
Jeff Brownbd6e1502012-08-28 03:27:37 -0700709 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
Jeff Brownfa25bf52012-07-23 19:26:30 -0700710 if (mContext == null
711 || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
712 != PackageManager.PERMISSION_GRANTED) {
713 pw.println("Permission Denial: can't dump DisplayManager from from pid="
714 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
715 return;
716 }
717
Jeff Brownbd6e1502012-08-28 03:27:37 -0700718 pw.println("DISPLAY MANAGER (dumpsys display)");
719 pw.println(" mHeadless=" + mHeadless);
Jeff Brownfa25bf52012-07-23 19:26:30 -0700720
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700721 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700722 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700723 ipw.increaseIndent();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700724
725 pw.println();
726 pw.println("Display Adapters: size=" + mDisplayAdapters.size());
Jeff Brown848c2dc2012-08-19 20:18:08 -0700727 for (DisplayAdapter adapter : mDisplayAdapters) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700728 pw.println(" " + adapter.getName());
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700729 adapter.dumpLocked(ipw);
Jeff Brown848c2dc2012-08-19 20:18:08 -0700730 }
Craig Mautner9de49362012-08-02 14:30:30 -0700731
Jeff Brownbd6e1502012-08-28 03:27:37 -0700732 pw.println();
733 pw.println("Display Devices: size=" + mDisplayDevices.size());
734 for (DisplayDevice device : mDisplayDevices) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700735 pw.println(" " + device.getDisplayDeviceInfoLocked());
736 device.dumpLocked(ipw);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700737 }
738
739 final int logicalDisplayCount = mLogicalDisplays.size();
740 pw.println();
741 pw.println("Logical Displays: size=" + logicalDisplayCount);
742 for (int i = 0; i < logicalDisplayCount; i++) {
743 int displayId = mLogicalDisplays.keyAt(i);
744 LogicalDisplay display = mLogicalDisplays.valueAt(i);
745 pw.println(" Display " + displayId + ":");
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700746 display.dumpLocked(ipw);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700747 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700748
749 pw.println();
750 pw.println("Default viewport: " + mDefaultViewport);
751 pw.println("External touch viewport: " + mExternalTouchViewport);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700752 }
753 }
754
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700755 /**
756 * This is the object that everything in the display manager locks on.
757 * We make it an inner class within the {@link DisplayManagerService} to so that it is
758 * clear that the object belongs to the display manager service and that it is
759 * a unique object with a special purpose.
760 */
761 public static final class SyncRoot {
762 }
763
764 /**
765 * Private interface to the window manager.
766 */
767 public interface WindowManagerFuncs {
768 /**
Craig Mautner722285e2012-09-07 13:55:58 -0700769 * Request that the window manager call
770 * {@link #performTraversalInTransactionFromWindowManager} within a surface
771 * transaction at a later time.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700772 */
773 void requestTraversal();
774 }
775
Jeff Brownd728bf52012-09-08 18:05:28 -0700776 /**
777 * Private interface to the input manager.
778 */
779 public interface InputManagerFuncs {
780 /**
781 * Sets information about the displays as needed by the input system.
782 * The input system should copy this information if required.
783 */
784 void setDisplayViewports(DisplayViewport defaultViewport,
785 DisplayViewport externalTouchViewport);
786 }
787
Jeff Brownbd6e1502012-08-28 03:27:37 -0700788 private final class DisplayManagerHandler extends Handler {
789 public DisplayManagerHandler(Looper looper) {
790 super(looper, null, true /*async*/);
Jeff Brown848c2dc2012-08-19 20:18:08 -0700791 }
Jeff Brownbf5740e2012-08-19 23:20:02 -0700792
Jeff Brownbd6e1502012-08-28 03:27:37 -0700793 @Override
794 public void handleMessage(Message msg) {
795 switch (msg.what) {
796 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
797 registerDefaultDisplayAdapter();
798 break;
799
800 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
801 registerAdditionalDisplayAdapters();
802 break;
803
804 case MSG_DELIVER_DISPLAY_EVENT:
805 deliverDisplayEvent(msg.arg1, msg.arg2);
806 break;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700807
808 case MSG_REQUEST_TRAVERSAL:
809 mWindowManagerFuncs.requestTraversal();
810 break;
Jeff Brownd728bf52012-09-08 18:05:28 -0700811
812 case MSG_UPDATE_VIEWPORT: {
813 synchronized (mSyncRoot) {
814 mTempDefaultViewport.copyFrom(mDefaultViewport);
815 mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
816 }
817 mInputManagerFuncs.setDisplayViewports(
818 mTempDefaultViewport, mTempExternalTouchViewport);
819 break;
820 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700821 }
822 }
823 }
824
825 private final class DisplayAdapterListener implements DisplayAdapter.Listener {
826 @Override
827 public void onDisplayDeviceEvent(DisplayDevice device, int event) {
828 switch (event) {
829 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
830 handleDisplayDeviceAdded(device);
831 break;
832
833 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
834 handleDisplayDeviceChanged(device);
835 break;
836
837 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
838 handleDisplayDeviceRemoved(device);
839 break;
840 }
841 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700842
843 @Override
844 public void onTraversalRequested() {
845 synchronized (mSyncRoot) {
846 scheduleTraversalLocked();
847 }
848 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700849 }
850
851 private final class CallbackRecord implements DeathRecipient {
852 private final int mPid;
853 private final IDisplayManagerCallback mCallback;
854
855 public CallbackRecord(int pid, IDisplayManagerCallback callback) {
856 mPid = pid;
857 mCallback = callback;
858 }
859
860 @Override
861 public void binderDied() {
862 if (DEBUG) {
863 Slog.d(TAG, "Display listener for pid " + mPid + " died.");
864 }
865 onCallbackDied(mPid);
866 }
867
868 public void notifyDisplayEventAsync(int displayId, int event) {
869 try {
870 mCallback.onDisplayEvent(displayId, event);
871 } catch (RemoteException ex) {
872 Slog.w(TAG, "Failed to notify process "
873 + mPid + " that displays changed, assuming it died.", ex);
874 binderDied();
875 }
876 }
877 }
Jeff Brownfa25bf52012-07-23 19:26:30 -0700878}