blob: f348cb619bc2645a0dbc3a11a43e51adf6befb2d [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
Jeff Brownbbd28a22012-09-20 16:47:15 -070092 // 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
Jeff Brownfa25bf52012-07-23 19:26:30 -070097 private static final String SYSTEM_HEADLESS = "ro.config.headless";
Jeff Brownbd6e1502012-08-28 03:27:37 -070098 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;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700103 private static final int MSG_REQUEST_TRAVERSAL = 4;
Jeff Brownd728bf52012-09-08 18:05:28 -0700104 private static final int MSG_UPDATE_VIEWPORT = 5;
Jeff Brownfa25bf52012-07-23 19:26:30 -0700105
Jeff Brown848c2dc2012-08-19 20:18:08 -0700106 private final Context mContext;
Jeff Brownfa25bf52012-07-23 19:26:30 -0700107 private final boolean mHeadless;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700108 private final DisplayManagerHandler mHandler;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700109 private final Handler mUiHandler;
110 private final DisplayAdapterListener mDisplayAdapterListener;
111 private WindowManagerFuncs mWindowManagerFuncs;
Jeff Brownd728bf52012-09-08 18:05:28 -0700112 private InputManagerFuncs mInputManagerFuncs;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700113
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 =
Jeff Brownbd6e1502012-08-28 03:27:37 -0700128 new SparseArray<CallbackRecord>();
Jeff Brownfa25bf52012-07-23 19:26:30 -0700129
Jeff Brownbd6e1502012-08-28 03:27:37 -0700130 // 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
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700136 // 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>();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700142 private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
143
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700144 // 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;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700147
Jeff Browne08ae382012-09-07 20:36:36 -0700148 // The Wifi display adapter, or null if not registered.
149 private WifiDisplayAdapter mWifiDisplayAdapter;
150
Jeff Brownd728bf52012-09-08 18:05:28 -0700151 // 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
Jeff Brown89d55462012-09-19 11:33:42 -0700156 // Persistent data store for all internal settings maintained by the display manager service.
157 private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();
158
Jeff Brownbd6e1502012-08-28 03:27:37 -0700159 // Temporary callback list, used when sending display events to applications.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700160 // May be used outside of the lock but only on the handler thread.
161 private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700162
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700163 // Temporary display info, used for comparing display configurations.
164 private final DisplayInfo mTempDisplayInfo = new DisplayInfo();
165
Jeff Brownd728bf52012-09-08 18:05:28 -0700166 // 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
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700171 public DisplayManagerService(Context context, Handler mainHandler, Handler uiHandler) {
Jeff Brown848c2dc2012-08-19 20:18:08 -0700172 mContext = context;
Jeff Brownfa25bf52012-07-23 19:26:30 -0700173 mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1");
Jeff Brown848c2dc2012-08-19 20:18:08 -0700174
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700175 mHandler = new DisplayManagerHandler(mainHandler.getLooper());
176 mUiHandler = uiHandler;
177 mDisplayAdapterListener = new DisplayAdapterListener();
178
Jeff Brownbd6e1502012-08-28 03:27:37 -0700179 mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
Craig Mautner4f67ba62012-08-02 11:23:00 -0700180 }
181
Jeff Brownbd6e1502012-08-28 03:27:37 -0700182 /**
183 * Pauses the boot process to wait for the first display to be initialized.
184 */
185 public boolean waitForDefaultDisplay() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700186 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700187 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 {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700197 mSyncRoot.wait(delay);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700198 } catch (InterruptedException ex) {
199 }
200 }
201 }
202 return true;
203 }
204
205 /**
Jeff Brownd728bf52012-09-08 18:05:28 -0700206 * Called during initialization to associate the display manager with the
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700207 * window manager.
208 */
209 public void setWindowManager(WindowManagerFuncs windowManagerFuncs) {
210 synchronized (mSyncRoot) {
211 mWindowManagerFuncs = windowManagerFuncs;
212 scheduleTraversalLocked();
213 }
214 }
215
216 /**
Jeff Brownd728bf52012-09-08 18:05:28 -0700217 * 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 /**
Jeff Brownbd6e1502012-08-28 03:27:37 -0700228 * Called when the system is ready to go.
229 */
230 public void systemReady(boolean safeMode, boolean onlyCore) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700231 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700232 mSafeMode = safeMode;
233 mOnlyCore = onlyCore;
234 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700235
Jeff Brownbd6e1502012-08-28 03:27:37 -0700236 mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
237 }
238
Jeff Brown848c2dc2012-08-19 20:18:08 -0700239 /**
240 * Returns true if the device is headless.
241 *
242 * @return True if the device is headless.
243 */
Jeff Brownfa25bf52012-07-23 19:26:30 -0700244 public boolean isHeadless() {
245 return mHeadless;
246 }
247
Craig Mautner4f67ba62012-08-02 11:23:00 -0700248 /**
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700249 * 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.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700254 *
Jeff Brown64a55af2012-08-26 02:47:39 -0700255 * @param displayId The logical display id.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700256 * @param info The new data to be stored.
Jeff Brown64a55af2012-08-26 02:47:39 -0700257 */
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700258 public void setDisplayInfoOverrideFromWindowManager(
259 int displayId, DisplayInfo info) {
260 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700261 LogicalDisplay display = mLogicalDisplays.get(displayId);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700262 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();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700268 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700269 }
270 }
271 }
272
273 /**
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700274 * Called by the window manager to perform traversals while holding a
275 * surface flinger transaction.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700276 */
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700277 public void performTraversalInTransactionFromWindowManager() {
278 synchronized (mSyncRoot) {
279 if (!mPendingTraversal) {
280 return;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700281 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700282 mPendingTraversal = false;
283
284 performTraversalInTransactionLocked();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700285 }
286 }
287
288 /**
289 * Returns information about the specified logical display.
290 *
291 * @param displayId The logical display id.
Craig Mautner722285e2012-09-07 13:55:58 -0700292 * @return The logical display info, or null if the display does not exist. The
293 * returned object must be treated as immutable.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700294 */
295 @Override // Binder call
296 public DisplayInfo getDisplayInfo(int displayId) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700297 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700298 LogicalDisplay display = mLogicalDisplays.get(displayId);
299 if (display != null) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700300 return display.getDisplayInfoLocked();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700301 }
302 return null;
303 }
304 }
305
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700306 /**
307 * Returns the list of all display ids.
308 */
Jeff Brownbd6e1502012-08-28 03:27:37 -0700309 @Override // Binder call
310 public int[] getDisplayIds() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700311 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700312 final int count = mLogicalDisplays.size();
313 int[] displayIds = new int[count];
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700314 for (int i = 0; i < count; i++) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700315 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
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700327 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700328 int callingPid = Binder.getCallingPid();
329 if (mCallbacks.get(callingPid) != null) {
330 throw new SecurityException("The calling process has already "
331 + "registered an IDisplayManagerCallback.");
Jeff Brown64a55af2012-08-26 02:47:39 -0700332 }
333
Jeff Brownbd6e1502012-08-28 03:27:37 -0700334 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) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700348 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700349 mCallbacks.remove(pid);
350 }
351 }
352
Jeff Browne08ae382012-09-07 20:36:36 -0700353 @Override // Binder call
354 public void scanWifiDisplays() {
Jeff Browne08ae382012-09-07 20:36:36 -0700355 final long token = Binder.clearCallingIdentity();
356 try {
357 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700358 if (mWifiDisplayAdapter != null) {
359 mWifiDisplayAdapter.requestScanLocked();
360 }
Jeff Browne08ae382012-09-07 20:36:36 -0700361 }
362 } finally {
363 Binder.restoreCallingIdentity(token);
364 }
365 }
366
367 @Override // Binder call
368 public void connectWifiDisplay(String address) {
Jeff Browne08ae382012-09-07 20:36:36 -0700369 if (address == null) {
370 throw new IllegalArgumentException("address must not be null");
371 }
372
Jeff Brownbc335452012-09-26 18:34:47 -0700373 final boolean trusted = canCallerConfigureWifiDisplay();
Jeff Browne08ae382012-09-07 20:36:36 -0700374 final long token = Binder.clearCallingIdentity();
375 try {
376 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700377 if (mWifiDisplayAdapter != null) {
Jeff Brownbc335452012-09-26 18:34:47 -0700378 mWifiDisplayAdapter.requestConnectLocked(address, trusted);
Jeff Brown21c71532012-09-09 13:26:55 -0700379 }
Jeff Browne08ae382012-09-07 20:36:36 -0700380 }
381 } finally {
382 Binder.restoreCallingIdentity(token);
383 }
384 }
385
386 @Override // Binder call
387 public void disconnectWifiDisplay() {
Jeff Browne08ae382012-09-07 20:36:36 -0700388 final long token = Binder.clearCallingIdentity();
389 try {
390 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700391 if (mWifiDisplayAdapter != null) {
392 mWifiDisplayAdapter.requestDisconnectLocked();
393 }
Jeff Browne08ae382012-09-07 20:36:36 -0700394 }
395 } finally {
396 Binder.restoreCallingIdentity(token);
397 }
398 }
399
400 @Override // Binder call
Jeff Brown89d55462012-09-19 11:33:42 -0700401 public void renameWifiDisplay(String address, String alias) {
Jeff Brown89d55462012-09-19 11:33:42 -0700402 if (address == null) {
403 throw new IllegalArgumentException("address must not be null");
404 }
Jeff Brownbc335452012-09-26 18:34:47 -0700405 if (!canCallerConfigureWifiDisplay()) {
406 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to "
407 + "rename a wifi display.");
408 }
Jeff Brown89d55462012-09-19 11:33:42 -0700409
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) {
Jeff Brown89d55462012-09-19 11:33:42 -0700424 if (address == null) {
425 throw new IllegalArgumentException("address must not be null");
426 }
Jeff Brownbc335452012-09-26 18:34:47 -0700427 if (!canCallerConfigureWifiDisplay()) {
428 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to "
429 + "forget a wifi display.");
430 }
Jeff Brown89d55462012-09-19 11:33:42 -0700431
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
Jeff Browne08ae382012-09-07 20:36:36 -0700445 public WifiDisplayStatus getWifiDisplayStatus() {
Jeff Browne08ae382012-09-07 20:36:36 -0700446 final long token = Binder.clearCallingIdentity();
447 try {
448 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700449 if (mWifiDisplayAdapter != null) {
450 return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
451 } else {
452 return new WifiDisplayStatus();
453 }
Jeff Browne08ae382012-09-07 20:36:36 -0700454 }
455 } finally {
456 Binder.restoreCallingIdentity(token);
457 }
458 }
459
Jeff Brownbc335452012-09-26 18:34:47 -0700460 private boolean canCallerConfigureWifiDisplay() {
461 return mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
462 == PackageManager.PERMISSION_GRANTED;
463 }
464
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700465 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()) {
Jeff Brown89d55462012-09-19 11:33:42 -0700481 registerOverlayDisplayAdapterLocked();
482 registerWifiDisplayAdapterLocked();
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700483 }
484 }
485 }
486
Jeff Brown89d55462012-09-19 11:33:42 -0700487 private void registerOverlayDisplayAdapterLocked() {
488 registerDisplayAdapterLocked(new OverlayDisplayAdapter(
489 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
490 }
491
492 private void registerWifiDisplayAdapterLocked() {
493 if (mContext.getResources().getBoolean(
Jeff Brownbbd28a22012-09-20 16:47:15 -0700494 com.android.internal.R.bool.config_enableWifiDisplay)
495 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
Jeff Brown89d55462012-09-19 11:33:42 -0700496 mWifiDisplayAdapter = new WifiDisplayAdapter(
497 mSyncRoot, mContext, mHandler, mDisplayAdapterListener,
498 mPersistentDataStore);
499 registerDisplayAdapterLocked(mWifiDisplayAdapter);
500 }
501 }
502
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700503 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
Jeff Brownbd6e1502012-08-28 03:27:37 -0700518 private void handleDisplayDeviceAdded(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700519 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700520 if (mDisplayDevices.contains(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700521 Slog.w(TAG, "Attempted to add already added display device: "
522 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700523 return;
524 }
525
Jeff Browne87bf032012-09-20 18:30:13 -0700526 Slog.i(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked());
527
Jeff Brownbd6e1502012-08-28 03:27:37 -0700528 mDisplayDevices.add(device);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700529 addLogicalDisplayLocked(device);
530 scheduleTraversalLocked();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700531 }
532 }
533
Jeff Brownbd6e1502012-08-28 03:27:37 -0700534 private void handleDisplayDeviceChanged(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700535 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700536 if (!mDisplayDevices.contains(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700537 Slog.w(TAG, "Attempted to change non-existent display device: "
538 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700539 return;
540 }
541
Jeff Browne87bf032012-09-20 18:30:13 -0700542 Slog.i(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked());
543
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700544 device.applyPendingDisplayDeviceInfoChangesLocked();
545 if (updateLogicalDisplaysLocked()) {
546 scheduleTraversalLocked();
Jeff Brown64a55af2012-08-26 02:47:39 -0700547 }
548 }
549 }
550
Jeff Brownbd6e1502012-08-28 03:27:37 -0700551 private void handleDisplayDeviceRemoved(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700552 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700553 if (!mDisplayDevices.remove(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700554 Slog.w(TAG, "Attempted to remove non-existent display device: "
555 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700556 return;
Craig Mautner4f67ba62012-08-02 11:23:00 -0700557 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700558
Jeff Browne87bf032012-09-20 18:30:13 -0700559 Slog.i(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked());
560
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700561 mRemovedDisplayDevices.add(device);
562 updateLogicalDisplaysLocked();
563 scheduleTraversalLocked();
Craig Mautner4f67ba62012-08-02 11:23:00 -0700564 }
565 }
566
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700567 // 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
Jeff Brownd728bf52012-09-08 18:05:28 -0700581 LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700582 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
Jeff Brownd728bf52012-09-08 18:05:28 -0700642 // Clear all viewports before configuring displays so that we can keep
643 // track of which ones we have configured.
644 clearViewportsLocked();
645
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700646 // 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 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700653
654 // Tell the input system about these new viewports.
655 if (mInputManagerFuncs != null) {
656 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
657 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700658 }
659
Craig Mautner722285e2012-09-07 13:55:58 -0700660 /**
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 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700680 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700681
Jeff Brownd728bf52012-09-08 18:05:28 -0700682 private void clearViewportsLocked() {
683 mDefaultViewport.valid = false;
684 mExternalTouchViewport.valid = false;
Craig Mautner722285e2012-09-07 13:55:58 -0700685 }
686
687 private void configureDisplayInTransactionLocked(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700688 // Find the logical display that the display device is showing.
Craig Mautner722285e2012-09-07 13:55:58 -0700689 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
690 if (display != null && !display.hasContentLocked()) {
691 display = null;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700692 }
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
Jeff Brownd728bf52012-09-08 18:05:28 -0700700 Slog.w(TAG, "Missing logical display to use for physical display device: "
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700701 + device.getDisplayDeviceInfoLocked());
Jeff Brownd728bf52012-09-08 18:05:28 -0700702 return;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700703 } else {
704 display.configureDisplayInTransactionLocked(device);
705 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700706
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);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700724 }
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
Jeff Brownbd6e1502012-08-28 03:27:37 -0700737 private void sendDisplayEventLocked(int displayId, int event) {
738 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
739 mHandler.sendMessage(msg);
740 }
741
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700742 // 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.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700753 private void deliverDisplayEvent(int displayId, int event) {
754 if (DEBUG) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700755 Slog.d(TAG, "Delivering display event: displayId="
756 + displayId + ", event=" + event);
Jeff Brownfa25bf52012-07-23 19:26:30 -0700757 }
Jeff Brownfa25bf52012-07-23 19:26:30 -0700758
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700759 // Grab the lock and copy the callbacks.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700760 final int count;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700761 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700762 count = mCallbacks.size();
763 mTempCallbacks.clear();
764 for (int i = 0; i < count; i++) {
765 mTempCallbacks.add(mCallbacks.valueAt(i));
Craig Mautner4f67ba62012-08-02 11:23:00 -0700766 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700767 }
Craig Mautner4f67ba62012-08-02 11:23:00 -0700768
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700769 // After releasing the lock, send the notifications out.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700770 for (int i = 0; i < count; i++) {
771 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
772 }
773 mTempCallbacks.clear();
Craig Mautner4f67ba62012-08-02 11:23:00 -0700774 }
775
Jeff Brownfa25bf52012-07-23 19:26:30 -0700776 @Override // Binder call
Jeff Brownbd6e1502012-08-28 03:27:37 -0700777 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
Jeff Brownfa25bf52012-07-23 19:26:30 -0700778 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
Jeff Brownbd6e1502012-08-28 03:27:37 -0700786 pw.println("DISPLAY MANAGER (dumpsys display)");
787 pw.println(" mHeadless=" + mHeadless);
Jeff Brownfa25bf52012-07-23 19:26:30 -0700788
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700789 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700790 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700791 ipw.increaseIndent();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700792
793 pw.println();
794 pw.println("Display Adapters: size=" + mDisplayAdapters.size());
Jeff Brown848c2dc2012-08-19 20:18:08 -0700795 for (DisplayAdapter adapter : mDisplayAdapters) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700796 pw.println(" " + adapter.getName());
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700797 adapter.dumpLocked(ipw);
Jeff Brown848c2dc2012-08-19 20:18:08 -0700798 }
Craig Mautner9de49362012-08-02 14:30:30 -0700799
Jeff Brownbd6e1502012-08-28 03:27:37 -0700800 pw.println();
801 pw.println("Display Devices: size=" + mDisplayDevices.size());
802 for (DisplayDevice device : mDisplayDevices) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700803 pw.println(" " + device.getDisplayDeviceInfoLocked());
804 device.dumpLocked(ipw);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700805 }
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 + ":");
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700814 display.dumpLocked(ipw);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700815 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700816
817 pw.println();
818 pw.println("Default viewport: " + mDefaultViewport);
819 pw.println("External touch viewport: " + mExternalTouchViewport);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700820 }
821 }
822
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700823 /**
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 /**
Craig Mautner722285e2012-09-07 13:55:58 -0700837 * Request that the window manager call
838 * {@link #performTraversalInTransactionFromWindowManager} within a surface
839 * transaction at a later time.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700840 */
841 void requestTraversal();
842 }
843
Jeff Brownd728bf52012-09-08 18:05:28 -0700844 /**
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
Jeff Brownbd6e1502012-08-28 03:27:37 -0700856 private final class DisplayManagerHandler extends Handler {
857 public DisplayManagerHandler(Looper looper) {
858 super(looper, null, true /*async*/);
Jeff Brown848c2dc2012-08-19 20:18:08 -0700859 }
Jeff Brownbf5740e2012-08-19 23:20:02 -0700860
Jeff Brownbd6e1502012-08-28 03:27:37 -0700861 @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;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700875
876 case MSG_REQUEST_TRAVERSAL:
877 mWindowManagerFuncs.requestTraversal();
878 break;
Jeff Brownd728bf52012-09-08 18:05:28 -0700879
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 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700889 }
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 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700910
911 @Override
912 public void onTraversalRequested() {
913 synchronized (mSyncRoot) {
914 scheduleTraversalLocked();
915 }
916 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700917 }
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 }
Jeff Brownfa25bf52012-07-23 19:26:30 -0700946}