blob: ca85e427fc180b5639bbfea508d0f8622d0306ee [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;
Dianne Hackborn8d044e82013-04-30 17:24:15 -070040import com.android.server.UiThread;
Jeff Brownfa25bf52012-07-23 19:26:30 -070041
42import java.io.FileDescriptor;
43import java.io.PrintWriter;
44import java.util.ArrayList;
Jeff Brown7f3994e2012-12-04 14:04:28 -080045import java.util.concurrent.CopyOnWriteArrayList;
Jeff Brownfa25bf52012-07-23 19:26:30 -070046
47/**
Jeff Brownbd6e1502012-08-28 03:27:37 -070048 * Manages attached displays.
Jeff Brownfa25bf52012-07-23 19:26:30 -070049 * <p>
Jeff Brownbd6e1502012-08-28 03:27:37 -070050 * The {@link DisplayManagerService} manages the global lifecycle of displays,
51 * decides how to configure logical displays based on the physical display devices currently
52 * attached, sends notifications to the system and to applications when the state
53 * changes, and so on.
54 * </p><p>
55 * The display manager service relies on a collection of {@link DisplayAdapter} components,
56 * for discovering and configuring physical display devices attached to the system.
57 * There are separate display adapters for each manner that devices are attached:
58 * one display adapter for built-in local displays, one for simulated non-functional
59 * displays when the system is headless, one for simulated overlay displays used for
60 * development, one for wifi displays, etc.
61 * </p><p>
62 * Display adapters are only weakly coupled to the display manager service.
63 * Display adapters communicate changes in display device state to the display manager
Craig Mautner722285e2012-09-07 13:55:58 -070064 * service asynchronously via a {@link DisplayAdapter.Listener} registered
Jeff Brownbd6e1502012-08-28 03:27:37 -070065 * by the display manager service. This separation of concerns is important for
66 * two main reasons. First, it neatly encapsulates the responsibilities of these
67 * two classes: display adapters handle individual display devices whereas
68 * the display manager service handles the global state. Second, it eliminates
69 * the potential for deadlocks resulting from asynchronous display device discovery.
Jeff Brown4ed8fe72012-08-30 18:18:29 -070070 * </p>
71 *
72 * <h3>Synchronization</h3>
73 * <p>
74 * Because the display manager may be accessed by multiple threads, the synchronization
75 * story gets a little complicated. In particular, the window manager may call into
76 * the display manager while holding a surface transaction with the expectation that
77 * it can apply changes immediately. Unfortunately, that means we can't just do
78 * everything asynchronously (*grump*).
Jeff Brownbd6e1502012-08-28 03:27:37 -070079 * </p><p>
Jeff Brown4ed8fe72012-08-30 18:18:29 -070080 * To make this work, all of the objects that belong to the display manager must
81 * use the same lock. We call this lock the synchronization root and it has a unique
82 * type {@link DisplayManagerService.SyncRoot}. Methods that require this lock are
83 * named with the "Locked" suffix.
84 * </p><p>
85 * Where things get tricky is that the display manager is not allowed to make
86 * any potentially reentrant calls, especially into the window manager. We generally
87 * avoid this by making all potentially reentrant out-calls asynchronous.
Jeff Brownfa25bf52012-07-23 19:26:30 -070088 * </p>
89 */
90public final class DisplayManagerService extends IDisplayManager.Stub {
91 private static final String TAG = "DisplayManagerService";
Jeff Brownbd6e1502012-08-28 03:27:37 -070092 private static final boolean DEBUG = false;
Jeff Brownfa25bf52012-07-23 19:26:30 -070093
Jeff Brownbbd28a22012-09-20 16:47:15 -070094 // When this system property is set to 0, WFD is forcibly disabled on boot.
95 // When this system property is set to 1, WFD is forcibly enabled on boot.
96 // Otherwise WFD is enabled according to the value of config_enableWifiDisplay.
97 private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable";
98
Jeff Brownfa25bf52012-07-23 19:26:30 -070099 private static final String SYSTEM_HEADLESS = "ro.config.headless";
Jeff Brownbd6e1502012-08-28 03:27:37 -0700100 private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
101
102 private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER = 1;
103 private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;
104 private static final int MSG_DELIVER_DISPLAY_EVENT = 3;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700105 private static final int MSG_REQUEST_TRAVERSAL = 4;
Jeff Brownd728bf52012-09-08 18:05:28 -0700106 private static final int MSG_UPDATE_VIEWPORT = 5;
Jeff Brownfa25bf52012-07-23 19:26:30 -0700107
Jeff Brown9e316a12012-10-08 19:17:06 -0700108 private static final int DISPLAY_BLANK_STATE_UNKNOWN = 0;
109 private static final int DISPLAY_BLANK_STATE_BLANKED = 1;
110 private static final int DISPLAY_BLANK_STATE_UNBLANKED = 2;
111
Jeff Brown848c2dc2012-08-19 20:18:08 -0700112 private final Context mContext;
Jeff Brownfa25bf52012-07-23 19:26:30 -0700113 private final boolean mHeadless;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700114 private final DisplayManagerHandler mHandler;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700115 private final Handler mUiHandler;
116 private final DisplayAdapterListener mDisplayAdapterListener;
117 private WindowManagerFuncs mWindowManagerFuncs;
Jeff Brownd728bf52012-09-08 18:05:28 -0700118 private InputManagerFuncs mInputManagerFuncs;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700119
120 // The synchronization root for the display manager.
121 // This lock guards most of the display manager's state.
Craig Mautner0bf6ec92012-12-18 08:33:27 -0800122 // NOTE: This is synchronized on while holding WindowManagerService.mWindowMap so never call
123 // into WindowManagerService methods that require mWindowMap while holding this unless you are
124 // very very sure that no deadlock can occur.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700125 private final SyncRoot mSyncRoot = new SyncRoot();
126
127 // True if in safe mode.
128 // This option may disable certain display adapters.
129 public boolean mSafeMode;
130
131 // True if we are in a special boot mode where only core applications and
132 // services should be started. This option may disable certain display adapters.
133 public boolean mOnlyCore;
134
Jeff Brown27f1d672012-10-17 18:32:34 -0700135 // True if the display manager service should pretend there is only one display
136 // and only tell applications about the existence of the default logical display.
137 // The display manager can still mirror content to secondary displays but applications
138 // cannot present unique content on those displays.
139 // Used for demonstration purposes only.
140 private final boolean mSingleDisplayDemoMode;
141
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700142 // All callback records indexed by calling process id.
143 public final SparseArray<CallbackRecord> mCallbacks =
Jeff Brownbd6e1502012-08-28 03:27:37 -0700144 new SparseArray<CallbackRecord>();
Jeff Brownfa25bf52012-07-23 19:26:30 -0700145
Jeff Brownbd6e1502012-08-28 03:27:37 -0700146 // List of all currently registered display adapters.
147 private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
148
149 // List of all currently connected display devices.
150 private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>();
151
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700152 // List of all removed display devices.
153 private final ArrayList<DisplayDevice> mRemovedDisplayDevices = new ArrayList<DisplayDevice>();
154
155 // List of all logical displays indexed by logical display id.
156 private final SparseArray<LogicalDisplay> mLogicalDisplays =
157 new SparseArray<LogicalDisplay>();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700158 private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
159
Jeff Brown7f3994e2012-12-04 14:04:28 -0800160 // List of all display transaction listeners.
161 private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners =
162 new CopyOnWriteArrayList<DisplayTransactionListener>();
163
Jeff Brown9e316a12012-10-08 19:17:06 -0700164 // Set to true if all displays have been blanked by the power manager.
Craig Mautner0bf6ec92012-12-18 08:33:27 -0800165 private int mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNKNOWN;
Jeff Brown9e316a12012-10-08 19:17:06 -0700166
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700167 // Set to true when there are pending display changes that have yet to be applied
168 // to the surface flinger state.
169 private boolean mPendingTraversal;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700170
Jeff Browne08ae382012-09-07 20:36:36 -0700171 // The Wifi display adapter, or null if not registered.
172 private WifiDisplayAdapter mWifiDisplayAdapter;
173
Jeff Brownd728bf52012-09-08 18:05:28 -0700174 // Viewports of the default display and the display that should receive touch
175 // input from an external source. Used by the input system.
176 private final DisplayViewport mDefaultViewport = new DisplayViewport();
177 private final DisplayViewport mExternalTouchViewport = new DisplayViewport();
178
Jeff Brown89d55462012-09-19 11:33:42 -0700179 // Persistent data store for all internal settings maintained by the display manager service.
180 private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();
181
Jeff Brownbd6e1502012-08-28 03:27:37 -0700182 // Temporary callback list, used when sending display events to applications.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700183 // May be used outside of the lock but only on the handler thread.
184 private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700185
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700186 // Temporary display info, used for comparing display configurations.
187 private final DisplayInfo mTempDisplayInfo = new DisplayInfo();
188
Jeff Brownd728bf52012-09-08 18:05:28 -0700189 // Temporary viewports, used when sending new viewport information to the
190 // input system. May be used outside of the lock but only on the handler thread.
191 private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
192 private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
193
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700194 public DisplayManagerService(Context context, Handler mainHandler) {
Jeff Brown848c2dc2012-08-19 20:18:08 -0700195 mContext = context;
Jeff Brownfa25bf52012-07-23 19:26:30 -0700196 mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1");
Jeff Brown848c2dc2012-08-19 20:18:08 -0700197
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700198 mHandler = new DisplayManagerHandler(mainHandler.getLooper());
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700199 mUiHandler = UiThread.getHandler();
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700200 mDisplayAdapterListener = new DisplayAdapterListener();
Jeff Brown27f1d672012-10-17 18:32:34 -0700201 mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700202
Jeff Brownbd6e1502012-08-28 03:27:37 -0700203 mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
Craig Mautner4f67ba62012-08-02 11:23:00 -0700204 }
205
Jeff Brownbd6e1502012-08-28 03:27:37 -0700206 /**
207 * Pauses the boot process to wait for the first display to be initialized.
208 */
209 public boolean waitForDefaultDisplay() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700210 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700211 long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
212 while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) {
213 long delay = timeout - SystemClock.uptimeMillis();
214 if (delay <= 0) {
215 return false;
216 }
217 if (DEBUG) {
218 Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
219 }
220 try {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700221 mSyncRoot.wait(delay);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700222 } catch (InterruptedException ex) {
223 }
224 }
225 }
226 return true;
227 }
228
229 /**
Jeff Brownd728bf52012-09-08 18:05:28 -0700230 * Called during initialization to associate the display manager with the
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700231 * window manager.
232 */
233 public void setWindowManager(WindowManagerFuncs windowManagerFuncs) {
234 synchronized (mSyncRoot) {
235 mWindowManagerFuncs = windowManagerFuncs;
Craig Mautner65d11b32012-10-01 13:59:52 -0700236 scheduleTraversalLocked(false);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700237 }
238 }
239
240 /**
Jeff Brownd728bf52012-09-08 18:05:28 -0700241 * Called during initialization to associate the display manager with the
242 * input manager.
243 */
244 public void setInputManager(InputManagerFuncs inputManagerFuncs) {
245 synchronized (mSyncRoot) {
246 mInputManagerFuncs = inputManagerFuncs;
Craig Mautner65d11b32012-10-01 13:59:52 -0700247 scheduleTraversalLocked(false);
Jeff Brownd728bf52012-09-08 18:05:28 -0700248 }
249 }
250
251 /**
Jeff Brownbd6e1502012-08-28 03:27:37 -0700252 * Called when the system is ready to go.
253 */
254 public void systemReady(boolean safeMode, boolean onlyCore) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700255 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700256 mSafeMode = safeMode;
257 mOnlyCore = onlyCore;
258 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700259
Jeff Brownbd6e1502012-08-28 03:27:37 -0700260 mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
261 }
262
Jeff Brown848c2dc2012-08-19 20:18:08 -0700263 /**
264 * Returns true if the device is headless.
265 *
266 * @return True if the device is headless.
267 */
Jeff Brownfa25bf52012-07-23 19:26:30 -0700268 public boolean isHeadless() {
269 return mHeadless;
270 }
271
Craig Mautner4f67ba62012-08-02 11:23:00 -0700272 /**
Jeff Brown7f3994e2012-12-04 14:04:28 -0800273 * Registers a display transaction listener to provide the client a chance to
274 * update its surfaces within the same transaction as any display layout updates.
275 *
276 * @param listener The listener to register.
277 */
278 public void registerDisplayTransactionListener(DisplayTransactionListener listener) {
279 if (listener == null) {
280 throw new IllegalArgumentException("listener must not be null");
281 }
282
283 // List is self-synchronized copy-on-write.
284 mDisplayTransactionListeners.add(listener);
285 }
286
287 /**
288 * Unregisters a display transaction listener to provide the client a chance to
289 * update its surfaces within the same transaction as any display layout updates.
290 *
291 * @param listener The listener to unregister.
292 */
293 public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) {
294 if (listener == null) {
295 throw new IllegalArgumentException("listener must not be null");
296 }
297
298 // List is self-synchronized copy-on-write.
299 mDisplayTransactionListeners.remove(listener);
300 }
301
302 /**
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700303 * Overrides the display information of a particular logical display.
304 * This is used by the window manager to control the size and characteristics
305 * of the default display. It is expected to apply the requested change
306 * to the display information synchronously so that applications will immediately
307 * observe the new state.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700308 *
Jeff Brown64a55af2012-08-26 02:47:39 -0700309 * @param displayId The logical display id.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700310 * @param info The new data to be stored.
Jeff Brown64a55af2012-08-26 02:47:39 -0700311 */
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700312 public void setDisplayInfoOverrideFromWindowManager(
313 int displayId, DisplayInfo info) {
314 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700315 LogicalDisplay display = mLogicalDisplays.get(displayId);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700316 if (display != null) {
317 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
318 display.setDisplayInfoOverrideFromWindowManagerLocked(info);
319 if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
320 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
Craig Mautner65d11b32012-10-01 13:59:52 -0700321 scheduleTraversalLocked(false);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700322 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700323 }
324 }
325 }
326
327 /**
Dianne Hackbornc652de82013-02-15 16:32:56 -0800328 * Sets the overscan insets for a particular display.
329 */
330 public void setOverscan(int displayId, int left, int top, int right, int bottom) {
331 synchronized (mSyncRoot) {
332 LogicalDisplay display = mLogicalDisplays.get(displayId);
333 if (display != null) {
334 display.setOverscan(left, top, right, bottom);
335 }
336 }
337 }
338
339 /**
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700340 * Called by the window manager to perform traversals while holding a
341 * surface flinger transaction.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700342 */
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700343 public void performTraversalInTransactionFromWindowManager() {
344 synchronized (mSyncRoot) {
345 if (!mPendingTraversal) {
346 return;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700347 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700348 mPendingTraversal = false;
349
350 performTraversalInTransactionLocked();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700351 }
Jeff Brown7f3994e2012-12-04 14:04:28 -0800352
353 // List is self-synchronized copy-on-write.
354 for (DisplayTransactionListener listener : mDisplayTransactionListeners) {
355 listener.onDisplayTransaction();
356 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700357 }
358
359 /**
Jeff Brown9e316a12012-10-08 19:17:06 -0700360 * Called by the power manager to blank all displays.
361 */
362 public void blankAllDisplaysFromPowerManager() {
363 synchronized (mSyncRoot) {
364 if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_BLANKED) {
365 mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_BLANKED;
366
367 final int count = mDisplayDevices.size();
368 for (int i = 0; i < count; i++) {
369 DisplayDevice device = mDisplayDevices.get(i);
370 device.blankLocked();
371 }
Jeff Brown8ec09432012-10-16 16:19:23 -0700372
373 scheduleTraversalLocked(false);
Jeff Brown9e316a12012-10-08 19:17:06 -0700374 }
375 }
376 }
377
378 /**
379 * Called by the power manager to unblank all displays.
380 */
381 public void unblankAllDisplaysFromPowerManager() {
382 synchronized (mSyncRoot) {
383 if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_UNBLANKED) {
384 mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNBLANKED;
385
386 final int count = mDisplayDevices.size();
387 for (int i = 0; i < count; i++) {
388 DisplayDevice device = mDisplayDevices.get(i);
389 device.unblankLocked();
390 }
Jeff Brown8ec09432012-10-16 16:19:23 -0700391
392 scheduleTraversalLocked(false);
Jeff Brown9e316a12012-10-08 19:17:06 -0700393 }
394 }
395 }
396
397 /**
Jeff Brownbd6e1502012-08-28 03:27:37 -0700398 * Returns information about the specified logical display.
399 *
400 * @param displayId The logical display id.
Craig Mautner722285e2012-09-07 13:55:58 -0700401 * @return The logical display info, or null if the display does not exist. The
402 * returned object must be treated as immutable.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700403 */
404 @Override // Binder call
405 public DisplayInfo getDisplayInfo(int displayId) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700406 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700407 LogicalDisplay display = mLogicalDisplays.get(displayId);
408 if (display != null) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700409 return display.getDisplayInfoLocked();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700410 }
411 return null;
412 }
413 }
414
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700415 /**
416 * Returns the list of all display ids.
417 */
Jeff Brownbd6e1502012-08-28 03:27:37 -0700418 @Override // Binder call
419 public int[] getDisplayIds() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700420 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700421 final int count = mLogicalDisplays.size();
422 int[] displayIds = new int[count];
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700423 for (int i = 0; i < count; i++) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700424 displayIds[i] = mLogicalDisplays.keyAt(i);
425 }
426 return displayIds;
427 }
428 }
429
430 @Override // Binder call
431 public void registerCallback(IDisplayManagerCallback callback) {
432 if (callback == null) {
433 throw new IllegalArgumentException("listener must not be null");
434 }
435
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700436 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700437 int callingPid = Binder.getCallingPid();
438 if (mCallbacks.get(callingPid) != null) {
439 throw new SecurityException("The calling process has already "
440 + "registered an IDisplayManagerCallback.");
Jeff Brown64a55af2012-08-26 02:47:39 -0700441 }
442
Jeff Brownbd6e1502012-08-28 03:27:37 -0700443 CallbackRecord record = new CallbackRecord(callingPid, callback);
444 try {
445 IBinder binder = callback.asBinder();
446 binder.linkToDeath(record, 0);
447 } catch (RemoteException ex) {
448 // give up
449 throw new RuntimeException(ex);
450 }
451
452 mCallbacks.put(callingPid, record);
453 }
454 }
455
456 private void onCallbackDied(int pid) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700457 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700458 mCallbacks.remove(pid);
459 }
460 }
461
Jeff Browne08ae382012-09-07 20:36:36 -0700462 @Override // Binder call
463 public void scanWifiDisplays() {
Jeff Browne08ae382012-09-07 20:36:36 -0700464 final long token = Binder.clearCallingIdentity();
465 try {
466 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700467 if (mWifiDisplayAdapter != null) {
468 mWifiDisplayAdapter.requestScanLocked();
469 }
Jeff Browne08ae382012-09-07 20:36:36 -0700470 }
471 } finally {
472 Binder.restoreCallingIdentity(token);
473 }
474 }
475
476 @Override // Binder call
477 public void connectWifiDisplay(String address) {
Jeff Browne08ae382012-09-07 20:36:36 -0700478 if (address == null) {
479 throw new IllegalArgumentException("address must not be null");
480 }
481
Jeff Brownbc335452012-09-26 18:34:47 -0700482 final boolean trusted = canCallerConfigureWifiDisplay();
Jeff Browne08ae382012-09-07 20:36:36 -0700483 final long token = Binder.clearCallingIdentity();
484 try {
485 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700486 if (mWifiDisplayAdapter != null) {
Jeff Brownbc335452012-09-26 18:34:47 -0700487 mWifiDisplayAdapter.requestConnectLocked(address, trusted);
Jeff Brown21c71532012-09-09 13:26:55 -0700488 }
Jeff Browne08ae382012-09-07 20:36:36 -0700489 }
490 } finally {
491 Binder.restoreCallingIdentity(token);
492 }
493 }
494
495 @Override // Binder call
496 public void disconnectWifiDisplay() {
Jeff Browne08ae382012-09-07 20:36:36 -0700497 final long token = Binder.clearCallingIdentity();
498 try {
499 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700500 if (mWifiDisplayAdapter != null) {
501 mWifiDisplayAdapter.requestDisconnectLocked();
502 }
Jeff Browne08ae382012-09-07 20:36:36 -0700503 }
504 } finally {
505 Binder.restoreCallingIdentity(token);
506 }
507 }
508
509 @Override // Binder call
Jeff Brown89d55462012-09-19 11:33:42 -0700510 public void renameWifiDisplay(String address, String alias) {
Jeff Brown89d55462012-09-19 11:33:42 -0700511 if (address == null) {
512 throw new IllegalArgumentException("address must not be null");
513 }
Jeff Brownbc335452012-09-26 18:34:47 -0700514 if (!canCallerConfigureWifiDisplay()) {
515 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to "
516 + "rename a wifi display.");
517 }
Jeff Brown89d55462012-09-19 11:33:42 -0700518
519 final long token = Binder.clearCallingIdentity();
520 try {
521 synchronized (mSyncRoot) {
522 if (mWifiDisplayAdapter != null) {
523 mWifiDisplayAdapter.requestRenameLocked(address, alias);
524 }
525 }
526 } finally {
527 Binder.restoreCallingIdentity(token);
528 }
529 }
530
531 @Override // Binder call
532 public void forgetWifiDisplay(String address) {
Jeff Brown89d55462012-09-19 11:33:42 -0700533 if (address == null) {
534 throw new IllegalArgumentException("address must not be null");
535 }
Jeff Brownbc335452012-09-26 18:34:47 -0700536 if (!canCallerConfigureWifiDisplay()) {
537 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to "
538 + "forget a wifi display.");
539 }
Jeff Brown89d55462012-09-19 11:33:42 -0700540
541 final long token = Binder.clearCallingIdentity();
542 try {
543 synchronized (mSyncRoot) {
544 if (mWifiDisplayAdapter != null) {
545 mWifiDisplayAdapter.requestForgetLocked(address);
546 }
547 }
548 } finally {
549 Binder.restoreCallingIdentity(token);
550 }
551 }
552
553 @Override // Binder call
Jeff Browne08ae382012-09-07 20:36:36 -0700554 public WifiDisplayStatus getWifiDisplayStatus() {
Jeff Browne08ae382012-09-07 20:36:36 -0700555 final long token = Binder.clearCallingIdentity();
556 try {
557 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700558 if (mWifiDisplayAdapter != null) {
559 return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
Jeff Brown21c71532012-09-09 13:26:55 -0700560 }
Craig Mautner0bf6ec92012-12-18 08:33:27 -0800561 return new WifiDisplayStatus();
Jeff Browne08ae382012-09-07 20:36:36 -0700562 }
563 } finally {
564 Binder.restoreCallingIdentity(token);
565 }
566 }
567
Jeff Brownbc335452012-09-26 18:34:47 -0700568 private boolean canCallerConfigureWifiDisplay() {
569 return mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
570 == PackageManager.PERMISSION_GRANTED;
571 }
572
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700573 private void registerDefaultDisplayAdapter() {
574 // Register default display adapter.
575 synchronized (mSyncRoot) {
576 if (mHeadless) {
577 registerDisplayAdapterLocked(new HeadlessDisplayAdapter(
578 mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
579 } else {
580 registerDisplayAdapterLocked(new LocalDisplayAdapter(
581 mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
582 }
583 }
584 }
585
586 private void registerAdditionalDisplayAdapters() {
587 synchronized (mSyncRoot) {
588 if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
Jeff Brown89d55462012-09-19 11:33:42 -0700589 registerOverlayDisplayAdapterLocked();
590 registerWifiDisplayAdapterLocked();
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700591 }
592 }
593 }
594
Jeff Brown89d55462012-09-19 11:33:42 -0700595 private void registerOverlayDisplayAdapterLocked() {
596 registerDisplayAdapterLocked(new OverlayDisplayAdapter(
597 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
598 }
599
600 private void registerWifiDisplayAdapterLocked() {
601 if (mContext.getResources().getBoolean(
Jeff Brownbbd28a22012-09-20 16:47:15 -0700602 com.android.internal.R.bool.config_enableWifiDisplay)
603 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
Jeff Brown89d55462012-09-19 11:33:42 -0700604 mWifiDisplayAdapter = new WifiDisplayAdapter(
605 mSyncRoot, mContext, mHandler, mDisplayAdapterListener,
606 mPersistentDataStore);
607 registerDisplayAdapterLocked(mWifiDisplayAdapter);
608 }
609 }
610
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700611 private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
612 // In safe mode, we disable non-essential display adapters to give the user
613 // an opportunity to fix broken settings or other problems that might affect
614 // system stability.
615 // In only-core mode, we disable non-essential display adapters to minimize
616 // the number of dependencies that are started while in this mode and to
617 // prevent problems that might occur due to the device being encrypted.
618 return !mSafeMode && !mOnlyCore;
619 }
620
621 private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
622 mDisplayAdapters.add(adapter);
623 adapter.registerLocked();
624 }
625
Jeff Brownbd6e1502012-08-28 03:27:37 -0700626 private void handleDisplayDeviceAdded(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700627 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700628 if (mDisplayDevices.contains(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700629 Slog.w(TAG, "Attempted to add already added display device: "
630 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700631 return;
632 }
633
Jeff Browne87bf032012-09-20 18:30:13 -0700634 Slog.i(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked());
635
Jeff Brownbd6e1502012-08-28 03:27:37 -0700636 mDisplayDevices.add(device);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700637 addLogicalDisplayLocked(device);
Craig Mautner65d11b32012-10-01 13:59:52 -0700638 scheduleTraversalLocked(false);
Jeff Brown9e316a12012-10-08 19:17:06 -0700639
640 // Blank or unblank the display immediately to match the state requested
641 // by the power manager (if known).
642 switch (mAllDisplayBlankStateFromPowerManager) {
643 case DISPLAY_BLANK_STATE_BLANKED:
644 device.blankLocked();
645 break;
646 case DISPLAY_BLANK_STATE_UNBLANKED:
647 device.unblankLocked();
648 break;
649 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700650 }
651 }
652
Jeff Brownbd6e1502012-08-28 03:27:37 -0700653 private void handleDisplayDeviceChanged(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700654 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700655 if (!mDisplayDevices.contains(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700656 Slog.w(TAG, "Attempted to change non-existent display device: "
657 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700658 return;
659 }
660
Jeff Browne87bf032012-09-20 18:30:13 -0700661 Slog.i(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked());
662
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700663 device.applyPendingDisplayDeviceInfoChangesLocked();
664 if (updateLogicalDisplaysLocked()) {
Craig Mautner65d11b32012-10-01 13:59:52 -0700665 scheduleTraversalLocked(false);
Jeff Brown64a55af2012-08-26 02:47:39 -0700666 }
667 }
668 }
669
Jeff Brownbd6e1502012-08-28 03:27:37 -0700670 private void handleDisplayDeviceRemoved(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700671 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700672 if (!mDisplayDevices.remove(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700673 Slog.w(TAG, "Attempted to remove non-existent display device: "
674 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700675 return;
Craig Mautner4f67ba62012-08-02 11:23:00 -0700676 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700677
Jeff Browne87bf032012-09-20 18:30:13 -0700678 Slog.i(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked());
679
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700680 mRemovedDisplayDevices.add(device);
681 updateLogicalDisplaysLocked();
Craig Mautner65d11b32012-10-01 13:59:52 -0700682 scheduleTraversalLocked(false);
Craig Mautner4f67ba62012-08-02 11:23:00 -0700683 }
684 }
685
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700686 // Adds a new logical display based on the given display device.
687 // Sends notifications if needed.
688 private void addLogicalDisplayLocked(DisplayDevice device) {
689 DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
690 boolean isDefault = (deviceInfo.flags
691 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
692 if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
693 Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo);
694 isDefault = false;
695 }
696
Jeff Brown27f1d672012-10-17 18:32:34 -0700697 if (!isDefault && mSingleDisplayDemoMode) {
698 Slog.i(TAG, "Not creating a logical display for a secondary display "
699 + " because single display demo mode is enabled: " + deviceInfo);
700 return;
701 }
702
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700703 final int displayId = assignDisplayIdLocked(isDefault);
704 final int layerStack = assignLayerStackLocked(displayId);
705
Jeff Brownd728bf52012-09-08 18:05:28 -0700706 LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700707 display.updateLocked(mDisplayDevices);
708 if (!display.isValidLocked()) {
709 // This should never happen currently.
710 Slog.w(TAG, "Ignoring display device because the logical display "
711 + "created from it was not considered valid: " + deviceInfo);
712 return;
713 }
714
715 mLogicalDisplays.put(displayId, display);
716
717 // Wake up waitForDefaultDisplay.
718 if (isDefault) {
719 mSyncRoot.notifyAll();
720 }
721
722 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
723 }
724
725 private int assignDisplayIdLocked(boolean isDefault) {
726 return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
727 }
728
729 private int assignLayerStackLocked(int displayId) {
730 // Currently layer stacks and display ids are the same.
731 // This need not be the case.
732 return displayId;
733 }
734
735 // Updates all existing logical displays given the current set of display devices.
736 // Removes invalid logical displays.
737 // Sends notifications if needed.
738 private boolean updateLogicalDisplaysLocked() {
739 boolean changed = false;
740 for (int i = mLogicalDisplays.size(); i-- > 0; ) {
741 final int displayId = mLogicalDisplays.keyAt(i);
742 LogicalDisplay display = mLogicalDisplays.valueAt(i);
743
744 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
745 display.updateLocked(mDisplayDevices);
746 if (!display.isValidLocked()) {
747 mLogicalDisplays.removeAt(i);
748 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
749 changed = true;
750 } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
751 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
752 changed = true;
753 }
754 }
755 return changed;
756 }
757
758 private void performTraversalInTransactionLocked() {
759 // Perform one last traversal for each removed display device.
760 final int removedCount = mRemovedDisplayDevices.size();
761 for (int i = 0; i < removedCount; i++) {
762 DisplayDevice device = mRemovedDisplayDevices.get(i);
763 device.performTraversalInTransactionLocked();
764 }
765 mRemovedDisplayDevices.clear();
766
Jeff Brownd728bf52012-09-08 18:05:28 -0700767 // Clear all viewports before configuring displays so that we can keep
768 // track of which ones we have configured.
769 clearViewportsLocked();
770
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700771 // Configure each display device.
772 final int count = mDisplayDevices.size();
773 for (int i = 0; i < count; i++) {
774 DisplayDevice device = mDisplayDevices.get(i);
775 configureDisplayInTransactionLocked(device);
776 device.performTraversalInTransactionLocked();
777 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700778
779 // Tell the input system about these new viewports.
780 if (mInputManagerFuncs != null) {
781 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
782 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700783 }
784
Craig Mautner722285e2012-09-07 13:55:58 -0700785 /**
786 * Tells the display manager whether there is interesting unique content on the
787 * specified logical display. This is used to control automatic mirroring.
788 * <p>
789 * If the display has unique content, then the display manager arranges for it
790 * to be presented on a physical display if appropriate. Otherwise, the display manager
791 * may choose to make the physical display mirror some other logical display.
792 * </p>
793 *
794 * @param displayId The logical display id to update.
795 * @param hasContent True if the logical display has content.
Craig Mautner65d11b32012-10-01 13:59:52 -0700796 * @param inTraversal True if called from WindowManagerService during a window traversal prior
797 * to call to performTraversalInTransactionFromWindowManager.
Craig Mautner722285e2012-09-07 13:55:58 -0700798 */
Craig Mautner65d11b32012-10-01 13:59:52 -0700799 public void setDisplayHasContent(int displayId, boolean hasContent, boolean inTraversal) {
Craig Mautner722285e2012-09-07 13:55:58 -0700800 synchronized (mSyncRoot) {
801 LogicalDisplay display = mLogicalDisplays.get(displayId);
802 if (display != null && display.hasContentLocked() != hasContent) {
803 display.setHasContentLocked(hasContent);
Craig Mautner65d11b32012-10-01 13:59:52 -0700804 scheduleTraversalLocked(inTraversal);
Craig Mautner722285e2012-09-07 13:55:58 -0700805 }
806 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700807 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700808
Jeff Brownd728bf52012-09-08 18:05:28 -0700809 private void clearViewportsLocked() {
810 mDefaultViewport.valid = false;
811 mExternalTouchViewport.valid = false;
Craig Mautner722285e2012-09-07 13:55:58 -0700812 }
813
814 private void configureDisplayInTransactionLocked(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700815 // Find the logical display that the display device is showing.
Craig Mautner722285e2012-09-07 13:55:58 -0700816 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
817 if (display != null && !display.hasContentLocked()) {
818 display = null;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700819 }
820 if (display == null) {
821 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
822 }
823
824 // Apply the logical display configuration to the display device.
825 if (display == null) {
826 // TODO: no logical display for the device, blank it
Jeff Brownd728bf52012-09-08 18:05:28 -0700827 Slog.w(TAG, "Missing logical display to use for physical display device: "
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700828 + device.getDisplayDeviceInfoLocked());
Jeff Brownd728bf52012-09-08 18:05:28 -0700829 return;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700830 }
Craig Mautner0bf6ec92012-12-18 08:33:27 -0800831 boolean isBlanked = (mAllDisplayBlankStateFromPowerManager == DISPLAY_BLANK_STATE_BLANKED);
832 display.configureDisplayInTransactionLocked(device, isBlanked);
Jeff Brownd728bf52012-09-08 18:05:28 -0700833
834 // Update the viewports if needed.
835 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
836 if (!mDefaultViewport.valid
837 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
838 setViewportLocked(mDefaultViewport, display, device);
839 }
840 if (!mExternalTouchViewport.valid
841 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
842 setViewportLocked(mExternalTouchViewport, display, device);
843 }
844 }
845
846 private static void setViewportLocked(DisplayViewport viewport,
847 LogicalDisplay display, DisplayDevice device) {
848 viewport.valid = true;
849 viewport.displayId = display.getDisplayIdLocked();
850 device.populateViewportLocked(viewport);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700851 }
852
853 private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) {
854 final int count = mLogicalDisplays.size();
855 for (int i = 0; i < count; i++) {
856 LogicalDisplay display = mLogicalDisplays.valueAt(i);
857 if (display.getPrimaryDisplayDeviceLocked() == device) {
858 return display;
859 }
860 }
861 return null;
862 }
863
Jeff Brownbd6e1502012-08-28 03:27:37 -0700864 private void sendDisplayEventLocked(int displayId, int event) {
865 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
866 mHandler.sendMessage(msg);
867 }
868
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700869 // Requests that performTraversalsInTransactionFromWindowManager be called at a
870 // later time to apply changes to surfaces and displays.
Craig Mautner65d11b32012-10-01 13:59:52 -0700871 private void scheduleTraversalLocked(boolean inTraversal) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700872 if (!mPendingTraversal && mWindowManagerFuncs != null) {
873 mPendingTraversal = true;
Craig Mautner65d11b32012-10-01 13:59:52 -0700874 if (!inTraversal) {
875 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
876 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700877 }
878 }
879
880 // Runs on Handler thread.
881 // Delivers display event notifications to callbacks.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700882 private void deliverDisplayEvent(int displayId, int event) {
883 if (DEBUG) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700884 Slog.d(TAG, "Delivering display event: displayId="
885 + displayId + ", event=" + event);
Jeff Brownfa25bf52012-07-23 19:26:30 -0700886 }
Jeff Brownfa25bf52012-07-23 19:26:30 -0700887
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700888 // Grab the lock and copy the callbacks.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700889 final int count;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700890 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700891 count = mCallbacks.size();
892 mTempCallbacks.clear();
893 for (int i = 0; i < count; i++) {
894 mTempCallbacks.add(mCallbacks.valueAt(i));
Craig Mautner4f67ba62012-08-02 11:23:00 -0700895 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700896 }
Craig Mautner4f67ba62012-08-02 11:23:00 -0700897
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700898 // After releasing the lock, send the notifications out.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700899 for (int i = 0; i < count; i++) {
900 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
901 }
902 mTempCallbacks.clear();
Craig Mautner4f67ba62012-08-02 11:23:00 -0700903 }
904
Jeff Brownfa25bf52012-07-23 19:26:30 -0700905 @Override // Binder call
Jeff Brownbd6e1502012-08-28 03:27:37 -0700906 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
Jeff Brownfa25bf52012-07-23 19:26:30 -0700907 if (mContext == null
908 || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
909 != PackageManager.PERMISSION_GRANTED) {
910 pw.println("Permission Denial: can't dump DisplayManager from from pid="
911 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
912 return;
913 }
914
Jeff Brownbd6e1502012-08-28 03:27:37 -0700915 pw.println("DISPLAY MANAGER (dumpsys display)");
Jeff Brownfa25bf52012-07-23 19:26:30 -0700916
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700917 synchronized (mSyncRoot) {
Jeff Brown9e316a12012-10-08 19:17:06 -0700918 pw.println(" mHeadless=" + mHeadless);
919 pw.println(" mOnlyCode=" + mOnlyCore);
920 pw.println(" mSafeMode=" + mSafeMode);
921 pw.println(" mPendingTraversal=" + mPendingTraversal);
922 pw.println(" mAllDisplayBlankStateFromPowerManager="
923 + mAllDisplayBlankStateFromPowerManager);
924 pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
925 pw.println(" mDefaultViewport=" + mDefaultViewport);
926 pw.println(" mExternalTouchViewport=" + mExternalTouchViewport);
Jeff Brown27f1d672012-10-17 18:32:34 -0700927 pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
Jeff Brown9e316a12012-10-08 19:17:06 -0700928
Jeff Brownbd6e1502012-08-28 03:27:37 -0700929 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700930 ipw.increaseIndent();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700931
932 pw.println();
933 pw.println("Display Adapters: size=" + mDisplayAdapters.size());
Jeff Brown848c2dc2012-08-19 20:18:08 -0700934 for (DisplayAdapter adapter : mDisplayAdapters) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700935 pw.println(" " + adapter.getName());
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700936 adapter.dumpLocked(ipw);
Jeff Brown848c2dc2012-08-19 20:18:08 -0700937 }
Craig Mautner9de49362012-08-02 14:30:30 -0700938
Jeff Brownbd6e1502012-08-28 03:27:37 -0700939 pw.println();
940 pw.println("Display Devices: size=" + mDisplayDevices.size());
941 for (DisplayDevice device : mDisplayDevices) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700942 pw.println(" " + device.getDisplayDeviceInfoLocked());
943 device.dumpLocked(ipw);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700944 }
945
946 final int logicalDisplayCount = mLogicalDisplays.size();
947 pw.println();
948 pw.println("Logical Displays: size=" + logicalDisplayCount);
949 for (int i = 0; i < logicalDisplayCount; i++) {
950 int displayId = mLogicalDisplays.keyAt(i);
951 LogicalDisplay display = mLogicalDisplays.valueAt(i);
952 pw.println(" Display " + displayId + ":");
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700953 display.dumpLocked(ipw);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700954 }
955 }
956 }
957
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700958 /**
959 * This is the object that everything in the display manager locks on.
960 * We make it an inner class within the {@link DisplayManagerService} to so that it is
961 * clear that the object belongs to the display manager service and that it is
962 * a unique object with a special purpose.
963 */
964 public static final class SyncRoot {
965 }
966
967 /**
968 * Private interface to the window manager.
969 */
970 public interface WindowManagerFuncs {
971 /**
Craig Mautner722285e2012-09-07 13:55:58 -0700972 * Request that the window manager call
973 * {@link #performTraversalInTransactionFromWindowManager} within a surface
974 * transaction at a later time.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700975 */
976 void requestTraversal();
977 }
978
Jeff Brownd728bf52012-09-08 18:05:28 -0700979 /**
980 * Private interface to the input manager.
981 */
982 public interface InputManagerFuncs {
983 /**
984 * Sets information about the displays as needed by the input system.
985 * The input system should copy this information if required.
986 */
987 void setDisplayViewports(DisplayViewport defaultViewport,
988 DisplayViewport externalTouchViewport);
989 }
990
Jeff Brownbd6e1502012-08-28 03:27:37 -0700991 private final class DisplayManagerHandler extends Handler {
992 public DisplayManagerHandler(Looper looper) {
993 super(looper, null, true /*async*/);
Jeff Brown848c2dc2012-08-19 20:18:08 -0700994 }
Jeff Brownbf5740e2012-08-19 23:20:02 -0700995
Jeff Brownbd6e1502012-08-28 03:27:37 -0700996 @Override
997 public void handleMessage(Message msg) {
998 switch (msg.what) {
999 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
1000 registerDefaultDisplayAdapter();
1001 break;
1002
1003 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
1004 registerAdditionalDisplayAdapters();
1005 break;
1006
1007 case MSG_DELIVER_DISPLAY_EVENT:
1008 deliverDisplayEvent(msg.arg1, msg.arg2);
1009 break;
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001010
1011 case MSG_REQUEST_TRAVERSAL:
1012 mWindowManagerFuncs.requestTraversal();
1013 break;
Jeff Brownd728bf52012-09-08 18:05:28 -07001014
1015 case MSG_UPDATE_VIEWPORT: {
1016 synchronized (mSyncRoot) {
1017 mTempDefaultViewport.copyFrom(mDefaultViewport);
1018 mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
1019 }
1020 mInputManagerFuncs.setDisplayViewports(
1021 mTempDefaultViewport, mTempExternalTouchViewport);
1022 break;
1023 }
Jeff Brownbd6e1502012-08-28 03:27:37 -07001024 }
1025 }
1026 }
1027
1028 private final class DisplayAdapterListener implements DisplayAdapter.Listener {
1029 @Override
1030 public void onDisplayDeviceEvent(DisplayDevice device, int event) {
1031 switch (event) {
1032 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
1033 handleDisplayDeviceAdded(device);
1034 break;
1035
1036 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
1037 handleDisplayDeviceChanged(device);
1038 break;
1039
1040 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
1041 handleDisplayDeviceRemoved(device);
1042 break;
1043 }
1044 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001045
1046 @Override
1047 public void onTraversalRequested() {
1048 synchronized (mSyncRoot) {
Craig Mautner65d11b32012-10-01 13:59:52 -07001049 scheduleTraversalLocked(false);
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001050 }
1051 }
Jeff Brownbd6e1502012-08-28 03:27:37 -07001052 }
1053
1054 private final class CallbackRecord implements DeathRecipient {
1055 private final int mPid;
1056 private final IDisplayManagerCallback mCallback;
1057
1058 public CallbackRecord(int pid, IDisplayManagerCallback callback) {
1059 mPid = pid;
1060 mCallback = callback;
1061 }
1062
1063 @Override
1064 public void binderDied() {
1065 if (DEBUG) {
1066 Slog.d(TAG, "Display listener for pid " + mPid + " died.");
1067 }
1068 onCallbackDied(mPid);
1069 }
1070
1071 public void notifyDisplayEventAsync(int displayId, int event) {
1072 try {
1073 mCallback.onDisplayEvent(displayId, event);
1074 } catch (RemoteException ex) {
1075 Slog.w(TAG, "Failed to notify process "
1076 + mPid + " that displays changed, assuming it died.", ex);
1077 binderDied();
1078 }
1079 }
1080 }
Jeff Brownfa25bf52012-07-23 19:26:30 -07001081}