Merge "Grant SYSTEM_ALERT_WINDOW during screen capture." into rvc-dev am: 9b081e496d
Change-Id: I5c3b942f8c3b5acee6d20dbbe2952cf0ff0f20a3
This commit is contained in:
@@ -23,8 +23,6 @@ import android.app.Activity;
|
|||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.media.projection.IMediaProjection;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
@@ -86,6 +84,12 @@ public final class MediaProjectionManager {
|
|||||||
* capture request. Will be null if the result from the
|
* capture request. Will be null if the result from the
|
||||||
* startActivityForResult() is anything other than RESULT_OK.
|
* 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,
|
* @param resultCode The result code from {@link android.app.Activity#onActivityResult(int,
|
||||||
* int, android.content.Intent)}
|
* int, android.content.Intent)}
|
||||||
* @param resultData The resulting data from {@link android.app.Activity#onActivityResult(int,
|
* @param resultData The resulting data from {@link android.app.Activity#onActivityResult(int,
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import android.app.AppOpsManager;
|
|||||||
import android.app.IProcessObserver;
|
import android.app.IProcessObserver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import android.content.pm.ServiceInfo;
|
import android.content.pm.ServiceInfo;
|
||||||
@@ -43,6 +44,7 @@ import android.os.UserHandle;
|
|||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
|
import com.android.internal.util.ArrayUtils;
|
||||||
import com.android.internal.util.DumpUtils;
|
import com.android.internal.util.DumpUtils;
|
||||||
import com.android.server.LocalServices;
|
import com.android.server.LocalServices;
|
||||||
import com.android.server.SystemService;
|
import com.android.server.SystemService;
|
||||||
@@ -399,11 +401,12 @@ public final class MediaProjectionManagerService extends SystemService
|
|||||||
public final UserHandle userHandle;
|
public final UserHandle userHandle;
|
||||||
private final int mTargetSdkVersion;
|
private final int mTargetSdkVersion;
|
||||||
private final boolean mIsPrivileged;
|
private final boolean mIsPrivileged;
|
||||||
|
private final int mType;
|
||||||
|
|
||||||
private IMediaProjectionCallback mCallback;
|
private IMediaProjectionCallback mCallback;
|
||||||
private IBinder mToken;
|
private IBinder mToken;
|
||||||
private IBinder.DeathRecipient mDeathEater;
|
private IBinder.DeathRecipient mDeathEater;
|
||||||
private int mType;
|
private boolean mRestoreSystemAlertWindow;
|
||||||
|
|
||||||
MediaProjection(int type, int uid, String packageName, int targetSdkVersion,
|
MediaProjection(int type, int uid, String packageName, int targetSdkVersion,
|
||||||
boolean isPrivileged) {
|
boolean isPrivileged) {
|
||||||
@@ -494,6 +497,35 @@ public final class MediaProjectionManagerService extends SystemService
|
|||||||
"MediaProjectionCallbacks must be valid, aborting MediaProjection", e);
|
"MediaProjectionCallbacks must be valid, aborting MediaProjection", e);
|
||||||
return;
|
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);
|
startProjectionLocked(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -507,6 +539,24 @@ public final class MediaProjectionManagerService extends SystemService
|
|||||||
+ "pid=" + Binder.getCallingPid() + ")");
|
+ "pid=" + Binder.getCallingPid() + ")");
|
||||||
return;
|
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);
|
stopProjectionLocked(this);
|
||||||
mToken.unlinkToDeath(mDeathEater, 0);
|
mToken.unlinkToDeath(mDeathEater, 0);
|
||||||
mToken = null;
|
mToken = null;
|
||||||
|
|||||||
Reference in New Issue
Block a user