DO NOT MERGE revoke certain app-ops on suspend
Revoking an apps authorizations to use camera and record or play audio
while suspended. Appops watchers will also be notified of this change to
re-evaluate privileges at the time of suspension.
Test: atest FrameworksServicesTests:SuspendPackagesTest
atest GtsSuspendAppsTestCases
Bug: 138636979
Change-Id: Ie95555856afdd56728125f7e60b6a78cf9fc0e58
Merged-In: Ic5fb1807deceabfd956b666fa76f8bcc94020ac3
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 7569363..f0fac67 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -18,9 +18,11 @@
import static android.app.AppOpsManager.MAX_PRIORITY_UID_STATE;
import static android.app.AppOpsManager.MIN_PRIORITY_UID_STATE;
+import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_FLAGS_ALL;
import static android.app.AppOpsManager.OP_NONE;
import static android.app.AppOpsManager.OP_PLAY_AUDIO;
+import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.app.AppOpsManager.UID_STATE_BACKGROUND;
import static android.app.AppOpsManager.UID_STATE_CACHED;
import static android.app.AppOpsManager.UID_STATE_FOREGROUND;
@@ -173,6 +175,12 @@
UID_STATE_CACHED, // ActivityManager.PROCESS_STATE_NONEXISTENT
};
+ private static final int[] OPS_RESTRICTED_ON_SUSPEND = {
+ OP_PLAY_AUDIO,
+ OP_RECORD_AUDIO,
+ OP_CAMERA,
+ };
+
Context mContext;
final AtomicFile mFile;
final Handler mHandler;
@@ -784,20 +792,22 @@
final int[] changedUids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
final String[] changedPkgs = intent.getStringArrayExtra(
Intent.EXTRA_CHANGED_PACKAGE_LIST);
- ArraySet<ModeCallback> callbacks;
- synchronized (AppOpsService.this) {
- callbacks = mOpModeWatchers.get(OP_PLAY_AUDIO);
- if (callbacks == null) {
- return;
+ for (int code : OPS_RESTRICTED_ON_SUSPEND) {
+ ArraySet<ModeCallback> callbacks;
+ synchronized (AppOpsService.this) {
+ callbacks = mOpModeWatchers.get(code);
+ if (callbacks == null) {
+ continue;
+ }
+ callbacks = new ArraySet<>(callbacks);
}
- callbacks = new ArraySet<>(callbacks);
- }
- for (int i = 0; i < changedUids.length; i++) {
- final int changedUid = changedUids[i];
- final String changedPkg = changedPkgs[i];
- // We trust packagemanager to insert matching uid and packageNames in the
- // extras
- notifyOpChanged(callbacks, OP_PLAY_AUDIO, changedUid, changedPkg);
+ for (int i = 0; i < changedUids.length; i++) {
+ final int changedUid = changedUids[i];
+ final String changedPkg = changedPkgs[i];
+ // We trust packagemanager to insert matching uid and packageNames in the
+ // extras
+ notifyOpChanged(callbacks, code, changedUid, changedPkg);
+ }
}
}
}, packageSuspendFilter);
@@ -1800,6 +1810,9 @@
*/
private @Mode int checkOperationUnchecked(int code, int uid, @NonNull String packageName,
boolean raw, boolean verify) {
+ if (isOpRestrictedDueToSuspend(code, packageName, uid)) {
+ return AppOpsManager.MODE_IGNORED;
+ }
synchronized (this) {
if (verify) {
checkPackage(uid, packageName);
@@ -2654,6 +2667,14 @@
return op;
}
+ private boolean isOpRestrictedDueToSuspend(int code, String packageName, int uid) {
+ if (!ArrayUtils.contains(OPS_RESTRICTED_ON_SUSPEND, code)) {
+ return false;
+ }
+ final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
+ return pmi.isPackageSuspended(packageName, UserHandle.getUserId(uid));
+ }
+
private boolean isOpRestrictedLocked(int uid, int code, String packageName) {
int userHandle = UserHandle.getUserId(uid);
final int restrictionSetCount = mOpUserRestrictions.size();