Loading media/java/android/media/projection/MediaProjectionManager.java +6 −2 Original line number Diff line number Diff line Loading @@ -23,8 +23,6 @@ import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.media.projection.IMediaProjection; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; Loading Loading @@ -86,6 +84,12 @@ public final class MediaProjectionManager { * capture request. Will be null if the result from the * startActivityForResult() is anything other than RESULT_OK. * * Starting from Android {@link android.os.Build.VERSION_CODES#R}, if your application requests * the {@link android.Manifest.permission#SYSTEM_ALERT_WINDOW} permission, and the * user has not explicitly denied it, the permission will be automatically granted until the * projection is stopped. This allows for user controls to be displayed on top of the screen * being captured. * * @param resultCode The result code from {@link android.app.Activity#onActivityResult(int, * int, android.content.Intent)} * @param resultData The resulting data from {@link android.app.Activity#onActivityResult(int, Loading services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java +51 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.app.AppOpsManager; import android.app.IProcessObserver; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ServiceInfo; Loading @@ -43,6 +44,7 @@ import android.os.UserHandle; import android.util.ArrayMap; import android.util.Slog; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.server.LocalServices; import com.android.server.SystemService; Loading Loading @@ -399,11 +401,12 @@ public final class MediaProjectionManagerService extends SystemService public final UserHandle userHandle; private final int mTargetSdkVersion; private final boolean mIsPrivileged; private final int mType; private IMediaProjectionCallback mCallback; private IBinder mToken; private IBinder.DeathRecipient mDeathEater; private int mType; private boolean mRestoreSystemAlertWindow; MediaProjection(int type, int uid, String packageName, int targetSdkVersion, boolean isPrivileged) { Loading Loading @@ -494,6 +497,35 @@ public final class MediaProjectionManagerService extends SystemService "MediaProjectionCallbacks must be valid, aborting MediaProjection", e); return; } if (mType == MediaProjectionManager.TYPE_SCREEN_CAPTURE) { final long token = Binder.clearCallingIdentity(); try { // We allow an app running a current screen capture session to use // SYSTEM_ALERT_WINDOW for the duration of the session, to enable // them to overlay their UX on top of what is being captured. // We only do this if the app requests the permission, and the appop // is in its default state (the user has neither explicitly allowed nor // disallowed it). final PackageInfo packageInfo = mPackageManager.getPackageInfoAsUser( packageName, PackageManager.GET_PERMISSIONS, UserHandle.getUserId(uid)); if (ArrayUtils.contains(packageInfo.requestedPermissions, Manifest.permission.SYSTEM_ALERT_WINDOW)) { final int currentMode = mAppOps.unsafeCheckOpRawNoThrow( AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid, packageName); if (currentMode == AppOpsManager.MODE_DEFAULT) { mAppOps.setMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid, packageName, AppOpsManager.MODE_ALLOWED); mRestoreSystemAlertWindow = true; } } } catch (PackageManager.NameNotFoundException e) { Slog.w(TAG, "Package not found, aborting MediaProjection", e); return; } finally { Binder.restoreCallingIdentity(token); } } startProjectionLocked(this); } } Loading @@ -507,6 +539,24 @@ public final class MediaProjectionManagerService extends SystemService + "pid=" + Binder.getCallingPid() + ")"); return; } if (mRestoreSystemAlertWindow) { final long token = Binder.clearCallingIdentity(); try { // Put the appop back how it was, unless it has been changed from what // we set it to. // Note that WindowManager takes care of removing any existing overlay // windows when we do this. final int currentMode = mAppOps.unsafeCheckOpRawNoThrow( AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid, packageName); if (currentMode == AppOpsManager.MODE_ALLOWED) { mAppOps.setMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid, packageName, AppOpsManager.MODE_DEFAULT); } mRestoreSystemAlertWindow = false; } finally { Binder.restoreCallingIdentity(token); } } stopProjectionLocked(this); mToken.unlinkToDeath(mDeathEater, 0); mToken = null; Loading Loading
media/java/android/media/projection/MediaProjectionManager.java +6 −2 Original line number Diff line number Diff line Loading @@ -23,8 +23,6 @@ import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.media.projection.IMediaProjection; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; Loading Loading @@ -86,6 +84,12 @@ public final class MediaProjectionManager { * capture request. Will be null if the result from the * startActivityForResult() is anything other than RESULT_OK. * * Starting from Android {@link android.os.Build.VERSION_CODES#R}, if your application requests * the {@link android.Manifest.permission#SYSTEM_ALERT_WINDOW} permission, and the * user has not explicitly denied it, the permission will be automatically granted until the * projection is stopped. This allows for user controls to be displayed on top of the screen * being captured. * * @param resultCode The result code from {@link android.app.Activity#onActivityResult(int, * int, android.content.Intent)} * @param resultData The resulting data from {@link android.app.Activity#onActivityResult(int, Loading
services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java +51 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.app.AppOpsManager; import android.app.IProcessObserver; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ServiceInfo; Loading @@ -43,6 +44,7 @@ import android.os.UserHandle; import android.util.ArrayMap; import android.util.Slog; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.server.LocalServices; import com.android.server.SystemService; Loading Loading @@ -399,11 +401,12 @@ public final class MediaProjectionManagerService extends SystemService public final UserHandle userHandle; private final int mTargetSdkVersion; private final boolean mIsPrivileged; private final int mType; private IMediaProjectionCallback mCallback; private IBinder mToken; private IBinder.DeathRecipient mDeathEater; private int mType; private boolean mRestoreSystemAlertWindow; MediaProjection(int type, int uid, String packageName, int targetSdkVersion, boolean isPrivileged) { Loading Loading @@ -494,6 +497,35 @@ public final class MediaProjectionManagerService extends SystemService "MediaProjectionCallbacks must be valid, aborting MediaProjection", e); return; } if (mType == MediaProjectionManager.TYPE_SCREEN_CAPTURE) { final long token = Binder.clearCallingIdentity(); try { // We allow an app running a current screen capture session to use // SYSTEM_ALERT_WINDOW for the duration of the session, to enable // them to overlay their UX on top of what is being captured. // We only do this if the app requests the permission, and the appop // is in its default state (the user has neither explicitly allowed nor // disallowed it). final PackageInfo packageInfo = mPackageManager.getPackageInfoAsUser( packageName, PackageManager.GET_PERMISSIONS, UserHandle.getUserId(uid)); if (ArrayUtils.contains(packageInfo.requestedPermissions, Manifest.permission.SYSTEM_ALERT_WINDOW)) { final int currentMode = mAppOps.unsafeCheckOpRawNoThrow( AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid, packageName); if (currentMode == AppOpsManager.MODE_DEFAULT) { mAppOps.setMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid, packageName, AppOpsManager.MODE_ALLOWED); mRestoreSystemAlertWindow = true; } } } catch (PackageManager.NameNotFoundException e) { Slog.w(TAG, "Package not found, aborting MediaProjection", e); return; } finally { Binder.restoreCallingIdentity(token); } } startProjectionLocked(this); } } Loading @@ -507,6 +539,24 @@ public final class MediaProjectionManagerService extends SystemService + "pid=" + Binder.getCallingPid() + ")"); return; } if (mRestoreSystemAlertWindow) { final long token = Binder.clearCallingIdentity(); try { // Put the appop back how it was, unless it has been changed from what // we set it to. // Note that WindowManager takes care of removing any existing overlay // windows when we do this. final int currentMode = mAppOps.unsafeCheckOpRawNoThrow( AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid, packageName); if (currentMode == AppOpsManager.MODE_ALLOWED) { mAppOps.setMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, uid, packageName, AppOpsManager.MODE_DEFAULT); } mRestoreSystemAlertWindow = false; } finally { Binder.restoreCallingIdentity(token); } } stopProjectionLocked(this); mToken.unlinkToDeath(mDeathEater, 0); mToken = null; Loading