blob: 93896af4b58bca55438067cf2a0a621d16db955c [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 Brown9e316a12012-10-08 19:17:06 -0700106 private static final int DISPLAY_BLANK_STATE_UNKNOWN = 0;
107 private static final int DISPLAY_BLANK_STATE_BLANKED = 1;
108 private static final int DISPLAY_BLANK_STATE_UNBLANKED = 2;
109
Jeff Brown848c2dc2012-08-19 20:18:08 -0700110 private final Context mContext;
Jeff Brownfa25bf52012-07-23 19:26:30 -0700111 private final boolean mHeadless;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700112 private final DisplayManagerHandler mHandler;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700113 private final Handler mUiHandler;
114 private final DisplayAdapterListener mDisplayAdapterListener;
115 private WindowManagerFuncs mWindowManagerFuncs;
Jeff Brownd728bf52012-09-08 18:05:28 -0700116 private InputManagerFuncs mInputManagerFuncs;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700117
118 // The synchronization root for the display manager.
119 // This lock guards most of the display manager's state.
120 private final SyncRoot mSyncRoot = new SyncRoot();
121
122 // True if in safe mode.
123 // This option may disable certain display adapters.
124 public boolean mSafeMode;
125
126 // True if we are in a special boot mode where only core applications and
127 // services should be started. This option may disable certain display adapters.
128 public boolean mOnlyCore;
129
130 // All callback records indexed by calling process id.
131 public final SparseArray<CallbackRecord> mCallbacks =
Jeff Brownbd6e1502012-08-28 03:27:37 -0700132 new SparseArray<CallbackRecord>();
Jeff Brownfa25bf52012-07-23 19:26:30 -0700133
Jeff Brownbd6e1502012-08-28 03:27:37 -0700134 // List of all currently registered display adapters.
135 private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
136
137 // List of all currently connected display devices.
138 private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>();
139
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700140 // List of all removed display devices.
141 private final ArrayList<DisplayDevice> mRemovedDisplayDevices = new ArrayList<DisplayDevice>();
142
143 // List of all logical displays indexed by logical display id.
144 private final SparseArray<LogicalDisplay> mLogicalDisplays =
145 new SparseArray<LogicalDisplay>();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700146 private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
147
Jeff Brown9e316a12012-10-08 19:17:06 -0700148 // Set to true if all displays have been blanked by the power manager.
149 private int mAllDisplayBlankStateFromPowerManager;
150
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700151 // Set to true when there are pending display changes that have yet to be applied
152 // to the surface flinger state.
153 private boolean mPendingTraversal;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700154
Jeff Browne08ae382012-09-07 20:36:36 -0700155 // The Wifi display adapter, or null if not registered.
156 private WifiDisplayAdapter mWifiDisplayAdapter;
157
Jeff Brownd728bf52012-09-08 18:05:28 -0700158 // Viewports of the default display and the display that should receive touch
159 // input from an external source. Used by the input system.
160 private final DisplayViewport mDefaultViewport = new DisplayViewport();
161 private final DisplayViewport mExternalTouchViewport = new DisplayViewport();
162
Jeff Brown89d55462012-09-19 11:33:42 -0700163 // Persistent data store for all internal settings maintained by the display manager service.
164 private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();
165
Jeff Brownbd6e1502012-08-28 03:27:37 -0700166 // Temporary callback list, used when sending display events to applications.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700167 // May be used outside of the lock but only on the handler thread.
168 private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700169
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700170 // Temporary display info, used for comparing display configurations.
171 private final DisplayInfo mTempDisplayInfo = new DisplayInfo();
172
Jeff Brownd728bf52012-09-08 18:05:28 -0700173 // Temporary viewports, used when sending new viewport information to the
174 // input system. May be used outside of the lock but only on the handler thread.
175 private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
176 private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
177
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700178 public DisplayManagerService(Context context, Handler mainHandler, Handler uiHandler) {
Jeff Brown848c2dc2012-08-19 20:18:08 -0700179 mContext = context;
Jeff Brownfa25bf52012-07-23 19:26:30 -0700180 mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1");
Jeff Brown848c2dc2012-08-19 20:18:08 -0700181
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700182 mHandler = new DisplayManagerHandler(mainHandler.getLooper());
183 mUiHandler = uiHandler;
184 mDisplayAdapterListener = new DisplayAdapterListener();
185
Jeff Brownbd6e1502012-08-28 03:27:37 -0700186 mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
Craig Mautner4f67ba62012-08-02 11:23:00 -0700187 }
188
Jeff Brownbd6e1502012-08-28 03:27:37 -0700189 /**
190 * Pauses the boot process to wait for the first display to be initialized.
191 */
192 public boolean waitForDefaultDisplay() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700193 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700194 long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
195 while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) {
196 long delay = timeout - SystemClock.uptimeMillis();
197 if (delay <= 0) {
198 return false;
199 }
200 if (DEBUG) {
201 Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
202 }
203 try {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700204 mSyncRoot.wait(delay);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700205 } catch (InterruptedException ex) {
206 }
207 }
208 }
209 return true;
210 }
211
212 /**
Jeff Brownd728bf52012-09-08 18:05:28 -0700213 * Called during initialization to associate the display manager with the
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700214 * window manager.
215 */
216 public void setWindowManager(WindowManagerFuncs windowManagerFuncs) {
217 synchronized (mSyncRoot) {
218 mWindowManagerFuncs = windowManagerFuncs;
Craig Mautner65d11b32012-10-01 13:59:52 -0700219 scheduleTraversalLocked(false);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700220 }
221 }
222
223 /**
Jeff Brownd728bf52012-09-08 18:05:28 -0700224 * Called during initialization to associate the display manager with the
225 * input manager.
226 */
227 public void setInputManager(InputManagerFuncs inputManagerFuncs) {
228 synchronized (mSyncRoot) {
229 mInputManagerFuncs = inputManagerFuncs;
Craig Mautner65d11b32012-10-01 13:59:52 -0700230 scheduleTraversalLocked(false);
Jeff Brownd728bf52012-09-08 18:05:28 -0700231 }
232 }
233
234 /**
Jeff Brownbd6e1502012-08-28 03:27:37 -0700235 * Called when the system is ready to go.
236 */
237 public void systemReady(boolean safeMode, boolean onlyCore) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700238 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700239 mSafeMode = safeMode;
240 mOnlyCore = onlyCore;
241 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700242
Jeff Brownbd6e1502012-08-28 03:27:37 -0700243 mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
244 }
245
Jeff Brown848c2dc2012-08-19 20:18:08 -0700246 /**
247 * Returns true if the device is headless.
248 *
249 * @return True if the device is headless.
250 */
Jeff Brownfa25bf52012-07-23 19:26:30 -0700251 public boolean isHeadless() {
252 return mHeadless;
253 }
254
Craig Mautner4f67ba62012-08-02 11:23:00 -0700255 /**
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700256 * Overrides the display information of a particular logical display.
257 * This is used by the window manager to control the size and characteristics
258 * of the default display. It is expected to apply the requested change
259 * to the display information synchronously so that applications will immediately
260 * observe the new state.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700261 *
Jeff Brown64a55af2012-08-26 02:47:39 -0700262 * @param displayId The logical display id.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700263 * @param info The new data to be stored.
Jeff Brown64a55af2012-08-26 02:47:39 -0700264 */
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700265 public void setDisplayInfoOverrideFromWindowManager(
266 int displayId, DisplayInfo info) {
267 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700268 LogicalDisplay display = mLogicalDisplays.get(displayId);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700269 if (display != null) {
270 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
271 display.setDisplayInfoOverrideFromWindowManagerLocked(info);
272 if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
273 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
Craig Mautner65d11b32012-10-01 13:59:52 -0700274 scheduleTraversalLocked(false);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700275 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700276 }
277 }
278 }
279
280 /**
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700281 * Called by the window manager to perform traversals while holding a
282 * surface flinger transaction.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700283 */
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700284 public void performTraversalInTransactionFromWindowManager() {
285 synchronized (mSyncRoot) {
286 if (!mPendingTraversal) {
287 return;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700288 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700289 mPendingTraversal = false;
290
291 performTraversalInTransactionLocked();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700292 }
293 }
294
295 /**
Jeff Brown9e316a12012-10-08 19:17:06 -0700296 * Called by the power manager to blank all displays.
297 */
298 public void blankAllDisplaysFromPowerManager() {
299 synchronized (mSyncRoot) {
300 if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_BLANKED) {
301 mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_BLANKED;
302
303 final int count = mDisplayDevices.size();
304 for (int i = 0; i < count; i++) {
305 DisplayDevice device = mDisplayDevices.get(i);
306 device.blankLocked();
307 }
Jeff Brown8ec09432012-10-16 16:19:23 -0700308
309 scheduleTraversalLocked(false);
Jeff Brown9e316a12012-10-08 19:17:06 -0700310 }
311 }
312 }
313
314 /**
315 * Called by the power manager to unblank all displays.
316 */
317 public void unblankAllDisplaysFromPowerManager() {
318 synchronized (mSyncRoot) {
319 if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_UNBLANKED) {
320 mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNBLANKED;
321
322 final int count = mDisplayDevices.size();
323 for (int i = 0; i < count; i++) {
324 DisplayDevice device = mDisplayDevices.get(i);
325 device.unblankLocked();
326 }
Jeff Brown8ec09432012-10-16 16:19:23 -0700327
328 scheduleTraversalLocked(false);
Jeff Brown9e316a12012-10-08 19:17:06 -0700329 }
330 }
331 }
332
333 /**
Jeff Brownbd6e1502012-08-28 03:27:37 -0700334 * Returns information about the specified logical display.
335 *
336 * @param displayId The logical display id.
Craig Mautner722285e2012-09-07 13:55:58 -0700337 * @return The logical display info, or null if the display does not exist. The
338 * returned object must be treated as immutable.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700339 */
340 @Override // Binder call
341 public DisplayInfo getDisplayInfo(int displayId) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700342 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700343 LogicalDisplay display = mLogicalDisplays.get(displayId);
344 if (display != null) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700345 return display.getDisplayInfoLocked();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700346 }
347 return null;
348 }
349 }
350
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700351 /**
352 * Returns the list of all display ids.
353 */
Jeff Brownbd6e1502012-08-28 03:27:37 -0700354 @Override // Binder call
355 public int[] getDisplayIds() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700356 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700357 final int count = mLogicalDisplays.size();
358 int[] displayIds = new int[count];
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700359 for (int i = 0; i < count; i++) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700360 displayIds[i] = mLogicalDisplays.keyAt(i);
361 }
362 return displayIds;
363 }
364 }
365
366 @Override // Binder call
367 public void registerCallback(IDisplayManagerCallback callback) {
368 if (callback == null) {
369 throw new IllegalArgumentException("listener must not be null");
370 }
371
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700372 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700373 int callingPid = Binder.getCallingPid();
374 if (mCallbacks.get(callingPid) != null) {
375 throw new SecurityException("The calling process has already "
376 + "registered an IDisplayManagerCallback.");
Jeff Brown64a55af2012-08-26 02:47:39 -0700377 }
378
Jeff Brownbd6e1502012-08-28 03:27:37 -0700379 CallbackRecord record = new CallbackRecord(callingPid, callback);
380 try {
381 IBinder binder = callback.asBinder();
382 binder.linkToDeath(record, 0);
383 } catch (RemoteException ex) {
384 // give up
385 throw new RuntimeException(ex);
386 }
387
388 mCallbacks.put(callingPid, record);
389 }
390 }
391
392 private void onCallbackDied(int pid) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700393 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700394 mCallbacks.remove(pid);
395 }
396 }
397
Jeff Browne08ae382012-09-07 20:36:36 -0700398 @Override // Binder call
399 public void scanWifiDisplays() {
Jeff Browne08ae382012-09-07 20:36:36 -0700400 final long token = Binder.clearCallingIdentity();
401 try {
402 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700403 if (mWifiDisplayAdapter != null) {
404 mWifiDisplayAdapter.requestScanLocked();
405 }
Jeff Browne08ae382012-09-07 20:36:36 -0700406 }
407 } finally {
408 Binder.restoreCallingIdentity(token);
409 }
410 }
411
412 @Override // Binder call
413 public void connectWifiDisplay(String address) {
Jeff Browne08ae382012-09-07 20:36:36 -0700414 if (address == null) {
415 throw new IllegalArgumentException("address must not be null");
416 }
417
Jeff Brownbc335452012-09-26 18:34:47 -0700418 final boolean trusted = canCallerConfigureWifiDisplay();
Jeff Browne08ae382012-09-07 20:36:36 -0700419 final long token = Binder.clearCallingIdentity();
420 try {
421 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700422 if (mWifiDisplayAdapter != null) {
Jeff Brownbc335452012-09-26 18:34:47 -0700423 mWifiDisplayAdapter.requestConnectLocked(address, trusted);
Jeff Brown21c71532012-09-09 13:26:55 -0700424 }
Jeff Browne08ae382012-09-07 20:36:36 -0700425 }
426 } finally {
427 Binder.restoreCallingIdentity(token);
428 }
429 }
430
431 @Override // Binder call
432 public void disconnectWifiDisplay() {
Jeff Browne08ae382012-09-07 20:36:36 -0700433 final long token = Binder.clearCallingIdentity();
434 try {
435 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700436 if (mWifiDisplayAdapter != null) {
437 mWifiDisplayAdapter.requestDisconnectLocked();
438 }
Jeff Browne08ae382012-09-07 20:36:36 -0700439 }
440 } finally {
441 Binder.restoreCallingIdentity(token);
442 }
443 }
444
445 @Override // Binder call
Jeff Brown89d55462012-09-19 11:33:42 -0700446 public void renameWifiDisplay(String address, String alias) {
Jeff Brown89d55462012-09-19 11:33:42 -0700447 if (address == null) {
448 throw new IllegalArgumentException("address must not be null");
449 }
Jeff Brownbc335452012-09-26 18:34:47 -0700450 if (!canCallerConfigureWifiDisplay()) {
451 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to "
452 + "rename a wifi display.");
453 }
Jeff Brown89d55462012-09-19 11:33:42 -0700454
455 final long token = Binder.clearCallingIdentity();
456 try {
457 synchronized (mSyncRoot) {
458 if (mWifiDisplayAdapter != null) {
459 mWifiDisplayAdapter.requestRenameLocked(address, alias);
460 }
461 }
462 } finally {
463 Binder.restoreCallingIdentity(token);
464 }
465 }
466
467 @Override // Binder call
468 public void forgetWifiDisplay(String address) {
Jeff Brown89d55462012-09-19 11:33:42 -0700469 if (address == null) {
470 throw new IllegalArgumentException("address must not be null");
471 }
Jeff Brownbc335452012-09-26 18:34:47 -0700472 if (!canCallerConfigureWifiDisplay()) {
473 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to "
474 + "forget a wifi display.");
475 }
Jeff Brown89d55462012-09-19 11:33:42 -0700476
477 final long token = Binder.clearCallingIdentity();
478 try {
479 synchronized (mSyncRoot) {
480 if (mWifiDisplayAdapter != null) {
481 mWifiDisplayAdapter.requestForgetLocked(address);
482 }
483 }
484 } finally {
485 Binder.restoreCallingIdentity(token);
486 }
487 }
488
489 @Override // Binder call
Jeff Browne08ae382012-09-07 20:36:36 -0700490 public WifiDisplayStatus getWifiDisplayStatus() {
Jeff Browne08ae382012-09-07 20:36:36 -0700491 final long token = Binder.clearCallingIdentity();
492 try {
493 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700494 if (mWifiDisplayAdapter != null) {
495 return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
496 } else {
497 return new WifiDisplayStatus();
498 }
Jeff Browne08ae382012-09-07 20:36:36 -0700499 }
500 } finally {
501 Binder.restoreCallingIdentity(token);
502 }
503 }
504
Jeff Brownbc335452012-09-26 18:34:47 -0700505 private boolean canCallerConfigureWifiDisplay() {
506 return mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
507 == PackageManager.PERMISSION_GRANTED;
508 }
509
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700510 private void registerDefaultDisplayAdapter() {
511 // Register default display adapter.
512 synchronized (mSyncRoot) {
513 if (mHeadless) {
514 registerDisplayAdapterLocked(new HeadlessDisplayAdapter(
515 mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
516 } else {
517 registerDisplayAdapterLocked(new LocalDisplayAdapter(
518 mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
519 }
520 }
521 }
522
523 private void registerAdditionalDisplayAdapters() {
524 synchronized (mSyncRoot) {
525 if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
Jeff Brown89d55462012-09-19 11:33:42 -0700526 registerOverlayDisplayAdapterLocked();
527 registerWifiDisplayAdapterLocked();
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700528 }
529 }
530 }
531
Jeff Brown89d55462012-09-19 11:33:42 -0700532 private void registerOverlayDisplayAdapterLocked() {
533 registerDisplayAdapterLocked(new OverlayDisplayAdapter(
534 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
535 }
536
537 private void registerWifiDisplayAdapterLocked() {
538 if (mContext.getResources().getBoolean(
Jeff Brownbbd28a22012-09-20 16:47:15 -0700539 com.android.internal.R.bool.config_enableWifiDisplay)
540 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
Jeff Brown89d55462012-09-19 11:33:42 -0700541 mWifiDisplayAdapter = new WifiDisplayAdapter(
542 mSyncRoot, mContext, mHandler, mDisplayAdapterListener,
543 mPersistentDataStore);
544 registerDisplayAdapterLocked(mWifiDisplayAdapter);
545 }
546 }
547
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700548 private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
549 // In safe mode, we disable non-essential display adapters to give the user
550 // an opportunity to fix broken settings or other problems that might affect
551 // system stability.
552 // In only-core mode, we disable non-essential display adapters to minimize
553 // the number of dependencies that are started while in this mode and to
554 // prevent problems that might occur due to the device being encrypted.
555 return !mSafeMode && !mOnlyCore;
556 }
557
558 private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
559 mDisplayAdapters.add(adapter);
560 adapter.registerLocked();
561 }
562
Jeff Brownbd6e1502012-08-28 03:27:37 -0700563 private void handleDisplayDeviceAdded(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700564 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700565 if (mDisplayDevices.contains(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700566 Slog.w(TAG, "Attempted to add already added display device: "
567 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700568 return;
569 }
570
Jeff Browne87bf032012-09-20 18:30:13 -0700571 Slog.i(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked());
572
Jeff Brownbd6e1502012-08-28 03:27:37 -0700573 mDisplayDevices.add(device);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700574 addLogicalDisplayLocked(device);
Craig Mautner65d11b32012-10-01 13:59:52 -0700575 scheduleTraversalLocked(false);
Jeff Brown9e316a12012-10-08 19:17:06 -0700576
577 // Blank or unblank the display immediately to match the state requested
578 // by the power manager (if known).
579 switch (mAllDisplayBlankStateFromPowerManager) {
580 case DISPLAY_BLANK_STATE_BLANKED:
581 device.blankLocked();
582 break;
583 case DISPLAY_BLANK_STATE_UNBLANKED:
584 device.unblankLocked();
585 break;
586 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700587 }
588 }
589
Jeff Brownbd6e1502012-08-28 03:27:37 -0700590 private void handleDisplayDeviceChanged(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700591 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700592 if (!mDisplayDevices.contains(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700593 Slog.w(TAG, "Attempted to change non-existent display device: "
594 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700595 return;
596 }
597
Jeff Browne87bf032012-09-20 18:30:13 -0700598 Slog.i(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked());
599
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700600 device.applyPendingDisplayDeviceInfoChangesLocked();
601 if (updateLogicalDisplaysLocked()) {
Craig Mautner65d11b32012-10-01 13:59:52 -0700602 scheduleTraversalLocked(false);
Jeff Brown64a55af2012-08-26 02:47:39 -0700603 }
604 }
605 }
606
Jeff Brownbd6e1502012-08-28 03:27:37 -0700607 private void handleDisplayDeviceRemoved(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700608 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700609 if (!mDisplayDevices.remove(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700610 Slog.w(TAG, "Attempted to remove non-existent display device: "
611 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700612 return;
Craig Mautner4f67ba62012-08-02 11:23:00 -0700613 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700614
Jeff Browne87bf032012-09-20 18:30:13 -0700615 Slog.i(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked());
616
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700617 mRemovedDisplayDevices.add(device);
618 updateLogicalDisplaysLocked();
Craig Mautner65d11b32012-10-01 13:59:52 -0700619 scheduleTraversalLocked(false);
Craig Mautner4f67ba62012-08-02 11:23:00 -0700620 }
621 }
622
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700623 // Adds a new logical display based on the given display device.
624 // Sends notifications if needed.
625 private void addLogicalDisplayLocked(DisplayDevice device) {
626 DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
627 boolean isDefault = (deviceInfo.flags
628 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
629 if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
630 Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo);
631 isDefault = false;
632 }
633
634 final int displayId = assignDisplayIdLocked(isDefault);
635 final int layerStack = assignLayerStackLocked(displayId);
636
Jeff Brownd728bf52012-09-08 18:05:28 -0700637 LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700638 display.updateLocked(mDisplayDevices);
639 if (!display.isValidLocked()) {
640 // This should never happen currently.
641 Slog.w(TAG, "Ignoring display device because the logical display "
642 + "created from it was not considered valid: " + deviceInfo);
643 return;
644 }
645
646 mLogicalDisplays.put(displayId, display);
647
648 // Wake up waitForDefaultDisplay.
649 if (isDefault) {
650 mSyncRoot.notifyAll();
651 }
652
653 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
654 }
655
656 private int assignDisplayIdLocked(boolean isDefault) {
657 return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
658 }
659
660 private int assignLayerStackLocked(int displayId) {
661 // Currently layer stacks and display ids are the same.
662 // This need not be the case.
663 return displayId;
664 }
665
666 // Updates all existing logical displays given the current set of display devices.
667 // Removes invalid logical displays.
668 // Sends notifications if needed.
669 private boolean updateLogicalDisplaysLocked() {
670 boolean changed = false;
671 for (int i = mLogicalDisplays.size(); i-- > 0; ) {
672 final int displayId = mLogicalDisplays.keyAt(i);
673 LogicalDisplay display = mLogicalDisplays.valueAt(i);
674
675 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
676 display.updateLocked(mDisplayDevices);
677 if (!display.isValidLocked()) {
678 mLogicalDisplays.removeAt(i);
679 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
680 changed = true;
681 } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
682 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
683 changed = true;
684 }
685 }
686 return changed;
687 }
688
689 private void performTraversalInTransactionLocked() {
690 // Perform one last traversal for each removed display device.
691 final int removedCount = mRemovedDisplayDevices.size();
692 for (int i = 0; i < removedCount; i++) {
693 DisplayDevice device = mRemovedDisplayDevices.get(i);
694 device.performTraversalInTransactionLocked();
695 }
696 mRemovedDisplayDevices.clear();
697
Jeff Brownd728bf52012-09-08 18:05:28 -0700698 // Clear all viewports before configuring displays so that we can keep
699 // track of which ones we have configured.
700 clearViewportsLocked();
701
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700702 // Configure each display device.
703 final int count = mDisplayDevices.size();
704 for (int i = 0; i < count; i++) {
705 DisplayDevice device = mDisplayDevices.get(i);
706 configureDisplayInTransactionLocked(device);
707 device.performTraversalInTransactionLocked();
708 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700709
710 // Tell the input system about these new viewports.
711 if (mInputManagerFuncs != null) {
712 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
713 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700714 }
715
Craig Mautner722285e2012-09-07 13:55:58 -0700716 /**
717 * Tells the display manager whether there is interesting unique content on the
718 * specified logical display. This is used to control automatic mirroring.
719 * <p>
720 * If the display has unique content, then the display manager arranges for it
721 * to be presented on a physical display if appropriate. Otherwise, the display manager
722 * may choose to make the physical display mirror some other logical display.
723 * </p>
724 *
725 * @param displayId The logical display id to update.
726 * @param hasContent True if the logical display has content.
Craig Mautner65d11b32012-10-01 13:59:52 -0700727 * @param inTraversal True if called from WindowManagerService during a window traversal prior
728 * to call to performTraversalInTransactionFromWindowManager.
Craig Mautner722285e2012-09-07 13:55:58 -0700729 */
Craig Mautner65d11b32012-10-01 13:59:52 -0700730 public void setDisplayHasContent(int displayId, boolean hasContent, boolean inTraversal) {
Craig Mautner722285e2012-09-07 13:55:58 -0700731 synchronized (mSyncRoot) {
732 LogicalDisplay display = mLogicalDisplays.get(displayId);
733 if (display != null && display.hasContentLocked() != hasContent) {
734 display.setHasContentLocked(hasContent);
Craig Mautner65d11b32012-10-01 13:59:52 -0700735 scheduleTraversalLocked(inTraversal);
Craig Mautner722285e2012-09-07 13:55:58 -0700736 }
737 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700738 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700739
Jeff Brownd728bf52012-09-08 18:05:28 -0700740 private void clearViewportsLocked() {
741 mDefaultViewport.valid = false;
742 mExternalTouchViewport.valid = false;
Craig Mautner722285e2012-09-07 13:55:58 -0700743 }
744
745 private void configureDisplayInTransactionLocked(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700746 // Find the logical display that the display device is showing.
Craig Mautner722285e2012-09-07 13:55:58 -0700747 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
748 if (display != null && !display.hasContentLocked()) {
749 display = null;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700750 }
751 if (display == null) {
752 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
753 }
754
755 // Apply the logical display configuration to the display device.
756 if (display == null) {
757 // TODO: no logical display for the device, blank it
Jeff Brownd728bf52012-09-08 18:05:28 -0700758 Slog.w(TAG, "Missing logical display to use for physical display device: "
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700759 + device.getDisplayDeviceInfoLocked());
Jeff Brownd728bf52012-09-08 18:05:28 -0700760 return;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700761 } else {
Jeff Brown8ec09432012-10-16 16:19:23 -0700762 boolean isBlanked = (mAllDisplayBlankStateFromPowerManager
763 == DISPLAY_BLANK_STATE_BLANKED);
764 display.configureDisplayInTransactionLocked(device, isBlanked);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700765 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700766
767 // Update the viewports if needed.
768 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
769 if (!mDefaultViewport.valid
770 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
771 setViewportLocked(mDefaultViewport, display, device);
772 }
773 if (!mExternalTouchViewport.valid
774 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
775 setViewportLocked(mExternalTouchViewport, display, device);
776 }
777 }
778
779 private static void setViewportLocked(DisplayViewport viewport,
780 LogicalDisplay display, DisplayDevice device) {
781 viewport.valid = true;
782 viewport.displayId = display.getDisplayIdLocked();
783 device.populateViewportLocked(viewport);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700784 }
785
786 private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) {
787 final int count = mLogicalDisplays.size();
788 for (int i = 0; i < count; i++) {
789 LogicalDisplay display = mLogicalDisplays.valueAt(i);
790 if (display.getPrimaryDisplayDeviceLocked() == device) {
791 return display;
792 }
793 }
794 return null;
795 }
796
Jeff Brownbd6e1502012-08-28 03:27:37 -0700797 private void sendDisplayEventLocked(int displayId, int event) {
798 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
799 mHandler.sendMessage(msg);
800 }
801
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700802 // Requests that performTraversalsInTransactionFromWindowManager be called at a
803 // later time to apply changes to surfaces and displays.
Craig Mautner65d11b32012-10-01 13:59:52 -0700804 private void scheduleTraversalLocked(boolean inTraversal) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700805 if (!mPendingTraversal && mWindowManagerFuncs != null) {
806 mPendingTraversal = true;
Craig Mautner65d11b32012-10-01 13:59:52 -0700807 if (!inTraversal) {
808 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
809 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700810 }
811 }
812
813 // Runs on Handler thread.
814 // Delivers display event notifications to callbacks.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700815 private void deliverDisplayEvent(int displayId, int event) {
816 if (DEBUG) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700817 Slog.d(TAG, "Delivering display event: displayId="
818 + displayId + ", event=" + event);
Jeff Brownfa25bf52012-07-23 19:26:30 -0700819 }
Jeff Brownfa25bf52012-07-23 19:26:30 -0700820
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700821 // Grab the lock and copy the callbacks.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700822 final int count;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700823 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700824 count = mCallbacks.size();
825 mTempCallbacks.clear();
826 for (int i = 0; i < count; i++) {
827 mTempCallbacks.add(mCallbacks.valueAt(i));
Craig Mautner4f67ba62012-08-02 11:23:00 -0700828 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700829 }
Craig Mautner4f67ba62012-08-02 11:23:00 -0700830
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700831 // After releasing the lock, send the notifications out.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700832 for (int i = 0; i < count; i++) {
833 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
834 }
835 mTempCallbacks.clear();
Craig Mautner4f67ba62012-08-02 11:23:00 -0700836 }
837
Jeff Brownfa25bf52012-07-23 19:26:30 -0700838 @Override // Binder call
Jeff Brownbd6e1502012-08-28 03:27:37 -0700839 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
Jeff Brownfa25bf52012-07-23 19:26:30 -0700840 if (mContext == null
841 || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
842 != PackageManager.PERMISSION_GRANTED) {
843 pw.println("Permission Denial: can't dump DisplayManager from from pid="
844 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
845 return;
846 }
847
Jeff Brownbd6e1502012-08-28 03:27:37 -0700848 pw.println("DISPLAY MANAGER (dumpsys display)");
Jeff Brownfa25bf52012-07-23 19:26:30 -0700849
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700850 synchronized (mSyncRoot) {
Jeff Brown9e316a12012-10-08 19:17:06 -0700851 pw.println(" mHeadless=" + mHeadless);
852 pw.println(" mOnlyCode=" + mOnlyCore);
853 pw.println(" mSafeMode=" + mSafeMode);
854 pw.println(" mPendingTraversal=" + mPendingTraversal);
855 pw.println(" mAllDisplayBlankStateFromPowerManager="
856 + mAllDisplayBlankStateFromPowerManager);
857 pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
858 pw.println(" mDefaultViewport=" + mDefaultViewport);
859 pw.println(" mExternalTouchViewport=" + mExternalTouchViewport);
860
Jeff Brownbd6e1502012-08-28 03:27:37 -0700861 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700862 ipw.increaseIndent();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700863
864 pw.println();
865 pw.println("Display Adapters: size=" + mDisplayAdapters.size());
Jeff Brown848c2dc2012-08-19 20:18:08 -0700866 for (DisplayAdapter adapter : mDisplayAdapters) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700867 pw.println(" " + adapter.getName());
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700868 adapter.dumpLocked(ipw);
Jeff Brown848c2dc2012-08-19 20:18:08 -0700869 }
Craig Mautner9de49362012-08-02 14:30:30 -0700870
Jeff Brownbd6e1502012-08-28 03:27:37 -0700871 pw.println();
872 pw.println("Display Devices: size=" + mDisplayDevices.size());
873 for (DisplayDevice device : mDisplayDevices) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700874 pw.println(" " + device.getDisplayDeviceInfoLocked());
875 device.dumpLocked(ipw);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700876 }
877
878 final int logicalDisplayCount = mLogicalDisplays.size();
879 pw.println();
880 pw.println("Logical Displays: size=" + logicalDisplayCount);
881 for (int i = 0; i < logicalDisplayCount; i++) {
882 int displayId = mLogicalDisplays.keyAt(i);
883 LogicalDisplay display = mLogicalDisplays.valueAt(i);
884 pw.println(" Display " + displayId + ":");
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700885 display.dumpLocked(ipw);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700886 }
887 }
888 }
889
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700890 /**
891 * This is the object that everything in the display manager locks on.
892 * We make it an inner class within the {@link DisplayManagerService} to so that it is
893 * clear that the object belongs to the display manager service and that it is
894 * a unique object with a special purpose.
895 */
896 public static final class SyncRoot {
897 }
898
899 /**
900 * Private interface to the window manager.
901 */
902 public interface WindowManagerFuncs {
903 /**
Craig Mautner722285e2012-09-07 13:55:58 -0700904 * Request that the window manager call
905 * {@link #performTraversalInTransactionFromWindowManager} within a surface
906 * transaction at a later time.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700907 */
908 void requestTraversal();
909 }
910
Jeff Brownd728bf52012-09-08 18:05:28 -0700911 /**
912 * Private interface to the input manager.
913 */
914 public interface InputManagerFuncs {
915 /**
916 * Sets information about the displays as needed by the input system.
917 * The input system should copy this information if required.
918 */
919 void setDisplayViewports(DisplayViewport defaultViewport,
920 DisplayViewport externalTouchViewport);
921 }
922
Jeff Brownbd6e1502012-08-28 03:27:37 -0700923 private final class DisplayManagerHandler extends Handler {
924 public DisplayManagerHandler(Looper looper) {
925 super(looper, null, true /*async*/);
Jeff Brown848c2dc2012-08-19 20:18:08 -0700926 }
Jeff Brownbf5740e2012-08-19 23:20:02 -0700927
Jeff Brownbd6e1502012-08-28 03:27:37 -0700928 @Override
929 public void handleMessage(Message msg) {
930 switch (msg.what) {
931 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
932 registerDefaultDisplayAdapter();
933 break;
934
935 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
936 registerAdditionalDisplayAdapters();
937 break;
938
939 case MSG_DELIVER_DISPLAY_EVENT:
940 deliverDisplayEvent(msg.arg1, msg.arg2);
941 break;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700942
943 case MSG_REQUEST_TRAVERSAL:
944 mWindowManagerFuncs.requestTraversal();
945 break;
Jeff Brownd728bf52012-09-08 18:05:28 -0700946
947 case MSG_UPDATE_VIEWPORT: {
948 synchronized (mSyncRoot) {
949 mTempDefaultViewport.copyFrom(mDefaultViewport);
950 mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
951 }
952 mInputManagerFuncs.setDisplayViewports(
953 mTempDefaultViewport, mTempExternalTouchViewport);
954 break;
955 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700956 }
957 }
958 }
959
960 private final class DisplayAdapterListener implements DisplayAdapter.Listener {
961 @Override
962 public void onDisplayDeviceEvent(DisplayDevice device, int event) {
963 switch (event) {
964 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
965 handleDisplayDeviceAdded(device);
966 break;
967
968 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
969 handleDisplayDeviceChanged(device);
970 break;
971
972 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
973 handleDisplayDeviceRemoved(device);
974 break;
975 }
976 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700977
978 @Override
979 public void onTraversalRequested() {
980 synchronized (mSyncRoot) {
Craig Mautner65d11b32012-10-01 13:59:52 -0700981 scheduleTraversalLocked(false);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700982 }
983 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700984 }
985
986 private final class CallbackRecord implements DeathRecipient {
987 private final int mPid;
988 private final IDisplayManagerCallback mCallback;
989
990 public CallbackRecord(int pid, IDisplayManagerCallback callback) {
991 mPid = pid;
992 mCallback = callback;
993 }
994
995 @Override
996 public void binderDied() {
997 if (DEBUG) {
998 Slog.d(TAG, "Display listener for pid " + mPid + " died.");
999 }
1000 onCallbackDied(mPid);
1001 }
1002
1003 public void notifyDisplayEventAsync(int displayId, int event) {
1004 try {
1005 mCallback.onDisplayEvent(displayId, event);
1006 } catch (RemoteException ex) {
1007 Slog.w(TAG, "Failed to notify process "
1008 + mPid + " that displays changed, assuming it died.", ex);
1009 binderDied();
1010 }
1011 }
1012 }
Jeff Brownfa25bf52012-07-23 19:26:30 -07001013}