diff options
| author | 2019-09-16 13:20:22 -0700 | |
|---|---|---|
| committer | 2019-09-16 17:12:40 -0700 | |
| commit | 873e19f63f97dbb74db499c1145a1102b1ce8fda (patch) | |
| tree | 29fcfcf024b5d72567a5edece18212e8d4f48b40 | |
| parent | 23b6339ebd2cfc0c9a82e2ab21b0e85b40c27ad1 (diff) | |
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
| -rw-r--r-- | services/core/java/com/android/server/appop/AppOpsService.java | 47 | ||||
| -rw-r--r-- | services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java | 36 |
2 files changed, 60 insertions, 23 deletions
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 7569363a7134..f0fac67f3494 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 @@ package com.android.server.appop; 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 @@ public class AppOpsService extends IAppOpsService.Stub { 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 @@ public class AppOpsService extends IAppOpsService.Stub { 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); + } + 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); } - 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); } } }, packageSuspendFilter); @@ -1800,6 +1810,9 @@ public class AppOpsService extends IAppOpsService.Stub { */ 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 @@ public class AppOpsService extends IAppOpsService.Stub { 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(); diff --git a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java index d5d32bdd00cc..376f5cd3ab47 100644 --- a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java @@ -18,7 +18,10 @@ package com.android.server.pm; import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.MODE_IGNORED; +import static android.app.AppOpsManager.OP_CAMERA; import static android.app.AppOpsManager.OP_PLAY_AUDIO; +import static android.app.AppOpsManager.OP_RECORD_AUDIO; +import static android.app.AppOpsManager.opToName; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -39,7 +42,6 @@ import android.content.pm.LauncherApps; import android.content.pm.PackageManager; import android.content.pm.SuspendDialogInfo; import android.content.res.Resources; -import android.media.AudioAttributes; import android.os.BaseBundle; import android.os.Bundle; import android.os.Handler; @@ -551,28 +553,42 @@ public class SuspendPackagesTest { } @Test - public void testAudioOpBlockedOnSuspend() throws Exception { + public void testCameraBlockedOnSuspend() throws Exception { + assertOpBlockedOnSuspend(OP_CAMERA); + } + + @Test + public void testPlayAudioBlockedOnSuspend() throws Exception { + assertOpBlockedOnSuspend(OP_PLAY_AUDIO); + } + + @Test + public void testRecordAudioBlockedOnSuspend() throws Exception { + assertOpBlockedOnSuspend(OP_RECORD_AUDIO); + } + + private void assertOpBlockedOnSuspend(int code) throws Exception { final IAppOpsService iAppOps = IAppOpsService.Stub.asInterface( ServiceManager.getService(Context.APP_OPS_SERVICE)); final CountDownLatch latch = new CountDownLatch(1); final IAppOpsCallback watcher = new IAppOpsCallback.Stub() { @Override public void opChanged(int op, int uid, String packageName) { - if (op == OP_PLAY_AUDIO && packageName.equals(TEST_APP_PACKAGE_NAME)) { + if (op == code && packageName.equals(TEST_APP_PACKAGE_NAME)) { latch.countDown(); } } }; - iAppOps.startWatchingMode(OP_PLAY_AUDIO, TEST_APP_PACKAGE_NAME, watcher); + iAppOps.startWatchingMode(code, TEST_APP_PACKAGE_NAME, watcher); final int testPackageUid = mPackageManager.getPackageUid(TEST_APP_PACKAGE_NAME, 0); - int audioOpMode = iAppOps.checkAudioOperation(OP_PLAY_AUDIO, - AudioAttributes.USAGE_UNKNOWN, testPackageUid, TEST_APP_PACKAGE_NAME); - assertEquals("Audio muted for unsuspended package", MODE_ALLOWED, audioOpMode); + int opMode = iAppOps.checkOperation(code, testPackageUid, TEST_APP_PACKAGE_NAME); + assertEquals("Op " + opToName(code) + " disallowed for unsuspended package", MODE_ALLOWED, + opMode); suspendTestPackage(null, null, null); assertTrue("AppOpsWatcher did not callback", latch.await(5, TimeUnit.SECONDS)); - audioOpMode = iAppOps.checkAudioOperation(OP_PLAY_AUDIO, - AudioAttributes.USAGE_UNKNOWN, testPackageUid, TEST_APP_PACKAGE_NAME); - assertEquals("Audio not muted for suspended package", MODE_IGNORED, audioOpMode); + opMode = iAppOps.checkOperation(code, testPackageUid, TEST_APP_PACKAGE_NAME); + assertEquals("Op " + opToName(code) + " allowed for suspended package", MODE_IGNORED, + opMode); iAppOps.stopWatchingMode(watcher); } |