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 android.media.projection; 18c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 19c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.annotation.NonNull; 20d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wrightimport android.annotation.Nullable; 21c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.app.Activity; 22c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.content.Context; 23c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.content.Intent; 24c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.media.projection.IMediaProjection; 25d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wrightimport android.os.Handler; 26c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightimport android.os.IBinder; 27d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wrightimport android.os.RemoteException; 28d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wrightimport android.os.ServiceManager; 29d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wrightimport android.util.ArrayMap; 30d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wrightimport android.util.Log; 31d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 32d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wrightimport java.util.Map; 33c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 34c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright/** 35c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * Manages the retrieval of certain types of {@link MediaProjection} tokens. 36c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * 37c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * <p> 38c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * Get an instance of this class by calling {@link 39c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * android.content.Context#getSystemService(java.lang.String) 40c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * Context.getSystemService()} with the argument {@link 41c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * android.content.Context#MEDIA_PROJECTION_SERVICE}. 42c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * </p> 43c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright */ 44c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wrightpublic final class MediaProjectionManager { 45d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private static final String TAG = "MediaProjectionManager"; 46c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright /** @hide */ 47c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public static final String EXTRA_APP_TOKEN = "android.media.projection.extra.EXTRA_APP_TOKEN"; 48c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright /** @hide */ 49c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public static final String EXTRA_MEDIA_PROJECTION = 50c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright "android.media.projection.extra.EXTRA_MEDIA_PROJECTION"; 51c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 52c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright /** @hide */ 53c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public static final int TYPE_SCREEN_CAPTURE = 0; 54c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright /** @hide */ 55c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public static final int TYPE_MIRRORING = 1; 56c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright /** @hide */ 57c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public static final int TYPE_PRESENTATION = 2; 58c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 59c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright private Context mContext; 60d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private Map<Callback, CallbackDelegate> mCallbacks; 61d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private IMediaProjectionManager mService; 62c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 63c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright /** @hide */ 64c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public MediaProjectionManager(Context context) { 65c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright mContext = context; 66d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE); 67d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mService = IMediaProjectionManager.Stub.asInterface(b); 68d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mCallbacks = new ArrayMap<>(); 69c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 70c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 71c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright /** 72c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * Returns an Intent that <b>must</b> passed to startActivityForResult() 73c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * in order to start screen capture. The activity will prompt 74c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * the user whether to allow screen capture. The result of this 75c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * activity should be passed to getMediaProjection. 76c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright */ 77cde5bb45cc86d181d96ee69da1832e6132162871Michael Wright public Intent createScreenCaptureIntent() { 78c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright Intent i = new Intent(); 79c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright i.setClassName("com.android.systemui", 80c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright "com.android.systemui.media.MediaProjectionPermissionActivity"); 81c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright return i; 82c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 83c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright 84c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright /** 85c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * Retrieve the MediaProjection obtained from a succesful screen 86c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * capture request. Will be null if the result from the 87c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * startActivityForResult() is anything other than RESULT_OK. 88c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * 89c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * @param resultCode The result code from {@link android.app.Activity#onActivityResult(int, 90c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * int, android.content.Intent)} 91c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * @param resultData The resulting data from {@link android.app.Activity#onActivityResult(int, 92c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright * int, android.content.Intent)} 93c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright */ 94c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright public MediaProjection getMediaProjection(int resultCode, @NonNull Intent resultData) { 95c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright if (resultCode != Activity.RESULT_OK || resultData == null) { 96c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright return null; 97c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 98c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright IBinder projection = resultData.getIBinderExtra(EXTRA_MEDIA_PROJECTION); 99c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright if (projection == null) { 100c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright return null; 101c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 102c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright return new MediaProjection(mContext, IMediaProjection.Stub.asInterface(projection)); 103c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright } 104d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 105d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright /** 106d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright * Get the {@link MediaProjectionInfo} for the active {@link MediaProjection}. 107d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright * @hide 108d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright */ 109d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public MediaProjectionInfo getActiveProjectionInfo() { 110d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright try { 111d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright return mService.getActiveProjectionInfo(); 112d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } catch (RemoteException e) { 113d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright Log.e(TAG, "Unable to get the active projection info", e); 114d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 115d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright return null; 116d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 117d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 118d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright /** 119d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright * Stop the current projection if there is one. 120d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright * @hide 121d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright */ 122d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void stopActiveProjection() { 123d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright try { 124d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mService.stopActiveProjection(); 125d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } catch (RemoteException e) { 126d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright Log.e(TAG, "Unable to stop the currently active media projection", e); 127d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 128d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 129d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 130d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright /** 131d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright * Add a callback to monitor all of the {@link MediaProjection}s activity. 132d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright * Not for use by regular applications, must have the MANAGE_MEDIA_PROJECTION permission. 133d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright * @hide 134d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright */ 135d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void addCallback(@NonNull Callback callback, @Nullable Handler handler) { 136d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (callback == null) { 137d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright throw new IllegalArgumentException("callback must not be null"); 138d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 139d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright CallbackDelegate delegate = new CallbackDelegate(callback, handler); 140d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mCallbacks.put(callback, delegate); 141d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright try { 142d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mService.addCallback(delegate); 143d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } catch (RemoteException e) { 144d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright Log.e(TAG, "Unable to add callbacks to MediaProjection service", e); 145d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 146d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 147d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 148d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright /** 149d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright * Remove a MediaProjection monitoring callback. 150d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright * @hide 151d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright */ 152d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void removeCallback(@NonNull Callback callback) { 153d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (callback == null) { 154d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright throw new IllegalArgumentException("callback must not be null"); 155d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 156d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright CallbackDelegate delegate = mCallbacks.remove(callback); 157d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright try { 158d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (delegate != null) { 159d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mService.removeCallback(delegate); 160d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 161d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } catch (RemoteException e) { 162d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright Log.e(TAG, "Unable to add callbacks to MediaProjection service", e); 163d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 164d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 165d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 166d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright /** @hide */ 167d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public static abstract class Callback { 168d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public abstract void onStart(MediaProjectionInfo info); 169d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public abstract void onStop(MediaProjectionInfo info); 170d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 171d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 172d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright /** @hide */ 173d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private final static class CallbackDelegate extends IMediaProjectionWatcherCallback.Stub { 174d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private Callback mCallback; 175d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright private Handler mHandler; 176d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 177d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public CallbackDelegate(Callback callback, Handler handler) { 178d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mCallback = callback; 179d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright if (handler == null) { 180d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright handler = new Handler(); 181d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 182d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mHandler = handler; 183d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 184d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 185d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright @Override 186d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void onStart(final MediaProjectionInfo info) { 187d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mHandler.post(new Runnable() { 188d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright @Override 189d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void run() { 190d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mCallback.onStart(info); 191d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 192d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright }); 193d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 194d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright 195d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright @Override 196d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void onStop(final MediaProjectionInfo info) { 197d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mHandler.post(new Runnable() { 198d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright @Override 199d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright public void run() { 200d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright mCallback.onStop(info); 201d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 202d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright }); 203d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 204d86ecd26d78c7bcd7f820b9ef5e3f4c3eb037510Michael Wright } 205c39d47a8e7c74bd539104b0efab898ef6fc43ddfMichael Wright} 206