blob: 121a187b3639f70ee786417f19a19290b09602bd [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;
Wale Ogunwale7c726682015-02-06 17:34:28 -080020import android.content.res.Configuration;
Jeff Brownbd6e1502012-08-28 03:27:37 -070021import android.hardware.display.DisplayManager.DisplayListener;
Michael Wrightc39d47a2014-07-08 18:07:36 -070022import android.media.projection.MediaProjection;
23import android.media.projection.IMediaProjection;
Jeff Brownbd6e1502012-08-28 03:27:37 -070024import android.os.Handler;
25import android.os.IBinder;
26import android.os.Looper;
27import android.os.Message;
28import android.os.RemoteException;
29import android.os.ServiceManager;
Jeff Browna506a6e2013-06-04 00:02:38 -070030import android.text.TextUtils;
Jeff Brownbd6e1502012-08-28 03:27:37 -070031import android.util.Log;
32import android.util.SparseArray;
Craig Mautner48d0d182013-06-11 07:53:06 -070033import android.view.DisplayAdjustments;
Jeff Brownbd6e1502012-08-28 03:27:37 -070034import android.view.Display;
35import android.view.DisplayInfo;
Jeff Browna506a6e2013-06-04 00:02:38 -070036import android.view.Surface;
Jeff Brownbd6e1502012-08-28 03:27:37 -070037
38import java.util.ArrayList;
39
40/**
41 * Manager communication with the display manager service on behalf of
42 * an application process. You're probably looking for {@link DisplayManager}.
43 *
44 * @hide
45 */
46public final class DisplayManagerGlobal {
47 private static final String TAG = "DisplayManager";
48 private static final boolean DEBUG = false;
49
Jeff Brown4ed8fe72012-08-30 18:18:29 -070050 // True if display info and display ids should be cached.
51 //
52 // FIXME: The cache is currently disabled because it's unclear whether we have the
53 // necessary guarantees that the caches will always be flushed before clients
54 // attempt to observe their new state. For example, depending on the order
55 // in which the binder transactions take place, we might have a problem where
56 // an application could start processing a configuration change due to a display
57 // orientation change before the display info cache has actually been invalidated.
58 private static final boolean USE_CACHE = false;
59
Jeff Brownbd6e1502012-08-28 03:27:37 -070060 public static final int EVENT_DISPLAY_ADDED = 1;
61 public static final int EVENT_DISPLAY_CHANGED = 2;
62 public static final int EVENT_DISPLAY_REMOVED = 3;
63
64 private static DisplayManagerGlobal sInstance;
65
66 private final Object mLock = new Object();
67
68 private final IDisplayManager mDm;
69
70 private DisplayManagerCallback mCallback;
71 private final ArrayList<DisplayListenerDelegate> mDisplayListeners =
72 new ArrayList<DisplayListenerDelegate>();
73
74 private final SparseArray<DisplayInfo> mDisplayInfoCache = new SparseArray<DisplayInfo>();
75 private int[] mDisplayIdCache;
76
Jeff Brownce468a32013-11-21 16:42:03 -080077 private int mWifiDisplayScanNestCount;
78
Jeff Brownbd6e1502012-08-28 03:27:37 -070079 private DisplayManagerGlobal(IDisplayManager dm) {
80 mDm = dm;
81 }
82
83 /**
84 * Gets an instance of the display manager global singleton.
85 *
86 * @return The display manager instance, may be null early in system startup
87 * before the display manager has been fully initialized.
88 */
89 public static DisplayManagerGlobal getInstance() {
90 synchronized (DisplayManagerGlobal.class) {
91 if (sInstance == null) {
92 IBinder b = ServiceManager.getService(Context.DISPLAY_SERVICE);
93 if (b != null) {
94 sInstance = new DisplayManagerGlobal(IDisplayManager.Stub.asInterface(b));
95 }
96 }
97 return sInstance;
98 }
99 }
100
101 /**
102 * Get information about a particular logical display.
103 *
104 * @param displayId The logical display id.
105 * @return Information about the specified display, or null if it does not exist.
106 * This object belongs to an internal cache and should be treated as if it were immutable.
107 */
108 public DisplayInfo getDisplayInfo(int displayId) {
109 try {
110 synchronized (mLock) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700111 DisplayInfo info;
112 if (USE_CACHE) {
113 info = mDisplayInfoCache.get(displayId);
114 if (info != null) {
115 return info;
116 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700117 }
118
119 info = mDm.getDisplayInfo(displayId);
120 if (info == null) {
121 return null;
122 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700123
124 if (USE_CACHE) {
125 mDisplayInfoCache.put(displayId, info);
126 }
127 registerCallbackIfNeededLocked();
128
Jeff Brownbd6e1502012-08-28 03:27:37 -0700129 if (DEBUG) {
130 Log.d(TAG, "getDisplayInfo: displayId=" + displayId + ", info=" + info);
131 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700132 return info;
133 }
134 } catch (RemoteException ex) {
135 Log.e(TAG, "Could not get display information from display manager.", ex);
136 return null;
137 }
138 }
139
140 /**
141 * Gets all currently valid logical display ids.
142 *
143 * @return An array containing all display ids.
144 */
145 public int[] getDisplayIds() {
146 try {
147 synchronized (mLock) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700148 if (USE_CACHE) {
149 if (mDisplayIdCache != null) {
150 return mDisplayIdCache;
151 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700152 }
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700153
154 int[] displayIds = mDm.getDisplayIds();
155 if (USE_CACHE) {
156 mDisplayIdCache = displayIds;
157 }
158 registerCallbackIfNeededLocked();
159 return displayIds;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700160 }
161 } catch (RemoteException ex) {
162 Log.e(TAG, "Could not get display ids from display manager.", ex);
163 return new int[] { Display.DEFAULT_DISPLAY };
164 }
165 }
166
167 /**
168 * Gets information about a logical display.
169 *
170 * The display metrics may be adjusted to provide compatibility
Craig Mautner48d0d182013-06-11 07:53:06 -0700171 * for legacy applications or limited screen areas.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700172 *
173 * @param displayId The logical display id.
Craig Mautner48d0d182013-06-11 07:53:06 -0700174 * @param daj The compatibility info and activityToken.
Jeff Brownbd6e1502012-08-28 03:27:37 -0700175 * @return The display object, or null if there is no display with the given id.
176 */
Craig Mautner48d0d182013-06-11 07:53:06 -0700177 public Display getCompatibleDisplay(int displayId, DisplayAdjustments daj) {
Jeff Brownbd6e1502012-08-28 03:27:37 -0700178 DisplayInfo displayInfo = getDisplayInfo(displayId);
179 if (displayInfo == null) {
180 return null;
181 }
Craig Mautner48d0d182013-06-11 07:53:06 -0700182 return new Display(this, displayId, displayInfo, daj);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700183 }
184
185 /**
186 * Gets information about a logical display without applying any compatibility metrics.
187 *
188 * @param displayId The logical display id.
189 * @return The display object, or null if there is no display with the given id.
190 */
191 public Display getRealDisplay(int displayId) {
Craig Mautner48d0d182013-06-11 07:53:06 -0700192 return getCompatibleDisplay(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
193 }
194
Jeff Brownbd6e1502012-08-28 03:27:37 -0700195 public void registerDisplayListener(DisplayListener listener, Handler handler) {
196 if (listener == null) {
197 throw new IllegalArgumentException("listener must not be null");
198 }
199
200 synchronized (mLock) {
201 int index = findDisplayListenerLocked(listener);
202 if (index < 0) {
203 mDisplayListeners.add(new DisplayListenerDelegate(listener, handler));
204 registerCallbackIfNeededLocked();
205 }
206 }
207 }
208
209 public void unregisterDisplayListener(DisplayListener listener) {
210 if (listener == null) {
211 throw new IllegalArgumentException("listener must not be null");
212 }
213
214 synchronized (mLock) {
215 int index = findDisplayListenerLocked(listener);
216 if (index >= 0) {
217 DisplayListenerDelegate d = mDisplayListeners.get(index);
218 d.clearEvents();
219 mDisplayListeners.remove(index);
220 }
221 }
222 }
223
224 private int findDisplayListenerLocked(DisplayListener listener) {
225 final int numListeners = mDisplayListeners.size();
226 for (int i = 0; i < numListeners; i++) {
227 if (mDisplayListeners.get(i).mListener == listener) {
228 return i;
229 }
230 }
231 return -1;
232 }
233
234 private void registerCallbackIfNeededLocked() {
235 if (mCallback == null) {
236 mCallback = new DisplayManagerCallback();
237 try {
238 mDm.registerCallback(mCallback);
239 } catch (RemoteException ex) {
240 Log.e(TAG, "Failed to register callback with display manager service.", ex);
241 mCallback = null;
242 }
243 }
244 }
245
246 private void handleDisplayEvent(int displayId, int event) {
247 synchronized (mLock) {
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700248 if (USE_CACHE) {
249 mDisplayInfoCache.remove(displayId);
Jeff Brownbd6e1502012-08-28 03:27:37 -0700250
Jeff Brown4ed8fe72012-08-30 18:18:29 -0700251 if (event == EVENT_DISPLAY_ADDED || event == EVENT_DISPLAY_REMOVED) {
252 mDisplayIdCache = null;
253 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700254 }
255
256 final int numListeners = mDisplayListeners.size();
257 for (int i = 0; i < numListeners; i++) {
258 mDisplayListeners.get(i).sendDisplayEvent(displayId, event);
259 }
260 }
261 }
262
Jeff Brownce468a32013-11-21 16:42:03 -0800263 public void startWifiDisplayScan() {
264 synchronized (mLock) {
265 if (mWifiDisplayScanNestCount++ == 0) {
266 registerCallbackIfNeededLocked();
267 try {
268 mDm.startWifiDisplayScan();
269 } catch (RemoteException ex) {
270 Log.e(TAG, "Failed to scan for Wifi displays.", ex);
271 }
272 }
273 }
274 }
275
276 public void stopWifiDisplayScan() {
277 synchronized (mLock) {
278 if (--mWifiDisplayScanNestCount == 0) {
279 try {
280 mDm.stopWifiDisplayScan();
281 } catch (RemoteException ex) {
282 Log.e(TAG, "Failed to scan for Wifi displays.", ex);
283 }
284 } else if (mWifiDisplayScanNestCount < 0) {
285 Log.wtf(TAG, "Wifi display scan nest count became negative: "
286 + mWifiDisplayScanNestCount);
287 mWifiDisplayScanNestCount = 0;
288 }
Jeff Browne08ae382012-09-07 20:36:36 -0700289 }
290 }
291
292 public void connectWifiDisplay(String deviceAddress) {
293 if (deviceAddress == null) {
294 throw new IllegalArgumentException("deviceAddress must not be null");
295 }
296
297 try {
298 mDm.connectWifiDisplay(deviceAddress);
299 } catch (RemoteException ex) {
300 Log.e(TAG, "Failed to connect to Wifi display " + deviceAddress + ".", ex);
301 }
302 }
303
Chong Zhang1f3ecaa2013-05-03 15:55:36 -0700304 public void pauseWifiDisplay() {
305 try {
306 mDm.pauseWifiDisplay();
307 } catch (RemoteException ex) {
308 Log.e(TAG, "Failed to pause Wifi display.", ex);
309 }
310 }
311
312 public void resumeWifiDisplay() {
313 try {
314 mDm.resumeWifiDisplay();
315 } catch (RemoteException ex) {
316 Log.e(TAG, "Failed to resume Wifi display.", ex);
317 }
318 }
319
Jeff Browne08ae382012-09-07 20:36:36 -0700320 public void disconnectWifiDisplay() {
321 try {
322 mDm.disconnectWifiDisplay();
323 } catch (RemoteException ex) {
324 Log.e(TAG, "Failed to disconnect from Wifi display.", ex);
325 }
326 }
327
Jeff Brown89d55462012-09-19 11:33:42 -0700328 public void renameWifiDisplay(String deviceAddress, String alias) {
329 if (deviceAddress == null) {
330 throw new IllegalArgumentException("deviceAddress must not be null");
331 }
332
333 try {
334 mDm.renameWifiDisplay(deviceAddress, alias);
335 } catch (RemoteException ex) {
336 Log.e(TAG, "Failed to rename Wifi display " + deviceAddress
337 + " with alias " + alias + ".", ex);
338 }
339 }
340
341 public void forgetWifiDisplay(String deviceAddress) {
342 if (deviceAddress == null) {
343 throw new IllegalArgumentException("deviceAddress must not be null");
344 }
345
346 try {
347 mDm.forgetWifiDisplay(deviceAddress);
348 } catch (RemoteException ex) {
349 Log.e(TAG, "Failed to forget Wifi display.", ex);
350 }
351 }
352
Jeff Browne08ae382012-09-07 20:36:36 -0700353 public WifiDisplayStatus getWifiDisplayStatus() {
354 try {
355 return mDm.getWifiDisplayStatus();
356 } catch (RemoteException ex) {
357 Log.e(TAG, "Failed to get Wifi display status.", ex);
358 return new WifiDisplayStatus();
359 }
360 }
361
Michael Wright58e829f2015-09-15 00:13:26 +0100362 public void requestColorTransform(int displayId, int colorTransformId) {
363 try {
364 mDm.requestColorTransform(displayId, colorTransformId);
365 } catch (RemoteException ex) {
366 Log.e(TAG, "Failed to request color transform.", ex);
367 }
368 }
369
Michael Wrightc39d47a2014-07-08 18:07:36 -0700370 public VirtualDisplay createVirtualDisplay(Context context, MediaProjection projection,
371 String name, int width, int height, int densityDpi, Surface surface, int flags,
Michael Wright75ee9fc2014-09-01 19:55:22 -0700372 VirtualDisplay.Callback callback, Handler handler) {
Jeff Browna506a6e2013-06-04 00:02:38 -0700373 if (TextUtils.isEmpty(name)) {
374 throw new IllegalArgumentException("name must be non-null and non-empty");
375 }
376 if (width <= 0 || height <= 0 || densityDpi <= 0) {
377 throw new IllegalArgumentException("width, height, and densityDpi must be "
378 + "greater than 0");
379 }
Jeff Browna506a6e2013-06-04 00:02:38 -0700380
Michael Wright75ee9fc2014-09-01 19:55:22 -0700381 VirtualDisplayCallback callbackWrapper = new VirtualDisplayCallback(callback, handler);
Michael Wrightc39d47a2014-07-08 18:07:36 -0700382 IMediaProjection projectionToken = projection != null ? projection.getProjection() : null;
Jeff Browna506a6e2013-06-04 00:02:38 -0700383 int displayId;
384 try {
Michael Wrightc39d47a2014-07-08 18:07:36 -0700385 displayId = mDm.createVirtualDisplay(callbackWrapper, projectionToken,
386 context.getPackageName(), name, width, height, densityDpi, surface, flags);
Jeff Browna506a6e2013-06-04 00:02:38 -0700387 } catch (RemoteException ex) {
Jeff Brown7d00aff2013-08-02 19:03:49 -0700388 Log.e(TAG, "Could not create virtual display: " + name, ex);
Jeff Browna506a6e2013-06-04 00:02:38 -0700389 return null;
390 }
391 if (displayId < 0) {
Jeff Brown7d00aff2013-08-02 19:03:49 -0700392 Log.e(TAG, "Could not create virtual display: " + name);
Jeff Browna506a6e2013-06-04 00:02:38 -0700393 return null;
394 }
395 Display display = getRealDisplay(displayId);
396 if (display == null) {
397 Log.wtf(TAG, "Could not obtain display info for newly created "
Jeff Brown7d00aff2013-08-02 19:03:49 -0700398 + "virtual display: " + name);
Jeff Browna506a6e2013-06-04 00:02:38 -0700399 try {
Michael Wrightc39d47a2014-07-08 18:07:36 -0700400 mDm.releaseVirtualDisplay(callbackWrapper);
Jeff Browna506a6e2013-06-04 00:02:38 -0700401 } catch (RemoteException ex) {
402 }
403 return null;
404 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700405 return new VirtualDisplay(this, display, callbackWrapper, surface);
Jeff Brown92207df2014-04-16 13:16:07 -0700406 }
407
Michael Wright75ee9fc2014-09-01 19:55:22 -0700408 public void setVirtualDisplaySurface(IVirtualDisplayCallback token, Surface surface) {
Jeff Brown92207df2014-04-16 13:16:07 -0700409 try {
410 mDm.setVirtualDisplaySurface(token, surface);
411 } catch (RemoteException ex) {
412 Log.w(TAG, "Failed to set virtual display surface.", ex);
413 }
Jeff Browna506a6e2013-06-04 00:02:38 -0700414 }
415
Michael Wright75ee9fc2014-09-01 19:55:22 -0700416 public void resizeVirtualDisplay(IVirtualDisplayCallback token,
Michael Wright01e840f2014-06-26 16:03:25 -0700417 int width, int height, int densityDpi) {
418 try {
419 mDm.resizeVirtualDisplay(token, width, height, densityDpi);
420 } catch (RemoteException ex) {
421 Log.w(TAG, "Failed to resize virtual display.", ex);
422 }
423 }
424
Michael Wright75ee9fc2014-09-01 19:55:22 -0700425 public void releaseVirtualDisplay(IVirtualDisplayCallback token) {
Jeff Browna506a6e2013-06-04 00:02:38 -0700426 try {
427 mDm.releaseVirtualDisplay(token);
428 } catch (RemoteException ex) {
429 Log.w(TAG, "Failed to release virtual display.", ex);
430 }
431 }
432
Jeff Brownbd6e1502012-08-28 03:27:37 -0700433 private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub {
434 @Override
435 public void onDisplayEvent(int displayId, int event) {
436 if (DEBUG) {
437 Log.d(TAG, "onDisplayEvent: displayId=" + displayId + ", event=" + event);
438 }
439 handleDisplayEvent(displayId, event);
440 }
441 }
442
443 private static final class DisplayListenerDelegate extends Handler {
444 public final DisplayListener mListener;
445
446 public DisplayListenerDelegate(DisplayListener listener, Handler handler) {
447 super(handler != null ? handler.getLooper() : Looper.myLooper(), null, true /*async*/);
448 mListener = listener;
449 }
450
451 public void sendDisplayEvent(int displayId, int event) {
452 Message msg = obtainMessage(event, displayId, 0);
453 sendMessage(msg);
454 }
455
456 public void clearEvents() {
457 removeCallbacksAndMessages(null);
458 }
459
460 @Override
461 public void handleMessage(Message msg) {
462 switch (msg.what) {
463 case EVENT_DISPLAY_ADDED:
464 mListener.onDisplayAdded(msg.arg1);
465 break;
466 case EVENT_DISPLAY_CHANGED:
467 mListener.onDisplayChanged(msg.arg1);
468 break;
469 case EVENT_DISPLAY_REMOVED:
470 mListener.onDisplayRemoved(msg.arg1);
471 break;
472 }
473 }
474 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700475
Michael Wright75ee9fc2014-09-01 19:55:22 -0700476 private final static class VirtualDisplayCallback extends IVirtualDisplayCallback.Stub {
477 private VirtualDisplayCallbackDelegate mDelegate;
Michael Wrightc39d47a2014-07-08 18:07:36 -0700478
Michael Wright75ee9fc2014-09-01 19:55:22 -0700479 public VirtualDisplayCallback(VirtualDisplay.Callback callback, Handler handler) {
480 if (callback != null) {
481 mDelegate = new VirtualDisplayCallbackDelegate(callback, handler);
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700482 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700483 }
484
485 @Override // Binder call
Michael Wright75ee9fc2014-09-01 19:55:22 -0700486 public void onPaused() {
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700487 if (mDelegate != null) {
Michael Wright75ee9fc2014-09-01 19:55:22 -0700488 mDelegate.sendEmptyMessage(VirtualDisplayCallbackDelegate.MSG_DISPLAY_PAUSED);
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700489 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700490 }
491
492 @Override // Binder call
Michael Wright75ee9fc2014-09-01 19:55:22 -0700493 public void onResumed() {
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700494 if (mDelegate != null) {
Michael Wright75ee9fc2014-09-01 19:55:22 -0700495 mDelegate.sendEmptyMessage(VirtualDisplayCallbackDelegate.MSG_DISPLAY_RESUMED);
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700496 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700497 }
498
499 @Override // Binder call
Michael Wright75ee9fc2014-09-01 19:55:22 -0700500 public void onStopped() {
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700501 if (mDelegate != null) {
Michael Wright75ee9fc2014-09-01 19:55:22 -0700502 mDelegate.sendEmptyMessage(VirtualDisplayCallbackDelegate.MSG_DISPLAY_STOPPED);
Craig Mautner3d0c57a2014-07-21 14:18:29 -0700503 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700504 }
505 }
506
Michael Wright75ee9fc2014-09-01 19:55:22 -0700507 private final static class VirtualDisplayCallbackDelegate extends Handler {
Michael Wrightc39d47a2014-07-08 18:07:36 -0700508 public static final int MSG_DISPLAY_PAUSED = 0;
509 public static final int MSG_DISPLAY_RESUMED = 1;
510 public static final int MSG_DISPLAY_STOPPED = 2;
511
Michael Wright75ee9fc2014-09-01 19:55:22 -0700512 private final VirtualDisplay.Callback mCallback;
Michael Wrightc39d47a2014-07-08 18:07:36 -0700513
Michael Wright75ee9fc2014-09-01 19:55:22 -0700514 public VirtualDisplayCallbackDelegate(VirtualDisplay.Callback callback,
Michael Wrightc39d47a2014-07-08 18:07:36 -0700515 Handler handler) {
516 super(handler != null ? handler.getLooper() : Looper.myLooper(), null, true /*async*/);
Michael Wright75ee9fc2014-09-01 19:55:22 -0700517 mCallback = callback;
Michael Wrightc39d47a2014-07-08 18:07:36 -0700518 }
519
520 @Override
521 public void handleMessage(Message msg) {
Michael Wrightc39d47a2014-07-08 18:07:36 -0700522 switch (msg.what) {
523 case MSG_DISPLAY_PAUSED:
Michael Wright75ee9fc2014-09-01 19:55:22 -0700524 mCallback.onPaused();
Michael Wrightc39d47a2014-07-08 18:07:36 -0700525 break;
526 case MSG_DISPLAY_RESUMED:
Michael Wright75ee9fc2014-09-01 19:55:22 -0700527 mCallback.onResumed();
Michael Wrightc39d47a2014-07-08 18:07:36 -0700528 break;
529 case MSG_DISPLAY_STOPPED:
Michael Wright75ee9fc2014-09-01 19:55:22 -0700530 mCallback.onStopped();
Michael Wrightc39d47a2014-07-08 18:07:36 -0700531 break;
532 }
533 }
534 }
Jeff Brownbd6e1502012-08-28 03:27:37 -0700535}