blob: 693f7d8bd7050bda3d5b2cb405e971faab3b1191 [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 Brownad9ef192014-04-08 17:26:30 -070024import android.hardware.SensorManager;
Jeff Brown7d00aff2013-08-02 19:03:49 -070025import android.hardware.display.DisplayManager;
Jeff Brownbd6e1502012-08-28 03:27:37 -070026import android.hardware.display.DisplayManagerGlobal;
Jeff Brown4ccb8232014-01-16 22:16:42 -080027import android.hardware.display.DisplayManagerInternal;
28import android.hardware.display.DisplayViewport;
29import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
Jeff Brownfa25bf52012-07-23 19:26:30 -070030import android.hardware.display.IDisplayManager;
Jeff Brownbd6e1502012-08-28 03:27:37 -070031import android.hardware.display.IDisplayManagerCallback;
Jeff Browne08ae382012-09-07 20:36:36 -070032import android.hardware.display.WifiDisplayStatus;
Jeff Brown4ccb8232014-01-16 22:16:42 -080033import android.hardware.input.InputManagerInternal;
Jeff Brownfa25bf52012-07-23 19:26:30 -070034import android.os.Binder;
Jeff Brownbd6e1502012-08-28 03:27:37 -070035import android.os.Handler;
Jeff Brown64a55af2012-08-26 02:47:39 -070036import android.os.IBinder;
Jeff Brown4ccb8232014-01-16 22:16:42 -080037import android.os.IBinder.DeathRecipient;
Jeff Brownbd6e1502012-08-28 03:27:37 -070038import android.os.Looper;
39import android.os.Message;
Craig Mautner4504de52013-12-20 09:06:56 -080040import android.os.Process;
Jeff Brownbd6e1502012-08-28 03:27:37 -070041import android.os.RemoteException;
42import android.os.SystemClock;
Jeff Brownfa25bf52012-07-23 19:26:30 -070043import android.os.SystemProperties;
Jeff Browna506a6e2013-06-04 00:02:38 -070044import android.text.TextUtils;
Jeff Brownce468a32013-11-21 16:42:03 -080045import android.util.Log;
Jeff Brownbd6e1502012-08-28 03:27:37 -070046import android.util.Slog;
47import android.util.SparseArray;
Jeff Brownfa25bf52012-07-23 19:26:30 -070048import android.view.Display;
49import android.view.DisplayInfo;
Jeff Browna506a6e2013-06-04 00:02:38 -070050import android.view.Surface;
Jeff Brown4ccb8232014-01-16 22:16:42 -080051import android.view.WindowManagerInternal;
Jeff Browna506a6e2013-06-04 00:02:38 -070052
Jeff Brown4ccb8232014-01-16 22:16:42 -080053import com.android.server.DisplayThread;
54import com.android.server.LocalServices;
55import com.android.server.SystemService;
Dianne Hackborn8d044e82013-04-30 17:24:15 -070056import com.android.server.UiThread;
Jeff Brownfa25bf52012-07-23 19:26:30 -070057
58import java.io.FileDescriptor;
59import java.io.PrintWriter;
60import java.util.ArrayList;
Jeff Browna506a6e2013-06-04 00:02:38 -070061import java.util.Arrays;
Jeff Brown7f3994e2012-12-04 14:04:28 -080062import java.util.concurrent.CopyOnWriteArrayList;
Jeff Brownfa25bf52012-07-23 19:26:30 -070063
64/**
Jeff Brownbd6e1502012-08-28 03:27:37 -070065 * Manages attached displays.
Jeff Brownfa25bf52012-07-23 19:26:30 -070066 * <p>
Jeff Brownbd6e1502012-08-28 03:27:37 -070067 * The {@link DisplayManagerService} manages the global lifecycle of displays,
68 * decides how to configure logical displays based on the physical display devices currently
69 * attached, sends notifications to the system and to applications when the state
70 * changes, and so on.
71 * </p><p>
72 * The display manager service relies on a collection of {@link DisplayAdapter} components,
73 * for discovering and configuring physical display devices attached to the system.
74 * There are separate display adapters for each manner that devices are attached:
75 * one display adapter for built-in local displays, one for simulated non-functional
76 * displays when the system is headless, one for simulated overlay displays used for
77 * development, one for wifi displays, etc.
78 * </p><p>
79 * Display adapters are only weakly coupled to the display manager service.
80 * Display adapters communicate changes in display device state to the display manager
Craig Mautner722285e2012-09-07 13:55:58 -070081 * service asynchronously via a {@link DisplayAdapter.Listener} registered
Jeff Brownbd6e1502012-08-28 03:27:37 -070082 * by the display manager service. This separation of concerns is important for
83 * two main reasons. First, it neatly encapsulates the responsibilities of these
84 * two classes: display adapters handle individual display devices whereas
85 * the display manager service handles the global state. Second, it eliminates
86 * the potential for deadlocks resulting from asynchronous display device discovery.
Jeff Brown4ed8fe72012-08-30 18:18:29 -070087 * </p>
88 *
89 * <h3>Synchronization</h3>
90 * <p>
91 * Because the display manager may be accessed by multiple threads, the synchronization
92 * story gets a little complicated. In particular, the window manager may call into
93 * the display manager while holding a surface transaction with the expectation that
94 * it can apply changes immediately. Unfortunately, that means we can't just do
95 * everything asynchronously (*grump*).
Jeff Brownbd6e1502012-08-28 03:27:37 -070096 * </p><p>
Jeff Brown4ed8fe72012-08-30 18:18:29 -070097 * To make this work, all of the objects that belong to the display manager must
98 * use the same lock. We call this lock the synchronization root and it has a unique
99 * type {@link DisplayManagerService.SyncRoot}. Methods that require this lock are
100 * named with the "Locked" suffix.
101 * </p><p>
102 * Where things get tricky is that the display manager is not allowed to make
103 * any potentially reentrant calls, especially into the window manager. We generally
104 * avoid this by making all potentially reentrant out-calls asynchronous.
Jeff Brownfa25bf52012-07-23 19:26:30 -0700105 * </p>
106 */
Jeff Brown4ccb8232014-01-16 22:16:42 -0800107public final class DisplayManagerService extends SystemService {
Jeff Brownfa25bf52012-07-23 19:26:30 -0700108 private static final String TAG = "DisplayManagerService";
Jeff Brownbd6e1502012-08-28 03:27:37 -0700109 private static final boolean DEBUG = false;
Jeff Brownfa25bf52012-07-23 19:26:30 -0700110
Jeff Brownbbd28a22012-09-20 16:47:15 -0700111 // When this system property is set to 0, WFD is forcibly disabled on boot.
112 // When this system property is set to 1, WFD is forcibly enabled on boot.
113 // Otherwise WFD is enabled according to the value of config_enableWifiDisplay.
114 private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable";
115
Jeff Brownbd6e1502012-08-28 03:27:37 -0700116 private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
117
118 private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER = 1;
119 private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;
120 private static final int MSG_DELIVER_DISPLAY_EVENT = 3;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700121 private static final int MSG_REQUEST_TRAVERSAL = 4;
Jeff Brownd728bf52012-09-08 18:05:28 -0700122 private static final int MSG_UPDATE_VIEWPORT = 5;
Jeff Brownfa25bf52012-07-23 19:26:30 -0700123
Jeff Brown9e316a12012-10-08 19:17:06 -0700124 private static final int DISPLAY_BLANK_STATE_UNKNOWN = 0;
125 private static final int DISPLAY_BLANK_STATE_BLANKED = 1;
126 private static final int DISPLAY_BLANK_STATE_UNBLANKED = 2;
127
Jeff Brownb880d882014-02-10 19:47:07 -0800128 private final Context mContext;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700129 private final DisplayManagerHandler mHandler;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700130 private final Handler mUiHandler;
131 private final DisplayAdapterListener mDisplayAdapterListener;
Jeff Brown4ccb8232014-01-16 22:16:42 -0800132 private WindowManagerInternal mWindowManagerInternal;
133 private InputManagerInternal mInputManagerInternal;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700134
135 // The synchronization root for the display manager.
136 // This lock guards most of the display manager's state.
Craig Mautner0bf6ec92012-12-18 08:33:27 -0800137 // NOTE: This is synchronized on while holding WindowManagerService.mWindowMap so never call
138 // into WindowManagerService methods that require mWindowMap while holding this unless you are
139 // very very sure that no deadlock can occur.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700140 private final SyncRoot mSyncRoot = new SyncRoot();
141
142 // True if in safe mode.
143 // This option may disable certain display adapters.
144 public boolean mSafeMode;
145
146 // True if we are in a special boot mode where only core applications and
147 // services should be started. This option may disable certain display adapters.
148 public boolean mOnlyCore;
149
Jeff Brown27f1d672012-10-17 18:32:34 -0700150 // True if the display manager service should pretend there is only one display
151 // and only tell applications about the existence of the default logical display.
152 // The display manager can still mirror content to secondary displays but applications
153 // cannot present unique content on those displays.
154 // Used for demonstration purposes only.
155 private final boolean mSingleDisplayDemoMode;
156
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700157 // All callback records indexed by calling process id.
158 public final SparseArray<CallbackRecord> mCallbacks =
Jeff Brownbd6e1502012-08-28 03:27:37 -0700159 new SparseArray<CallbackRecord>();
Jeff Brownfa25bf52012-07-23 19:26:30 -0700160
Jeff Brownbd6e1502012-08-28 03:27:37 -0700161 // List of all currently registered display adapters.
162 private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
163
164 // List of all currently connected display devices.
165 private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>();
166
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700167 // List of all logical displays indexed by logical display id.
168 private final SparseArray<LogicalDisplay> mLogicalDisplays =
169 new SparseArray<LogicalDisplay>();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700170 private int mNextNonDefaultDisplayId = Display.DEFAULT_DISPLAY + 1;
171
Jeff Brown7f3994e2012-12-04 14:04:28 -0800172 // List of all display transaction listeners.
173 private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners =
174 new CopyOnWriteArrayList<DisplayTransactionListener>();
175
Jeff Brownad9ef192014-04-08 17:26:30 -0700176 // Display power controller.
177 private DisplayPowerController mDisplayPowerController;
178
Jeff Brown9e316a12012-10-08 19:17:06 -0700179 // Set to true if all displays have been blanked by the power manager.
Craig Mautner0bf6ec92012-12-18 08:33:27 -0800180 private int mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNKNOWN;
Jeff Brown9e316a12012-10-08 19:17:06 -0700181
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700182 // Set to true when there are pending display changes that have yet to be applied
183 // to the surface flinger state.
184 private boolean mPendingTraversal;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700185
Jeff Browne08ae382012-09-07 20:36:36 -0700186 // The Wifi display adapter, or null if not registered.
187 private WifiDisplayAdapter mWifiDisplayAdapter;
188
Jeff Brownce468a32013-11-21 16:42:03 -0800189 // The number of active wifi display scan requests.
190 private int mWifiDisplayScanRequestCount;
191
Jeff Browna506a6e2013-06-04 00:02:38 -0700192 // The virtual display adapter, or null if not registered.
193 private VirtualDisplayAdapter mVirtualDisplayAdapter;
194
Jeff Brownd728bf52012-09-08 18:05:28 -0700195 // Viewports of the default display and the display that should receive touch
196 // input from an external source. Used by the input system.
197 private final DisplayViewport mDefaultViewport = new DisplayViewport();
198 private final DisplayViewport mExternalTouchViewport = new DisplayViewport();
199
Jeff Brown89d55462012-09-19 11:33:42 -0700200 // Persistent data store for all internal settings maintained by the display manager service.
201 private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();
202
Jeff Brownbd6e1502012-08-28 03:27:37 -0700203 // Temporary callback list, used when sending display events to applications.
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700204 // May be used outside of the lock but only on the handler thread.
205 private final ArrayList<CallbackRecord> mTempCallbacks = new ArrayList<CallbackRecord>();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700206
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700207 // Temporary display info, used for comparing display configurations.
208 private final DisplayInfo mTempDisplayInfo = new DisplayInfo();
209
Jeff Brownd728bf52012-09-08 18:05:28 -0700210 // Temporary viewports, used when sending new viewport information to the
211 // input system. May be used outside of the lock but only on the handler thread.
212 private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
213 private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
214
Jeff Brownb880d882014-02-10 19:47:07 -0800215 public DisplayManagerService(Context context) {
216 super(context);
217 mContext = context;
Jeff Brown4ccb8232014-01-16 22:16:42 -0800218 mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
Dianne Hackborn8d044e82013-04-30 17:24:15 -0700219 mUiHandler = UiThread.getHandler();
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700220 mDisplayAdapterListener = new DisplayAdapterListener();
Jeff Brown27f1d672012-10-17 18:32:34 -0700221 mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
Craig Mautner4f67ba62012-08-02 11:23:00 -0700222 }
223
Jeff Brown4ccb8232014-01-16 22:16:42 -0800224 @Override
Jeff Brown4ccb8232014-01-16 22:16:42 -0800225 public void onStart() {
226 mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
227
228 publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
229 true /*allowIsolated*/);
230 publishLocalService(DisplayManagerInternal.class, new LocalService());
231 }
232
233 @Override
234 public void onBootPhase(int phase) {
235 if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) {
236 synchronized (mSyncRoot) {
237 long timeout = SystemClock.uptimeMillis() + WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT;
238 while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null) {
239 long delay = timeout - SystemClock.uptimeMillis();
240 if (delay <= 0) {
241 throw new RuntimeException("Timeout waiting for default display "
242 + "to be initialized.");
243 }
244 if (DEBUG) {
245 Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
246 }
247 try {
248 mSyncRoot.wait(delay);
249 } catch (InterruptedException ex) {
250 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700251 }
252 }
253 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700254 }
255
Jeff Brown4ccb8232014-01-16 22:16:42 -0800256 // TODO: Use dependencies or a boot phase
257 public void windowManagerAndInputReady() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700258 synchronized (mSyncRoot) {
Jeff Brown4ccb8232014-01-16 22:16:42 -0800259 mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
260 mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
Craig Mautner65d11b32012-10-01 13:59:52 -0700261 scheduleTraversalLocked(false);
Jeff Brownd728bf52012-09-08 18:05:28 -0700262 }
263 }
264
265 /**
Jeff Brownbd6e1502012-08-28 03:27:37 -0700266 * Called when the system is ready to go.
267 */
268 public void systemReady(boolean safeMode, boolean onlyCore) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700269 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700270 mSafeMode = safeMode;
271 mOnlyCore = onlyCore;
272 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700273
Jeff Brownbd6e1502012-08-28 03:27:37 -0700274 mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
275 }
276
Jeff Brown4ccb8232014-01-16 22:16:42 -0800277 private void registerDisplayTransactionListenerInternal(
278 DisplayTransactionListener listener) {
Jeff Brown7f3994e2012-12-04 14:04:28 -0800279 // List is self-synchronized copy-on-write.
280 mDisplayTransactionListeners.add(listener);
281 }
282
Jeff Brown4ccb8232014-01-16 22:16:42 -0800283 private void unregisterDisplayTransactionListenerInternal(
284 DisplayTransactionListener listener) {
Jeff Brown7f3994e2012-12-04 14:04:28 -0800285 // List is self-synchronized copy-on-write.
286 mDisplayTransactionListeners.remove(listener);
287 }
288
Jeff Brown4ccb8232014-01-16 22:16:42 -0800289 private void setDisplayInfoOverrideFromWindowManagerInternal(
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700290 int displayId, DisplayInfo info) {
291 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700292 LogicalDisplay display = mLogicalDisplays.get(displayId);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700293 if (display != null) {
Jeff Brownef981a42013-08-07 14:13:37 -0700294 if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700295 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
Craig Mautner65d11b32012-10-01 13:59:52 -0700296 scheduleTraversalLocked(false);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700297 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700298 }
299 }
300 }
301
Jeff Brown4ccb8232014-01-16 22:16:42 -0800302 private void performTraversalInTransactionFromWindowManagerInternal() {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700303 synchronized (mSyncRoot) {
304 if (!mPendingTraversal) {
305 return;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700306 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700307 mPendingTraversal = false;
308
309 performTraversalInTransactionLocked();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700310 }
Jeff Brown7f3994e2012-12-04 14:04:28 -0800311
312 // List is self-synchronized copy-on-write.
313 for (DisplayTransactionListener listener : mDisplayTransactionListeners) {
314 listener.onDisplayTransaction();
315 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700316 }
317
Jeff Brown4ccb8232014-01-16 22:16:42 -0800318 private void blankAllDisplaysFromPowerManagerInternal() {
Jeff Brown9e316a12012-10-08 19:17:06 -0700319 synchronized (mSyncRoot) {
320 if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_BLANKED) {
321 mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_BLANKED;
Jeff Browna506a6e2013-06-04 00:02:38 -0700322 updateAllDisplayBlankingLocked();
Jeff Brown8ec09432012-10-16 16:19:23 -0700323 scheduleTraversalLocked(false);
Jeff Brown9e316a12012-10-08 19:17:06 -0700324 }
325 }
326 }
327
Jeff Brown4ccb8232014-01-16 22:16:42 -0800328 private void unblankAllDisplaysFromPowerManagerInternal() {
Jeff Brown9e316a12012-10-08 19:17:06 -0700329 synchronized (mSyncRoot) {
330 if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_UNBLANKED) {
331 mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNBLANKED;
Jeff Browna506a6e2013-06-04 00:02:38 -0700332 updateAllDisplayBlankingLocked();
Jeff Brown8ec09432012-10-16 16:19:23 -0700333 scheduleTraversalLocked(false);
Jeff Brown9e316a12012-10-08 19:17:06 -0700334 }
335 }
336 }
337
Jeff Brown4ccb8232014-01-16 22:16:42 -0800338 private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700339 synchronized (mSyncRoot) {
Jeff Brown4ccb8232014-01-16 22:16:42 -0800340 LogicalDisplay display = mLogicalDisplays.get(displayId);
341 if (display != null) {
342 DisplayInfo info = display.getDisplayInfoLocked();
343 if (info.hasAccess(callingUid)) {
344 return info;
345 }
346 }
347 return null;
348 }
349 }
350
351 private int[] getDisplayIdsInternal(int callingUid) {
352 synchronized (mSyncRoot) {
353 final int count = mLogicalDisplays.size();
354 int[] displayIds = new int[count];
355 int n = 0;
356 for (int i = 0; i < count; i++) {
357 LogicalDisplay display = mLogicalDisplays.valueAt(i);
358 DisplayInfo info = display.getDisplayInfoLocked();
359 if (info.hasAccess(callingUid)) {
360 displayIds[n++] = mLogicalDisplays.keyAt(i);
361 }
362 }
363 if (n != count) {
364 displayIds = Arrays.copyOfRange(displayIds, 0, n);
365 }
366 return displayIds;
367 }
368 }
369
370 private void registerCallbackInternal(IDisplayManagerCallback callback, int callingPid) {
371 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700372 if (mCallbacks.get(callingPid) != null) {
373 throw new SecurityException("The calling process has already "
374 + "registered an IDisplayManagerCallback.");
Jeff Brown64a55af2012-08-26 02:47:39 -0700375 }
376
Jeff Brownbd6e1502012-08-28 03:27:37 -0700377 CallbackRecord record = new CallbackRecord(callingPid, callback);
378 try {
379 IBinder binder = callback.asBinder();
380 binder.linkToDeath(record, 0);
381 } catch (RemoteException ex) {
382 // give up
383 throw new RuntimeException(ex);
384 }
385
386 mCallbacks.put(callingPid, record);
387 }
388 }
389
Jeff Brownce468a32013-11-21 16:42:03 -0800390 private void onCallbackDied(CallbackRecord record) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700391 synchronized (mSyncRoot) {
Jeff Brownce468a32013-11-21 16:42:03 -0800392 mCallbacks.remove(record.mPid);
393 stopWifiDisplayScanLocked(record);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700394 }
395 }
396
Jeff Brown4ccb8232014-01-16 22:16:42 -0800397 private void startWifiDisplayScanInternal(int callingPid) {
398 synchronized (mSyncRoot) {
399 CallbackRecord record = mCallbacks.get(callingPid);
400 if (record == null) {
401 throw new IllegalStateException("The calling process has not "
402 + "registered an IDisplayManagerCallback.");
Jeff Browne08ae382012-09-07 20:36:36 -0700403 }
Jeff Brown4ccb8232014-01-16 22:16:42 -0800404 startWifiDisplayScanLocked(record);
Jeff Browne08ae382012-09-07 20:36:36 -0700405 }
406 }
407
Jeff Brownce468a32013-11-21 16:42:03 -0800408 private void startWifiDisplayScanLocked(CallbackRecord record) {
409 if (!record.mWifiDisplayScanRequested) {
410 record.mWifiDisplayScanRequested = true;
411 if (mWifiDisplayScanRequestCount++ == 0) {
412 if (mWifiDisplayAdapter != null) {
413 mWifiDisplayAdapter.requestStartScanLocked();
414 }
415 }
416 }
417 }
418
Jeff Brown4ccb8232014-01-16 22:16:42 -0800419 private void stopWifiDisplayScanInternal(int callingPid) {
420 synchronized (mSyncRoot) {
421 CallbackRecord record = mCallbacks.get(callingPid);
422 if (record == null) {
423 throw new IllegalStateException("The calling process has not "
424 + "registered an IDisplayManagerCallback.");
Jeff Brownce468a32013-11-21 16:42:03 -0800425 }
Jeff Brown4ccb8232014-01-16 22:16:42 -0800426 stopWifiDisplayScanLocked(record);
Jeff Brownce468a32013-11-21 16:42:03 -0800427 }
428 }
429
430 private void stopWifiDisplayScanLocked(CallbackRecord record) {
431 if (record.mWifiDisplayScanRequested) {
432 record.mWifiDisplayScanRequested = false;
433 if (--mWifiDisplayScanRequestCount == 0) {
434 if (mWifiDisplayAdapter != null) {
435 mWifiDisplayAdapter.requestStopScanLocked();
436 }
437 } else if (mWifiDisplayScanRequestCount < 0) {
438 Log.wtf(TAG, "mWifiDisplayScanRequestCount became negative: "
439 + mWifiDisplayScanRequestCount);
440 mWifiDisplayScanRequestCount = 0;
441 }
442 }
443 }
444
Jeff Brown4ccb8232014-01-16 22:16:42 -0800445 private void connectWifiDisplayInternal(String address) {
446 synchronized (mSyncRoot) {
447 if (mWifiDisplayAdapter != null) {
448 mWifiDisplayAdapter.requestConnectLocked(address);
Jeff Browne08ae382012-09-07 20:36:36 -0700449 }
Jeff Browne08ae382012-09-07 20:36:36 -0700450 }
451 }
452
Jeff Brown4ccb8232014-01-16 22:16:42 -0800453 private void pauseWifiDisplayInternal() {
454 synchronized (mSyncRoot) {
455 if (mWifiDisplayAdapter != null) {
456 mWifiDisplayAdapter.requestPauseLocked();
Chong Zhang1f3ecaa2013-05-03 15:55:36 -0700457 }
Chong Zhang1f3ecaa2013-05-03 15:55:36 -0700458 }
459 }
460
Jeff Brown4ccb8232014-01-16 22:16:42 -0800461 private void resumeWifiDisplayInternal() {
462 synchronized (mSyncRoot) {
463 if (mWifiDisplayAdapter != null) {
464 mWifiDisplayAdapter.requestResumeLocked();
Chong Zhang1f3ecaa2013-05-03 15:55:36 -0700465 }
Chong Zhang1f3ecaa2013-05-03 15:55:36 -0700466 }
467 }
468
Jeff Brown4ccb8232014-01-16 22:16:42 -0800469 private void disconnectWifiDisplayInternal() {
470 synchronized (mSyncRoot) {
471 if (mWifiDisplayAdapter != null) {
472 mWifiDisplayAdapter.requestDisconnectLocked();
Jeff Browne08ae382012-09-07 20:36:36 -0700473 }
Jeff Browne08ae382012-09-07 20:36:36 -0700474 }
475 }
476
Jeff Brown4ccb8232014-01-16 22:16:42 -0800477 private void renameWifiDisplayInternal(String address, String alias) {
478 synchronized (mSyncRoot) {
479 if (mWifiDisplayAdapter != null) {
480 mWifiDisplayAdapter.requestRenameLocked(address, alias);
Jeff Brown89d55462012-09-19 11:33:42 -0700481 }
Jeff Brown89d55462012-09-19 11:33:42 -0700482 }
483 }
484
Jeff Brown4ccb8232014-01-16 22:16:42 -0800485 private void forgetWifiDisplayInternal(String address) {
486 synchronized (mSyncRoot) {
487 if (mWifiDisplayAdapter != null) {
488 mWifiDisplayAdapter.requestForgetLocked(address);
Jeff Brown89d55462012-09-19 11:33:42 -0700489 }
Jeff Brown89d55462012-09-19 11:33:42 -0700490 }
491 }
492
Jeff Brown4ccb8232014-01-16 22:16:42 -0800493 private WifiDisplayStatus getWifiDisplayStatusInternal() {
494 synchronized (mSyncRoot) {
495 if (mWifiDisplayAdapter != null) {
496 return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
Jeff Browne08ae382012-09-07 20:36:36 -0700497 }
Jeff Brown4ccb8232014-01-16 22:16:42 -0800498 return new WifiDisplayStatus();
Jeff Browne08ae382012-09-07 20:36:36 -0700499 }
500 }
501
Jeff Brown4ccb8232014-01-16 22:16:42 -0800502 private int createVirtualDisplayInternal(IBinder appToken, int callingUid, String packageName,
Jeff Brown7d00aff2013-08-02 19:03:49 -0700503 String name, int width, int height, int densityDpi, Surface surface, int flags) {
Jeff Brown4ccb8232014-01-16 22:16:42 -0800504 synchronized (mSyncRoot) {
505 if (mVirtualDisplayAdapter == null) {
506 Slog.w(TAG, "Rejecting request to create private virtual display "
507 + "because the virtual display adapter is not available.");
508 return -1;
Jeff Brown7d00aff2013-08-02 19:03:49 -0700509 }
Jeff Brown4ccb8232014-01-16 22:16:42 -0800510
511 DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
512 appToken, callingUid, packageName, name, width, height, densityDpi,
513 surface, flags);
514 if (device == null) {
515 return -1;
Jeff Brown7d00aff2013-08-02 19:03:49 -0700516 }
Jeff Browna506a6e2013-06-04 00:02:38 -0700517
Jeff Brown4ccb8232014-01-16 22:16:42 -0800518 handleDisplayDeviceAddedLocked(device);
519 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
520 if (display != null) {
521 return display.getDisplayIdLocked();
Jeff Browna506a6e2013-06-04 00:02:38 -0700522 }
Jeff Brown4ccb8232014-01-16 22:16:42 -0800523
524 // Something weird happened and the logical display was not created.
525 Slog.w(TAG, "Rejecting request to create virtual display "
526 + "because the logical display was not created.");
527 mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
528 handleDisplayDeviceRemovedLocked(device);
Jeff Browna506a6e2013-06-04 00:02:38 -0700529 }
530 return -1;
531 }
532
Jeff Brown4ccb8232014-01-16 22:16:42 -0800533 private void releaseVirtualDisplayInternal(IBinder appToken) {
534 synchronized (mSyncRoot) {
535 if (mVirtualDisplayAdapter == null) {
536 return;
Jeff Browna506a6e2013-06-04 00:02:38 -0700537 }
Jeff Browna506a6e2013-06-04 00:02:38 -0700538
Jeff Brown4ccb8232014-01-16 22:16:42 -0800539 DisplayDevice device =
540 mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
541 if (device != null) {
542 handleDisplayDeviceRemovedLocked(device);
Jeff Browna506a6e2013-06-04 00:02:38 -0700543 }
544 }
Jeff Browna506a6e2013-06-04 00:02:38 -0700545 }
546
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700547 private void registerDefaultDisplayAdapter() {
548 // Register default display adapter.
549 synchronized (mSyncRoot) {
Mike Lockwoode63f6f72013-11-15 11:01:47 -0800550 registerDisplayAdapterLocked(new LocalDisplayAdapter(
551 mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700552 }
553 }
554
555 private void registerAdditionalDisplayAdapters() {
556 synchronized (mSyncRoot) {
557 if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
Jeff Brown89d55462012-09-19 11:33:42 -0700558 registerOverlayDisplayAdapterLocked();
559 registerWifiDisplayAdapterLocked();
Jeff Browna506a6e2013-06-04 00:02:38 -0700560 registerVirtualDisplayAdapterLocked();
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700561 }
562 }
563 }
564
Jeff Brown89d55462012-09-19 11:33:42 -0700565 private void registerOverlayDisplayAdapterLocked() {
566 registerDisplayAdapterLocked(new OverlayDisplayAdapter(
567 mSyncRoot, mContext, mHandler, mDisplayAdapterListener, mUiHandler));
568 }
569
570 private void registerWifiDisplayAdapterLocked() {
571 if (mContext.getResources().getBoolean(
Jeff Brownbbd28a22012-09-20 16:47:15 -0700572 com.android.internal.R.bool.config_enableWifiDisplay)
573 || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
Jeff Brown89d55462012-09-19 11:33:42 -0700574 mWifiDisplayAdapter = new WifiDisplayAdapter(
575 mSyncRoot, mContext, mHandler, mDisplayAdapterListener,
576 mPersistentDataStore);
577 registerDisplayAdapterLocked(mWifiDisplayAdapter);
578 }
579 }
580
Jeff Browna506a6e2013-06-04 00:02:38 -0700581 private void registerVirtualDisplayAdapterLocked() {
582 mVirtualDisplayAdapter = new VirtualDisplayAdapter(
583 mSyncRoot, mContext, mHandler, mDisplayAdapterListener);
584 registerDisplayAdapterLocked(mVirtualDisplayAdapter);
585 }
586
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700587 private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() {
588 // In safe mode, we disable non-essential display adapters to give the user
589 // an opportunity to fix broken settings or other problems that might affect
590 // system stability.
591 // In only-core mode, we disable non-essential display adapters to minimize
592 // the number of dependencies that are started while in this mode and to
593 // prevent problems that might occur due to the device being encrypted.
594 return !mSafeMode && !mOnlyCore;
595 }
596
597 private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
598 mDisplayAdapters.add(adapter);
599 adapter.registerLocked();
600 }
601
Jeff Brownbd6e1502012-08-28 03:27:37 -0700602 private void handleDisplayDeviceAdded(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700603 synchronized (mSyncRoot) {
Jeff Browna506a6e2013-06-04 00:02:38 -0700604 handleDisplayDeviceAddedLocked(device);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700605 }
606 }
607
Jeff Browna506a6e2013-06-04 00:02:38 -0700608 private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
609 if (mDisplayDevices.contains(device)) {
610 Slog.w(TAG, "Attempted to add already added display device: "
611 + device.getDisplayDeviceInfoLocked());
612 return;
613 }
614
615 Slog.i(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked());
616
617 mDisplayDevices.add(device);
618 addLogicalDisplayLocked(device);
619 updateDisplayBlankingLocked(device);
620 scheduleTraversalLocked(false);
621 }
622
Jeff Brownbd6e1502012-08-28 03:27:37 -0700623 private void handleDisplayDeviceChanged(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700624 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700625 if (!mDisplayDevices.contains(device)) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700626 Slog.w(TAG, "Attempted to change non-existent display device: "
627 + device.getDisplayDeviceInfoLocked());
Jeff Brownbd6e1502012-08-28 03:27:37 -0700628 return;
629 }
630
Jeff Browne87bf032012-09-20 18:30:13 -0700631 Slog.i(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked());
632
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700633 device.applyPendingDisplayDeviceInfoChangesLocked();
634 if (updateLogicalDisplaysLocked()) {
Craig Mautner65d11b32012-10-01 13:59:52 -0700635 scheduleTraversalLocked(false);
Jeff Brown64a55af2012-08-26 02:47:39 -0700636 }
637 }
638 }
639
Jeff Brownbd6e1502012-08-28 03:27:37 -0700640 private void handleDisplayDeviceRemoved(DisplayDevice device) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700641 synchronized (mSyncRoot) {
Jeff Browna506a6e2013-06-04 00:02:38 -0700642 handleDisplayDeviceRemovedLocked(device);
643 }
644 }
645 private void handleDisplayDeviceRemovedLocked(DisplayDevice device) {
646 if (!mDisplayDevices.remove(device)) {
647 Slog.w(TAG, "Attempted to remove non-existent display device: "
648 + device.getDisplayDeviceInfoLocked());
649 return;
650 }
651
652 Slog.i(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked());
653
Jeff Browna506a6e2013-06-04 00:02:38 -0700654 updateLogicalDisplaysLocked();
655 scheduleTraversalLocked(false);
656 }
657
658 private void updateAllDisplayBlankingLocked() {
659 final int count = mDisplayDevices.size();
660 for (int i = 0; i < count; i++) {
661 DisplayDevice device = mDisplayDevices.get(i);
662 updateDisplayBlankingLocked(device);
663 }
664 }
665
666 private void updateDisplayBlankingLocked(DisplayDevice device) {
667 // Blank or unblank the display immediately to match the state requested
668 // by the power manager (if known).
669 DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
670 if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
671 switch (mAllDisplayBlankStateFromPowerManager) {
672 case DISPLAY_BLANK_STATE_BLANKED:
673 device.blankLocked();
674 break;
675 case DISPLAY_BLANK_STATE_UNBLANKED:
676 device.unblankLocked();
677 break;
Craig Mautner4f67ba62012-08-02 11:23:00 -0700678 }
Craig Mautner4f67ba62012-08-02 11:23:00 -0700679 }
680 }
681
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700682 // Adds a new logical display based on the given display device.
683 // Sends notifications if needed.
684 private void addLogicalDisplayLocked(DisplayDevice device) {
685 DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
686 boolean isDefault = (deviceInfo.flags
687 & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
688 if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) {
689 Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo);
690 isDefault = false;
691 }
692
Jeff Brown27f1d672012-10-17 18:32:34 -0700693 if (!isDefault && mSingleDisplayDemoMode) {
694 Slog.i(TAG, "Not creating a logical display for a secondary display "
695 + " because single display demo mode is enabled: " + deviceInfo);
696 return;
697 }
698
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700699 final int displayId = assignDisplayIdLocked(isDefault);
700 final int layerStack = assignLayerStackLocked(displayId);
701
Jeff Brownd728bf52012-09-08 18:05:28 -0700702 LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700703 display.updateLocked(mDisplayDevices);
704 if (!display.isValidLocked()) {
705 // This should never happen currently.
706 Slog.w(TAG, "Ignoring display device because the logical display "
707 + "created from it was not considered valid: " + deviceInfo);
708 return;
709 }
710
711 mLogicalDisplays.put(displayId, display);
712
713 // Wake up waitForDefaultDisplay.
714 if (isDefault) {
715 mSyncRoot.notifyAll();
716 }
717
718 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
719 }
720
721 private int assignDisplayIdLocked(boolean isDefault) {
722 return isDefault ? Display.DEFAULT_DISPLAY : mNextNonDefaultDisplayId++;
723 }
724
725 private int assignLayerStackLocked(int displayId) {
726 // Currently layer stacks and display ids are the same.
727 // This need not be the case.
728 return displayId;
729 }
730
731 // Updates all existing logical displays given the current set of display devices.
732 // Removes invalid logical displays.
733 // Sends notifications if needed.
734 private boolean updateLogicalDisplaysLocked() {
735 boolean changed = false;
736 for (int i = mLogicalDisplays.size(); i-- > 0; ) {
737 final int displayId = mLogicalDisplays.keyAt(i);
738 LogicalDisplay display = mLogicalDisplays.valueAt(i);
739
740 mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
741 display.updateLocked(mDisplayDevices);
742 if (!display.isValidLocked()) {
743 mLogicalDisplays.removeAt(i);
744 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
745 changed = true;
746 } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
747 sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
748 changed = true;
749 }
750 }
751 return changed;
752 }
753
754 private void performTraversalInTransactionLocked() {
Jeff Brownd728bf52012-09-08 18:05:28 -0700755 // Clear all viewports before configuring displays so that we can keep
756 // track of which ones we have configured.
757 clearViewportsLocked();
758
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700759 // Configure each display device.
760 final int count = mDisplayDevices.size();
761 for (int i = 0; i < count; i++) {
762 DisplayDevice device = mDisplayDevices.get(i);
763 configureDisplayInTransactionLocked(device);
764 device.performTraversalInTransactionLocked();
765 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700766
767 // Tell the input system about these new viewports.
Jeff Brown4ccb8232014-01-16 22:16:42 -0800768 if (mInputManagerInternal != null) {
Jeff Brownd728bf52012-09-08 18:05:28 -0700769 mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT);
770 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700771 }
772
Jeff Brown4ccb8232014-01-16 22:16:42 -0800773 private void setDisplayHasContentInternal(int displayId, boolean hasContent,
774 boolean inTraversal) {
Craig Mautner722285e2012-09-07 13:55:58 -0700775 synchronized (mSyncRoot) {
776 LogicalDisplay display = mLogicalDisplays.get(displayId);
777 if (display != null && display.hasContentLocked() != hasContent) {
Jeff Brown33041bd2013-08-02 21:11:14 -0700778 if (DEBUG) {
779 Slog.d(TAG, "Display " + displayId + " hasContent flag changed: "
780 + "hasContent=" + hasContent + ", inTraversal=" + inTraversal);
781 }
782
Craig Mautner722285e2012-09-07 13:55:58 -0700783 display.setHasContentLocked(hasContent);
Craig Mautner65d11b32012-10-01 13:59:52 -0700784 scheduleTraversalLocked(inTraversal);
Craig Mautner722285e2012-09-07 13:55:58 -0700785 }
786 }
Jeff Brownd728bf52012-09-08 18:05:28 -0700787 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700788
Jeff Brownd728bf52012-09-08 18:05:28 -0700789 private void clearViewportsLocked() {
790 mDefaultViewport.valid = false;
791 mExternalTouchViewport.valid = false;
Craig Mautner722285e2012-09-07 13:55:58 -0700792 }
793
794 private void configureDisplayInTransactionLocked(DisplayDevice device) {
Jeff Brownd14c8c92014-01-07 18:13:09 -0800795 final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
796 final boolean ownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) != 0;
Jeff Browna506a6e2013-06-04 00:02:38 -0700797
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700798 // Find the logical display that the display device is showing.
Jeff Brownd14c8c92014-01-07 18:13:09 -0800799 // Certain displays only ever show their own content.
Craig Mautner722285e2012-09-07 13:55:58 -0700800 LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
Jeff Brownd14c8c92014-01-07 18:13:09 -0800801 if (!ownContent) {
Jeff Browna506a6e2013-06-04 00:02:38 -0700802 if (display != null && !display.hasContentLocked()) {
803 // If the display does not have any content of its own, then
804 // automatically mirror the default logical display contents.
805 display = null;
806 }
807 if (display == null) {
808 display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
809 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700810 }
811
812 // Apply the logical display configuration to the display device.
813 if (display == null) {
814 // TODO: no logical display for the device, blank it
Jeff Brownd728bf52012-09-08 18:05:28 -0700815 Slog.w(TAG, "Missing logical display to use for physical display device: "
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700816 + device.getDisplayDeviceInfoLocked());
Jeff Brownd728bf52012-09-08 18:05:28 -0700817 return;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700818 }
Jeff Browna506a6e2013-06-04 00:02:38 -0700819 boolean isBlanked = (mAllDisplayBlankStateFromPowerManager == DISPLAY_BLANK_STATE_BLANKED)
820 && (info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0;
Craig Mautner0bf6ec92012-12-18 08:33:27 -0800821 display.configureDisplayInTransactionLocked(device, isBlanked);
Jeff Brownd728bf52012-09-08 18:05:28 -0700822
823 // Update the viewports if needed.
Jeff Brownd728bf52012-09-08 18:05:28 -0700824 if (!mDefaultViewport.valid
825 && (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0) {
826 setViewportLocked(mDefaultViewport, display, device);
827 }
828 if (!mExternalTouchViewport.valid
829 && info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
830 setViewportLocked(mExternalTouchViewport, display, device);
831 }
832 }
833
834 private static void setViewportLocked(DisplayViewport viewport,
835 LogicalDisplay display, DisplayDevice device) {
836 viewport.valid = true;
837 viewport.displayId = display.getDisplayIdLocked();
838 device.populateViewportLocked(viewport);
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700839 }
840
841 private LogicalDisplay findLogicalDisplayForDeviceLocked(DisplayDevice device) {
842 final int count = mLogicalDisplays.size();
843 for (int i = 0; i < count; i++) {
844 LogicalDisplay display = mLogicalDisplays.valueAt(i);
845 if (display.getPrimaryDisplayDeviceLocked() == device) {
846 return display;
847 }
848 }
849 return null;
850 }
851
Jeff Brownbd6e1502012-08-28 03:27:37 -0700852 private void sendDisplayEventLocked(int displayId, int event) {
853 Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
854 mHandler.sendMessage(msg);
855 }
856
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700857 // Requests that performTraversalsInTransactionFromWindowManager be called at a
858 // later time to apply changes to surfaces and displays.
Craig Mautner65d11b32012-10-01 13:59:52 -0700859 private void scheduleTraversalLocked(boolean inTraversal) {
Jeff Brown4ccb8232014-01-16 22:16:42 -0800860 if (!mPendingTraversal && mWindowManagerInternal != null) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700861 mPendingTraversal = true;
Craig Mautner65d11b32012-10-01 13:59:52 -0700862 if (!inTraversal) {
863 mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
864 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700865 }
866 }
867
868 // Runs on Handler thread.
869 // Delivers display event notifications to callbacks.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700870 private void deliverDisplayEvent(int displayId, int event) {
871 if (DEBUG) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700872 Slog.d(TAG, "Delivering display event: displayId="
873 + displayId + ", event=" + event);
Jeff Brownfa25bf52012-07-23 19:26:30 -0700874 }
Jeff Brownfa25bf52012-07-23 19:26:30 -0700875
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700876 // Grab the lock and copy the callbacks.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700877 final int count;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700878 synchronized (mSyncRoot) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700879 count = mCallbacks.size();
880 mTempCallbacks.clear();
881 for (int i = 0; i < count; i++) {
882 mTempCallbacks.add(mCallbacks.valueAt(i));
Craig Mautner4f67ba62012-08-02 11:23:00 -0700883 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700884 }
Craig Mautner4f67ba62012-08-02 11:23:00 -0700885
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700886 // After releasing the lock, send the notifications out.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700887 for (int i = 0; i < count; i++) {
888 mTempCallbacks.get(i).notifyDisplayEventAsync(displayId, event);
889 }
890 mTempCallbacks.clear();
Craig Mautner4f67ba62012-08-02 11:23:00 -0700891 }
892
Jeff Brown4ccb8232014-01-16 22:16:42 -0800893 private void dumpInternal(PrintWriter pw) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700894 pw.println("DISPLAY MANAGER (dumpsys display)");
Jeff Brownfa25bf52012-07-23 19:26:30 -0700895
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700896 synchronized (mSyncRoot) {
Jeff Brown9e316a12012-10-08 19:17:06 -0700897 pw.println(" mOnlyCode=" + mOnlyCore);
898 pw.println(" mSafeMode=" + mSafeMode);
899 pw.println(" mPendingTraversal=" + mPendingTraversal);
900 pw.println(" mAllDisplayBlankStateFromPowerManager="
901 + mAllDisplayBlankStateFromPowerManager);
902 pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
903 pw.println(" mDefaultViewport=" + mDefaultViewport);
904 pw.println(" mExternalTouchViewport=" + mExternalTouchViewport);
Jeff Brown27f1d672012-10-17 18:32:34 -0700905 pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
Jeff Brownce468a32013-11-21 16:42:03 -0800906 pw.println(" mWifiDisplayScanRequestCount=" + mWifiDisplayScanRequestCount);
Jeff Brown9e316a12012-10-08 19:17:06 -0700907
Jeff Brownbd6e1502012-08-28 03:27:37 -0700908 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700909 ipw.increaseIndent();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700910
911 pw.println();
912 pw.println("Display Adapters: size=" + mDisplayAdapters.size());
Jeff Brown848c2dc2012-08-19 20:18:08 -0700913 for (DisplayAdapter adapter : mDisplayAdapters) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700914 pw.println(" " + adapter.getName());
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700915 adapter.dumpLocked(ipw);
Jeff Brown848c2dc2012-08-19 20:18:08 -0700916 }
Craig Mautner9de49362012-08-02 14:30:30 -0700917
Jeff Brownbd6e1502012-08-28 03:27:37 -0700918 pw.println();
919 pw.println("Display Devices: size=" + mDisplayDevices.size());
920 for (DisplayDevice device : mDisplayDevices) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700921 pw.println(" " + device.getDisplayDeviceInfoLocked());
922 device.dumpLocked(ipw);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700923 }
924
925 final int logicalDisplayCount = mLogicalDisplays.size();
926 pw.println();
927 pw.println("Logical Displays: size=" + logicalDisplayCount);
928 for (int i = 0; i < logicalDisplayCount; i++) {
929 int displayId = mLogicalDisplays.keyAt(i);
930 LogicalDisplay display = mLogicalDisplays.valueAt(i);
931 pw.println(" Display " + displayId + ":");
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700932 display.dumpLocked(ipw);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700933 }
Jeff Brownce468a32013-11-21 16:42:03 -0800934
935 final int callbackCount = mCallbacks.size();
936 pw.println();
937 pw.println("Callbacks: size=" + callbackCount);
938 for (int i = 0; i < callbackCount; i++) {
939 CallbackRecord callback = mCallbacks.valueAt(i);
940 pw.println(" " + i + ": mPid=" + callback.mPid
941 + ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested);
942 }
Jeff Brownad9ef192014-04-08 17:26:30 -0700943
944 if (mDisplayPowerController != null) {
945 mDisplayPowerController.dump(pw);
946 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700947 }
948 }
949
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700950 /**
951 * This is the object that everything in the display manager locks on.
952 * We make it an inner class within the {@link DisplayManagerService} to so that it is
953 * clear that the object belongs to the display manager service and that it is
954 * a unique object with a special purpose.
955 */
956 public static final class SyncRoot {
957 }
958
Jeff Brownbd6e1502012-08-28 03:27:37 -0700959 private final class DisplayManagerHandler extends Handler {
960 public DisplayManagerHandler(Looper looper) {
961 super(looper, null, true /*async*/);
Jeff Brown848c2dc2012-08-19 20:18:08 -0700962 }
Jeff Brownbf5740e2012-08-19 23:20:02 -0700963
Jeff Brownbd6e1502012-08-28 03:27:37 -0700964 @Override
965 public void handleMessage(Message msg) {
966 switch (msg.what) {
967 case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER:
968 registerDefaultDisplayAdapter();
969 break;
970
971 case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
972 registerAdditionalDisplayAdapters();
973 break;
974
975 case MSG_DELIVER_DISPLAY_EVENT:
976 deliverDisplayEvent(msg.arg1, msg.arg2);
977 break;
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700978
979 case MSG_REQUEST_TRAVERSAL:
Jeff Brown4ccb8232014-01-16 22:16:42 -0800980 mWindowManagerInternal.requestTraversalFromDisplayManager();
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700981 break;
Jeff Brownd728bf52012-09-08 18:05:28 -0700982
983 case MSG_UPDATE_VIEWPORT: {
984 synchronized (mSyncRoot) {
985 mTempDefaultViewport.copyFrom(mDefaultViewport);
986 mTempExternalTouchViewport.copyFrom(mExternalTouchViewport);
987 }
Jeff Brown4ccb8232014-01-16 22:16:42 -0800988 mInputManagerInternal.setDisplayViewports(
Jeff Brownd728bf52012-09-08 18:05:28 -0700989 mTempDefaultViewport, mTempExternalTouchViewport);
990 break;
991 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700992 }
993 }
994 }
995
996 private final class DisplayAdapterListener implements DisplayAdapter.Listener {
997 @Override
998 public void onDisplayDeviceEvent(DisplayDevice device, int event) {
999 switch (event) {
1000 case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
1001 handleDisplayDeviceAdded(device);
1002 break;
1003
1004 case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
1005 handleDisplayDeviceChanged(device);
1006 break;
1007
1008 case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
1009 handleDisplayDeviceRemoved(device);
1010 break;
1011 }
1012 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001013
1014 @Override
1015 public void onTraversalRequested() {
1016 synchronized (mSyncRoot) {
Craig Mautner65d11b32012-10-01 13:59:52 -07001017 scheduleTraversalLocked(false);
Jeff Brown4ed8fe72012-08-30 18:18:29 -07001018 }
1019 }
Jeff Brownbd6e1502012-08-28 03:27:37 -07001020 }
1021
1022 private final class CallbackRecord implements DeathRecipient {
Jeff Brownce468a32013-11-21 16:42:03 -08001023 public final int mPid;
Jeff Brownbd6e1502012-08-28 03:27:37 -07001024 private final IDisplayManagerCallback mCallback;
1025
Jeff Brownce468a32013-11-21 16:42:03 -08001026 public boolean mWifiDisplayScanRequested;
1027
Jeff Brownbd6e1502012-08-28 03:27:37 -07001028 public CallbackRecord(int pid, IDisplayManagerCallback callback) {
1029 mPid = pid;
1030 mCallback = callback;
1031 }
1032
1033 @Override
1034 public void binderDied() {
1035 if (DEBUG) {
1036 Slog.d(TAG, "Display listener for pid " + mPid + " died.");
1037 }
Jeff Brownce468a32013-11-21 16:42:03 -08001038 onCallbackDied(this);
Jeff Brownbd6e1502012-08-28 03:27:37 -07001039 }
1040
1041 public void notifyDisplayEventAsync(int displayId, int event) {
1042 try {
1043 mCallback.onDisplayEvent(displayId, event);
1044 } catch (RemoteException ex) {
1045 Slog.w(TAG, "Failed to notify process "
1046 + mPid + " that displays changed, assuming it died.", ex);
1047 binderDied();
1048 }
1049 }
1050 }
Jeff Brown4ccb8232014-01-16 22:16:42 -08001051
1052 private final class BinderService extends IDisplayManager.Stub {
1053 /**
1054 * Returns information about the specified logical display.
1055 *
1056 * @param displayId The logical display id.
1057 * @return The logical display info, or null if the display does not exist. The
1058 * returned object must be treated as immutable.
1059 */
1060 @Override // Binder call
1061 public DisplayInfo getDisplayInfo(int displayId) {
1062 final int callingUid = Binder.getCallingUid();
1063 final long token = Binder.clearCallingIdentity();
1064 try {
1065 return getDisplayInfoInternal(displayId, callingUid);
1066 } finally {
1067 Binder.restoreCallingIdentity(token);
1068 }
1069 }
1070
1071 /**
1072 * Returns the list of all display ids.
1073 */
1074 @Override // Binder call
1075 public int[] getDisplayIds() {
1076 final int callingUid = Binder.getCallingUid();
1077 final long token = Binder.clearCallingIdentity();
1078 try {
1079 return getDisplayIdsInternal(callingUid);
1080 } finally {
1081 Binder.restoreCallingIdentity(token);
1082 }
1083 }
1084
1085 @Override // Binder call
1086 public void registerCallback(IDisplayManagerCallback callback) {
1087 if (callback == null) {
1088 throw new IllegalArgumentException("listener must not be null");
1089 }
1090
1091 final int callingPid = Binder.getCallingPid();
1092 final long token = Binder.clearCallingIdentity();
1093 try {
1094 registerCallbackInternal(callback, callingPid);
1095 } finally {
1096 Binder.restoreCallingIdentity(token);
1097 }
1098 }
1099
1100 @Override // Binder call
1101 public void startWifiDisplayScan() {
1102 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1103 "Permission required to start wifi display scans");
1104
1105 final int callingPid = Binder.getCallingPid();
1106 final long token = Binder.clearCallingIdentity();
1107 try {
1108 startWifiDisplayScanInternal(callingPid);
1109 } finally {
1110 Binder.restoreCallingIdentity(token);
1111 }
1112 }
1113
1114 @Override // Binder call
1115 public void stopWifiDisplayScan() {
1116 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1117 "Permission required to stop wifi display scans");
1118
1119 final int callingPid = Binder.getCallingPid();
1120 final long token = Binder.clearCallingIdentity();
1121 try {
1122 stopWifiDisplayScanInternal(callingPid);
1123 } finally {
1124 Binder.restoreCallingIdentity(token);
1125 }
1126 }
1127
1128 @Override // Binder call
1129 public void connectWifiDisplay(String address) {
1130 if (address == null) {
1131 throw new IllegalArgumentException("address must not be null");
1132 }
1133 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1134 "Permission required to connect to a wifi display");
1135
1136 final long token = Binder.clearCallingIdentity();
1137 try {
1138 connectWifiDisplayInternal(address);
1139 } finally {
1140 Binder.restoreCallingIdentity(token);
1141 }
1142 }
1143
1144 @Override // Binder call
1145 public void disconnectWifiDisplay() {
1146 // This request does not require special permissions.
1147 // Any app can request disconnection from the currently active wifi display.
1148 // This exception should no longer be needed once wifi display control moves
1149 // to the media router service.
1150
1151 final long token = Binder.clearCallingIdentity();
1152 try {
1153 disconnectWifiDisplayInternal();
1154 } finally {
1155 Binder.restoreCallingIdentity(token);
1156 }
1157 }
1158
1159 @Override // Binder call
1160 public void renameWifiDisplay(String address, String alias) {
1161 if (address == null) {
1162 throw new IllegalArgumentException("address must not be null");
1163 }
1164 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1165 "Permission required to rename to a wifi display");
1166
1167 final long token = Binder.clearCallingIdentity();
1168 try {
1169 renameWifiDisplayInternal(address, alias);
1170 } finally {
1171 Binder.restoreCallingIdentity(token);
1172 }
1173 }
1174
1175 @Override // Binder call
1176 public void forgetWifiDisplay(String address) {
1177 if (address == null) {
1178 throw new IllegalArgumentException("address must not be null");
1179 }
1180 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1181 "Permission required to forget to a wifi display");
1182
1183 final long token = Binder.clearCallingIdentity();
1184 try {
1185 forgetWifiDisplayInternal(address);
1186 } finally {
1187 Binder.restoreCallingIdentity(token);
1188 }
1189 }
1190
1191 @Override // Binder call
1192 public void pauseWifiDisplay() {
1193 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1194 "Permission required to pause a wifi display session");
1195
1196 final long token = Binder.clearCallingIdentity();
1197 try {
1198 pauseWifiDisplayInternal();
1199 } finally {
1200 Binder.restoreCallingIdentity(token);
1201 }
1202 }
1203
1204 @Override // Binder call
1205 public void resumeWifiDisplay() {
1206 mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY,
1207 "Permission required to resume a wifi display session");
1208
1209 final long token = Binder.clearCallingIdentity();
1210 try {
1211 resumeWifiDisplayInternal();
1212 } finally {
1213 Binder.restoreCallingIdentity(token);
1214 }
1215 }
1216
1217 @Override // Binder call
1218 public WifiDisplayStatus getWifiDisplayStatus() {
1219 // This request does not require special permissions.
1220 // Any app can get information about available wifi displays.
1221
1222 final long token = Binder.clearCallingIdentity();
1223 try {
1224 return getWifiDisplayStatusInternal();
1225 } finally {
1226 Binder.restoreCallingIdentity(token);
1227 }
1228 }
1229
1230 @Override // Binder call
1231 public int createVirtualDisplay(IBinder appToken, String packageName,
1232 String name, int width, int height, int densityDpi, Surface surface, int flags) {
1233 final int callingUid = Binder.getCallingUid();
1234 if (!validatePackageName(callingUid, packageName)) {
1235 throw new SecurityException("packageName must match the calling uid");
1236 }
1237 if (appToken == null) {
1238 throw new IllegalArgumentException("appToken must not be null");
1239 }
1240 if (TextUtils.isEmpty(name)) {
1241 throw new IllegalArgumentException("name must be non-null and non-empty");
1242 }
1243 if (width <= 0 || height <= 0 || densityDpi <= 0) {
1244 throw new IllegalArgumentException("width, height, and densityDpi must be "
1245 + "greater than 0");
1246 }
1247 if (surface == null) {
1248 throw new IllegalArgumentException("surface must not be null");
1249 }
1250 if (callingUid != Process.SYSTEM_UID &&
1251 (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
1252 if (mContext.checkCallingPermission(android.Manifest.permission.CAPTURE_VIDEO_OUTPUT)
1253 != PackageManager.PERMISSION_GRANTED
1254 && mContext.checkCallingPermission(
1255 android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT)
1256 != PackageManager.PERMISSION_GRANTED) {
1257 throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
1258 + "CAPTURE_SECURE_VIDEO_OUTPUT permission to create a "
1259 + "public virtual display.");
1260 }
1261 }
1262 if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
1263 if (mContext.checkCallingPermission(
1264 android.Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT)
1265 != PackageManager.PERMISSION_GRANTED) {
1266 throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT "
1267 + "to create a secure virtual display.");
1268 }
1269 }
1270
1271 final long token = Binder.clearCallingIdentity();
1272 try {
1273 return createVirtualDisplayInternal(appToken, callingUid, packageName,
1274 name, width, height, densityDpi, surface, flags);
1275 } finally {
1276 Binder.restoreCallingIdentity(token);
1277 }
1278 }
1279
1280 @Override // Binder call
1281 public void releaseVirtualDisplay(IBinder appToken) {
1282 final long token = Binder.clearCallingIdentity();
1283 try {
1284 releaseVirtualDisplayInternal(appToken);
1285 } finally {
1286 Binder.restoreCallingIdentity(token);
1287 }
1288 }
1289
1290 @Override // Binder call
1291 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
1292 if (mContext == null
1293 || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
1294 != PackageManager.PERMISSION_GRANTED) {
1295 pw.println("Permission Denial: can't dump DisplayManager from from pid="
1296 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
1297 return;
1298 }
1299
1300 final long token = Binder.clearCallingIdentity();
1301 try {
1302 dumpInternal(pw);
1303 } finally {
1304 Binder.restoreCallingIdentity(token);
1305 }
1306 }
1307
1308 private boolean validatePackageName(int uid, String packageName) {
1309 if (packageName != null) {
1310 String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
1311 if (packageNames != null) {
1312 for (String n : packageNames) {
1313 if (n.equals(packageName)) {
1314 return true;
1315 }
1316 }
1317 }
1318 }
1319 return false;
1320 }
1321 }
1322
1323 private final class LocalService extends DisplayManagerInternal {
1324 @Override
Jeff Brownad9ef192014-04-08 17:26:30 -07001325 public void initPowerManagement(DisplayPowerCallbacks callbacks, Handler handler,
1326 SensorManager sensorManager) {
1327 synchronized (mSyncRoot) {
1328 mDisplayPowerController = new DisplayPowerController(
1329 mContext, callbacks, handler, sensorManager);
1330 }
1331 }
1332
1333 @Override
1334 public boolean requestPowerState(DisplayPowerRequest request,
1335 boolean waitForNegativeProximity) {
1336 return mDisplayPowerController.requestPowerState(request,
1337 waitForNegativeProximity);
1338 }
1339
1340 @Override
1341 public boolean isProximitySensorAvailable() {
1342 return mDisplayPowerController.isProximitySensorAvailable();
1343 }
1344
1345 @Override
Jeff Brown4ccb8232014-01-16 22:16:42 -08001346 public void blankAllDisplaysFromPowerManager() {
1347 blankAllDisplaysFromPowerManagerInternal();
1348 }
1349
1350 @Override
1351 public void unblankAllDisplaysFromPowerManager() {
1352 unblankAllDisplaysFromPowerManagerInternal();
1353 }
1354
1355 @Override
1356 public DisplayInfo getDisplayInfo(int displayId) {
1357 return getDisplayInfoInternal(displayId, Process.myUid());
1358 }
1359
1360 @Override
1361 public void registerDisplayTransactionListener(DisplayTransactionListener listener) {
1362 if (listener == null) {
1363 throw new IllegalArgumentException("listener must not be null");
1364 }
1365
1366 registerDisplayTransactionListenerInternal(listener);
1367 }
1368
1369 @Override
1370 public void unregisterDisplayTransactionListener(DisplayTransactionListener listener) {
1371 if (listener == null) {
1372 throw new IllegalArgumentException("listener must not be null");
1373 }
1374
1375 unregisterDisplayTransactionListenerInternal(listener);
1376 }
1377
1378 @Override
1379 public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) {
1380 setDisplayInfoOverrideFromWindowManagerInternal(displayId, info);
1381 }
1382
1383 @Override
1384 public void performTraversalInTransactionFromWindowManager() {
1385 performTraversalInTransactionFromWindowManagerInternal();
1386 }
1387
1388 @Override
1389 public void setDisplayHasContent(int displayId, boolean hasContent, boolean inTraversal) {
1390 setDisplayHasContentInternal(displayId, hasContent, inTraversal);
1391 }
1392 }
Jeff Brownfa25bf52012-07-23 19:26:30 -07001393}