Loading services/core/java/com/android/server/appop/AppOpsService.java +34 −13 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -784,11 +792,12 @@ 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); for (int code : OPS_RESTRICTED_ON_SUSPEND) { ArraySet<ModeCallback> callbacks; synchronized (AppOpsService.this) { callbacks = mOpModeWatchers.get(OP_PLAY_AUDIO); callbacks = mOpModeWatchers.get(code); if (callbacks == null) { return; continue; } callbacks = new ArraySet<>(callbacks); } Loading @@ -797,7 +806,8 @@ public class AppOpsService extends IAppOpsService.Stub { final String changedPkg = changedPkgs[i]; // We trust packagemanager to insert matching uid and packageNames in the // extras notifyOpChanged(callbacks, OP_PLAY_AUDIO, changedUid, changedPkg); notifyOpChanged(callbacks, code, changedUid, changedPkg); } } } }, packageSuspendFilter); Loading Loading @@ -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); Loading Loading @@ -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(); Loading services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java +26 −10 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); } Loading Loading
services/core/java/com/android/server/appop/AppOpsService.java +34 −13 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -784,11 +792,12 @@ 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); for (int code : OPS_RESTRICTED_ON_SUSPEND) { ArraySet<ModeCallback> callbacks; synchronized (AppOpsService.this) { callbacks = mOpModeWatchers.get(OP_PLAY_AUDIO); callbacks = mOpModeWatchers.get(code); if (callbacks == null) { return; continue; } callbacks = new ArraySet<>(callbacks); } Loading @@ -797,7 +806,8 @@ public class AppOpsService extends IAppOpsService.Stub { final String changedPkg = changedPkgs[i]; // We trust packagemanager to insert matching uid and packageNames in the // extras notifyOpChanged(callbacks, OP_PLAY_AUDIO, changedUid, changedPkg); notifyOpChanged(callbacks, code, changedUid, changedPkg); } } } }, packageSuspendFilter); Loading Loading @@ -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); Loading Loading @@ -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(); Loading
services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java +26 −10 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); } Loading