blob: 0a4252813188a590733914848dc568f7a7f63b40 [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 }
308 }
309 }
310 }
311
312 /**
313 * Called by the power manager to unblank all displays.
314 */
315 public void unblankAllDisplaysFromPowerManager() {
316 synchronized (mSyncRoot) {
317 if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_UNBLANKED) {
318 mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNBLANKED;
319
320 final int count = mDisplayDevices.size();
321 for (int i = 0; i < count; i++) {
322 DisplayDevice device = mDisplayDevices.get(i);
323 device.unblankLocked();
324 }
325 }
326 }
327 }
328
329 /**
Jeff Brownbd6e1502012-08-28 03:27:37 -0700330 * Returns information about the specified logical display.
331 *
332 * @param displayId The logical display id.
Craig Mautner722285e2012-09-07 13:55:58 -0700333 * @return The logical display info, or null if the display does not exist. The
334 * returned object must be treated as immutable.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700335 */
336 @Override // Binder call
337 public DisplayInfo getDisplayInfo(int displayId) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700338 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700339 LogicalDisplay display = mLogicalDisplays.get(displayId);
340 if (display != null) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700341 return display.getDisplayInfoLocked();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700342 }
343 return null;
344 }
345 }
346
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700347 /**
348 * Returns the list of all display ids.
349 */
Jeff Brownbd6e1502012-08-28 03:27:37 -0700350 @Override // Binder call
351 public int[] getDisplayIds() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700352 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700353 final int count = mLogicalDisplays.size();
354 int[] displayIds = new int[count];
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700355 for (int i = 0; i < count; i++) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700356 displayIds[i] = mLogicalDisplays.keyAt(i);
357 }
358 return displayIds;
359 }
360 }
361
362 @Override // Binder call
363 public void registerCallback(IDisplayManagerCallback callback) {
364 if (callback == null) {
365 throw new IllegalArgumentException("listener must not be null");
366 }
367
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700368 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700369 int callingPid = Binder.getCallingPid();
370 if (mCallbacks.get(callingPid) != null) {
371 throw new SecurityException("The calling process has already "
372 + "registered an IDisplayManagerCallback.");
Jeff Brown64a55af2012-08-26 02:47:39 -0700373 }
374
Jeff Brownbd6e1502012-08-28 03:27:37 -0700375 CallbackRecord record = new CallbackRecord(callingPid, callback);
376 try {
377 IBinder binder = callback.asBinder();
378 binder.linkToDeath(record, 0);
379 } catch (RemoteException ex) {
380 // give up
381 throw new RuntimeException(ex);
382 }
383
384 mCallbacks.put(callingPid, record);
385 }
386 }
387
388 private void onCallbackDied(int pid) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700389 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700390 mCallbacks.remove(pid);
391 }
392 }
393
Jeff Browne08ae382012-09-07 20:36:36 -0700394 @Override // Binder call
395 public void scanWifiDisplays() {
Jeff Browne08ae382012-09-07 20:36:36 -0700396 final long token = Binder.clearCallingIdentity();
397 try {
398 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700399 if (mWifiDisplayAdapter != null) {
400 mWifiDisplayAdapter.requestScanLocked();
401 }
Jeff Browne08ae382012-09-07 20:36:36 -0700402 }
403 } finally {
404 Binder.restoreCallingIdentity(token);
405 }
406 }
407
408 @Override // Binder call
409 public void connectWifiDisplay(String address) {
Jeff Browne08ae382012-09-07 20:36:36 -0700410 if (address == null) {
411 throw new IllegalArgumentException("address must not be null");
412 }
413
Jeff Brownbc335452012-09-26 18:34:47 -0700414 final boolean trusted = canCallerConfigureWifiDisplay();
Jeff Browne08ae382012-09-07 20:36:36 -0700415 final long token = Binder.clearCallingIdentity();
416 try {
417 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700418 if (mWifiDisplayAdapter != null) {
Jeff Brownbc335452012-09-26 18:34:47 -0700419 mWifiDisplayAdapter.requestConnectLocked(address, trusted);
Jeff Brown21c71532012-09-09 13:26:55 -0700420 }
Jeff Browne08ae382012-09-07 20:36:36 -0700421 }
422 } finally {
423 Binder.restoreCallingIdentity(token);
424 }
425 }
426
427 @Override // Binder call
428 public void disconnectWifiDisplay() {
Jeff Browne08ae382012-09-07 20:36:36 -0700429 final long token = Binder.clearCallingIdentity();
430 try {
431 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700432 if (mWifiDisplayAdapter != null) {
433 mWifiDisplayAdapter.requestDisconnectLocked();
434 }
Jeff Browne08ae382012-09-07 20:36:36 -0700435 }
436 } finally {
437 Binder.restoreCallingIdentity(token);
438 }
439 }
440
441 @Override // Binder call
Jeff Brown89d55462012-09-19 11:33:42 -0700442 public void renameWifiDisplay(String address, String alias) {
Jeff Brown89d55462012-09-19 11:33:42 -0700443 if (address == null) {
444 throw new IllegalArgumentException("address must not be null");
445 }
Jeff Brownbc335452012-09-26 18:34:47 -0700446 if (!canCallerConfigureWifiDisplay()) {
447 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to "
448 + "rename a wifi display.");
449 }
Jeff Brown89d55462012-09-19 11:33:42 -0700450
451 final long token = Binder.clearCallingIdentity();
452 try {
453 synchronized (mSyncRoot) {
454 if (mWifiDisplayAdapter != null) {
455 mWifiDisplayAdapter.requestRenameLocked(address, alias);
456 }
457 }
458 } finally {
459 Binder.restoreCallingIdentity(token);
460 }
461 }
462
463 @Override // Binder call
464 public void forgetWifiDisplay(String address) {
Jeff Brown89d55462012-09-19 11:33:42 -0700465 if (address == null) {
466 throw new IllegalArgumentException("address must not be null");
467 }
Jeff Brownbc335452012-09-26 18:34:47 -0700468 if (!canCallerConfigureWifiDisplay()) {
469 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to "
470 + "forget a wifi display.");
471 }
Jeff Brown89d55462012-09-19 11:33:42 -0700472
473 final long token = Binder.clearCallingIdentity();
474 try {
475 synchronized (mSyncRoot) {
476 if (mWifiDisplayAdapter != null) {
477 mWifiDisplayAdapter.requestForgetLocked(address);
478 }
479 }
480 } finally {
481 Binder.restoreCallingIdentity(token);
482 }
483 }
484
485 @Override // Binder call
Jeff Browne08ae382012-09-07 20:36:36 -0700486 public WifiDisplayStatus getWifiDisplayStatus() {
Jeff Browne08ae382012-09-07 20:36:36 -0700487 final long token = Binder.clearCallingIdentity();
488 try {
489 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700490 if (mWifiDisplayAdapter != null) {
491 return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
492 } else {
493 return new WifiDisplayStatus();
494 }
Jeff Browne08ae382012-09-07 20:36:36 -0700495 }
496 } finally {
497 Binder.restoreCallingIdentity(token);
498 }
499 }
500
Jeff Brownbc335452012-09-26 18:34:47 -0700501 private boolean canCallerConfigureWifiDisplay() {
502 return mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
503 == PackageManager.PERMISSION_GRANTED;
504 }
505
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700506 private void registerDefaultDisplayAdapter() {
507 // Register default display adapter.
508 synchronized (mSyncRoot) {
509 if (mHeadless) {
510 registerDisplayAdapterLocked(new HeadlessDisplayAdapter(
511 mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
512 } else {
513 registerDisplayAdapterLocked(new LocalDisplayAdapter(
514 mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
515 }
516 }
517 }
518
519 private void registerAdditionalDisplayAdapters() {
520 synchronized (mSyncRoot) {
521 if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
Jeff Brown89d55462012-09-19 11:33:42 -0700522 registerOverlayDisplayAdapterLocked();
523 registerWifiDisplayAdapterLocked();
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700524 }
525 }
526 }
527
Jeff Brown89d55462012-09-19 11:33:42 -0700528 private void registerOverlayDisplayAdapterLocked() {
529 registerDisplayAdapterLocked(new OverlayDisplayAdapter(
530 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
531 }
532
533 private void registerWifiDisplayAdapterLocked() {
534 if (mContext.getResources().getBoolean(
Jeff Brownbbd28a22012-09-20 16:47:15 -0700535 com.android.internal.R.bool.config_enableWifiDisplay)
536 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
Jeff Brown89d55462012-09-19 11:33:42 -0700537 mWifiDisplayAdapter = new WifiDisplayAdapter(
538 mSyncRoot, mContext, mHandler, mDisplayAdapterListener,
539 mPersistentDataStore);
540 registerDisplayAdapterLocked(mWifiDisplayAdapter);
541 }
542 }
543
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700544 private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
545 // In safe mode, we disable non-essential display adapters to give the user
546 // an opportunity to fix broken settings or other problems that might affect
547 // system stability.
548 // In only-core mode, we disable non-essential display adapters to minimize
549 // the number of dependencies that are started while in this mode and to
550 // prevent problems that might occur due to the device being encrypted.
551 return !mSafeMode && !mOnlyCore;
552 }
553
554 private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
555 mDisplayAdapters.add(adapter);
556 adapter.registerLocked();
557 }
558
Jeff Brownbd6e1502012-08-28 03:27:37 -0700559 private void handleDisplayDeviceAdded(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700560 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700561 if (mDisplayDevices.contains(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700562 Slog.w(TAG, "Attempted to add already added display device: "
563 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700564 return;
565 }
566
Jeff Browne87bf032012-09-20 18:30:13 -0700567 Slog.i(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked());
568
Jeff Brownbd6e1502012-08-28 03:27:37 -0700569 mDisplayDevices.add(device);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700570 addLogicalDisplayLocked(device);
Craig Mautner65d11b32012-10-01 13:59:52 -0700571 scheduleTraversalLocked(false);
Jeff Brown9e316a12012-10-08 19:17:06 -0700572
573 // Blank or unblank the display immediately to match the state requested
574 // by the power manager (if known).
575 switch (mAllDisplayBlankStateFromPowerManager) {
576 case DISPLAY_BLANK_STATE_BLANKED:
577 device.blankLocked();
578 break;
579 case DISPLAY_BLANK_STATE_UNBLANKED:
580 device.unblankLocked();
581 break;
582 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700583 }
584 }
585
Jeff Brownbd6e1502012-08-28 03:27:37 -0700586 private void handleDisplayDeviceChanged(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700587 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700588 if (!mDisplayDevices.contains(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700589 Slog.w(TAG, "Attempted to change non-existent display device: "
590 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700591 return;
592 }
593
Jeff Browne87bf032012-09-20 18:30:13 -0700594 Slog.i(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked());
595
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700596 device.applyPendingDisplayDeviceInfoChangesLocked();
597 if (updateLogicalDisplaysLocked()) {
Craig Mautner65d11b32012-10-01 13:59:52 -0700598 scheduleTraversalLocked(false);
Jeff Brown64a55af2012-08-26 02:47:39 -0700599 }
600 }
601 }
602
Jeff Brownbd6e1502012-08-28 03:27:37 -0700603 private void handleDisplayDeviceRemoved(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700604 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700605 if (!mDisplayDevices.remove(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700606 Slog.w(TAG, "Attempted to remove non-existent display device: "
607 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700608 return;
Craig Mautner4f67ba62012-08-02 11:23:00 -0700609 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700610
Jeff Browne87bf032012-09-20 18:30:13 -0700611 Slog.i(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked());
612
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700613 mRemovedDisplayDevices.add(device);
614 updateLogicalDisplaysLocked();
Craig Mautner65d11b32012-10-01 13:59:52 -0700615 scheduleTraversalLocked(false);
Craig Mautner4f67ba62012-08-02 11:23:00 -0700616 }
617 }
618
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700619 // Adds a new logical display based on the given display device.
620 // Sends notifications if needed.
621 private void addLogicalDisplayLocked(DisplayDevice device) {
622 DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
623 boolean isDefault = (deviceInfo.flags
624 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
625 if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
626 Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo);
627 isDefault = false;
628 }
629
630 final int displayId = assignDisplayIdLocked(isDefault);
631 final int layerStack = assignLayerStackLocked(displayId);
632
Jeff Brownd728bf52012-09-08 18:05:28 -0700633 LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700634 display.updateLocked(mDisplayDevices);
635 if (!display.isValidLocked()) {
636 // This should never happen currently.
637 Slog.w(TAG, "Ignoring display device because the logical display "
638 + "created from it was not considered valid: " + deviceInfo);
639 return;
640 }
641
642 mLogicalDisplays.put(displayId, display);
643
644 // Wake up waitForDefaultDisplay.
645 if (isDefault) {
646 mSyncRoot.notifyAll();
647 }
648
649 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
650 }
651
652 private int assignDisplayIdLocked(boolean isDefault) {
653 return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
654 }
655
656 private int assignLayerStackLocked(int displayId) {
657 // Currently layer stacks and display ids are the same.
658 // This need not be the case.
659 return displayId;
660 }
661
662 // Updates all existing logical displays given the current set of display devices.
663 // Removes invalid logical displays.
664 // Sends notifications if needed.
665 private boolean updateLogicalDisplaysLocked() {
666 boolean changed = false;
667 for (int i = mLogicalDisplays.size(); i-- > 0; ) {
668 final int displayId = mLogicalDisplays.keyAt(i);
669 LogicalDisplay display = mLogicalDisplays.valueAt(i);
670
671 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
672 display.updateLocked(mDisplayDevices);
673 if (!display.isValidLocked()) {
674 mLogicalDisplays.removeAt(i);
675 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
676 changed = true;
677 } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
678 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
679 changed = true;
680 }
681 }
682 return changed;
683 }
684
685 private void performTraversalInTransactionLocked() {
686 // Perform one last traversal for each removed display device.
687 final int removedCount = mRemovedDisplayDevices.size();
688 for (int i = 0; i < removedCount; i++) {
689 DisplayDevice device = mRemovedDisplayDevices.get(i);
690 device.performTraversalInTransactionLocked();
691 }
692 mRemovedDisplayDevices.clear();
693
Jeff Brownd728bf52012-09-08 18:05:28 -0700694 // Clear all viewports before configuring displays so that we can keep
695 // track of which ones we have configured.
696 clearViewportsLocked();
697
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700698 // Configure each display device.
699 final int count = mDisplayDevices.size();
700 for (int i = 0; i < count; i++) {
701 DisplayDevice device = mDisplayDevices.get(i);
702 configureDisplayInTransactionLocked(device);
703 device.performTraversalInTransactionLocked();
704 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700705
706 // Tell the input system about these new viewports.
707 if (mInputManagerFuncs != null) {
708 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
709 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700710 }
711
Craig Mautner722285e2012-09-07 13:55:58 -0700712 /**
713 * Tells the display manager whether there is interesting unique content on the
714 * specified logical display. This is used to control automatic mirroring.
715 * <p>
716 * If the display has unique content, then the display manager arranges for it
717 * to be presented on a physical display if appropriate. Otherwise, the display manager
718 * may choose to make the physical display mirror some other logical display.
719 * </p>
720 *
721 * @param displayId The logical display id to update.
722 * @param hasContent True if the logical display has content.
Craig Mautner65d11b32012-10-01 13:59:52 -0700723 * @param inTraversal True if called from WindowManagerService during a window traversal prior
724 * to call to performTraversalInTransactionFromWindowManager.
Craig Mautner722285e2012-09-07 13:55:58 -0700725 */
Craig Mautner65d11b32012-10-01 13:59:52 -0700726 public void setDisplayHasContent(int displayId, boolean hasContent, boolean inTraversal) {
Craig Mautner722285e2012-09-07 13:55:58 -0700727 synchronized (mSyncRoot) {
728 LogicalDisplay display = mLogicalDisplays.get(displayId);
729 if (display != null && display.hasContentLocked() != hasContent) {
730 display.setHasContentLocked(hasContent);
Craig Mautner65d11b32012-10-01 13:59:52 -0700731 scheduleTraversalLocked(inTraversal);
Craig Mautner722285e2012-09-07 13:55:58 -0700732 }
733 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700734 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700735
Jeff Brownd728bf52012-09-08 18:05:28 -0700736 private void clearViewportsLocked() {
737 mDefaultViewport.valid = false;
738 mExternalTouchViewport.valid = false;
Craig Mautner722285e2012-09-07 13:55:58 -0700739 }
740
741 private void configureDisplayInTransactionLocked(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700742 // Find the logical display that the display device is showing.
Craig Mautner722285e2012-09-07 13:55:58 -0700743 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
744 if (display != null && !display.hasContentLocked()) {
745 display = null;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700746 }
747 if (display == null) {
748 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
749 }
750
751 // Apply the logical display configuration to the display device.
752 if (display == null) {
753 // TODO: no logical display for the device, blank it
Jeff Brownd728bf52012-09-08 18:05:28 -0700754 Slog.w(TAG, "Missing logical display to use for physical display device: "
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700755 + device.getDisplayDeviceInfoLocked());
Jeff Brownd728bf52012-09-08 18:05:28 -0700756 return;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700757 } else {
758 display.configureDisplayInTransactionLocked(device);
759 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700760
761 // Update the viewports if needed.
762 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
763 if (!mDefaultViewport.valid
764 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
765 setViewportLocked(mDefaultViewport, display, device);
766 }
767 if (!mExternalTouchViewport.valid
768 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
769 setViewportLocked(mExternalTouchViewport, display, device);
770 }
771 }
772
773 private static void setViewportLocked(DisplayViewport viewport,
774 LogicalDisplay display, DisplayDevice device) {
775 viewport.valid = true;
776 viewport.displayId = display.getDisplayIdLocked();
777 device.populateViewportLocked(viewport);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700778 }
779
780 private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) {
781 final int count = mLogicalDisplays.size();
782 for (int i = 0; i < count; i++) {
783 LogicalDisplay display = mLogicalDisplays.valueAt(i);
784 if (display.getPrimaryDisplayDeviceLocked() == device) {
785 return display;
786 }
787 }
788 return null;
789 }
790
Jeff Brownbd6e1502012-08-28 03:27:37 -0700791 private void sendDisplayEventLocked(int displayId, int event) {
792 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
793 mHandler.sendMessage(msg);
794 }
795
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700796 // Requests that performTraversalsInTransactionFromWindowManager be called at a
797 // later time to apply changes to surfaces and displays.
Craig Mautner65d11b32012-10-01 13:59:52 -0700798 private void scheduleTraversalLocked(boolean inTraversal) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700799 if (!mPendingTraversal && mWindowManagerFuncs != null) {
800 mPendingTraversal = true;
Craig Mautner65d11b32012-10-01 13:59:52 -0700801 if (!inTraversal) {
802 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
803 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700804 }
805 }
806
807 // Runs on Handler thread.
808 // Delivers display event notifications to callbacks.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700809 private void deliverDisplayEvent(int displayId, int event) {
810 if (DEBUG) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700811 Slog.d(TAG, "Delivering display event: displayId="
812 + displayId + ", event=" + event);
Jeff Brownfa25bf52012-07-23 19:26:30 -0700813 }
Jeff Brownfa25bf52012-07-23 19:26:30 -0700814
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700815 // Grab the lock and copy the callbacks.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700816 final int count;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700817 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700818 count = mCallbacks.size();
819 mTempCallbacks.clear();
820 for (int i = 0; i < count; i++) {
821 mTempCallbacks.add(mCallbacks.valueAt(i));
Craig Mautner4f67ba62012-08-02 11:23:00 -0700822 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700823 }
Craig Mautner4f67ba62012-08-02 11:23:00 -0700824
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700825 // After releasing the lock, send the notifications out.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700826 for (int i = 0; i < count; i++) {
827 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
828 }
829 mTempCallbacks.clear();
Craig Mautner4f67ba62012-08-02 11:23:00 -0700830 }
831
Jeff Brownfa25bf52012-07-23 19:26:30 -0700832 @Override // Binder call
Jeff Brownbd6e1502012-08-28 03:27:37 -0700833 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
Jeff Brownfa25bf52012-07-23 19:26:30 -0700834 if (mContext == null
835 || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
836 != PackageManager.PERMISSION_GRANTED) {
837 pw.println("Permission Denial: can't dump DisplayManager from from pid="
838 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
839 return;
840 }
841
Jeff Brownbd6e1502012-08-28 03:27:37 -0700842 pw.println("DISPLAY MANAGER (dumpsys display)");
Jeff Brownfa25bf52012-07-23 19:26:30 -0700843
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700844 synchronized (mSyncRoot) {
Jeff Brown9e316a12012-10-08 19:17:06 -0700845 pw.println(" mHeadless=" + mHeadless);
846 pw.println(" mOnlyCode=" + mOnlyCore);
847 pw.println(" mSafeMode=" + mSafeMode);
848 pw.println(" mPendingTraversal=" + mPendingTraversal);
849 pw.println(" mAllDisplayBlankStateFromPowerManager="
850 + mAllDisplayBlankStateFromPowerManager);
851 pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
852 pw.println(" mDefaultViewport=" + mDefaultViewport);
853 pw.println(" mExternalTouchViewport=" + mExternalTouchViewport);
854
Jeff Brownbd6e1502012-08-28 03:27:37 -0700855 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700856 ipw.increaseIndent();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700857
858 pw.println();
859 pw.println("Display Adapters: size=" + mDisplayAdapters.size());
Jeff Brown848c2dc2012-08-19 20:18:08 -0700860 for (DisplayAdapter adapter : mDisplayAdapters) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700861 pw.println(" " + adapter.getName());
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700862 adapter.dumpLocked(ipw);
Jeff Brown848c2dc2012-08-19 20:18:08 -0700863 }
Craig Mautner9de49362012-08-02 14:30:30 -0700864
Jeff Brownbd6e1502012-08-28 03:27:37 -0700865 pw.println();
866 pw.println("Display Devices: size=" + mDisplayDevices.size());
867 for (DisplayDevice device : mDisplayDevices) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700868 pw.println(" " + device.getDisplayDeviceInfoLocked());
869 device.dumpLocked(ipw);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700870 }
871
872 final int logicalDisplayCount = mLogicalDisplays.size();
873 pw.println();
874 pw.println("Logical Displays: size=" + logicalDisplayCount);
875 for (int i = 0; i < logicalDisplayCount; i++) {
876 int displayId = mLogicalDisplays.keyAt(i);
877 LogicalDisplay display = mLogicalDisplays.valueAt(i);
878 pw.println(" Display " + displayId + ":");
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700879 display.dumpLocked(ipw);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700880 }
881 }
882 }
883
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700884 /**
885 * This is the object that everything in the display manager locks on.
886 * We make it an inner class within the {@link DisplayManagerService} to so that it is
887 * clear that the object belongs to the display manager service and that it is
888 * a unique object with a special purpose.
889 */
890 public static final class SyncRoot {
891 }
892
893 /**
894 * Private interface to the window manager.
895 */
896 public interface WindowManagerFuncs {
897 /**
Craig Mautner722285e2012-09-07 13:55:58 -0700898 * Request that the window manager call
899 * {@link #performTraversalInTransactionFromWindowManager} within a surface
900 * transaction at a later time.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700901 */
902 void requestTraversal();
903 }
904
Jeff Brownd728bf52012-09-08 18:05:28 -0700905 /**
906 * Private interface to the input manager.
907 */
908 public interface InputManagerFuncs {
909 /**
910 * Sets information about the displays as needed by the input system.
911 * The input system should copy this information if required.
912 */
913 void setDisplayViewports(DisplayViewport defaultViewport,
914 DisplayViewport externalTouchViewport);
915 }
916
Jeff Brownbd6e1502012-08-28 03:27:37 -0700917 private final class DisplayManagerHandler extends Handler {
918 public DisplayManagerHandler(Looper looper) {
919 super(looper, null, true /*async*/);
Jeff Brown848c2dc2012-08-19 20:18:08 -0700920 }
Jeff Brownbf5740e2012-08-19 23:20:02 -0700921
Jeff Brownbd6e1502012-08-28 03:27:37 -0700922 @Override
923 public void handleMessage(Message msg) {
924 switch (msg.what) {
925 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
926 registerDefaultDisplayAdapter();
927 break;
928
929 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
930 registerAdditionalDisplayAdapters();
931 break;
932
933 case MSG_DELIVER_DISPLAY_EVENT:
934 deliverDisplayEvent(msg.arg1, msg.arg2);
935 break;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700936
937 case MSG_REQUEST_TRAVERSAL:
938 mWindowManagerFuncs.requestTraversal();
939 break;
Jeff Brownd728bf52012-09-08 18:05:28 -0700940
941 case MSG_UPDATE_VIEWPORT: {
942 synchronized (mSyncRoot) {
943 mTempDefaultViewport.copyFrom(mDefaultViewport);
944 mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
945 }
946 mInputManagerFuncs.setDisplayViewports(
947 mTempDefaultViewport, mTempExternalTouchViewport);
948 break;
949 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700950 }
951 }
952 }
953
954 private final class DisplayAdapterListener implements DisplayAdapter.Listener {
955 @Override
956 public void onDisplayDeviceEvent(DisplayDevice device, int event) {
957 switch (event) {
958 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
959 handleDisplayDeviceAdded(device);
960 break;
961
962 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
963 handleDisplayDeviceChanged(device);
964 break;
965
966 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
967 handleDisplayDeviceRemoved(device);
968 break;
969 }
970 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700971
972 @Override
973 public void onTraversalRequested() {
974 synchronized (mSyncRoot) {
Craig Mautner65d11b32012-10-01 13:59:52 -0700975 scheduleTraversalLocked(false);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700976 }
977 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700978 }
979
980 private final class CallbackRecord implements DeathRecipient {
981 private final int mPid;
982 private final IDisplayManagerCallback mCallback;
983
984 public CallbackRecord(int pid, IDisplayManagerCallback callback) {
985 mPid = pid;
986 mCallback = callback;
987 }
988
989 @Override
990 public void binderDied() {
991 if (DEBUG) {
992 Slog.d(TAG, "Display listener for pid " + mPid + " died.");
993 }
994 onCallbackDied(mPid);
995 }
996
997 public void notifyDisplayEventAsync(int displayId, int event) {
998 try {
999 mCallback.onDisplayEvent(displayId, event);
1000 } catch (RemoteException ex) {
1001 Slog.w(TAG, "Failed to notify process "
1002 + mPid + " that displays changed, assuming it died.", ex);
1003 binderDied();
1004 }
1005 }
1006 }
Jeff Brownfa25bf52012-07-23 19:26:30 -07001007}