blob: bf4cc1d826a93036e4b4719e5b13952a4eac9aff [file] [log] [blame]
Jeff Brownbd6e1502012-08-28 03:27:37 -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 android.hardware.display;
18
19import android.content.Context;
Kenny Guy22bd0442017-10-26 00:15:54 +010020import android.content.pm.ParceledListSlice;
Bryce Lee609bf652017-02-09 16:50:13 -080021import android.content.res.Resources;
Michael Wrighteedcbf12017-08-16 23:14:54 +010022import android.graphics.Point;
Jeff Brownbd6e1502012-08-28 03:27:37 -070023import android.hardware.display.DisplayManager.DisplayListener;
Michael Wrightc39d47a2014-07-08 18:07:36 -070024import android.media.projection.IMediaProjection;
Santos Cordonee8931e2017-04-05 10:31:15 -070025import android.media.projection.MediaProjection;
Jeff Brownbd6e1502012-08-28 03:27:37 -070026import android.os.Handler;
27import android.os.IBinder;
28import android.os.Looper;
29import android.os.Message;
30import android.os.RemoteException;
31import android.os.ServiceManager;
Jeff Browna506a6e2013-06-04 00:02:38 -070032import android.text.TextUtils;
Jeff Brownbd6e1502012-08-28 03:27:37 -070033import android.util.Log;
34import android.util.SparseArray;
Jeff Brownbd6e1502012-08-28 03:27:37 -070035import android.view.Display;
Santos Cordonee8931e2017-04-05 10:31:15 -070036import android.view.DisplayAdjustments;
Jeff Brownbd6e1502012-08-28 03:27:37 -070037import android.view.DisplayInfo;
Jeff Browna506a6e2013-06-04 00:02:38 -070038import android.view.Surface;
Jeff Brownbd6e1502012-08-28 03:27:37 -070039
40import java.util.ArrayList;
Kenny Guy22bd0442017-10-26 00:15:54 +010041import java.util.Collections;
42import java.util.List;
Jeff Brownbd6e1502012-08-28 03:27:37 -070043
44/**
45 * Manager communication with the display manager service on behalf of
46 * an application process. You're probably looking for {@link DisplayManager}.
47 *
48 * @hide
49 */
50public final class DisplayManagerGlobal {
51 private static final String TAG = "DisplayManager";
52 private static final boolean DEBUG = false;
53
Jeff Brown4ed8fe72012-08-30 18:18:29 -070054 // True if display info and display ids should be cached.
55 //
56 // FIXME: The cache is currently disabled because it's unclear whether we have the
57 // necessary guarantees that the caches will always be flushed before clients
58 // attempt to observe their new state. For example, depending on the order
59 // in which the binder transactions take place, we might have a problem where
60 // an application could start processing a configuration change due to a display
61 // orientation change before the display info cache has actually been invalidated.
62 private static final boolean USE_CACHE = false;
63
Jeff Brownbd6e1502012-08-28 03:27:37 -070064 public static final int EVENT_DISPLAY_ADDED = 1;
65 public static final int EVENT_DISPLAY_CHANGED = 2;
66 public static final int EVENT_DISPLAY_REMOVED = 3;
67
68 private static DisplayManagerGlobal sInstance;
69
70 private final Object mLock = new Object();
71
72 private final IDisplayManager mDm;
73
74 private DisplayManagerCallback mCallback;
75 private final ArrayList<DisplayListenerDelegate> mDisplayListeners =
76 new ArrayList<DisplayListenerDelegate>();
77
78 private final SparseArray<DisplayInfo> mDisplayInfoCache = new SparseArray<DisplayInfo>();
79 private int[] mDisplayIdCache;
80
Jeff Brownce468a32013-11-21 16:42:03 -080081 private int mWifiDisplayScanNestCount;
82
Jeff Brownbd6e1502012-08-28 03:27:37 -070083 private DisplayManagerGlobal(IDisplayManager dm) {
84 mDm = dm;
85 }
86
87 /**
88 * Gets an instance of the display manager global singleton.
89 *
90 * @return The display manager instance, may be null early in system startup
91 * before the display manager has been fully initialized.
92 */
93 public static DisplayManagerGlobal getInstance() {
94 synchronized (DisplayManagerGlobal.class) {
95 if (sInstance == null) {
96 IBinder b = ServiceManager.getService(Context.DISPLAY_SERVICE);
97 if (b != null) {
98 sInstance = new DisplayManagerGlobal(IDisplayManager.Stub.asInterface(b));
99 }
100 }
101 return sInstance;
102 }
103 }
104
105 /**
106 * Get information about a particular logical display.
107 *
108 * @param displayId The logical display id.
109 * @return Information about the specified display, or null if it does not exist.
110 * This object belongs to an internal cache and should be treated as if it were immutable.
111 */
112 public DisplayInfo getDisplayInfo(int displayId) {
113 try {
114 synchronized (mLock) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700115 DisplayInfo info;
116 if (USE_CACHE) {
117 info = mDisplayInfoCache.get(displayId);
118 if (info != null) {
119 return info;
120 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700121 }
122
123 info = mDm.getDisplayInfo(displayId);
124 if (info == null) {
125 return null;
126 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700127
128 if (USE_CACHE) {
129 mDisplayInfoCache.put(displayId, info);
130 }
131 registerCallbackIfNeededLocked();
132
Jeff Brownbd6e1502012-08-28 03:27:37 -0700133 if (DEBUG) {
134 Log.d(TAG, "getDisplayInfo: displayId=" + displayId + ", info=" + info);
135 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700136 return info;
137 }
138 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700139 throw ex.rethrowFromSystemServer();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700140 }
141 }
142
143 /**
144 * Gets all currently valid logical display ids.
145 *
146 * @return An array containing all display ids.
147 */
148 public int[] getDisplayIds() {
149 try {
150 synchronized (mLock) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700151 if (USE_CACHE) {
152 if (mDisplayIdCache != null) {
153 return mDisplayIdCache;
154 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700155 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700156
157 int[] displayIds = mDm.getDisplayIds();
158 if (USE_CACHE) {
159 mDisplayIdCache = displayIds;
160 }
161 registerCallbackIfNeededLocked();
162 return displayIds;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700163 }
164 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700165 throw ex.rethrowFromSystemServer();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700166 }
167 }
168
169 /**
170 * Gets information about a logical display.
171 *
172 * The display metrics may be adjusted to provide compatibility
Craig Mautner48d0d182013-06-11 07:53:06 -0700173 * for legacy applications or limited screen areas.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700174 *
175 * @param displayId The logical display id.
Craig Mautner48d0d182013-06-11 07:53:06 -0700176 * @param daj The compatibility info and activityToken.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700177 * @return The display object, or null if there is no display with the given id.
178 */
Craig Mautner48d0d182013-06-11 07:53:06 -0700179 public Display getCompatibleDisplay(int displayId, DisplayAdjustments daj) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700180 DisplayInfo displayInfo = getDisplayInfo(displayId);
181 if (displayInfo == null) {
182 return null;
183 }
Craig Mautner48d0d182013-06-11 07:53:06 -0700184 return new Display(this, displayId, displayInfo, daj);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700185 }
186
187 /**
Bryce Lee609bf652017-02-09 16:50:13 -0800188 * Gets information about a logical display.
189 *
190 * The display metrics may be adjusted to provide compatibility
191 * for legacy applications or limited screen areas.
192 *
193 * @param displayId The logical display id.
194 * @param resources Resources providing compatibility info.
195 * @return The display object, or null if there is no display with the given id.
196 */
197 public Display getCompatibleDisplay(int displayId, Resources resources) {
198 DisplayInfo displayInfo = getDisplayInfo(displayId);
199 if (displayInfo == null) {
200 return null;
201 }
202 return new Display(this, displayId, displayInfo, resources);
203 }
204
205 /**
Jeff Brownbd6e1502012-08-28 03:27:37 -0700206 * Gets information about a logical display without applying any compatibility metrics.
207 *
208 * @param displayId The logical display id.
209 * @return The display object, or null if there is no display with the given id.
210 */
211 public Display getRealDisplay(int displayId) {
Craig Mautner48d0d182013-06-11 07:53:06 -0700212 return getCompatibleDisplay(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
213 }
214
Jeff Brownbd6e1502012-08-28 03:27:37 -0700215 public void registerDisplayListener(DisplayListener listener, Handler handler) {
216 if (listener == null) {
217 throw new IllegalArgumentException("listener must not be null");
218 }
219
220 synchronized (mLock) {
221 int index = findDisplayListenerLocked(listener);
222 if (index < 0) {
223 mDisplayListeners.add(new DisplayListenerDelegate(listener, handler));
224 registerCallbackIfNeededLocked();
225 }
226 }
227 }
228
229 public void unregisterDisplayListener(DisplayListener listener) {
230 if (listener == null) {
231 throw new IllegalArgumentException("listener must not be null");
232 }
233
234 synchronized (mLock) {
235 int index = findDisplayListenerLocked(listener);
236 if (index >= 0) {
237 DisplayListenerDelegate d = mDisplayListeners.get(index);
238 d.clearEvents();
239 mDisplayListeners.remove(index);
240 }
241 }
242 }
243
244 private int findDisplayListenerLocked(DisplayListener listener) {
245 final int numListeners = mDisplayListeners.size();
246 for (int i = 0; i < numListeners; i++) {
247 if (mDisplayListeners.get(i).mListener == listener) {
248 return i;
249 }
250 }
251 return -1;
252 }
253
254 private void registerCallbackIfNeededLocked() {
255 if (mCallback == null) {
256 mCallback = new DisplayManagerCallback();
257 try {
258 mDm.registerCallback(mCallback);
259 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700260 throw ex.rethrowFromSystemServer();
Jeff Brownbd6e1502012-08-28 03:27:37 -0700261 }
262 }
263 }
264
265 private void handleDisplayEvent(int displayId, int event) {
266 synchronized (mLock) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700267 if (USE_CACHE) {
268 mDisplayInfoCache.remove(displayId);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700269
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700270 if (event == EVENT_DISPLAY_ADDED || event == EVENT_DISPLAY_REMOVED) {
271 mDisplayIdCache = null;
272 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700273 }
274
275 final int numListeners = mDisplayListeners.size();
276 for (int i = 0; i < numListeners; i++) {
277 mDisplayListeners.get(i).sendDisplayEvent(displayId, event);
278 }
279 }
280 }
281
Jeff Brownce468a32013-11-21 16:42:03 -0800282 public void startWifiDisplayScan() {
283 synchronized (mLock) {
284 if (mWifiDisplayScanNestCount++ == 0) {
285 registerCallbackIfNeededLocked();
286 try {
287 mDm.startWifiDisplayScan();
288 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700289 throw ex.rethrowFromSystemServer();
Jeff Brownce468a32013-11-21 16:42:03 -0800290 }
291 }
292 }
293 }
294
295 public void stopWifiDisplayScan() {
296 synchronized (mLock) {
297 if (--mWifiDisplayScanNestCount == 0) {
298 try {
299 mDm.stopWifiDisplayScan();
300 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700301 throw ex.rethrowFromSystemServer();
Jeff Brownce468a32013-11-21 16:42:03 -0800302 }
303 } else if (mWifiDisplayScanNestCount < 0) {
304 Log.wtf(TAG, "Wifi display scan nest count became negative: "
305 + mWifiDisplayScanNestCount);
306 mWifiDisplayScanNestCount = 0;
307 }
Jeff Browne08ae382012-09-07 20:36:36 -0700308 }
309 }
310
311 public void connectWifiDisplay(String deviceAddress) {
312 if (deviceAddress == null) {
313 throw new IllegalArgumentException("deviceAddress must not be null");
314 }
315
316 try {
317 mDm.connectWifiDisplay(deviceAddress);
318 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700319 throw ex.rethrowFromSystemServer();
Jeff Browne08ae382012-09-07 20:36:36 -0700320 }
321 }
322
Chong Zhang1f3ecaa2013-05-03 15:55:36 -0700323 public void pauseWifiDisplay() {
324 try {
325 mDm.pauseWifiDisplay();
326 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700327 throw ex.rethrowFromSystemServer();
Chong Zhang1f3ecaa2013-05-03 15:55:36 -0700328 }
329 }
330
331 public void resumeWifiDisplay() {
332 try {
333 mDm.resumeWifiDisplay();
334 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700335 throw ex.rethrowFromSystemServer();
Chong Zhang1f3ecaa2013-05-03 15:55:36 -0700336 }
337 }
338
Jeff Browne08ae382012-09-07 20:36:36 -0700339 public void disconnectWifiDisplay() {
340 try {
341 mDm.disconnectWifiDisplay();
342 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700343 throw ex.rethrowFromSystemServer();
Jeff Browne08ae382012-09-07 20:36:36 -0700344 }
345 }
346
Jeff Brown89d55462012-09-19 11:33:42 -0700347 public void renameWifiDisplay(String deviceAddress, String alias) {
348 if (deviceAddress == null) {
349 throw new IllegalArgumentException("deviceAddress must not be null");
350 }
351
352 try {
353 mDm.renameWifiDisplay(deviceAddress, alias);
354 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700355 throw ex.rethrowFromSystemServer();
Jeff Brown89d55462012-09-19 11:33:42 -0700356 }
357 }
358
359 public void forgetWifiDisplay(String deviceAddress) {
360 if (deviceAddress == null) {
361 throw new IllegalArgumentException("deviceAddress must not be null");
362 }
363
364 try {
365 mDm.forgetWifiDisplay(deviceAddress);
366 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700367 throw ex.rethrowFromSystemServer();
Jeff Brown89d55462012-09-19 11:33:42 -0700368 }
369 }
370
Jeff Browne08ae382012-09-07 20:36:36 -0700371 public WifiDisplayStatus getWifiDisplayStatus() {
372 try {
373 return mDm.getWifiDisplayStatus();
374 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700375 throw ex.rethrowFromSystemServer();
Jeff Browne08ae382012-09-07 20:36:36 -0700376 }
377 }
378
Michael Wright1c9977b2016-07-12 13:30:10 -0700379 public void requestColorMode(int displayId, int colorMode) {
Michael Wright58e829f2015-09-15 00:13:26 +0100380 try {
Michael Wright1c9977b2016-07-12 13:30:10 -0700381 mDm.requestColorMode(displayId, colorMode);
Michael Wright58e829f2015-09-15 00:13:26 +0100382 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700383 throw ex.rethrowFromSystemServer();
Michael Wright58e829f2015-09-15 00:13:26 +0100384 }
385 }
386
Michael Wrightc39d47a2014-07-08 18:07:36 -0700387 public VirtualDisplay createVirtualDisplay(Context context, MediaProjection projection,
388 String name, int width, int height, int densityDpi, Surface surface, int flags,
Santos Cordonee8931e2017-04-05 10:31:15 -0700389 VirtualDisplay.Callback callback, Handler handler, String uniqueId) {
Jeff Browna506a6e2013-06-04 00:02:38 -0700390 if (TextUtils.isEmpty(name)) {
391 throw new IllegalArgumentException("name must be non-null and non-empty");
392 }
393 if (width <= 0 || height <= 0 || densityDpi <= 0) {
394 throw new IllegalArgumentException("width, height, and densityDpi must be "
395 + "greater than 0");
396 }
Jeff Browna506a6e2013-06-04 00:02:38 -0700397
Michael Wright75ee9fc2014-09-01 19:55:22 -0700398 VirtualDisplayCallback callbackWrapper = new VirtualDisplayCallback(callback, handler);
Michael Wrightc39d47a2014-07-08 18:07:36 -0700399 IMediaProjection projectionToken = projection != null ? projection.getProjection() : null;
Jeff Browna506a6e2013-06-04 00:02:38 -0700400 int displayId;
401 try {
Michael Wrightc39d47a2014-07-08 18:07:36 -0700402 displayId = mDm.createVirtualDisplay(callbackWrapper, projectionToken,
Santos Cordonee8931e2017-04-05 10:31:15 -0700403 context.getPackageName(), name, width, height, densityDpi, surface, flags,
404 uniqueId);
Jeff Browna506a6e2013-06-04 00:02:38 -0700405 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700406 throw ex.rethrowFromSystemServer();
Jeff Browna506a6e2013-06-04 00:02:38 -0700407 }
408 if (displayId < 0) {
Jeff Brown7d00aff2013-08-02 19:03:49 -0700409 Log.e(TAG, "Could not create virtual display: " + name);
Jeff Browna506a6e2013-06-04 00:02:38 -0700410 return null;
411 }
412 Display display = getRealDisplay(displayId);
413 if (display == null) {
414 Log.wtf(TAG, "Could not obtain display info for newly created "
Jeff Brown7d00aff2013-08-02 19:03:49 -0700415 + "virtual display: " + name);
Jeff Browna506a6e2013-06-04 00:02:38 -0700416 try {
Michael Wrightc39d47a2014-07-08 18:07:36 -0700417 mDm.releaseVirtualDisplay(callbackWrapper);
Jeff Browna506a6e2013-06-04 00:02:38 -0700418 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700419 throw ex.rethrowFromSystemServer();
Jeff Browna506a6e2013-06-04 00:02:38 -0700420 }
421 return null;
422 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700423 return new VirtualDisplay(this, display, callbackWrapper, surface);
Jeff Brown92207df2014-04-16 13:16:07 -0700424 }
425
Michael Wright75ee9fc2014-09-01 19:55:22 -0700426 public void setVirtualDisplaySurface(IVirtualDisplayCallback token, Surface surface) {
Jeff Brown92207df2014-04-16 13:16:07 -0700427 try {
428 mDm.setVirtualDisplaySurface(token, surface);
429 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700430 throw ex.rethrowFromSystemServer();
Jeff Brown92207df2014-04-16 13:16:07 -0700431 }
Jeff Browna506a6e2013-06-04 00:02:38 -0700432 }
433
Michael Wright75ee9fc2014-09-01 19:55:22 -0700434 public void resizeVirtualDisplay(IVirtualDisplayCallback token,
Michael Wright01e840f2014-06-26 16:03:25 -0700435 int width, int height, int densityDpi) {
436 try {
437 mDm.resizeVirtualDisplay(token, width, height, densityDpi);
438 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700439 throw ex.rethrowFromSystemServer();
Michael Wright01e840f2014-06-26 16:03:25 -0700440 }
441 }
442
Michael Wright75ee9fc2014-09-01 19:55:22 -0700443 public void releaseVirtualDisplay(IVirtualDisplayCallback token) {
Jeff Browna506a6e2013-06-04 00:02:38 -0700444 try {
445 mDm.releaseVirtualDisplay(token);
446 } catch (RemoteException ex) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700447 throw ex.rethrowFromSystemServer();
Jeff Browna506a6e2013-06-04 00:02:38 -0700448 }
449 }
450
Michael Wrighteedcbf12017-08-16 23:14:54 +0100451 /**
452 * Gets the stable device display size, in pixels.
453 */
454 public Point getStableDisplaySize() {
455 try {
456 return mDm.getStableDisplaySize();
457 } catch (RemoteException ex) {
458 throw ex.rethrowFromSystemServer();
459 }
460 }
461
Kenny Guy22bd0442017-10-26 00:15:54 +0100462 /**
463 * Retrieves brightness change events.
464 */
Kenny Guy29aa30e2017-11-30 13:43:46 +0000465 public List<BrightnessChangeEvent> getBrightnessEvents(String callingPackage) {
Kenny Guy22bd0442017-10-26 00:15:54 +0100466 try {
Kenny Guy29aa30e2017-11-30 13:43:46 +0000467 ParceledListSlice<BrightnessChangeEvent> events =
468 mDm.getBrightnessEvents(callingPackage);
Kenny Guy22bd0442017-10-26 00:15:54 +0100469 if (events == null) {
470 return Collections.emptyList();
471 }
472 return events.getList();
473 } catch (RemoteException ex) {
474 throw ex.rethrowFromSystemServer();
475 }
476 }
477
478 /**
479 * Set brightness but don't add a BrightnessChangeEvent
480 * STOPSHIP remove when adaptive brightness accepts curves.
481 */
482 public void setBrightness(int brightness) {
483 try {
484 mDm.setBrightness(brightness);
485 } catch (RemoteException ex) {
486 throw ex.rethrowFromSystemServer();
487 }
488 }
489
Michael Wrighteef0e132017-11-21 17:57:52 +0000490 /**
491 * Sets the global brightness configuration for a given user.
492 *
493 * @hide
494 */
495 public void setBrightnessConfigurationForUser(BrightnessConfiguration c, int userId) {
496 try {
497 mDm.setBrightnessConfigurationForUser(c, userId);
498 } catch (RemoteException ex) {
499 throw ex.rethrowFromSystemServer();
500 }
501 }
502
Jeff Brownbd6e1502012-08-28 03:27:37 -0700503 private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub {
504 @Override
505 public void onDisplayEvent(int displayId, int event) {
506 if (DEBUG) {
507 Log.d(TAG, "onDisplayEvent: displayId=" + displayId + ", event=" + event);
508 }
509 handleDisplayEvent(displayId, event);
510 }
511 }
512
513 private static final class DisplayListenerDelegate extends Handler {
514 public final DisplayListener mListener;
515
516 public DisplayListenerDelegate(DisplayListener listener, Handler handler) {
517 super(handler != null ? handler.getLooper() : Looper.myLooper(), null, true /*async*/);
518 mListener = listener;
519 }
520
521 public void sendDisplayEvent(int displayId, int event) {
522 Message msg = obtainMessage(event, displayId, 0);
523 sendMessage(msg);
524 }
525
526 public void clearEvents() {
527 removeCallbacksAndMessages(null);
528 }
529
530 @Override
531 public void handleMessage(Message msg) {
532 switch (msg.what) {
533 case EVENT_DISPLAY_ADDED:
534 mListener.onDisplayAdded(msg.arg1);
535 break;
536 case EVENT_DISPLAY_CHANGED:
537 mListener.onDisplayChanged(msg.arg1);
538 break;
539 case EVENT_DISPLAY_REMOVED:
540 mListener.onDisplayRemoved(msg.arg1);
541 break;
542 }
543 }
544 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700545
Michael Wright75ee9fc2014-09-01 19:55:22 -0700546 private final static class VirtualDisplayCallback extends IVirtualDisplayCallback.Stub {
547 private VirtualDisplayCallbackDelegate mDelegate;
Michael Wrightc39d47a2014-07-08 18:07:36 -0700548
Michael Wright75ee9fc2014-09-01 19:55:22 -0700549 public VirtualDisplayCallback(VirtualDisplay.Callback callback, Handler handler) {
550 if (callback != null) {
551 mDelegate = new VirtualDisplayCallbackDelegate(callback, handler);
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700552 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700553 }
554
555 @Override // Binder call
Michael Wright75ee9fc2014-09-01 19:55:22 -0700556 public void onPaused() {
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700557 if (mDelegate != null) {
Michael Wright75ee9fc2014-09-01 19:55:22 -0700558 mDelegate.sendEmptyMessage(VirtualDisplayCallbackDelegate.MSG_DISPLAY_PAUSED);
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700559 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700560 }
561
562 @Override // Binder call
Michael Wright75ee9fc2014-09-01 19:55:22 -0700563 public void onResumed() {
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700564 if (mDelegate != null) {
Michael Wright75ee9fc2014-09-01 19:55:22 -0700565 mDelegate.sendEmptyMessage(VirtualDisplayCallbackDelegate.MSG_DISPLAY_RESUMED);
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700566 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700567 }
568
569 @Override // Binder call
Michael Wright75ee9fc2014-09-01 19:55:22 -0700570 public void onStopped() {
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700571 if (mDelegate != null) {
Michael Wright75ee9fc2014-09-01 19:55:22 -0700572 mDelegate.sendEmptyMessage(VirtualDisplayCallbackDelegate.MSG_DISPLAY_STOPPED);
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700573 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700574 }
575 }
576
Michael Wright75ee9fc2014-09-01 19:55:22 -0700577 private final static class VirtualDisplayCallbackDelegate extends Handler {
Michael Wrightc39d47a2014-07-08 18:07:36 -0700578 public static final int MSG_DISPLAY_PAUSED = 0;
579 public static final int MSG_DISPLAY_RESUMED = 1;
580 public static final int MSG_DISPLAY_STOPPED = 2;
581
Michael Wright75ee9fc2014-09-01 19:55:22 -0700582 private final VirtualDisplay.Callback mCallback;
Michael Wrightc39d47a2014-07-08 18:07:36 -0700583
Michael Wright75ee9fc2014-09-01 19:55:22 -0700584 public VirtualDisplayCallbackDelegate(VirtualDisplay.Callback callback,
Michael Wrightc39d47a2014-07-08 18:07:36 -0700585 Handler handler) {
586 super(handler != null ? handler.getLooper() : Looper.myLooper(), null, true /*async*/);
Michael Wright75ee9fc2014-09-01 19:55:22 -0700587 mCallback = callback;
Michael Wrightc39d47a2014-07-08 18:07:36 -0700588 }
589
590 @Override
591 public void handleMessage(Message msg) {
Michael Wrightc39d47a2014-07-08 18:07:36 -0700592 switch (msg.what) {
593 case MSG_DISPLAY_PAUSED:
Michael Wright75ee9fc2014-09-01 19:55:22 -0700594 mCallback.onPaused();
Michael Wrightc39d47a2014-07-08 18:07:36 -0700595 break;
596 case MSG_DISPLAY_RESUMED:
Michael Wright75ee9fc2014-09-01 19:55:22 -0700597 mCallback.onResumed();
Michael Wrightc39d47a2014-07-08 18:07:36 -0700598 break;
599 case MSG_DISPLAY_STOPPED:
Michael Wright75ee9fc2014-09-01 19:55:22 -0700600 mCallback.onStopped();
Michael Wrightc39d47a2014-07-08 18:07:36 -0700601 break;
602 }
603 }
604 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700605}