1c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright/* 2c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * Copyright (C) 2014 The Android Open Source Project 3c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * 4c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * Licensed under the Apache License, Version 2.0 (the "License"); 5c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * you may not use this file except in compliance with the License. 6c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * You may obtain a copy of the License at 7c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * 8c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * http://www.apache.org/licenses/LICENSE-2.0 9c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * 10c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * Unless required by applicable law or agreed to in writing, software 11c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * distributed under the License is distributed on an "AS IS" BASIS, 12c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * See the License for the specific language governing permissions and 14c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * limitations under the License. 15c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright */ 16c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 17c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightpackage com.android.server.media.projection; 18c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 19c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport com.android.server.Watchdog; 20c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 21c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.Manifest; 22c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.app.AppOpsManager; 23c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.content.Context; 24c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.content.pm.PackageManager; 25c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.hardware.display.DisplayManager; 2689c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wrightimport android.media.MediaRouter; 27c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.media.projection.IMediaProjectionManager; 28c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.media.projection.IMediaProjection; 29c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.media.projection.IMediaProjectionCallback; 30d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wrightimport android.media.projection.IMediaProjectionWatcherCallback; 31d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wrightimport android.media.projection.MediaProjectionInfo; 32c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.media.projection.MediaProjectionManager; 33c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.os.Binder; 34c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.os.Handler; 35c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.os.IBinder; 36c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.os.Looper; 37c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.os.RemoteException; 38d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wrightimport android.os.UserHandle; 39c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.util.ArrayMap; 40c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.util.Slog; 41c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 42c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport com.android.server.SystemService; 43c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 44c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport java.io.FileDescriptor; 45c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport java.io.PrintWriter; 46c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport java.util.Map; 47c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 48c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright/** 49c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * Manages MediaProjection sessions. 50c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * 51c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * The {@link MediaProjectionManagerService} manages the creation and lifetime of MediaProjections, 52c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * as well as the capabilities they grant. Any service using MediaProjection tokens as permission 53c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * grants <b>must</b> validate the token before use by calling {@link 54c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * IMediaProjectionService#isValidMediaProjection}. 55c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright */ 56c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightpublic final class MediaProjectionManagerService extends SystemService 57c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright implements Watchdog.Monitor { 58c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright private static final String TAG = "MediaProjectionManagerService"; 59c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 60c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright private final Object mLock = new Object(); // Protects the list of media projections 61d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private final Map<IBinder, IBinder.DeathRecipient> mDeathEaters; 62d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private final CallbackDelegate mCallbackDelegate; 63c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 64c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright private final Context mContext; 65c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright private final AppOpsManager mAppOps; 66c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 6789c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright private final MediaRouter mMediaRouter; 6889c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright private final MediaRouterCallback mMediaRouterCallback; 6989c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright private MediaRouter.RouteInfo mMediaRouteInfo; 7089c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright 71d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private IBinder mProjectionToken; 72d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private MediaProjection mProjectionGrant; 73d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 74c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public MediaProjectionManagerService(Context context) { 75c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright super(context); 76c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright mContext = context; 77d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mDeathEaters = new ArrayMap<IBinder, IBinder.DeathRecipient>(); 78d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mCallbackDelegate = new CallbackDelegate(); 79c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 8089c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright mMediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE); 8189c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright mMediaRouterCallback = new MediaRouterCallback(); 82c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright Watchdog.getInstance().addMonitor(this); 83c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 84c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 85c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright @Override 86c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public void onStart() { 87c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright publishBinderService(Context.MEDIA_PROJECTION_SERVICE, new BinderService(), 88c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright false /*allowIsolated*/); 894444c5b27874866f18cd8f4abb8914cc17857ea7Jason Monk mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY, mMediaRouterCallback, 904444c5b27874866f18cd8f4abb8914cc17857ea7Jason Monk MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY); 9189c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright } 9289c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright 9389c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright @Override 9489c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright public void onSwitchUser(int userId) { 9589c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright mMediaRouter.rebindAsUser(userId); 9605aab5810a5f0296c3650f104c58479b2765c0b7Michael Wright synchronized (mLock) { 9705aab5810a5f0296c3650f104c58479b2765c0b7Michael Wright if (mProjectionGrant != null) { 9805aab5810a5f0296c3650f104c58479b2765c0b7Michael Wright mProjectionGrant.stop(); 9905aab5810a5f0296c3650f104c58479b2765c0b7Michael Wright } 10005aab5810a5f0296c3650f104c58479b2765c0b7Michael Wright } 101c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 102c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 103c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright @Override 104c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public void monitor() { 105c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright synchronized (mLock) { /* check for deadlock */ } 106c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 107c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 108d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private void startProjectionLocked(final MediaProjection projection) { 109d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (mProjectionGrant != null) { 110d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mProjectionGrant.stop(); 111d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 11289c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright if (mMediaRouteInfo != null) { 11389c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright mMediaRouter.getDefaultRoute().select(); 11489c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright } 115d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mProjectionToken = projection.asBinder(); 116d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mProjectionGrant = projection; 117d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright dispatchStart(projection); 118d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 119d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 120d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private void stopProjectionLocked(final MediaProjection projection) { 121d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mProjectionToken = null; 122d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mProjectionGrant = null; 123d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright dispatchStop(projection); 124d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 125d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 126d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private void addCallback(final IMediaProjectionWatcherCallback callback) { 127d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() { 128d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright @Override 129d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void binderDied() { 130ac3f8e5534b1653a29714b63a3afbc6c1a90e669Jae Seo removeCallback(callback); 131d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 132d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright }; 133d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright synchronized (mLock) { 134d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mCallbackDelegate.add(callback); 135d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright linkDeathRecipientLocked(callback, deathRecipient); 136d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 137d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 138d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 139d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private void removeCallback(IMediaProjectionWatcherCallback callback) { 140d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright synchronized (mLock) { 141d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright unlinkDeathRecipientLocked(callback); 14278b8c8fbde12b214314cc2ab2644350b5d5189a5John Spurlock mCallbackDelegate.remove(callback); 143d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 144d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 145d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 146d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private void linkDeathRecipientLocked(IMediaProjectionWatcherCallback callback, 147d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright IBinder.DeathRecipient deathRecipient) { 148d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright try { 149d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright final IBinder token = callback.asBinder(); 150d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright token.linkToDeath(deathRecipient, 0); 151d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mDeathEaters.put(token, deathRecipient); 152d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } catch (RemoteException e) { 153d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright Slog.e(TAG, "Unable to link to death for media projection monitoring callback", e); 154d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 155d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 156d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 157d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private void unlinkDeathRecipientLocked(IMediaProjectionWatcherCallback callback) { 158d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright final IBinder token = callback.asBinder(); 159d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright IBinder.DeathRecipient deathRecipient = mDeathEaters.remove(token); 160d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (deathRecipient != null) { 161d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright token.unlinkToDeath(deathRecipient, 0); 162d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 163d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 164d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 165d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private void dispatchStart(MediaProjection projection) { 166d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mCallbackDelegate.dispatchStart(projection); 167d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 168d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 169d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private void dispatchStop(MediaProjection projection) { 170d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mCallbackDelegate.dispatchStop(projection); 171d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 172d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 173d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private boolean isValidMediaProjection(IBinder token) { 174d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright synchronized (mLock) { 175d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (mProjectionToken != null) { 176d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright return mProjectionToken.equals(token); 177d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 178d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright return false; 179d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 180d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 181d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 182d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private MediaProjectionInfo getActiveProjectionInfo() { 183d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright synchronized (mLock) { 184d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (mProjectionGrant == null) { 185d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright return null; 186d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 187d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright return mProjectionGrant.getProjectionInfo(); 188d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 189d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 190d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 191c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright private void dump(final PrintWriter pw) { 192c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright pw.println("MEDIA PROJECTION MANAGER (dumpsys media_projection)"); 193c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright synchronized (mLock) { 194d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright pw.println("Media Projection: "); 195d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (mProjectionGrant != null ) { 196d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mProjectionGrant.dump(pw); 197d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } else { 198d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright pw.println("null"); 199c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 200c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 201c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 202c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 203c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright private final class BinderService extends IMediaProjectionManager.Stub { 204c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 205c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright @Override // Binder call 206c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public boolean hasProjectionPermission(int uid, String packageName) { 207c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright long token = Binder.clearCallingIdentity(); 208c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright boolean hasPermission = false; 209c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright try { 210c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright hasPermission |= checkPermission(packageName, 211c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright android.Manifest.permission.CAPTURE_VIDEO_OUTPUT) 2126720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright || mAppOps.noteOpNoThrow( 213c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright AppOpsManager.OP_PROJECT_MEDIA, uid, packageName) 214c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright == AppOpsManager.MODE_ALLOWED; 215c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } finally { 216c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright Binder.restoreCallingIdentity(token); 217c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 218c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright return hasPermission; 219c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 220c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 221c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright @Override // Binder call 222c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public IMediaProjection createProjection(int uid, String packageName, int type, 223c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright boolean isPermanentGrant) { 224d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION) 225c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright != PackageManager.PERMISSION_GRANTED) { 226d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to grant " 227c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright + "projection permission"); 228c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 229d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (packageName == null || packageName.isEmpty()) { 230d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright throw new IllegalArgumentException("package name must not be empty"); 231d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 232c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright long callingToken = Binder.clearCallingIdentity(); 233c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright MediaProjection projection; 234c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright try { 235c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright projection = new MediaProjection(type, uid, packageName); 236c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright if (isPermanentGrant) { 237c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright mAppOps.setMode(AppOpsManager.OP_PROJECT_MEDIA, 238c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright projection.uid, projection.packageName, AppOpsManager.MODE_ALLOWED); 239c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 240c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } finally { 241c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright Binder.restoreCallingIdentity(callingToken); 242c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 243c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright return projection; 244c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 245c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 246c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright @Override // Binder call 247c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public boolean isValidMediaProjection(IMediaProjection projection) { 248d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright return MediaProjectionManagerService.this.isValidMediaProjection( 249d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright projection.asBinder()); 250d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 251d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 252d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright @Override // Binder call 253d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public MediaProjectionInfo getActiveProjectionInfo() { 254d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION) 255d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright != PackageManager.PERMISSION_GRANTED) { 256d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to add " 257d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright + "projection callbacks"); 258d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 259d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright final long token = Binder.clearCallingIdentity(); 260d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright try { 261d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright return MediaProjectionManagerService.this.getActiveProjectionInfo(); 262d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } finally { 263d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright Binder.restoreCallingIdentity(token); 264d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 265d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 266d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 267d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright @Override // Binder call 268d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void stopActiveProjection() { 269d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION) 270d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright != PackageManager.PERMISSION_GRANTED) { 271d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to add " 272d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright + "projection callbacks"); 273d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 274d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright final long token = Binder.clearCallingIdentity(); 275d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright try { 276d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (mProjectionGrant != null) { 277d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mProjectionGrant.stop(); 278d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 279d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } finally { 280d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright Binder.restoreCallingIdentity(token); 281d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 282d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 283d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 284d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 285d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright @Override //Binder call 286d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void addCallback(final IMediaProjectionWatcherCallback callback) { 287d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION) 288d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright != PackageManager.PERMISSION_GRANTED) { 289d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to add " 290d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright + "projection callbacks"); 291d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 292d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright final long token = Binder.clearCallingIdentity(); 293d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright try { 294d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright MediaProjectionManagerService.this.addCallback(callback); 295d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } finally { 296d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright Binder.restoreCallingIdentity(token); 297d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 298d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 299d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 300d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright @Override 301d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void removeCallback(IMediaProjectionWatcherCallback callback) { 302d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (mContext.checkCallingPermission(Manifest.permission.MANAGE_MEDIA_PROJECTION) 303d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright != PackageManager.PERMISSION_GRANTED) { 304d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright throw new SecurityException("Requires MANAGE_MEDIA_PROJECTION in order to remove " 305d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright + "projection callbacks"); 306d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 307d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright final long token = Binder.clearCallingIdentity(); 308d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright try { 309d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright MediaProjectionManagerService.this.removeCallback(callback); 310d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } finally { 311d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright Binder.restoreCallingIdentity(token); 312d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 313c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 314c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 315c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright @Override // Binder call 316c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 317c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright if (mContext == null 318c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) 319c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright != PackageManager.PERMISSION_GRANTED) { 320c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright pw.println("Permission Denial: can't dump MediaProjectionManager from from pid=" 321c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 322c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright return; 323c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 324c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 325c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright final long token = Binder.clearCallingIdentity(); 326c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright try { 3279b84309bea122e63009408b3fa94a3e498ae60c9John Spurlock MediaProjectionManagerService.this.dump(pw); 328c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } finally { 329c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright Binder.restoreCallingIdentity(token); 330c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 331c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 332c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 333d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 334c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright private boolean checkPermission(String packageName, String permission) { 335c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright return mContext.getPackageManager().checkPermission(permission, packageName) 336c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright == PackageManager.PERMISSION_GRANTED; 337c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 338c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 339c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 340d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private final class MediaProjection extends IMediaProjection.Stub { 341d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public final int uid; 342d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public final String packageName; 343d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public final UserHandle userHandle; 344c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 345ac3f8e5534b1653a29714b63a3afbc6c1a90e669Jae Seo private IMediaProjectionCallback mCallback; 346c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright private IBinder mToken; 347d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private IBinder.DeathRecipient mDeathEater; 348c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright private int mType; 349c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 350c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public MediaProjection(int type, int uid, String packageName) { 351c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright mType = type; 352c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright this.uid = uid; 353c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright this.packageName = packageName; 354d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright userHandle = new UserHandle(UserHandle.getUserId(uid)); 355c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 356c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 357c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright @Override // Binder call 358c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public boolean canProjectVideo() { 359c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright return mType == MediaProjectionManager.TYPE_MIRRORING || 360c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright mType == MediaProjectionManager.TYPE_SCREEN_CAPTURE; 361c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 362c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 363c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright @Override // Binder call 364c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public boolean canProjectSecureVideo() { 365c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright return false; 366c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 367c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 368c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright @Override // Binder call 369c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public boolean canProjectAudio() { 370c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright return mType == MediaProjectionManager.TYPE_MIRRORING || 371c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright mType == MediaProjectionManager.TYPE_PRESENTATION; 372c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 373c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 374c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright @Override // Binder call 3756720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright public int applyVirtualDisplayFlags(int flags) { 3766720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright if (mType == MediaProjectionManager.TYPE_SCREEN_CAPTURE) { 3776720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright flags &= ~DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY; 3786720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR 3796720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright | DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION; 3806720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright return flags; 3816720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright } else if (mType == MediaProjectionManager.TYPE_MIRRORING) { 3826720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright flags &= ~(DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC | 3836720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR); 3846720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | 3856720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION; 3866720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright return flags; 3876720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright } else if (mType == MediaProjectionManager.TYPE_PRESENTATION) { 3886720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright flags &= ~DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY; 3896720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC | 3906720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION | 3916720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; 3926720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright return flags; 3936720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright } else { 3946720be4e8c65e90d4453ddad5cef192bc3820038Michael Wright throw new RuntimeException("Unknown MediaProjection type"); 395c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 396c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 397c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 398c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright @Override // Binder call 399d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void start(final IMediaProjectionCallback callback) { 400c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright if (callback == null) { 401c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright throw new IllegalArgumentException("callback must not be null"); 402c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 403c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright synchronized (mLock) { 404d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (isValidMediaProjection(asBinder())) { 405c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright throw new IllegalStateException( 406c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright "Cannot start already started MediaProjection"); 407c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 408ac3f8e5534b1653a29714b63a3afbc6c1a90e669Jae Seo mCallback = callback; 409ac3f8e5534b1653a29714b63a3afbc6c1a90e669Jae Seo registerCallback(mCallback); 410c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright try { 411c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright mToken = callback.asBinder(); 412d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mDeathEater = new IBinder.DeathRecipient() { 413d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright @Override 414d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void binderDied() { 415d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mCallbackDelegate.remove(callback); 416d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright stop(); 417d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 418d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright }; 419d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mToken.linkToDeath(mDeathEater, 0); 420c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } catch (RemoteException e) { 421c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright Slog.w(TAG, 422c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright "MediaProjectionCallbacks must be valid, aborting MediaProjection", e); 423c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright return; 424c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 425d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright startProjectionLocked(this); 426c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 427c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 428c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 429c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright @Override // Binder call 430c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public void stop() { 431c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright synchronized (mLock) { 432d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (!isValidMediaProjection(asBinder())) { 433c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright Slog.w(TAG, "Attempted to stop inactive MediaProjection " 434c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright + "(uid=" + Binder.getCallingUid() + ", " 435c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright + "pid=" + Binder.getCallingPid() + ")"); 436c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright return; 437c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 438d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright stopProjectionLocked(this); 439ac3f8e5534b1653a29714b63a3afbc6c1a90e669Jae Seo mToken.unlinkToDeath(mDeathEater, 0); 440ac3f8e5534b1653a29714b63a3afbc6c1a90e669Jae Seo mToken = null; 441ac3f8e5534b1653a29714b63a3afbc6c1a90e669Jae Seo unregisterCallback(mCallback); 442ac3f8e5534b1653a29714b63a3afbc6c1a90e669Jae Seo mCallback = null; 443c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 444c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 445c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 446c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright @Override 447cde5bb45cc86d181d96ee69da1832e6132162871Michael Wright public void registerCallback(IMediaProjectionCallback callback) { 448c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright if (callback == null) { 449c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright throw new IllegalArgumentException("callback must not be null"); 450c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 451c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright mCallbackDelegate.add(callback); 452c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 453c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 454c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright @Override 455cde5bb45cc86d181d96ee69da1832e6132162871Michael Wright public void unregisterCallback(IMediaProjectionCallback callback) { 456c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright if (callback == null) { 457c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright throw new IllegalArgumentException("callback must not be null"); 458c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 459c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright mCallbackDelegate.remove(callback); 460c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 461c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 462d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public MediaProjectionInfo getProjectionInfo() { 463d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright return new MediaProjectionInfo(packageName, userHandle); 464d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 465d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 466d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void dump(PrintWriter pw) { 467d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright pw.println("(" + packageName + ", uid=" + uid + "): " + typeToString(mType)); 468c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 469c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 470c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 47189c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright private class MediaRouterCallback extends MediaRouter.SimpleCallback { 47289c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright @Override 47389c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright public void onRouteSelected(MediaRouter router, int type, MediaRouter.RouteInfo info) { 47489c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright synchronized (mLock) { 47589c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright if ((type & MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY) != 0) { 47689c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright mMediaRouteInfo = info; 47789c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright if (mProjectionGrant != null) { 47889c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright mProjectionGrant.stop(); 47989c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright } 48089c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright } 48189c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright } 48289c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright } 48389c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright 48489c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright @Override 48589c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright public void onRouteUnselected(MediaRouter route, int type, MediaRouter.RouteInfo info) { 48689c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright if (mMediaRouteInfo == info) { 48789c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright mMediaRouteInfo = null; 48889c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright } 48989c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright } 49089c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright } 49189c2cb6f31cddb926dea3498f8adf01a8cc1426aMichael Wright 492d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 493c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright private static class CallbackDelegate { 494d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private Map<IBinder, IMediaProjectionCallback> mClientCallbacks; 495d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private Map<IBinder, IMediaProjectionWatcherCallback> mWatcherCallbacks; 496c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright private Handler mHandler; 497c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright private Object mLock = new Object(); 498c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 499c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public CallbackDelegate() { 500c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright mHandler = new Handler(Looper.getMainLooper(), null, true /*async*/); 501d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mClientCallbacks = new ArrayMap<IBinder, IMediaProjectionCallback>(); 502d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mWatcherCallbacks = new ArrayMap<IBinder, IMediaProjectionWatcherCallback>(); 503c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 504c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 505c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public void add(IMediaProjectionCallback callback) { 506c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright synchronized (mLock) { 507d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mClientCallbacks.put(callback.asBinder(), callback); 508d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 509d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 510d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 511d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void add(IMediaProjectionWatcherCallback callback) { 512d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright synchronized (mLock) { 513d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mWatcherCallbacks.put(callback.asBinder(), callback); 514c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 515c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 516c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 517c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public void remove(IMediaProjectionCallback callback) { 518c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright synchronized (mLock) { 519d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mClientCallbacks.remove(callback.asBinder()); 520c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 521c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 522c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 523d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void remove(IMediaProjectionWatcherCallback callback) { 524c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright synchronized (mLock) { 525d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mWatcherCallbacks.remove(callback.asBinder()); 526d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 527d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 528d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 529d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void dispatchStart(MediaProjection projection) { 530d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (projection == null) { 531d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright Slog.e(TAG, "Tried to dispatch start notification for a null media projection." 532d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright + " Ignoring!"); 533d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright return; 534d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 535d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright synchronized (mLock) { 536d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright for (IMediaProjectionWatcherCallback callback : mWatcherCallbacks.values()) { 537d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright MediaProjectionInfo info = projection.getProjectionInfo(); 538d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mHandler.post(new WatcherStartCallback(info, callback)); 539c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 540c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 541c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 542d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 543d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void dispatchStop(MediaProjection projection) { 544d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (projection == null) { 545d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright Slog.e(TAG, "Tried to dispatch stop notification for a null media projection." 546d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright + " Ignoring!"); 547d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright return; 548d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 549d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright synchronized (mLock) { 550d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright for (IMediaProjectionCallback callback : mClientCallbacks.values()) { 551d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mHandler.post(new ClientStopCallback(callback)); 552d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 553d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 554d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright for (IMediaProjectionWatcherCallback callback : mWatcherCallbacks.values()) { 555d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright MediaProjectionInfo info = projection.getProjectionInfo(); 556d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mHandler.post(new WatcherStopCallback(info, callback)); 557d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 558d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 559d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 560d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 561d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 562d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private static final class WatcherStartCallback implements Runnable { 563d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private IMediaProjectionWatcherCallback mCallback; 564d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private MediaProjectionInfo mInfo; 565d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 566d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public WatcherStartCallback(MediaProjectionInfo info, 567d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright IMediaProjectionWatcherCallback callback) { 568d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mInfo = info; 569d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mCallback = callback; 570d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 571d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 572d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright @Override 573d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void run() { 574d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright try { 575d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mCallback.onStart(mInfo); 576d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } catch (RemoteException e) { 577d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright Slog.w(TAG, "Failed to notify media projection has stopped", e); 578d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 579d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 580d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 581d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 582d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private static final class WatcherStopCallback implements Runnable { 583d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private IMediaProjectionWatcherCallback mCallback; 584d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private MediaProjectionInfo mInfo; 585d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 586d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public WatcherStopCallback(MediaProjectionInfo info, 587d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright IMediaProjectionWatcherCallback callback) { 588d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mInfo = info; 589d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mCallback = callback; 590d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 591d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 592d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright @Override 593d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void run() { 594d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright try { 595d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mCallback.onStop(mInfo); 596d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } catch (RemoteException e) { 597d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright Slog.w(TAG, "Failed to notify media projection has stopped", e); 598d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 599d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 600c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 601c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 602d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private static final class ClientStopCallback implements Runnable { 603d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private IMediaProjectionCallback mCallback; 604d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 605d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public ClientStopCallback(IMediaProjectionCallback callback) { 606d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mCallback = callback; 607d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 608d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 609d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright @Override 610d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void run() { 611d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright try { 612d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mCallback.onStop(); 613d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } catch (RemoteException e) { 614d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright Slog.w(TAG, "Failed to notify media projection has stopped", e); 615d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 616d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 617d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 618d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 619d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 620c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright private static String typeToString(int type) { 621c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright switch (type) { 622c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright case MediaProjectionManager.TYPE_SCREEN_CAPTURE: 623c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright return "TYPE_SCREEN_CAPTURE"; 624c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright case MediaProjectionManager.TYPE_MIRRORING: 625c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright return "TYPE_MIRRORING"; 626c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright case MediaProjectionManager.TYPE_PRESENTATION: 627c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright return "TYPE_PRESENTATION"; 628c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 629c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright return Integer.toString(type); 630c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 631c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright} 632