blob: c339c26e51e53dc23da90d4335693d20929cfc6c [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 Browna506a6e2013-06-04 00:02:38 -070036import android.text.TextUtils;
Jeff Brownbd6e1502012-08-28 03:27:37 -070037import android.util.Slog;
38import android.util.SparseArray;
Jeff Brownfa25bf52012-07-23 19:26:30 -070039import android.view.Display;
40import android.view.DisplayInfo;
Jeff Browna506a6e2013-06-04 00:02:38 -070041import android.view.Surface;
42
Dianne Hackborn8d044e82013-04-30 17:24:15 -070043import com.android.server.UiThread;
Jeff Brownfa25bf52012-07-23 19:26:30 -070044
45import java.io.FileDescriptor;
46import java.io.PrintWriter;
47import java.util.ArrayList;
Jeff Browna506a6e2013-06-04 00:02:38 -070048import java.util.Arrays;
Jeff Brown7f3994e2012-12-04 14:04:28 -080049import java.util.concurrent.CopyOnWriteArrayList;
Jeff Brownfa25bf52012-07-23 19:26:30 -070050
51/**
Jeff Brownbd6e1502012-08-28 03:27:37 -070052 * Manages attached displays.
Jeff Brownfa25bf52012-07-23 19:26:30 -070053 * <p>
Jeff Brownbd6e1502012-08-28 03:27:37 -070054 * The {@link DisplayManagerService} manages the global lifecycle of displays,
55 * decides how to configure logical displays based on the physical display devices currently
56 * attached, sends notifications to the system and to applications when the state
57 * changes, and so on.
58 * </p><p>
59 * The display manager service relies on a collection of {@link DisplayAdapter} components,
60 * for discovering and configuring physical display devices attached to the system.
61 * There are separate display adapters for each manner that devices are attached:
62 * one display adapter for built-in local displays, one for simulated non-functional
63 * displays when the system is headless, one for simulated overlay displays used for
64 * development, one for wifi displays, etc.
65 * </p><p>
66 * Display adapters are only weakly coupled to the display manager service.
67 * Display adapters communicate changes in display device state to the display manager
Craig Mautner722285e2012-09-07 13:55:58 -070068 * service asynchronously via a {@link DisplayAdapter.Listener} registered
Jeff Brownbd6e1502012-08-28 03:27:37 -070069 * by the display manager service. This separation of concerns is important for
70 * two main reasons. First, it neatly encapsulates the responsibilities of these
71 * two classes: display adapters handle individual display devices whereas
72 * the display manager service handles the global state. Second, it eliminates
73 * the potential for deadlocks resulting from asynchronous display device discovery.
Jeff Brown4ed8fe72012-08-30 18:18:29 -070074 * </p>
75 *
76 * <h3>Synchronization</h3>
77 * <p>
78 * Because the display manager may be accessed by multiple threads, the synchronization
79 * story gets a little complicated. In particular, the window manager may call into
80 * the display manager while holding a surface transaction with the expectation that
81 * it can apply changes immediately. Unfortunately, that means we can't just do
82 * everything asynchronously (*grump*).
Jeff Brownbd6e1502012-08-28 03:27:37 -070083 * </p><p>
Jeff Brown4ed8fe72012-08-30 18:18:29 -070084 * To make this work, all of the objects that belong to the display manager must
85 * use the same lock. We call this lock the synchronization root and it has a unique
86 * type {@link DisplayManagerService.SyncRoot}. Methods that require this lock are
87 * named with the "Locked" suffix.
88 * </p><p>
89 * Where things get tricky is that the display manager is not allowed to make
90 * any potentially reentrant calls, especially into the window manager. We generally
91 * avoid this by making all potentially reentrant out-calls asynchronous.
Jeff Brownfa25bf52012-07-23 19:26:30 -070092 * </p>
93 */
94public final class DisplayManagerService extends IDisplayManager.Stub {
95 private static final String TAG = "DisplayManagerService";
Jeff Brownbd6e1502012-08-28 03:27:37 -070096 private static final boolean DEBUG = false;
Jeff Brownfa25bf52012-07-23 19:26:30 -070097
Jeff Brownbbd28a22012-09-20 16:47:15 -070098 // When this system property is set to 0, WFD is forcibly disabled on boot.
99 // When this system property is set to 1, WFD is forcibly enabled on boot.
100 // Otherwise WFD is enabled according to the value of config_enableWifiDisplay.
101 private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable";
102
Jeff Brownfa25bf52012-07-23 19:26:30 -0700103 private static final String SYSTEM_HEADLESS = "ro.config.headless";
Jeff Brownbd6e1502012-08-28 03:27:37 -0700104 private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
105
106 private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER = 1;
107 private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;
108 private static final int MSG_DELIVER_DISPLAY_EVENT = 3;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700109 private static final int MSG_REQUEST_TRAVERSAL = 4;
Jeff Brownd728bf52012-09-08 18:05:28 -0700110 private static final int MSG_UPDATE_VIEWPORT = 5;
Jeff Brownfa25bf52012-07-23 19:26:30 -0700111
Jeff Brown9e316a12012-10-08 19:17:06 -0700112 private static final int DISPLAY_BLANK_STATE_UNKNOWN = 0;
113 private static final int DISPLAY_BLANK_STATE_BLANKED = 1;
114 private static final int DISPLAY_BLANK_STATE_UNBLANKED = 2;
115
Jeff Brown848c2dc2012-08-19 20:18:08 -0700116 private final Context mContext;
Jeff Brownfa25bf52012-07-23 19:26:30 -0700117 private final boolean mHeadless;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700118 private final DisplayManagerHandler mHandler;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700119 private final Handler mUiHandler;
120 private final DisplayAdapterListener mDisplayAdapterListener;
121 private WindowManagerFuncs mWindowManagerFuncs;
Jeff Brownd728bf52012-09-08 18:05:28 -0700122 private InputManagerFuncs mInputManagerFuncs;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700123
124 // The synchronization root for the display manager.
125 // This lock guards most of the display manager's state.
Craig Mautner0bf6ec92012-12-18 08:33:27 -0800126 // NOTE: This is synchronized on while holding WindowManagerService.mWindowMap so never call
127 // into WindowManagerService methods that require mWindowMap while holding this unless you are
128 // very very sure that no deadlock can occur.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700129 private final SyncRoot mSyncRoot = new SyncRoot();
130
131 // True if in safe mode.
132 // This option may disable certain display adapters.
133 public boolean mSafeMode;
134
135 // True if we are in a special boot mode where only core applications and
136 // services should be started. This option may disable certain display adapters.
137 public boolean mOnlyCore;
138
Jeff Brown27f1d672012-10-17 18:32:34 -0700139 // True if the display manager service should pretend there is only one display
140 // and only tell applications about the existence of the default logical display.
141 // The display manager can still mirror content to secondary displays but applications
142 // cannot present unique content on those displays.
143 // Used for demonstration purposes only.
144 private final boolean mSingleDisplayDemoMode;
145
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700146 // All callback records indexed by calling process id.
147 public final SparseArray<CallbackRecord> mCallbacks =
Jeff Brownbd6e1502012-08-28 03:27:37 -0700148 new SparseArray<CallbackRecord>();
Jeff Brownfa25bf52012-07-23 19:26:30 -0700149
Jeff Brownbd6e1502012-08-28 03:27:37 -0700150 // List of all currently registered display adapters.
151 private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
152
153 // List of all currently connected display devices.
154 private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>();
155
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700156 // List of all removed display devices.
157 private final ArrayList<DisplayDevice> mRemovedDisplayDevices = new ArrayList<DisplayDevice>();
158
159 // List of all logical displays indexed by logical display id.
160 private final SparseArray<LogicalDisplay> mLogicalDisplays =
161 new SparseArray<LogicalDisplay>();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700162 private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
163
Jeff Brown7f3994e2012-12-04 14:04:28 -0800164 // List of all display transaction listeners.
165 private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners =
166 new CopyOnWriteArrayList<DisplayTransactionListener>();
167
Jeff Brown9e316a12012-10-08 19:17:06 -0700168 // Set to true if all displays have been blanked by the power manager.
Craig Mautner0bf6ec92012-12-18 08:33:27 -0800169 private int mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNKNOWN;
Jeff Brown9e316a12012-10-08 19:17:06 -0700170
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700171 // Set to true when there are pending display changes that have yet to be applied
172 // to the surface flinger state.
173 private boolean mPendingTraversal;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700174
Jeff Browne08ae382012-09-07 20:36:36 -0700175 // The Wifi display adapter, or null if not registered.
176 private WifiDisplayAdapter mWifiDisplayAdapter;
177
Jeff Browna506a6e2013-06-04 00:02:38 -0700178 // The virtual display adapter, or null if not registered.
179 private VirtualDisplayAdapter mVirtualDisplayAdapter;
180
Jeff Brownd728bf52012-09-08 18:05:28 -0700181 // Viewports of the default display and the display that should receive touch
182 // input from an external source. Used by the input system.
183 private final DisplayViewport mDefaultViewport = new DisplayViewport();
184 private final DisplayViewport mExternalTouchViewport = new DisplayViewport();
185
Jeff Brown89d55462012-09-19 11:33:42 -0700186 // Persistent data store for all internal settings maintained by the display manager service.
187 private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();
188
Jeff Brownbd6e1502012-08-28 03:27:37 -0700189 // Temporary callback list, used when sending display events to applications.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700190 // May be used outside of the lock but only on the handler thread.
191 private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700192
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700193 // Temporary display info, used for comparing display configurations.
194 private final DisplayInfo mTempDisplayInfo = new DisplayInfo();
195
Jeff Brownd728bf52012-09-08 18:05:28 -0700196 // Temporary viewports, used when sending new viewport information to the
197 // input system. May be used outside of the lock but only on the handler thread.
198 private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
199 private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
200
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700201 public DisplayManagerService(Context context, Handler mainHandler) {
Jeff Brown848c2dc2012-08-19 20:18:08 -0700202 mContext = context;
Jeff Brownfa25bf52012-07-23 19:26:30 -0700203 mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1");
Jeff Brown848c2dc2012-08-19 20:18:08 -0700204
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700205 mHandler = new DisplayManagerHandler(mainHandler.getLooper());
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700206 mUiHandler = UiThread.getHandler();
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700207 mDisplayAdapterListener = new DisplayAdapterListener();
Jeff Brown27f1d672012-10-17 18:32:34 -0700208 mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700209
Jeff Brownbd6e1502012-08-28 03:27:37 -0700210 mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
Craig Mautner4f67ba62012-08-02 11:23:00 -0700211 }
212
Jeff Brownbd6e1502012-08-28 03:27:37 -0700213 /**
214 * Pauses the boot process to wait for the first display to be initialized.
215 */
216 public boolean waitForDefaultDisplay() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700217 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700218 long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
219 while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) {
220 long delay = timeout - SystemClock.uptimeMillis();
221 if (delay <= 0) {
222 return false;
223 }
224 if (DEBUG) {
225 Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
226 }
227 try {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700228 mSyncRoot.wait(delay);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700229 } catch (InterruptedException ex) {
230 }
231 }
232 }
233 return true;
234 }
235
236 /**
Jeff Brownd728bf52012-09-08 18:05:28 -0700237 * Called during initialization to associate the display manager with the
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700238 * window manager.
239 */
240 public void setWindowManager(WindowManagerFuncs windowManagerFuncs) {
241 synchronized (mSyncRoot) {
242 mWindowManagerFuncs = windowManagerFuncs;
Craig Mautner65d11b32012-10-01 13:59:52 -0700243 scheduleTraversalLocked(false);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700244 }
245 }
246
247 /**
Jeff Brownd728bf52012-09-08 18:05:28 -0700248 * Called during initialization to associate the display manager with the
249 * input manager.
250 */
251 public void setInputManager(InputManagerFuncs inputManagerFuncs) {
252 synchronized (mSyncRoot) {
253 mInputManagerFuncs = inputManagerFuncs;
Craig Mautner65d11b32012-10-01 13:59:52 -0700254 scheduleTraversalLocked(false);
Jeff Brownd728bf52012-09-08 18:05:28 -0700255 }
256 }
257
258 /**
Jeff Brownbd6e1502012-08-28 03:27:37 -0700259 * Called when the system is ready to go.
260 */
261 public void systemReady(boolean safeMode, boolean onlyCore) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700262 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700263 mSafeMode = safeMode;
264 mOnlyCore = onlyCore;
265 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700266
Jeff Brownbd6e1502012-08-28 03:27:37 -0700267 mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
268 }
269
Jeff Brown848c2dc2012-08-19 20:18:08 -0700270 /**
271 * Returns true if the device is headless.
272 *
273 * @return True if the device is headless.
274 */
Jeff Brownfa25bf52012-07-23 19:26:30 -0700275 public boolean isHeadless() {
276 return mHeadless;
277 }
278
Craig Mautner4f67ba62012-08-02 11:23:00 -0700279 /**
Jeff Brown7f3994e2012-12-04 14:04:28 -0800280 * Registers a display transaction listener to provide the client a chance to
281 * update its surfaces within the same transaction as any display layout updates.
282 *
283 * @param listener The listener to register.
284 */
285 public void registerDisplayTransactionListener(DisplayTransactionListener listener) {
286 if (listener == null) {
287 throw new IllegalArgumentException("listener must not be null");
288 }
289
290 // List is self-synchronized copy-on-write.
291 mDisplayTransactionListeners.add(listener);
292 }
293
294 /**
295 * Unregisters a display transaction listener to provide the client a chance to
296 * update its surfaces within the same transaction as any display layout updates.
297 *
298 * @param listener The listener to unregister.
299 */
300 public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) {
301 if (listener == null) {
302 throw new IllegalArgumentException("listener must not be null");
303 }
304
305 // List is self-synchronized copy-on-write.
306 mDisplayTransactionListeners.remove(listener);
307 }
308
309 /**
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700310 * Overrides the display information of a particular logical display.
311 * This is used by the window manager to control the size and characteristics
312 * of the default display. It is expected to apply the requested change
313 * to the display information synchronously so that applications will immediately
314 * observe the new state.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700315 *
Jeff Brown64a55af2012-08-26 02:47:39 -0700316 * @param displayId The logical display id.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700317 * @param info The new data to be stored.
Jeff Brown64a55af2012-08-26 02:47:39 -0700318 */
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700319 public void setDisplayInfoOverrideFromWindowManager(
320 int displayId, DisplayInfo info) {
321 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700322 LogicalDisplay display = mLogicalDisplays.get(displayId);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700323 if (display != null) {
324 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
325 display.setDisplayInfoOverrideFromWindowManagerLocked(info);
326 if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
327 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
Craig Mautner65d11b32012-10-01 13:59:52 -0700328 scheduleTraversalLocked(false);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700329 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700330 }
331 }
332 }
333
334 /**
Dianne Hackbornc652de82013-02-15 16:32:56 -0800335 * Sets the overscan insets for a particular display.
336 */
337 public void setOverscan(int displayId, int left, int top, int right, int bottom) {
338 synchronized (mSyncRoot) {
339 LogicalDisplay display = mLogicalDisplays.get(displayId);
340 if (display != null) {
341 display.setOverscan(left, top, right, bottom);
342 }
343 }
344 }
345
346 /**
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700347 * Called by the window manager to perform traversals while holding a
348 * surface flinger transaction.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700349 */
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700350 public void performTraversalInTransactionFromWindowManager() {
351 synchronized (mSyncRoot) {
352 if (!mPendingTraversal) {
353 return;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700354 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700355 mPendingTraversal = false;
356
357 performTraversalInTransactionLocked();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700358 }
Jeff Brown7f3994e2012-12-04 14:04:28 -0800359
360 // List is self-synchronized copy-on-write.
361 for (DisplayTransactionListener listener : mDisplayTransactionListeners) {
362 listener.onDisplayTransaction();
363 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700364 }
365
366 /**
Jeff Brown9e316a12012-10-08 19:17:06 -0700367 * Called by the power manager to blank all displays.
368 */
369 public void blankAllDisplaysFromPowerManager() {
370 synchronized (mSyncRoot) {
371 if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_BLANKED) {
372 mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_BLANKED;
Jeff Browna506a6e2013-06-04 00:02:38 -0700373 updateAllDisplayBlankingLocked();
Jeff Brown8ec09432012-10-16 16:19:23 -0700374 scheduleTraversalLocked(false);
Jeff Brown9e316a12012-10-08 19:17:06 -0700375 }
376 }
377 }
378
379 /**
380 * Called by the power manager to unblank all displays.
381 */
382 public void unblankAllDisplaysFromPowerManager() {
383 synchronized (mSyncRoot) {
384 if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_UNBLANKED) {
385 mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNBLANKED;
Jeff Browna506a6e2013-06-04 00:02:38 -0700386 updateAllDisplayBlankingLocked();
Jeff Brown8ec09432012-10-16 16:19:23 -0700387 scheduleTraversalLocked(false);
Jeff Brown9e316a12012-10-08 19:17:06 -0700388 }
389 }
390 }
391
392 /**
Jeff Brownbd6e1502012-08-28 03:27:37 -0700393 * Returns information about the specified logical display.
394 *
395 * @param displayId The logical display id.
Craig Mautner722285e2012-09-07 13:55:58 -0700396 * @return The logical display info, or null if the display does not exist. The
397 * returned object must be treated as immutable.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700398 */
399 @Override // Binder call
400 public DisplayInfo getDisplayInfo(int displayId) {
Jeff Browna506a6e2013-06-04 00:02:38 -0700401 final int callingUid = Binder.getCallingUid();
402 final long token = Binder.clearCallingIdentity();
403 try {
404 synchronized (mSyncRoot) {
405 LogicalDisplay display = mLogicalDisplays.get(displayId);
406 if (display != null) {
407 DisplayInfo info = display.getDisplayInfoLocked();
408 if (info.hasAccess(callingUid)) {
409 return info;
410 }
411 }
412 return null;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700413 }
Jeff Browna506a6e2013-06-04 00:02:38 -0700414 } finally {
415 Binder.restoreCallingIdentity(token);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700416 }
417 }
418
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700419 /**
420 * Returns the list of all display ids.
421 */
Jeff Brownbd6e1502012-08-28 03:27:37 -0700422 @Override // Binder call
423 public int[] getDisplayIds() {
Jeff Browna506a6e2013-06-04 00:02:38 -0700424 final int callingUid = Binder.getCallingUid();
425 final long token = Binder.clearCallingIdentity();
426 try {
427 synchronized (mSyncRoot) {
428 final int count = mLogicalDisplays.size();
429 int[] displayIds = new int[count];
430 int n = 0;
431 for (int i = 0; i < count; i++) {
432 LogicalDisplay display = mLogicalDisplays.valueAt(i);
433 DisplayInfo info = display.getDisplayInfoLocked();
434 if (info.hasAccess(callingUid)) {
435 displayIds[n++] = mLogicalDisplays.keyAt(i);
436 }
437 }
438 if (n != count) {
439 displayIds = Arrays.copyOfRange(displayIds, 0, n);
440 }
441 return displayIds;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700442 }
Jeff Browna506a6e2013-06-04 00:02:38 -0700443 } finally {
444 Binder.restoreCallingIdentity(token);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700445 }
446 }
447
448 @Override // Binder call
449 public void registerCallback(IDisplayManagerCallback callback) {
450 if (callback == null) {
451 throw new IllegalArgumentException("listener must not be null");
452 }
453
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700454 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700455 int callingPid = Binder.getCallingPid();
456 if (mCallbacks.get(callingPid) != null) {
457 throw new SecurityException("The calling process has already "
458 + "registered an IDisplayManagerCallback.");
Jeff Brown64a55af2012-08-26 02:47:39 -0700459 }
460
Jeff Brownbd6e1502012-08-28 03:27:37 -0700461 CallbackRecord record = new CallbackRecord(callingPid, callback);
462 try {
463 IBinder binder = callback.asBinder();
464 binder.linkToDeath(record, 0);
465 } catch (RemoteException ex) {
466 // give up
467 throw new RuntimeException(ex);
468 }
469
470 mCallbacks.put(callingPid, record);
471 }
472 }
473
474 private void onCallbackDied(int pid) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700475 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700476 mCallbacks.remove(pid);
477 }
478 }
479
Jeff Browne08ae382012-09-07 20:36:36 -0700480 @Override // Binder call
481 public void scanWifiDisplays() {
Jeff Browne08ae382012-09-07 20:36:36 -0700482 final long token = Binder.clearCallingIdentity();
483 try {
484 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700485 if (mWifiDisplayAdapter != null) {
486 mWifiDisplayAdapter.requestScanLocked();
487 }
Jeff Browne08ae382012-09-07 20:36:36 -0700488 }
489 } finally {
490 Binder.restoreCallingIdentity(token);
491 }
492 }
493
494 @Override // Binder call
495 public void connectWifiDisplay(String address) {
Jeff Browne08ae382012-09-07 20:36:36 -0700496 if (address == null) {
497 throw new IllegalArgumentException("address must not be null");
498 }
499
Jeff Brownbc335452012-09-26 18:34:47 -0700500 final boolean trusted = canCallerConfigureWifiDisplay();
Jeff Browne08ae382012-09-07 20:36:36 -0700501 final long token = Binder.clearCallingIdentity();
502 try {
503 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700504 if (mWifiDisplayAdapter != null) {
Jeff Brownbc335452012-09-26 18:34:47 -0700505 mWifiDisplayAdapter.requestConnectLocked(address, trusted);
Jeff Brown21c71532012-09-09 13:26:55 -0700506 }
Jeff Browne08ae382012-09-07 20:36:36 -0700507 }
508 } finally {
509 Binder.restoreCallingIdentity(token);
510 }
511 }
512
513 @Override // Binder call
514 public void disconnectWifiDisplay() {
Jeff Browne08ae382012-09-07 20:36:36 -0700515 final long token = Binder.clearCallingIdentity();
516 try {
517 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700518 if (mWifiDisplayAdapter != null) {
519 mWifiDisplayAdapter.requestDisconnectLocked();
520 }
Jeff Browne08ae382012-09-07 20:36:36 -0700521 }
522 } finally {
523 Binder.restoreCallingIdentity(token);
524 }
525 }
526
527 @Override // Binder call
Jeff Brown89d55462012-09-19 11:33:42 -0700528 public void renameWifiDisplay(String address, String alias) {
Jeff Brown89d55462012-09-19 11:33:42 -0700529 if (address == null) {
530 throw new IllegalArgumentException("address must not be null");
531 }
Jeff Brownbc335452012-09-26 18:34:47 -0700532 if (!canCallerConfigureWifiDisplay()) {
533 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to "
534 + "rename a wifi display.");
535 }
Jeff Brown89d55462012-09-19 11:33:42 -0700536
537 final long token = Binder.clearCallingIdentity();
538 try {
539 synchronized (mSyncRoot) {
540 if (mWifiDisplayAdapter != null) {
541 mWifiDisplayAdapter.requestRenameLocked(address, alias);
542 }
543 }
544 } finally {
545 Binder.restoreCallingIdentity(token);
546 }
547 }
548
549 @Override // Binder call
550 public void forgetWifiDisplay(String address) {
Jeff Brown89d55462012-09-19 11:33:42 -0700551 if (address == null) {
552 throw new IllegalArgumentException("address must not be null");
553 }
Jeff Brownbc335452012-09-26 18:34:47 -0700554 if (!canCallerConfigureWifiDisplay()) {
555 throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to "
556 + "forget a wifi display.");
557 }
Jeff Brown89d55462012-09-19 11:33:42 -0700558
559 final long token = Binder.clearCallingIdentity();
560 try {
561 synchronized (mSyncRoot) {
562 if (mWifiDisplayAdapter != null) {
563 mWifiDisplayAdapter.requestForgetLocked(address);
564 }
565 }
566 } finally {
567 Binder.restoreCallingIdentity(token);
568 }
569 }
570
571 @Override // Binder call
Jeff Browne08ae382012-09-07 20:36:36 -0700572 public WifiDisplayStatus getWifiDisplayStatus() {
Jeff Browne08ae382012-09-07 20:36:36 -0700573 final long token = Binder.clearCallingIdentity();
574 try {
575 synchronized (mSyncRoot) {
Jeff Brown21c71532012-09-09 13:26:55 -0700576 if (mWifiDisplayAdapter != null) {
577 return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
Jeff Brown21c71532012-09-09 13:26:55 -0700578 }
Craig Mautner0bf6ec92012-12-18 08:33:27 -0800579 return new WifiDisplayStatus();
Jeff Browne08ae382012-09-07 20:36:36 -0700580 }
581 } finally {
582 Binder.restoreCallingIdentity(token);
583 }
584 }
585
Jeff Brownbc335452012-09-26 18:34:47 -0700586 private boolean canCallerConfigureWifiDisplay() {
587 return mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY)
588 == PackageManager.PERMISSION_GRANTED;
589 }
590
Jeff Browna506a6e2013-06-04 00:02:38 -0700591 @Override // Binder call
592 public int createPrivateVirtualDisplay(IBinder appToken, String packageName,
593 String name, int width, int height, int densityDpi, Surface surface) {
594 final int callingUid = Binder.getCallingUid();
595 if (!validatePackageName(callingUid, packageName)) {
596 throw new SecurityException("packageName must match the calling uid");
597 }
598 if (appToken == null) {
599 throw new IllegalArgumentException("appToken must not be null");
600 }
601 if (TextUtils.isEmpty(name)) {
602 throw new IllegalArgumentException("name must be non-null and non-empty");
603 }
604 if (width <= 0 || height <= 0 || densityDpi <= 0) {
605 throw new IllegalArgumentException("width, height, and densityDpi must be "
606 + "greater than 0");
607 }
608 if (surface == null) {
609 throw new IllegalArgumentException("surface must not be null");
610 }
611
612 final long token = Binder.clearCallingIdentity();
613 try {
614 synchronized (mSyncRoot) {
615 if (mVirtualDisplayAdapter == null) {
616 Slog.w(TAG, "Rejecting request to create private virtual display "
617 + "because the virtual display adapter is not available.");
618 return -1;
619 }
620
621 DisplayDevice device = mVirtualDisplayAdapter.createPrivateVirtualDisplayLocked(
622 appToken, callingUid, packageName, name, width, height, densityDpi,
623 surface);
624 if (device == null) {
625 return -1;
626 }
627
628 handleDisplayDeviceAddedLocked(device);
629 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
630 if (display != null) {
631 return display.getDisplayIdLocked();
632 }
633
634 // Something weird happened and the logical display was not created.
635 Slog.w(TAG, "Rejecting request to create private virtual display "
636 + "because the logical display was not created.");
637 mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
638 handleDisplayDeviceRemovedLocked(device);
639 }
640 } finally {
641 Binder.restoreCallingIdentity(token);
642 }
643 return -1;
644 }
645
646 @Override // Binder call
647 public void releaseVirtualDisplay(IBinder appToken) {
648 final long token = Binder.clearCallingIdentity();
649 try {
650 synchronized (mSyncRoot) {
651 if (mVirtualDisplayAdapter == null) {
652 return;
653 }
654
655 DisplayDevice device =
656 mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
657 if (device != null) {
658 handleDisplayDeviceRemovedLocked(device);
659 }
660 }
661 } finally {
662 Binder.restoreCallingIdentity(token);
663 }
664 }
665
666 private boolean validatePackageName(int uid, String packageName) {
667 if (packageName != null) {
668 String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
669 if (packageNames != null) {
670 for (String n : packageNames) {
671 if (n.equals(packageName)) {
672 return true;
673 }
674 }
675 }
676 }
677 return false;
678 }
679
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700680 private void registerDefaultDisplayAdapter() {
681 // Register default display adapter.
682 synchronized (mSyncRoot) {
683 if (mHeadless) {
684 registerDisplayAdapterLocked(new HeadlessDisplayAdapter(
685 mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
686 } else {
687 registerDisplayAdapterLocked(new LocalDisplayAdapter(
688 mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
689 }
690 }
691 }
692
693 private void registerAdditionalDisplayAdapters() {
694 synchronized (mSyncRoot) {
695 if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
Jeff Brown89d55462012-09-19 11:33:42 -0700696 registerOverlayDisplayAdapterLocked();
697 registerWifiDisplayAdapterLocked();
Jeff Browna506a6e2013-06-04 00:02:38 -0700698 registerVirtualDisplayAdapterLocked();
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700699 }
700 }
701 }
702
Jeff Brown89d55462012-09-19 11:33:42 -0700703 private void registerOverlayDisplayAdapterLocked() {
704 registerDisplayAdapterLocked(new OverlayDisplayAdapter(
705 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
706 }
707
708 private void registerWifiDisplayAdapterLocked() {
709 if (mContext.getResources().getBoolean(
Jeff Brownbbd28a22012-09-20 16:47:15 -0700710 com.android.internal.R.bool.config_enableWifiDisplay)
711 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
Jeff Brown89d55462012-09-19 11:33:42 -0700712 mWifiDisplayAdapter = new WifiDisplayAdapter(
713 mSyncRoot, mContext, mHandler, mDisplayAdapterListener,
714 mPersistentDataStore);
715 registerDisplayAdapterLocked(mWifiDisplayAdapter);
716 }
717 }
718
Jeff Browna506a6e2013-06-04 00:02:38 -0700719 private void registerVirtualDisplayAdapterLocked() {
720 mVirtualDisplayAdapter = new VirtualDisplayAdapter(
721 mSyncRoot, mContext, mHandler, mDisplayAdapterListener);
722 registerDisplayAdapterLocked(mVirtualDisplayAdapter);
723 }
724
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700725 private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
726 // In safe mode, we disable non-essential display adapters to give the user
727 // an opportunity to fix broken settings or other problems that might affect
728 // system stability.
729 // In only-core mode, we disable non-essential display adapters to minimize
730 // the number of dependencies that are started while in this mode and to
731 // prevent problems that might occur due to the device being encrypted.
732 return !mSafeMode && !mOnlyCore;
733 }
734
735 private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
736 mDisplayAdapters.add(adapter);
737 adapter.registerLocked();
738 }
739
Jeff Brownbd6e1502012-08-28 03:27:37 -0700740 private void handleDisplayDeviceAdded(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700741 synchronized (mSyncRoot) {
Jeff Browna506a6e2013-06-04 00:02:38 -0700742 handleDisplayDeviceAddedLocked(device);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700743 }
744 }
745
Jeff Browna506a6e2013-06-04 00:02:38 -0700746 private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
747 if (mDisplayDevices.contains(device)) {
748 Slog.w(TAG, "Attempted to add already added display device: "
749 + device.getDisplayDeviceInfoLocked());
750 return;
751 }
752
753 Slog.i(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked());
754
755 mDisplayDevices.add(device);
756 addLogicalDisplayLocked(device);
757 updateDisplayBlankingLocked(device);
758 scheduleTraversalLocked(false);
759 }
760
Jeff Brownbd6e1502012-08-28 03:27:37 -0700761 private void handleDisplayDeviceChanged(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700762 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700763 if (!mDisplayDevices.contains(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700764 Slog.w(TAG, "Attempted to change non-existent display device: "
765 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700766 return;
767 }
768
Jeff Browne87bf032012-09-20 18:30:13 -0700769 Slog.i(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked());
770
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700771 device.applyPendingDisplayDeviceInfoChangesLocked();
772 if (updateLogicalDisplaysLocked()) {
Craig Mautner65d11b32012-10-01 13:59:52 -0700773 scheduleTraversalLocked(false);
Jeff Brown64a55af2012-08-26 02:47:39 -0700774 }
775 }
776 }
777
Jeff Brownbd6e1502012-08-28 03:27:37 -0700778 private void handleDisplayDeviceRemoved(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700779 synchronized (mSyncRoot) {
Jeff Browna506a6e2013-06-04 00:02:38 -0700780 handleDisplayDeviceRemovedLocked(device);
781 }
782 }
783 private void handleDisplayDeviceRemovedLocked(DisplayDevice device) {
784 if (!mDisplayDevices.remove(device)) {
785 Slog.w(TAG, "Attempted to remove non-existent display device: "
786 + device.getDisplayDeviceInfoLocked());
787 return;
788 }
789
790 Slog.i(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked());
791
792 mRemovedDisplayDevices.add(device);
793 updateLogicalDisplaysLocked();
794 scheduleTraversalLocked(false);
795 }
796
797 private void updateAllDisplayBlankingLocked() {
798 final int count = mDisplayDevices.size();
799 for (int i = 0; i < count; i++) {
800 DisplayDevice device = mDisplayDevices.get(i);
801 updateDisplayBlankingLocked(device);
802 }
803 }
804
805 private void updateDisplayBlankingLocked(DisplayDevice device) {
806 // Blank or unblank the display immediately to match the state requested
807 // by the power manager (if known).
808 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
809 if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
810 switch (mAllDisplayBlankStateFromPowerManager) {
811 case DISPLAY_BLANK_STATE_BLANKED:
812 device.blankLocked();
813 break;
814 case DISPLAY_BLANK_STATE_UNBLANKED:
815 device.unblankLocked();
816 break;
Craig Mautner4f67ba62012-08-02 11:23:00 -0700817 }
Craig Mautner4f67ba62012-08-02 11:23:00 -0700818 }
819 }
820
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700821 // Adds a new logical display based on the given display device.
822 // Sends notifications if needed.
823 private void addLogicalDisplayLocked(DisplayDevice device) {
824 DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
825 boolean isDefault = (deviceInfo.flags
826 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
827 if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
828 Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo);
829 isDefault = false;
830 }
831
Jeff Brown27f1d672012-10-17 18:32:34 -0700832 if (!isDefault && mSingleDisplayDemoMode) {
833 Slog.i(TAG, "Not creating a logical display for a secondary display "
834 + " because single display demo mode is enabled: " + deviceInfo);
835 return;
836 }
837
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700838 final int displayId = assignDisplayIdLocked(isDefault);
839 final int layerStack = assignLayerStackLocked(displayId);
840
Jeff Brownd728bf52012-09-08 18:05:28 -0700841 LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700842 display.updateLocked(mDisplayDevices);
843 if (!display.isValidLocked()) {
844 // This should never happen currently.
845 Slog.w(TAG, "Ignoring display device because the logical display "
846 + "created from it was not considered valid: " + deviceInfo);
847 return;
848 }
849
850 mLogicalDisplays.put(displayId, display);
851
852 // Wake up waitForDefaultDisplay.
853 if (isDefault) {
854 mSyncRoot.notifyAll();
855 }
856
857 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
858 }
859
860 private int assignDisplayIdLocked(boolean isDefault) {
861 return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
862 }
863
864 private int assignLayerStackLocked(int displayId) {
865 // Currently layer stacks and display ids are the same.
866 // This need not be the case.
867 return displayId;
868 }
869
870 // Updates all existing logical displays given the current set of display devices.
871 // Removes invalid logical displays.
872 // Sends notifications if needed.
873 private boolean updateLogicalDisplaysLocked() {
874 boolean changed = false;
875 for (int i = mLogicalDisplays.size(); i-- > 0; ) {
876 final int displayId = mLogicalDisplays.keyAt(i);
877 LogicalDisplay display = mLogicalDisplays.valueAt(i);
878
879 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
880 display.updateLocked(mDisplayDevices);
881 if (!display.isValidLocked()) {
882 mLogicalDisplays.removeAt(i);
883 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
884 changed = true;
885 } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
886 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
887 changed = true;
888 }
889 }
890 return changed;
891 }
892
893 private void performTraversalInTransactionLocked() {
894 // Perform one last traversal for each removed display device.
895 final int removedCount = mRemovedDisplayDevices.size();
896 for (int i = 0; i < removedCount; i++) {
897 DisplayDevice device = mRemovedDisplayDevices.get(i);
898 device.performTraversalInTransactionLocked();
899 }
900 mRemovedDisplayDevices.clear();
901
Jeff Brownd728bf52012-09-08 18:05:28 -0700902 // Clear all viewports before configuring displays so that we can keep
903 // track of which ones we have configured.
904 clearViewportsLocked();
905
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700906 // Configure each display device.
907 final int count = mDisplayDevices.size();
908 for (int i = 0; i < count; i++) {
909 DisplayDevice device = mDisplayDevices.get(i);
910 configureDisplayInTransactionLocked(device);
911 device.performTraversalInTransactionLocked();
912 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700913
914 // Tell the input system about these new viewports.
915 if (mInputManagerFuncs != null) {
916 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
917 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700918 }
919
Craig Mautner722285e2012-09-07 13:55:58 -0700920 /**
921 * Tells the display manager whether there is interesting unique content on the
922 * specified logical display. This is used to control automatic mirroring.
923 * <p>
924 * If the display has unique content, then the display manager arranges for it
925 * to be presented on a physical display if appropriate. Otherwise, the display manager
926 * may choose to make the physical display mirror some other logical display.
927 * </p>
928 *
929 * @param displayId The logical display id to update.
930 * @param hasContent True if the logical display has content.
Craig Mautner65d11b32012-10-01 13:59:52 -0700931 * @param inTraversal True if called from WindowManagerService during a window traversal prior
932 * to call to performTraversalInTransactionFromWindowManager.
Craig Mautner722285e2012-09-07 13:55:58 -0700933 */
Craig Mautner65d11b32012-10-01 13:59:52 -0700934 public void setDisplayHasContent(int displayId, boolean hasContent, boolean inTraversal) {
Craig Mautner722285e2012-09-07 13:55:58 -0700935 synchronized (mSyncRoot) {
936 LogicalDisplay display = mLogicalDisplays.get(displayId);
937 if (display != null && display.hasContentLocked() != hasContent) {
938 display.setHasContentLocked(hasContent);
Craig Mautner65d11b32012-10-01 13:59:52 -0700939 scheduleTraversalLocked(inTraversal);
Craig Mautner722285e2012-09-07 13:55:58 -0700940 }
941 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700942 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700943
Jeff Brownd728bf52012-09-08 18:05:28 -0700944 private void clearViewportsLocked() {
945 mDefaultViewport.valid = false;
946 mExternalTouchViewport.valid = false;
Craig Mautner722285e2012-09-07 13:55:58 -0700947 }
948
949 private void configureDisplayInTransactionLocked(DisplayDevice device) {
Jeff Browna506a6e2013-06-04 00:02:38 -0700950 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
951 boolean isPrivate = (info.flags & DisplayDeviceInfo.FLAG_PRIVATE) != 0;
952
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700953 // Find the logical display that the display device is showing.
Jeff Browna506a6e2013-06-04 00:02:38 -0700954 // Private displays never mirror other displays.
Craig Mautner722285e2012-09-07 13:55:58 -0700955 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
Jeff Browna506a6e2013-06-04 00:02:38 -0700956 if (!isPrivate) {
957 if (display != null && !display.hasContentLocked()) {
958 // If the display does not have any content of its own, then
959 // automatically mirror the default logical display contents.
960 display = null;
961 }
962 if (display == null) {
963 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
964 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700965 }
966
967 // Apply the logical display configuration to the display device.
968 if (display == null) {
969 // TODO: no logical display for the device, blank it
Jeff Brownd728bf52012-09-08 18:05:28 -0700970 Slog.w(TAG, "Missing logical display to use for physical display device: "
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700971 + device.getDisplayDeviceInfoLocked());
Jeff Brownd728bf52012-09-08 18:05:28 -0700972 return;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700973 }
Jeff Browna506a6e2013-06-04 00:02:38 -0700974 boolean isBlanked = (mAllDisplayBlankStateFromPowerManager == DISPLAY_BLANK_STATE_BLANKED)
975 && (info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0;
Craig Mautner0bf6ec92012-12-18 08:33:27 -0800976 display.configureDisplayInTransactionLocked(device, isBlanked);
Jeff Brownd728bf52012-09-08 18:05:28 -0700977
978 // Update the viewports if needed.
Jeff Brownd728bf52012-09-08 18:05:28 -0700979 if (!mDefaultViewport.valid
980 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
981 setViewportLocked(mDefaultViewport, display, device);
982 }
983 if (!mExternalTouchViewport.valid
984 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
985 setViewportLocked(mExternalTouchViewport, display, device);
986 }
987 }
988
989 private static void setViewportLocked(DisplayViewport viewport,
990 LogicalDisplay display, DisplayDevice device) {
991 viewport.valid = true;
992 viewport.displayId = display.getDisplayIdLocked();
993 device.populateViewportLocked(viewport);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700994 }
995
996 private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) {
997 final int count = mLogicalDisplays.size();
998 for (int i = 0; i < count; i++) {
999 LogicalDisplay display = mLogicalDisplays.valueAt(i);
1000 if (display.getPrimaryDisplayDeviceLocked() == device) {
1001 return display;
1002 }
1003 }
1004 return null;
1005 }
1006
Jeff Brownbd6e1502012-08-28 03:27:37 -07001007 private void sendDisplayEventLocked(int displayId, int event) {
1008 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
1009 mHandler.sendMessage(msg);
1010 }
1011
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001012 // Requests that performTraversalsInTransactionFromWindowManager be called at a
1013 // later time to apply changes to surfaces and displays.
Craig Mautner65d11b32012-10-01 13:59:52 -07001014 private void scheduleTraversalLocked(boolean inTraversal) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001015 if (!mPendingTraversal && mWindowManagerFuncs != null) {
1016 mPendingTraversal = true;
Craig Mautner65d11b32012-10-01 13:59:52 -07001017 if (!inTraversal) {
1018 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
1019 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001020 }
1021 }
1022
1023 // Runs on Handler thread.
1024 // Delivers display event notifications to callbacks.
Jeff Brownbd6e1502012-08-28 03:27:37 -07001025 private void deliverDisplayEvent(int displayId, int event) {
1026 if (DEBUG) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001027 Slog.d(TAG, "Delivering display event: displayId="
1028 + displayId + ", event=" + event);
Jeff Brownfa25bf52012-07-23 19:26:30 -07001029 }
Jeff Brownfa25bf52012-07-23 19:26:30 -07001030
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001031 // Grab the lock and copy the callbacks.
Jeff Brownbd6e1502012-08-28 03:27:37 -07001032 final int count;
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001033 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -07001034 count = mCallbacks.size();
1035 mTempCallbacks.clear();
1036 for (int i = 0; i < count; i++) {
1037 mTempCallbacks.add(mCallbacks.valueAt(i));
Craig Mautner4f67ba62012-08-02 11:23:00 -07001038 }
Jeff Brownbd6e1502012-08-28 03:27:37 -07001039 }
Craig Mautner4f67ba62012-08-02 11:23:00 -07001040
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001041 // After releasing the lock, send the notifications out.
Jeff Brownbd6e1502012-08-28 03:27:37 -07001042 for (int i = 0; i < count; i++) {
1043 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
1044 }
1045 mTempCallbacks.clear();
Craig Mautner4f67ba62012-08-02 11:23:00 -07001046 }
1047
Jeff Brownfa25bf52012-07-23 19:26:30 -07001048 @Override // Binder call
Jeff Brownbd6e1502012-08-28 03:27:37 -07001049 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
Jeff Brownfa25bf52012-07-23 19:26:30 -07001050 if (mContext == null
1051 || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
1052 != PackageManager.PERMISSION_GRANTED) {
1053 pw.println("Permission Denial: can't dump DisplayManager from from pid="
1054 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
1055 return;
1056 }
1057
Jeff Brownbd6e1502012-08-28 03:27:37 -07001058 pw.println("DISPLAY MANAGER (dumpsys display)");
Jeff Brownfa25bf52012-07-23 19:26:30 -07001059
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001060 synchronized (mSyncRoot) {
Jeff Brown9e316a12012-10-08 19:17:06 -07001061 pw.println(" mHeadless=" + mHeadless);
1062 pw.println(" mOnlyCode=" + mOnlyCore);
1063 pw.println(" mSafeMode=" + mSafeMode);
1064 pw.println(" mPendingTraversal=" + mPendingTraversal);
1065 pw.println(" mAllDisplayBlankStateFromPowerManager="
1066 + mAllDisplayBlankStateFromPowerManager);
1067 pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
1068 pw.println(" mDefaultViewport=" + mDefaultViewport);
1069 pw.println(" mExternalTouchViewport=" + mExternalTouchViewport);
Jeff Brown27f1d672012-10-17 18:32:34 -07001070 pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
Jeff Brown9e316a12012-10-08 19:17:06 -07001071
Jeff Brownbd6e1502012-08-28 03:27:37 -07001072 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001073 ipw.increaseIndent();
Jeff Brownbd6e1502012-08-28 03:27:37 -07001074
1075 pw.println();
1076 pw.println("Display Adapters: size=" + mDisplayAdapters.size());
Jeff Brown848c2dc2012-08-19 20:18:08 -07001077 for (DisplayAdapter adapter : mDisplayAdapters) {
Jeff Brownbd6e1502012-08-28 03:27:37 -07001078 pw.println(" " + adapter.getName());
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001079 adapter.dumpLocked(ipw);
Jeff Brown848c2dc2012-08-19 20:18:08 -07001080 }
Craig Mautner9de49362012-08-02 14:30:30 -07001081
Jeff Brownbd6e1502012-08-28 03:27:37 -07001082 pw.println();
1083 pw.println("Display Devices: size=" + mDisplayDevices.size());
1084 for (DisplayDevice device : mDisplayDevices) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001085 pw.println(" " + device.getDisplayDeviceInfoLocked());
1086 device.dumpLocked(ipw);
Jeff Brownbd6e1502012-08-28 03:27:37 -07001087 }
1088
1089 final int logicalDisplayCount = mLogicalDisplays.size();
1090 pw.println();
1091 pw.println("Logical Displays: size=" + logicalDisplayCount);
1092 for (int i = 0; i < logicalDisplayCount; i++) {
1093 int displayId = mLogicalDisplays.keyAt(i);
1094 LogicalDisplay display = mLogicalDisplays.valueAt(i);
1095 pw.println(" Display " + displayId + ":");
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001096 display.dumpLocked(ipw);
Jeff Brownbd6e1502012-08-28 03:27:37 -07001097 }
1098 }
1099 }
1100
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001101 /**
1102 * This is the object that everything in the display manager locks on.
1103 * We make it an inner class within the {@link DisplayManagerService} to so that it is
1104 * clear that the object belongs to the display manager service and that it is
1105 * a unique object with a special purpose.
1106 */
1107 public static final class SyncRoot {
1108 }
1109
1110 /**
1111 * Private interface to the window manager.
1112 */
1113 public interface WindowManagerFuncs {
1114 /**
Craig Mautner722285e2012-09-07 13:55:58 -07001115 * Request that the window manager call
1116 * {@link #performTraversalInTransactionFromWindowManager} within a surface
1117 * transaction at a later time.
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001118 */
1119 void requestTraversal();
1120 }
1121
Jeff Brownd728bf52012-09-08 18:05:28 -07001122 /**
1123 * Private interface to the input manager.
1124 */
1125 public interface InputManagerFuncs {
1126 /**
1127 * Sets information about the displays as needed by the input system.
1128 * The input system should copy this information if required.
1129 */
1130 void setDisplayViewports(DisplayViewport defaultViewport,
1131 DisplayViewport externalTouchViewport);
1132 }
1133
Jeff Brownbd6e1502012-08-28 03:27:37 -07001134 private final class DisplayManagerHandler extends Handler {
1135 public DisplayManagerHandler(Looper looper) {
1136 super(looper, null, true /*async*/);
Jeff Brown848c2dc2012-08-19 20:18:08 -07001137 }
Jeff Brownbf5740e2012-08-19 23:20:02 -07001138
Jeff Brownbd6e1502012-08-28 03:27:37 -07001139 @Override
1140 public void handleMessage(Message msg) {
1141 switch (msg.what) {
1142 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
1143 registerDefaultDisplayAdapter();
1144 break;
1145
1146 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
1147 registerAdditionalDisplayAdapters();
1148 break;
1149
1150 case MSG_DELIVER_DISPLAY_EVENT:
1151 deliverDisplayEvent(msg.arg1, msg.arg2);
1152 break;
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001153
1154 case MSG_REQUEST_TRAVERSAL:
1155 mWindowManagerFuncs.requestTraversal();
1156 break;
Jeff Brownd728bf52012-09-08 18:05:28 -07001157
1158 case MSG_UPDATE_VIEWPORT: {
1159 synchronized (mSyncRoot) {
1160 mTempDefaultViewport.copyFrom(mDefaultViewport);
1161 mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
1162 }
1163 mInputManagerFuncs.setDisplayViewports(
1164 mTempDefaultViewport, mTempExternalTouchViewport);
1165 break;
1166 }
Jeff Brownbd6e1502012-08-28 03:27:37 -07001167 }
1168 }
1169 }
1170
1171 private final class DisplayAdapterListener implements DisplayAdapter.Listener {
1172 @Override
1173 public void onDisplayDeviceEvent(DisplayDevice device, int event) {
1174 switch (event) {
1175 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
1176 handleDisplayDeviceAdded(device);
1177 break;
1178
1179 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
1180 handleDisplayDeviceChanged(device);
1181 break;
1182
1183 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
1184 handleDisplayDeviceRemoved(device);
1185 break;
1186 }
1187 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001188
1189 @Override
1190 public void onTraversalRequested() {
1191 synchronized (mSyncRoot) {
Craig Mautner65d11b32012-10-01 13:59:52 -07001192 scheduleTraversalLocked(false);
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001193 }
1194 }
Jeff Brownbd6e1502012-08-28 03:27:37 -07001195 }
1196
1197 private final class CallbackRecord implements DeathRecipient {
1198 private final int mPid;
1199 private final IDisplayManagerCallback mCallback;
1200
1201 public CallbackRecord(int pid, IDisplayManagerCallback callback) {
1202 mPid = pid;
1203 mCallback = callback;
1204 }
1205
1206 @Override
1207 public void binderDied() {
1208 if (DEBUG) {
1209 Slog.d(TAG, "Display listener for pid " + mPid + " died.");
1210 }
1211 onCallbackDied(mPid);
1212 }
1213
1214 public void notifyDisplayEventAsync(int displayId, int event) {
1215 try {
1216 mCallback.onDisplayEvent(displayId, event);
1217 } catch (RemoteException ex) {
1218 Slog.w(TAG, "Failed to notify process "
1219 + mPid + " that displays changed, assuming it died.", ex);
1220 binderDied();
1221 }
1222 }
1223 }
Jeff Brownfa25bf52012-07-23 19:26:30 -07001224}