blob: 514993380564ac31902f9e124ebbe127a4c052b1 [file] [log] [blame]
Jeff Browna506a6e2013-06-04 00:02:38 -07001/*
2 * Copyright (C) 2013 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
Andrii Kulian7211d2e2017-01-27 15:58:05 -080019import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
20import static android.hardware.display.DisplayManager
21 .VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
22import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION;
23import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
24import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
25
Jeff Browna506a6e2013-06-04 00:02:38 -070026import android.content.Context;
Michael Wright75ee9fc2014-09-01 19:55:22 -070027import android.hardware.display.IVirtualDisplayCallback;
Michael Wrightc39d47a2014-07-08 18:07:36 -070028import android.media.projection.IMediaProjection;
29import android.media.projection.IMediaProjectionCallback;
Jeff Browna506a6e2013-06-04 00:02:38 -070030import android.os.Handler;
31import android.os.IBinder;
Chong Zhangae6119ff2014-11-11 18:54:39 -080032import android.os.SystemProperties;
Jeff Browna506a6e2013-06-04 00:02:38 -070033import android.os.IBinder.DeathRecipient;
Michael Wrightc39d47a2014-07-08 18:07:36 -070034import android.os.Message;
Jeff Browna506a6e2013-06-04 00:02:38 -070035import android.os.RemoteException;
36import android.util.ArrayMap;
37import android.util.Slog;
38import android.view.Display;
39import android.view.Surface;
40import android.view.SurfaceControl;
41
Michael Wrightc39d47a2014-07-08 18:07:36 -070042import java.io.PrintWriter;
Wale Ogunwale361ca212014-11-20 11:42:38 -080043import java.util.Iterator;
Michael Wrightc39d47a2014-07-08 18:07:36 -070044
Jeff Browna506a6e2013-06-04 00:02:38 -070045/**
46 * A display adapter that provides virtual displays on behalf of applications.
47 * <p>
48 * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
49 * </p>
50 */
51final class VirtualDisplayAdapter extends DisplayAdapter {
52 static final String TAG = "VirtualDisplayAdapter";
53 static final boolean DEBUG = false;
54
Wale Ogunwale361ca212014-11-20 11:42:38 -080055 // Unique id prefix for virtual displays
56 private static final String UNIQUE_ID_PREFIX = "virtual:";
57
Jeff Browna506a6e2013-06-04 00:02:38 -070058 private final ArrayMap<IBinder, VirtualDisplayDevice> mVirtualDisplayDevices =
59 new ArrayMap<IBinder, VirtualDisplayDevice>();
Michael Wrightc39d47a2014-07-08 18:07:36 -070060 private Handler mHandler;
Jeff Browna506a6e2013-06-04 00:02:38 -070061
62 // Called with SyncRoot lock held.
63 public VirtualDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
64 Context context, Handler handler, Listener listener) {
65 super(syncRoot, context, handler, listener, TAG);
Michael Wrightc39d47a2014-07-08 18:07:36 -070066 mHandler = handler;
Jeff Browna506a6e2013-06-04 00:02:38 -070067 }
68
Michael Wright75ee9fc2014-09-01 19:55:22 -070069 public DisplayDevice createVirtualDisplayLocked(IVirtualDisplayCallback callback,
Michael Wrightc39d47a2014-07-08 18:07:36 -070070 IMediaProjection projection, int ownerUid, String ownerPackageName,
Jeff Brown7d00aff2013-08-02 19:03:49 -070071 String name, int width, int height, int densityDpi, Surface surface, int flags) {
Andrii Kulian7211d2e2017-01-27 15:58:05 -080072 boolean secure = (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0;
Michael Wright75ee9fc2014-09-01 19:55:22 -070073 IBinder appToken = callback.asBinder();
Jeff Brown7d00aff2013-08-02 19:03:49 -070074 IBinder displayToken = SurfaceControl.createDisplay(name, secure);
Wale Ogunwale361ca212014-11-20 11:42:38 -080075 final String baseUniqueId =
76 UNIQUE_ID_PREFIX + ownerPackageName + "," + ownerUid + "," + name + ",";
77 final int uniqueIndex = getNextUniqueIndex(baseUniqueId);
Jeff Browna506a6e2013-06-04 00:02:38 -070078 VirtualDisplayDevice device = new VirtualDisplayDevice(displayToken, appToken,
Michael Wrightc39d47a2014-07-08 18:07:36 -070079 ownerUid, ownerPackageName, name, width, height, densityDpi, surface, flags,
Wale Ogunwale361ca212014-11-20 11:42:38 -080080 new Callback(callback, mHandler), baseUniqueId + uniqueIndex, uniqueIndex);
Michael Wrightc39d47a2014-07-08 18:07:36 -070081
82 mVirtualDisplayDevices.put(appToken, device);
Jeff Browna506a6e2013-06-04 00:02:38 -070083
84 try {
Michael Wrightc39d47a2014-07-08 18:07:36 -070085 if (projection != null) {
Michael Wrightcde5bb42014-09-08 13:26:34 -070086 projection.registerCallback(new MediaProjectionCallback(appToken));
Michael Wrightc39d47a2014-07-08 18:07:36 -070087 }
Jeff Browna506a6e2013-06-04 00:02:38 -070088 appToken.linkToDeath(device, 0);
89 } catch (RemoteException ex) {
Michael Wrightc39d47a2014-07-08 18:07:36 -070090 mVirtualDisplayDevices.remove(appToken);
Michael Wrightd1a5fae2015-05-05 14:16:35 +010091 device.destroyLocked(false);
Jeff Browna506a6e2013-06-04 00:02:38 -070092 return null;
93 }
94
Jeff Browna506a6e2013-06-04 00:02:38 -070095 // Return the display device without actually sending the event indicating
96 // that it was added. The caller will handle it.
97 return device;
98 }
99
Michael Wright01e840f2014-06-26 16:03:25 -0700100 public void resizeVirtualDisplayLocked(IBinder appToken,
101 int width, int height, int densityDpi) {
102 VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken);
103 if (device != null) {
104 device.resizeLocked(width, height, densityDpi);
105 }
106 }
107
108
Jeff Brown92207df2014-04-16 13:16:07 -0700109 public void setVirtualDisplaySurfaceLocked(IBinder appToken, Surface surface) {
110 VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken);
111 if (device != null) {
112 device.setSurfaceLocked(surface);
113 }
114 }
115
Jeff Browna506a6e2013-06-04 00:02:38 -0700116 public DisplayDevice releaseVirtualDisplayLocked(IBinder appToken) {
117 VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken);
118 if (device != null) {
Michael Wrightd1a5fae2015-05-05 14:16:35 +0100119 device.destroyLocked(true);
Jeff Browna506a6e2013-06-04 00:02:38 -0700120 appToken.unlinkToDeath(device, 0);
121 }
122
123 // Return the display device that was removed without actually sending the
124 // event indicating that it was removed. The caller will handle it.
125 return device;
126 }
127
Wale Ogunwale361ca212014-11-20 11:42:38 -0800128 /**
129 * Returns the next unique index for the uniqueIdPrefix
130 */
131 private int getNextUniqueIndex(String uniqueIdPrefix) {
132 if (mVirtualDisplayDevices.isEmpty()) {
133 return 0;
134 }
135
136 int nextUniqueIndex = 0;
137 Iterator<VirtualDisplayDevice> it = mVirtualDisplayDevices.values().iterator();
138 while (it.hasNext()) {
139 VirtualDisplayDevice device = it.next();
140 if (device.getUniqueId().startsWith(uniqueIdPrefix)
141 && device.mUniqueIndex >= nextUniqueIndex) {
142 // Increment the next unique index to be greater than ones we have already ran
143 // across for displays that have the same unique Id prefix.
144 nextUniqueIndex = device.mUniqueIndex + 1;
145 }
146 }
147
148 return nextUniqueIndex;
149 }
150
Jeff Browna506a6e2013-06-04 00:02:38 -0700151 private void handleBinderDiedLocked(IBinder appToken) {
Bryce Leea3320fe2017-02-15 17:47:25 -0800152 mVirtualDisplayDevices.remove(appToken);
Jeff Browna506a6e2013-06-04 00:02:38 -0700153 }
154
Michael Wrightc39d47a2014-07-08 18:07:36 -0700155 private void handleMediaProjectionStoppedLocked(IBinder appToken) {
156 VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken);
157 if (device != null) {
158 Slog.i(TAG, "Virtual display device released because media projection stopped: "
159 + device.mName);
160 device.stopLocked();
161 }
162 }
163
164 private final class VirtualDisplayDevice extends DisplayDevice implements DeathRecipient {
Michael Wright01e840f2014-06-26 16:03:25 -0700165 private static final int PENDING_SURFACE_CHANGE = 0x01;
166 private static final int PENDING_RESIZE = 0x02;
167
P.Y. Laligand5c7773d2015-05-04 13:30:58 -0700168 private static final float REFRESH_RATE = 60.0f;
169
Jeff Browna506a6e2013-06-04 00:02:38 -0700170 private final IBinder mAppToken;
171 private final int mOwnerUid;
172 final String mOwnerPackageName;
Michael Wrightc39d47a2014-07-08 18:07:36 -0700173 final String mName;
Jeff Brown7d00aff2013-08-02 19:03:49 -0700174 private final int mFlags;
Michael Wright75ee9fc2014-09-01 19:55:22 -0700175 private final Callback mCallback;
Jeff Browna506a6e2013-06-04 00:02:38 -0700176
Michael Wright01e840f2014-06-26 16:03:25 -0700177 private int mWidth;
178 private int mHeight;
179 private int mDensityDpi;
Jeff Browna506a6e2013-06-04 00:02:38 -0700180 private Surface mSurface;
181 private DisplayDeviceInfo mInfo;
Michael Wright01e840f2014-06-26 16:03:25 -0700182 private int mDisplayState;
Michael Wrightc39d47a2014-07-08 18:07:36 -0700183 private boolean mStopped;
Michael Wright01e840f2014-06-26 16:03:25 -0700184 private int mPendingChanges;
Wale Ogunwale361ca212014-11-20 11:42:38 -0800185 private int mUniqueIndex;
P.Y. Laligand5c7773d2015-05-04 13:30:58 -0700186 private Display.Mode mMode;
Jeff Browna506a6e2013-06-04 00:02:38 -0700187
Michael Wrightc39d47a2014-07-08 18:07:36 -0700188 public VirtualDisplayDevice(IBinder displayToken, IBinder appToken,
189 int ownerUid, String ownerPackageName,
190 String name, int width, int height, int densityDpi, Surface surface, int flags,
Wale Ogunwale361ca212014-11-20 11:42:38 -0800191 Callback callback, String uniqueId, int uniqueIndex) {
192 super(VirtualDisplayAdapter.this, displayToken, uniqueId);
Jeff Browna506a6e2013-06-04 00:02:38 -0700193 mAppToken = appToken;
194 mOwnerUid = ownerUid;
195 mOwnerPackageName = ownerPackageName;
196 mName = name;
197 mWidth = width;
198 mHeight = height;
P.Y. Laligand5c7773d2015-05-04 13:30:58 -0700199 mMode = createMode(width, height, REFRESH_RATE);
Jeff Browna506a6e2013-06-04 00:02:38 -0700200 mDensityDpi = densityDpi;
201 mSurface = surface;
Jeff Brown7d00aff2013-08-02 19:03:49 -0700202 mFlags = flags;
Michael Wright75ee9fc2014-09-01 19:55:22 -0700203 mCallback = callback;
Michael Wright01e840f2014-06-26 16:03:25 -0700204 mDisplayState = Display.STATE_UNKNOWN;
205 mPendingChanges |= PENDING_SURFACE_CHANGE;
Wale Ogunwale361ca212014-11-20 11:42:38 -0800206 mUniqueIndex = uniqueIndex;
Jeff Browna506a6e2013-06-04 00:02:38 -0700207 }
208
209 @Override
210 public void binderDied() {
211 synchronized (getSyncRoot()) {
Michael Wrightd1a5fae2015-05-05 14:16:35 +0100212 handleBinderDiedLocked(mAppToken);
Bryce Leea3320fe2017-02-15 17:47:25 -0800213 Slog.i(TAG, "Virtual display device released because application token died: "
214 + mOwnerPackageName);
215 destroyLocked(false);
216 sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_REMOVED);
Jeff Browna506a6e2013-06-04 00:02:38 -0700217 }
218 }
219
Michael Wrightd1a5fae2015-05-05 14:16:35 +0100220 public void destroyLocked(boolean binderAlive) {
Jesse Hall6a6bc212013-08-08 12:15:03 -0700221 if (mSurface != null) {
222 mSurface.release();
223 mSurface = null;
224 }
225 SurfaceControl.destroyDisplay(getDisplayTokenLocked());
Michael Wrightd1a5fae2015-05-05 14:16:35 +0100226 if (binderAlive) {
227 mCallback.dispatchDisplayStopped();
228 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700229 }
230
231 @Override
Michael Wright1c9977b2016-07-12 13:30:10 -0700232 public boolean hasStableUniqueId() {
233 return false;
234 }
235
236 @Override
Jeff Brown5d6443b2015-04-10 20:15:01 -0700237 public Runnable requestDisplayStateLocked(int state, int brightness) {
Michael Wright01e840f2014-06-26 16:03:25 -0700238 if (state != mDisplayState) {
239 mDisplayState = state;
Michael Wrightc39d47a2014-07-08 18:07:36 -0700240 if (state == Display.STATE_OFF) {
Michael Wright75ee9fc2014-09-01 19:55:22 -0700241 mCallback.dispatchDisplayPaused();
Michael Wrightc39d47a2014-07-08 18:07:36 -0700242 } else {
Michael Wright75ee9fc2014-09-01 19:55:22 -0700243 mCallback.dispatchDisplayResumed();
Michael Wrightc39d47a2014-07-08 18:07:36 -0700244 }
245 }
Jeff Browne75926d2014-09-18 15:24:49 -0700246 return null;
Jeff Browna506a6e2013-06-04 00:02:38 -0700247 }
248
249 @Override
250 public void performTraversalInTransactionLocked() {
Michael Wright01e840f2014-06-26 16:03:25 -0700251 if ((mPendingChanges & PENDING_RESIZE) != 0) {
252 SurfaceControl.setDisplaySize(getDisplayTokenLocked(), mWidth, mHeight);
253 }
254 if ((mPendingChanges & PENDING_SURFACE_CHANGE) != 0) {
255 setSurfaceInTransactionLocked(mSurface);
256 }
257 mPendingChanges = 0;
Jeff Browna506a6e2013-06-04 00:02:38 -0700258 }
259
Jeff Brown92207df2014-04-16 13:16:07 -0700260 public void setSurfaceLocked(Surface surface) {
Michael Wrightc39d47a2014-07-08 18:07:36 -0700261 if (!mStopped && mSurface != surface) {
Jeff Brown92207df2014-04-16 13:16:07 -0700262 if ((mSurface != null) != (surface != null)) {
263 sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
264 }
265 sendTraversalRequestLocked();
266 mSurface = surface;
267 mInfo = null;
Michael Wright01e840f2014-06-26 16:03:25 -0700268 mPendingChanges |= PENDING_SURFACE_CHANGE;
269 }
270 }
271
272 public void resizeLocked(int width, int height, int densityDpi) {
273 if (mWidth != width || mHeight != height || mDensityDpi != densityDpi) {
274 sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
275 sendTraversalRequestLocked();
276 mWidth = width;
277 mHeight = height;
P.Y. Laligand5c7773d2015-05-04 13:30:58 -0700278 mMode = createMode(width, height, REFRESH_RATE);
Michael Wright01e840f2014-06-26 16:03:25 -0700279 mDensityDpi = densityDpi;
280 mInfo = null;
281 mPendingChanges |= PENDING_RESIZE;
Jeff Brown92207df2014-04-16 13:16:07 -0700282 }
283 }
284
Michael Wrightc39d47a2014-07-08 18:07:36 -0700285 public void stopLocked() {
286 setSurfaceLocked(null);
287 mStopped = true;
288 }
289
290 @Override
291 public void dumpLocked(PrintWriter pw) {
292 super.dumpLocked(pw);
293 pw.println("mFlags=" + mFlags);
Michael Wright01e840f2014-06-26 16:03:25 -0700294 pw.println("mDisplayState=" + Display.stateToString(mDisplayState));
Michael Wrightc39d47a2014-07-08 18:07:36 -0700295 pw.println("mStopped=" + mStopped);
296 }
297
298
Jeff Browna506a6e2013-06-04 00:02:38 -0700299 @Override
300 public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
301 if (mInfo == null) {
302 mInfo = new DisplayDeviceInfo();
303 mInfo.name = mName;
Wale Ogunwale361ca212014-11-20 11:42:38 -0800304 mInfo.uniqueId = getUniqueId();
Jeff Browna506a6e2013-06-04 00:02:38 -0700305 mInfo.width = mWidth;
306 mInfo.height = mHeight;
P.Y. Laligand5c7773d2015-05-04 13:30:58 -0700307 mInfo.modeId = mMode.getModeId();
308 mInfo.defaultModeId = mMode.getModeId();
309 mInfo.supportedModes = new Display.Mode[] { mMode };
Jeff Browna506a6e2013-06-04 00:02:38 -0700310 mInfo.densityDpi = mDensityDpi;
311 mInfo.xDpi = mDensityDpi;
312 mInfo.yDpi = mDensityDpi;
P.Y. Laligand5c7773d2015-05-04 13:30:58 -0700313 mInfo.presentationDeadlineNanos = 1000000000L / (int) REFRESH_RATE; // 1 frame
Jeff Brown7d00aff2013-08-02 19:03:49 -0700314 mInfo.flags = 0;
Andrii Kulian7211d2e2017-01-27 15:58:05 -0800315 if ((mFlags & VIRTUAL_DISPLAY_FLAG_PUBLIC) == 0) {
Michael Wright6720be42014-07-29 19:14:16 -0700316 mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE
317 | DisplayDeviceInfo.FLAG_NEVER_BLANK;
318 }
Andrii Kulian7211d2e2017-01-27 15:58:05 -0800319 if ((mFlags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
Michael Wright6720be42014-07-29 19:14:16 -0700320 mInfo.flags &= ~DisplayDeviceInfo.FLAG_NEVER_BLANK;
321 } else {
Jeff Brownd14c8c92014-01-07 18:13:09 -0800322 mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;
Jeff Brown7d00aff2013-08-02 19:03:49 -0700323 }
Michael Wright6720be42014-07-29 19:14:16 -0700324
Andrii Kulian7211d2e2017-01-27 15:58:05 -0800325 if ((mFlags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
Jeff Brown7d00aff2013-08-02 19:03:49 -0700326 mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE;
327 }
Andrii Kulian7211d2e2017-01-27 15:58:05 -0800328 if ((mFlags & VIRTUAL_DISPLAY_FLAG_PRESENTATION) != 0) {
Jeff Brown7d00aff2013-08-02 19:03:49 -0700329 mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;
Chong Zhangae6119ff2014-11-11 18:54:39 -0800330
Andrii Kulian7211d2e2017-01-27 15:58:05 -0800331 if ((mFlags & VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
Chong Zhangae6119ff2014-11-11 18:54:39 -0800332 // For demonstration purposes, allow rotation of the external display.
333 // In the future we might allow the user to configure this directly.
334 if ("portrait".equals(SystemProperties.get(
335 "persist.demo.remoterotation"))) {
336 mInfo.rotation = Surface.ROTATION_270;
337 }
338 }
Jeff Brown7d00aff2013-08-02 19:03:49 -0700339 }
Andrii Kulian7211d2e2017-01-27 15:58:05 -0800340 if ((mFlags & VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
341 mInfo.flags |= DisplayDeviceInfo.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
Andrii Kulianfc8f82b2017-01-26 13:17:27 -0800342 }
Jeff Browna506a6e2013-06-04 00:02:38 -0700343 mInfo.type = Display.TYPE_VIRTUAL;
344 mInfo.touch = DisplayDeviceInfo.TOUCH_NONE;
Jeff Brown92207df2014-04-16 13:16:07 -0700345 mInfo.state = mSurface != null ? Display.STATE_ON : Display.STATE_OFF;
Jeff Browna506a6e2013-06-04 00:02:38 -0700346 mInfo.ownerUid = mOwnerUid;
347 mInfo.ownerPackageName = mOwnerPackageName;
348 }
349 return mInfo;
350 }
351 }
Michael Wrightc39d47a2014-07-08 18:07:36 -0700352
Michael Wright75ee9fc2014-09-01 19:55:22 -0700353 private static class Callback extends Handler {
Michael Wrightc39d47a2014-07-08 18:07:36 -0700354 private static final int MSG_ON_DISPLAY_PAUSED = 0;
355 private static final int MSG_ON_DISPLAY_RESUMED = 1;
356 private static final int MSG_ON_DISPLAY_STOPPED = 2;
357
Michael Wright75ee9fc2014-09-01 19:55:22 -0700358 private final IVirtualDisplayCallback mCallback;
Michael Wrightc39d47a2014-07-08 18:07:36 -0700359
Michael Wright75ee9fc2014-09-01 19:55:22 -0700360 public Callback(IVirtualDisplayCallback callback, Handler handler) {
Michael Wrightc39d47a2014-07-08 18:07:36 -0700361 super(handler.getLooper());
Michael Wright75ee9fc2014-09-01 19:55:22 -0700362 mCallback = callback;
Michael Wrightc39d47a2014-07-08 18:07:36 -0700363 }
364
365 @Override
366 public void handleMessage(Message msg) {
367 try {
368 switch (msg.what) {
369 case MSG_ON_DISPLAY_PAUSED:
Michael Wright75ee9fc2014-09-01 19:55:22 -0700370 mCallback.onPaused();
Michael Wrightc39d47a2014-07-08 18:07:36 -0700371 break;
372 case MSG_ON_DISPLAY_RESUMED:
Michael Wright75ee9fc2014-09-01 19:55:22 -0700373 mCallback.onResumed();
Michael Wrightc39d47a2014-07-08 18:07:36 -0700374 break;
375 case MSG_ON_DISPLAY_STOPPED:
Michael Wright75ee9fc2014-09-01 19:55:22 -0700376 mCallback.onStopped();
Michael Wrightc39d47a2014-07-08 18:07:36 -0700377 break;
378 }
379 } catch (RemoteException e) {
380 Slog.w(TAG, "Failed to notify listener of virtual display event.", e);
381 }
382 }
383
384 public void dispatchDisplayPaused() {
385 sendEmptyMessage(MSG_ON_DISPLAY_PAUSED);
386 }
387
388 public void dispatchDisplayResumed() {
389 sendEmptyMessage(MSG_ON_DISPLAY_RESUMED);
390 }
391
392 public void dispatchDisplayStopped() {
393 sendEmptyMessage(MSG_ON_DISPLAY_STOPPED);
394 }
395 }
396
397 private final class MediaProjectionCallback extends IMediaProjectionCallback.Stub {
398 private IBinder mAppToken;
399 public MediaProjectionCallback(IBinder appToken) {
400 mAppToken = appToken;
401 }
402
403 @Override
404 public void onStop() {
405 synchronized (getSyncRoot()) {
406 handleMediaProjectionStoppedLocked(mAppToken);
407 }
408 }
409 }
Jeff Browna506a6e2013-06-04 00:02:38 -0700410}