blob: b109f2a149aa166da18a1635ff55369acec8077f [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() {
355 if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
356 != PackageManager.PERMISSION_GRANTED) {
357 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission");
358 }
359
360 final long token = Binder.clearCallingIdentity();
361 try {
362 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700363 if (mWifiDisplayAdapter != null) {
364 mWifiDisplayAdapter.requestScanLocked();
365 }
Jeff Browne08ae382012-09-07 20:36:36 -0700366 }
367 } finally {
368 Binder.restoreCallingIdentity(token);
369 }
370 }
371
372 @Override // Binder call
373 public void connectWifiDisplay(String address) {
374 if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
375 != PackageManager.PERMISSION_GRANTED) {
376 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission");
377 }
378 if (address == null) {
379 throw new IllegalArgumentException("address must not be null");
380 }
381
382 final long token = Binder.clearCallingIdentity();
383 try {
384 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700385 if (mWifiDisplayAdapter != null) {
386 mWifiDisplayAdapter.requestConnectLocked(address);
387 }
Jeff Browne08ae382012-09-07 20:36:36 -0700388 }
389 } finally {
390 Binder.restoreCallingIdentity(token);
391 }
392 }
393
394 @Override // Binder call
395 public void disconnectWifiDisplay() {
396 if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
397 != PackageManager.PERMISSION_GRANTED) {
398 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission");
399 }
400
401 final long token = Binder.clearCallingIdentity();
402 try {
403 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700404 if (mWifiDisplayAdapter != null) {
405 mWifiDisplayAdapter.requestDisconnectLocked();
406 }
Jeff Browne08ae382012-09-07 20:36:36 -0700407 }
408 } finally {
409 Binder.restoreCallingIdentity(token);
410 }
411 }
412
413 @Override // Binder call
Jeff Brown89d55462012-09-19 11:33:42 -0700414 public void renameWifiDisplay(String address, String alias) {
415 if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
416 != PackageManager.PERMISSION_GRANTED) {
417 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission");
418 }
419 if (address == null) {
420 throw new IllegalArgumentException("address must not be null");
421 }
422
423 final long token = Binder.clearCallingIdentity();
424 try {
425 synchronized (mSyncRoot) {
426 if (mWifiDisplayAdapter != null) {
427 mWifiDisplayAdapter.requestRenameLocked(address, alias);
428 }
429 }
430 } finally {
431 Binder.restoreCallingIdentity(token);
432 }
433 }
434
435 @Override // Binder call
436 public void forgetWifiDisplay(String address) {
437 if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
438 != PackageManager.PERMISSION_GRANTED) {
439 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission");
440 }
441 if (address == null) {
442 throw new IllegalArgumentException("address must not be null");
443 }
444
445 final long token = Binder.clearCallingIdentity();
446 try {
447 synchronized (mSyncRoot) {
448 if (mWifiDisplayAdapter != null) {
449 mWifiDisplayAdapter.requestForgetLocked(address);
450 }
451 }
452 } finally {
453 Binder.restoreCallingIdentity(token);
454 }
455 }
456
457 @Override // Binder call
Jeff Browne08ae382012-09-07 20:36:36 -0700458 public WifiDisplayStatus getWifiDisplayStatus() {
459 if (mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
460 != PackageManager.PERMISSION_GRANTED) {
461 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission");
462 }
463
464 final long token = Binder.clearCallingIdentity();
465 try {
466 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700467 if (mWifiDisplayAdapter != null) {
468 return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
469 } else {
470 return new WifiDisplayStatus();
471 }
Jeff Browne08ae382012-09-07 20:36:36 -0700472 }
473 } finally {
474 Binder.restoreCallingIdentity(token);
475 }
476 }
477
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700478 private void registerDefaultDisplayAdapter() {
479 // Register default display adapter.
480 synchronized (mSyncRoot) {
481 if (mHeadless) {
482 registerDisplayAdapterLocked(new HeadlessDisplayAdapter(
483 mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
484 } else {
485 registerDisplayAdapterLocked(new LocalDisplayAdapter(
486 mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
487 }
488 }
489 }
490
491 private void registerAdditionalDisplayAdapters() {
492 synchronized (mSyncRoot) {
493 if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
Jeff Brown89d55462012-09-19 11:33:42 -0700494 registerOverlayDisplayAdapterLocked();
495 registerWifiDisplayAdapterLocked();
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700496 }
497 }
498 }
499
Jeff Brown89d55462012-09-19 11:33:42 -0700500 private void registerOverlayDisplayAdapterLocked() {
501 registerDisplayAdapterLocked(new OverlayDisplayAdapter(
502 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
503 }
504
505 private void registerWifiDisplayAdapterLocked() {
506 if (mContext.getResources().getBoolean(
Jeff Brownbbd28a22012-09-20 16:47:15 -0700507 com.android.internal.R.bool.config_enableWifiDisplay)
508 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
Jeff Brown89d55462012-09-19 11:33:42 -0700509 mWifiDisplayAdapter = new WifiDisplayAdapter(
510 mSyncRoot, mContext, mHandler, mDisplayAdapterListener,
511 mPersistentDataStore);
512 registerDisplayAdapterLocked(mWifiDisplayAdapter);
513 }
514 }
515
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700516 private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
517 // In safe mode, we disable non-essential display adapters to give the user
518 // an opportunity to fix broken settings or other problems that might affect
519 // system stability.
520 // In only-core mode, we disable non-essential display adapters to minimize
521 // the number of dependencies that are started while in this mode and to
522 // prevent problems that might occur due to the device being encrypted.
523 return !mSafeMode && !mOnlyCore;
524 }
525
526 private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
527 mDisplayAdapters.add(adapter);
528 adapter.registerLocked();
529 }
530
Jeff Brownbd6e1502012-08-28 03:27:37 -0700531 private void handleDisplayDeviceAdded(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700532 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700533 if (mDisplayDevices.contains(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700534 Slog.w(TAG, "Attempted to add already added display device: "
535 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700536 return;
537 }
538
539 mDisplayDevices.add(device);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700540 addLogicalDisplayLocked(device);
541 scheduleTraversalLocked();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700542 }
543 }
544
Jeff Brownbd6e1502012-08-28 03:27:37 -0700545 private void handleDisplayDeviceChanged(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700546 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700547 if (!mDisplayDevices.contains(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700548 Slog.w(TAG, "Attempted to change non-existent display device: "
549 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700550 return;
551 }
552
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700553 device.applyPendingDisplayDeviceInfoChangesLocked();
554 if (updateLogicalDisplaysLocked()) {
555 scheduleTraversalLocked();
Jeff Brown64a55af2012-08-26 02:47:39 -0700556 }
557 }
558 }
559
Jeff Brownbd6e1502012-08-28 03:27:37 -0700560 private void handleDisplayDeviceRemoved(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700561 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700562 if (!mDisplayDevices.remove(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700563 Slog.w(TAG, "Attempted to remove non-existent display device: "
564 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700565 return;
Craig Mautner4f67ba62012-08-02 11:23:00 -0700566 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700567
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700568 mRemovedDisplayDevices.add(device);
569 updateLogicalDisplaysLocked();
570 scheduleTraversalLocked();
Craig Mautner4f67ba62012-08-02 11:23:00 -0700571 }
572 }
573
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700574 // Adds a new logical display based on the given display device.
575 // Sends notifications if needed.
576 private void addLogicalDisplayLocked(DisplayDevice device) {
577 DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
578 boolean isDefault = (deviceInfo.flags
579 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
580 if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
581 Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo);
582 isDefault = false;
583 }
584
585 final int displayId = assignDisplayIdLocked(isDefault);
586 final int layerStack = assignLayerStackLocked(displayId);
587
Jeff Brownd728bf52012-09-08 18:05:28 -0700588 LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700589 display.updateLocked(mDisplayDevices);
590 if (!display.isValidLocked()) {
591 // This should never happen currently.
592 Slog.w(TAG, "Ignoring display device because the logical display "
593 + "created from it was not considered valid: " + deviceInfo);
594 return;
595 }
596
597 mLogicalDisplays.put(displayId, display);
598
599 // Wake up waitForDefaultDisplay.
600 if (isDefault) {
601 mSyncRoot.notifyAll();
602 }
603
604 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
605 }
606
607 private int assignDisplayIdLocked(boolean isDefault) {
608 return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
609 }
610
611 private int assignLayerStackLocked(int displayId) {
612 // Currently layer stacks and display ids are the same.
613 // This need not be the case.
614 return displayId;
615 }
616
617 // Updates all existing logical displays given the current set of display devices.
618 // Removes invalid logical displays.
619 // Sends notifications if needed.
620 private boolean updateLogicalDisplaysLocked() {
621 boolean changed = false;
622 for (int i = mLogicalDisplays.size(); i-- > 0; ) {
623 final int displayId = mLogicalDisplays.keyAt(i);
624 LogicalDisplay display = mLogicalDisplays.valueAt(i);
625
626 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
627 display.updateLocked(mDisplayDevices);
628 if (!display.isValidLocked()) {
629 mLogicalDisplays.removeAt(i);
630 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
631 changed = true;
632 } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
633 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
634 changed = true;
635 }
636 }
637 return changed;
638 }
639
640 private void performTraversalInTransactionLocked() {
641 // Perform one last traversal for each removed display device.
642 final int removedCount = mRemovedDisplayDevices.size();
643 for (int i = 0; i < removedCount; i++) {
644 DisplayDevice device = mRemovedDisplayDevices.get(i);
645 device.performTraversalInTransactionLocked();
646 }
647 mRemovedDisplayDevices.clear();
648
Jeff Brownd728bf52012-09-08 18:05:28 -0700649 // Clear all viewports before configuring displays so that we can keep
650 // track of which ones we have configured.
651 clearViewportsLocked();
652
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700653 // Configure each display device.
654 final int count = mDisplayDevices.size();
655 for (int i = 0; i < count; i++) {
656 DisplayDevice device = mDisplayDevices.get(i);
657 configureDisplayInTransactionLocked(device);
658 device.performTraversalInTransactionLocked();
659 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700660
661 // Tell the input system about these new viewports.
662 if (mInputManagerFuncs != null) {
663 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
664 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700665 }
666
Craig Mautner722285e2012-09-07 13:55:58 -0700667 /**
668 * Tells the display manager whether there is interesting unique content on the
669 * specified logical display. This is used to control automatic mirroring.
670 * <p>
671 * If the display has unique content, then the display manager arranges for it
672 * to be presented on a physical display if appropriate. Otherwise, the display manager
673 * may choose to make the physical display mirror some other logical display.
674 * </p>
675 *
676 * @param displayId The logical display id to update.
677 * @param hasContent True if the logical display has content.
678 */
679 public void setDisplayHasContent(int displayId, boolean hasContent) {
680 synchronized (mSyncRoot) {
681 LogicalDisplay display = mLogicalDisplays.get(displayId);
682 if (display != null && display.hasContentLocked() != hasContent) {
683 display.setHasContentLocked(hasContent);
684 scheduleTraversalLocked();
685 }
686 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700687 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700688
Jeff Brownd728bf52012-09-08 18:05:28 -0700689 private void clearViewportsLocked() {
690 mDefaultViewport.valid = false;
691 mExternalTouchViewport.valid = false;
Craig Mautner722285e2012-09-07 13:55:58 -0700692 }
693
694 private void configureDisplayInTransactionLocked(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700695 // Find the logical display that the display device is showing.
Craig Mautner722285e2012-09-07 13:55:58 -0700696 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
697 if (display != null && !display.hasContentLocked()) {
698 display = null;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700699 }
700 if (display == null) {
701 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
702 }
703
704 // Apply the logical display configuration to the display device.
705 if (display == null) {
706 // TODO: no logical display for the device, blank it
Jeff Brownd728bf52012-09-08 18:05:28 -0700707 Slog.w(TAG, "Missing logical display to use for physical display device: "
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700708 + device.getDisplayDeviceInfoLocked());
Jeff Brownd728bf52012-09-08 18:05:28 -0700709 return;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700710 } else {
711 display.configureDisplayInTransactionLocked(device);
712 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700713
714 // Update the viewports if needed.
715 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
716 if (!mDefaultViewport.valid
717 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
718 setViewportLocked(mDefaultViewport, display, device);
719 }
720 if (!mExternalTouchViewport.valid
721 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
722 setViewportLocked(mExternalTouchViewport, display, device);
723 }
724 }
725
726 private static void setViewportLocked(DisplayViewport viewport,
727 LogicalDisplay display, DisplayDevice device) {
728 viewport.valid = true;
729 viewport.displayId = display.getDisplayIdLocked();
730 device.populateViewportLocked(viewport);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700731 }
732
733 private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) {
734 final int count = mLogicalDisplays.size();
735 for (int i = 0; i < count; i++) {
736 LogicalDisplay display = mLogicalDisplays.valueAt(i);
737 if (display.getPrimaryDisplayDeviceLocked() == device) {
738 return display;
739 }
740 }
741 return null;
742 }
743
Jeff Brownbd6e1502012-08-28 03:27:37 -0700744 private void sendDisplayEventLocked(int displayId, int event) {
745 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
746 mHandler.sendMessage(msg);
747 }
748
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700749 // Requests that performTraversalsInTransactionFromWindowManager be called at a
750 // later time to apply changes to surfaces and displays.
751 private void scheduleTraversalLocked() {
752 if (!mPendingTraversal && mWindowManagerFuncs != null) {
753 mPendingTraversal = true;
754 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
755 }
756 }
757
758 // Runs on Handler thread.
759 // Delivers display event notifications to callbacks.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700760 private void deliverDisplayEvent(int displayId, int event) {
761 if (DEBUG) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700762 Slog.d(TAG, "Delivering display event: displayId="
763 + displayId + ", event=" + event);
Jeff Brownfa25bf52012-07-23 19:26:30 -0700764 }
Jeff Brownfa25bf52012-07-23 19:26:30 -0700765
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700766 // Grab the lock and copy the callbacks.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700767 final int count;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700768 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700769 count = mCallbacks.size();
770 mTempCallbacks.clear();
771 for (int i = 0; i < count; i++) {
772 mTempCallbacks.add(mCallbacks.valueAt(i));
Craig Mautner4f67ba62012-08-02 11:23:00 -0700773 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700774 }
Craig Mautner4f67ba62012-08-02 11:23:00 -0700775
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700776 // After releasing the lock, send the notifications out.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700777 for (int i = 0; i < count; i++) {
778 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
779 }
780 mTempCallbacks.clear();
Craig Mautner4f67ba62012-08-02 11:23:00 -0700781 }
782
Jeff Brownfa25bf52012-07-23 19:26:30 -0700783 @Override // Binder call
Jeff Brownbd6e1502012-08-28 03:27:37 -0700784 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
Jeff Brownfa25bf52012-07-23 19:26:30 -0700785 if (mContext == null
786 || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
787 != PackageManager.PERMISSION_GRANTED) {
788 pw.println("Permission Denial: can't dump DisplayManager from from pid="
789 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
790 return;
791 }
792
Jeff Brownbd6e1502012-08-28 03:27:37 -0700793 pw.println("DISPLAY MANAGER (dumpsys display)");
794 pw.println(" mHeadless=" + mHeadless);
Jeff Brownfa25bf52012-07-23 19:26:30 -0700795
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700796 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700797 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700798 ipw.increaseIndent();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700799
800 pw.println();
801 pw.println("Display Adapters: size=" + mDisplayAdapters.size());
Jeff Brown848c2dc2012-08-19 20:18:08 -0700802 for (DisplayAdapter adapter : mDisplayAdapters) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700803 pw.println(" " + adapter.getName());
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700804 adapter.dumpLocked(ipw);
Jeff Brown848c2dc2012-08-19 20:18:08 -0700805 }
Craig Mautner9de49362012-08-02 14:30:30 -0700806
Jeff Brownbd6e1502012-08-28 03:27:37 -0700807 pw.println();
808 pw.println("Display Devices: size=" + mDisplayDevices.size());
809 for (DisplayDevice device : mDisplayDevices) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700810 pw.println(" " + device.getDisplayDeviceInfoLocked());
811 device.dumpLocked(ipw);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700812 }
813
814 final int logicalDisplayCount = mLogicalDisplays.size();
815 pw.println();
816 pw.println("Logical Displays: size=" + logicalDisplayCount);
817 for (int i = 0; i < logicalDisplayCount; i++) {
818 int displayId = mLogicalDisplays.keyAt(i);
819 LogicalDisplay display = mLogicalDisplays.valueAt(i);
820 pw.println(" Display " + displayId + ":");
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700821 display.dumpLocked(ipw);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700822 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700823
824 pw.println();
825 pw.println("Default viewport: " + mDefaultViewport);
826 pw.println("External touch viewport: " + mExternalTouchViewport);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700827 }
828 }
829
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700830 /**
831 * This is the object that everything in the display manager locks on.
832 * We make it an inner class within the {@link DisplayManagerService} to so that it is
833 * clear that the object belongs to the display manager service and that it is
834 * a unique object with a special purpose.
835 */
836 public static final class SyncRoot {
837 }
838
839 /**
840 * Private interface to the window manager.
841 */
842 public interface WindowManagerFuncs {
843 /**
Craig Mautner722285e2012-09-07 13:55:58 -0700844 * Request that the window manager call
845 * {@link #performTraversalInTransactionFromWindowManager} within a surface
846 * transaction at a later time.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700847 */
848 void requestTraversal();
849 }
850
Jeff Brownd728bf52012-09-08 18:05:28 -0700851 /**
852 * Private interface to the input manager.
853 */
854 public interface InputManagerFuncs {
855 /**
856 * Sets information about the displays as needed by the input system.
857 * The input system should copy this information if required.
858 */
859 void setDisplayViewports(DisplayViewport defaultViewport,
860 DisplayViewport externalTouchViewport);
861 }
862
Jeff Brownbd6e1502012-08-28 03:27:37 -0700863 private final class DisplayManagerHandler extends Handler {
864 public DisplayManagerHandler(Looper looper) {
865 super(looper, null, true /*async*/);
Jeff Brown848c2dc2012-08-19 20:18:08 -0700866 }
Jeff Brownbf5740e2012-08-19 23:20:02 -0700867
Jeff Brownbd6e1502012-08-28 03:27:37 -0700868 @Override
869 public void handleMessage(Message msg) {
870 switch (msg.what) {
871 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
872 registerDefaultDisplayAdapter();
873 break;
874
875 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
876 registerAdditionalDisplayAdapters();
877 break;
878
879 case MSG_DELIVER_DISPLAY_EVENT:
880 deliverDisplayEvent(msg.arg1, msg.arg2);
881 break;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700882
883 case MSG_REQUEST_TRAVERSAL:
884 mWindowManagerFuncs.requestTraversal();
885 break;
Jeff Brownd728bf52012-09-08 18:05:28 -0700886
887 case MSG_UPDATE_VIEWPORT: {
888 synchronized (mSyncRoot) {
889 mTempDefaultViewport.copyFrom(mDefaultViewport);
890 mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
891 }
892 mInputManagerFuncs.setDisplayViewports(
893 mTempDefaultViewport, mTempExternalTouchViewport);
894 break;
895 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700896 }
897 }
898 }
899
900 private final class DisplayAdapterListener implements DisplayAdapter.Listener {
901 @Override
902 public void onDisplayDeviceEvent(DisplayDevice device, int event) {
903 switch (event) {
904 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
905 handleDisplayDeviceAdded(device);
906 break;
907
908 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
909 handleDisplayDeviceChanged(device);
910 break;
911
912 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
913 handleDisplayDeviceRemoved(device);
914 break;
915 }
916 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700917
918 @Override
919 public void onTraversalRequested() {
920 synchronized (mSyncRoot) {
921 scheduleTraversalLocked();
922 }
923 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700924 }
925
926 private final class CallbackRecord implements DeathRecipient {
927 private final int mPid;
928 private final IDisplayManagerCallback mCallback;
929
930 public CallbackRecord(int pid, IDisplayManagerCallback callback) {
931 mPid = pid;
932 mCallback = callback;
933 }
934
935 @Override
936 public void binderDied() {
937 if (DEBUG) {
938 Slog.d(TAG, "Display listener for pid " + mPid + " died.");
939 }
940 onCallbackDied(mPid);
941 }
942
943 public void notifyDisplayEventAsync(int displayId, int event) {
944 try {
945 mCallback.onDisplayEvent(displayId, event);
946 } catch (RemoteException ex) {
947 Slog.w(TAG, "Failed to notify process "
948 + mPid + " that displays changed, assuming it died.", ex);
949 binderDied();
950 }
951 }
952 }
Jeff Brownfa25bf52012-07-23 19:26:30 -0700953}