Loading packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java +1 −3 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ import android.os.UserHandle; import android.permission.PermissionManager; import android.util.ArraySet; import android.util.Log; import android.util.Slog; import android.util.SparseArray; import androidx.annotation.WorkerThread; Loading Loading @@ -122,7 +121,6 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon AppOpsManager.OP_SYSTEM_ALERT_WINDOW }; protected static final int[] OPS = concatOps(OPS_MIC, OPS_CAMERA, OPS_LOC, OPS_OTHERS); /** Loading packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java +102 −38 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE; import static com.android.systemui.appops.AppOpsControllerImpl.OPS_MIC; import static com.google.common.truth.Truth.assertThat; import static junit.framework.TestCase.assertFalse; import static org.junit.Assert.assertEquals; Loading Loading @@ -66,6 +68,7 @@ import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.Arrays; import java.util.Collections; import java.util.List; Loading Loading @@ -543,69 +546,114 @@ public class AppOpsControllerTest extends SysuiTestCase { @Test public void testAudioFilteredWhenMicDisabled() { mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO, AppOpsManager.OP_CAMERA}, mCallback); int micOp = AppOpsManager.OP_RECORD_AUDIO; int nonMicOp = AppOpsManager.OP_CAMERA; // Add callbacks for the micOp and nonMicOp, called for the micOp active state change, // verify the micOp is the only active op returned. mController.addCallback(new int[]{micOp, nonMicOp}, mCallback); mTestableLooper.processAllMessages(); mController.onOpActiveChanged( AppOpsManager.OPSTR_RECORD_AUDIO, TEST_UID_OTHER, TEST_PACKAGE_NAME, true); AppOpsManager.opToPublicName(micOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true); mTestableLooper.processAllMessages(); List<AppOpItem> list = mController.getActiveAppOps(); assertEquals(1, list.size()); assertEquals(AppOpsManager.OP_RECORD_AUDIO, list.get(0).getCode()); assertFalse(list.get(0).isDisabled()); verifySingleActiveOps(micOp); // Add a camera op, and disable the microphone. The camera op should be the only op returned // Add a non-mic op, and disable the microphone. The camera op should be the only active op // returned. mController.onSensorBlockedChanged(MICROPHONE, true); mController.onOpActiveChanged( AppOpsManager.OPSTR_CAMERA, TEST_UID_OTHER, TEST_PACKAGE_NAME, true); mController.onOpActiveChanged(AppOpsManager.opToPublicName(nonMicOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true); mTestableLooper.processAllMessages(); list = mController.getActiveAppOps(); assertEquals(1, list.size()); assertEquals(AppOpsManager.OP_CAMERA, list.get(0).getCode()); verifySingleActiveOps(nonMicOp); // Re enable the microphone, and verify the op returns // Re-enable the microphone, and verify the active op returns. mController.onSensorBlockedChanged(MICROPHONE, false); mTestableLooper.processAllMessages(); list = mController.getActiveAppOps(); assertEquals(2, list.size()); int micIdx = list.get(0).getCode() == AppOpsManager.OP_CAMERA ? 1 : 0; assertEquals(AppOpsManager.OP_RECORD_AUDIO, list.get(micIdx).getCode()); verifyActiveOps(micOp, nonMicOp); } @Test public void testPhoneCallMicrophoneFilteredWhenMicDisabled() { mController.addCallback( new int[]{AppOpsManager.OP_PHONE_CALL_MICROPHONE, AppOpsManager.OP_CAMERA}, mCallback); int micOp = AppOpsManager.OP_PHONE_CALL_MICROPHONE; int nonMicOp = AppOpsManager.OP_CAMERA; // Add callbacks for the micOp and nonMicOp, called for the micOp active state change, // verify the micOp is the only active op returned. mController.addCallback(new int[]{micOp, nonMicOp}, mCallback); mTestableLooper.processAllMessages(); mController.onOpActiveChanged( AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE, TEST_UID_OTHER, TEST_PACKAGE_NAME, true); AppOpsManager.opToPublicName(micOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true); mTestableLooper.processAllMessages(); List<AppOpItem> list = mController.getActiveAppOps(); assertEquals(1, list.size()); assertEquals(AppOpsManager.OP_PHONE_CALL_MICROPHONE, list.get(0).getCode()); assertFalse(list.get(0).isDisabled()); verifySingleActiveOps(micOp); // Add a camera op, and disable the microphone. The camera op should be the only op returned // Add a non-mic op, and disable the microphone. The camera op should be the only active op // returned. mController.onSensorBlockedChanged(MICROPHONE, true); mController.onOpActiveChanged(AppOpsManager.opToPublicName(nonMicOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true); mTestableLooper.processAllMessages(); verifySingleActiveOps(nonMicOp); // Re-enable the microphone, and verify the active op returns. mController.onSensorBlockedChanged(MICROPHONE, false); mTestableLooper.processAllMessages(); verifyActiveOps(micOp, nonMicOp); } @Test public void testAmbientTriggerMicrophoneFilteredWhenMicDisabled() { int micOp = AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO; int nonMicOp = AppOpsManager.OP_CAMERA; // Add callbacks for the micOp and nonMicOp, called for the micOp active state change, // verify the micOp is the only active op returned. mController.addCallback(new int[]{micOp, nonMicOp}, mCallback); mTestableLooper.processAllMessages(); mController.onOpActiveChanged( AppOpsManager.OPSTR_CAMERA, TEST_UID_OTHER, TEST_PACKAGE_NAME, true); AppOpsManager.opToPublicName(micOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true); mTestableLooper.processAllMessages(); list = mController.getActiveAppOps(); assertEquals(1, list.size()); assertEquals(AppOpsManager.OP_CAMERA, list.get(0).getCode()); verifySingleActiveOps(micOp); // Add a non-mic op, and disable the microphone. The camera op should be the only active op // returned. mController.onSensorBlockedChanged(MICROPHONE, true); mController.onOpActiveChanged(AppOpsManager.opToPublicName(nonMicOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true); mTestableLooper.processAllMessages(); verifySingleActiveOps(nonMicOp); // Re enable the microphone, and verify the op returns // Re-enable the microphone, and verify the active op returns. mController.onSensorBlockedChanged(MICROPHONE, false); mTestableLooper.processAllMessages(); verifyActiveOps(micOp, nonMicOp); } list = mController.getActiveAppOps(); assertEquals(2, list.size()); int micIdx = list.get(0).getCode() == AppOpsManager.OP_CAMERA ? 1 : 0; assertEquals(AppOpsManager.OP_PHONE_CALL_MICROPHONE, list.get(micIdx).getCode()); @Test public void testSandboxTriggerMicrophoneFilteredWhenMicDisabled() { int micOp = AppOpsManager.OP_RECEIVE_SANDBOX_TRIGGER_AUDIO; int nonMicOp = AppOpsManager.OP_CAMERA; // Add callbacks for the micOp and nonMicOp, called for the micOp active state change, // verify the micOp is the only active op returned. mController.addCallback(new int[]{micOp, nonMicOp}, mCallback); mTestableLooper.processAllMessages(); mController.onOpActiveChanged( AppOpsManager.opToPublicName(micOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true); mTestableLooper.processAllMessages(); verifySingleActiveOps(micOp); // Add a non-mic op, and disable the microphone. The camera op should be the only active op // returned. mController.onSensorBlockedChanged(MICROPHONE, true); mController.onOpActiveChanged(AppOpsManager.opToPublicName(nonMicOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true); mTestableLooper.processAllMessages(); verifySingleActiveOps(nonMicOp); // Re-enable the microphone, and verify the active op returns. mController.onSensorBlockedChanged(MICROPHONE, false); mTestableLooper.processAllMessages(); verifyActiveOps(micOp, nonMicOp); } @Test Loading Loading @@ -708,6 +756,22 @@ public class AppOpsControllerTest extends SysuiTestCase { micOpCode, TEST_UID_OTHER, TEST_PACKAGE_NAME, false); } private void verifySingleActiveOps(int op) { List<AppOpItem> list = mController.getActiveAppOps(); assertEquals(1, list.size()); assertEquals(op, list.get(0).getCode()); assertFalse(list.get(0).isDisabled()); } private void verifyActiveOps(int micOp, int nonMicOp) { List<AppOpItem> list = mController.getActiveAppOps(); assertEquals(2, list.size()); List<Integer> codes = Arrays.asList(list.get(0).getCode(), list.get(1).getCode()); assertThat(codes).containsExactly(micOp, nonMicOp); assertFalse(list.get(0).isDisabled()); assertFalse(list.get(1).isDisabled()); } private class TestHandler extends AppOpsControllerImpl.H { TestHandler(Looper looper) { mController.super(looper); Loading services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java +3 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import static android.app.AppOpsManager.OP_PHONE_CALL_CAMERA; import static android.app.AppOpsManager.OP_PHONE_CALL_MICROPHONE; import static android.app.AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO; import static android.app.AppOpsManager.OP_RECEIVE_EXPLICIT_USER_INTERACTION_AUDIO; import static android.app.AppOpsManager.OP_RECEIVE_SANDBOX_TRIGGER_AUDIO; import static android.app.AppOpsManager.OP_RECORD_AUDIO; import static android.content.Intent.EXTRA_PACKAGE_NAME; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; Loading Loading @@ -1125,6 +1126,8 @@ public final class SensorPrivacyService extends SystemService { case MICROPHONE: mAppOpsManagerInternal.setGlobalRestriction(OP_RECORD_AUDIO, enabled, mAppOpsRestrictionToken); mAppOpsManagerInternal.setGlobalRestriction( OP_RECEIVE_SANDBOX_TRIGGER_AUDIO, enabled, mAppOpsRestrictionToken); mAppOpsManagerInternal.setGlobalRestriction(OP_PHONE_CALL_MICROPHONE, enabled, mAppOpsRestrictionToken); // We don't show the dialog for RECEIVE_SOUNDTRIGGER_AUDIO, but still want to Loading Loading
packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java +1 −3 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ import android.os.UserHandle; import android.permission.PermissionManager; import android.util.ArraySet; import android.util.Log; import android.util.Slog; import android.util.SparseArray; import androidx.annotation.WorkerThread; Loading Loading @@ -122,7 +121,6 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon AppOpsManager.OP_SYSTEM_ALERT_WINDOW }; protected static final int[] OPS = concatOps(OPS_MIC, OPS_CAMERA, OPS_LOC, OPS_OTHERS); /** Loading
packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java +102 −38 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE; import static com.android.systemui.appops.AppOpsControllerImpl.OPS_MIC; import static com.google.common.truth.Truth.assertThat; import static junit.framework.TestCase.assertFalse; import static org.junit.Assert.assertEquals; Loading Loading @@ -66,6 +68,7 @@ import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.Arrays; import java.util.Collections; import java.util.List; Loading Loading @@ -543,69 +546,114 @@ public class AppOpsControllerTest extends SysuiTestCase { @Test public void testAudioFilteredWhenMicDisabled() { mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO, AppOpsManager.OP_CAMERA}, mCallback); int micOp = AppOpsManager.OP_RECORD_AUDIO; int nonMicOp = AppOpsManager.OP_CAMERA; // Add callbacks for the micOp and nonMicOp, called for the micOp active state change, // verify the micOp is the only active op returned. mController.addCallback(new int[]{micOp, nonMicOp}, mCallback); mTestableLooper.processAllMessages(); mController.onOpActiveChanged( AppOpsManager.OPSTR_RECORD_AUDIO, TEST_UID_OTHER, TEST_PACKAGE_NAME, true); AppOpsManager.opToPublicName(micOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true); mTestableLooper.processAllMessages(); List<AppOpItem> list = mController.getActiveAppOps(); assertEquals(1, list.size()); assertEquals(AppOpsManager.OP_RECORD_AUDIO, list.get(0).getCode()); assertFalse(list.get(0).isDisabled()); verifySingleActiveOps(micOp); // Add a camera op, and disable the microphone. The camera op should be the only op returned // Add a non-mic op, and disable the microphone. The camera op should be the only active op // returned. mController.onSensorBlockedChanged(MICROPHONE, true); mController.onOpActiveChanged( AppOpsManager.OPSTR_CAMERA, TEST_UID_OTHER, TEST_PACKAGE_NAME, true); mController.onOpActiveChanged(AppOpsManager.opToPublicName(nonMicOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true); mTestableLooper.processAllMessages(); list = mController.getActiveAppOps(); assertEquals(1, list.size()); assertEquals(AppOpsManager.OP_CAMERA, list.get(0).getCode()); verifySingleActiveOps(nonMicOp); // Re enable the microphone, and verify the op returns // Re-enable the microphone, and verify the active op returns. mController.onSensorBlockedChanged(MICROPHONE, false); mTestableLooper.processAllMessages(); list = mController.getActiveAppOps(); assertEquals(2, list.size()); int micIdx = list.get(0).getCode() == AppOpsManager.OP_CAMERA ? 1 : 0; assertEquals(AppOpsManager.OP_RECORD_AUDIO, list.get(micIdx).getCode()); verifyActiveOps(micOp, nonMicOp); } @Test public void testPhoneCallMicrophoneFilteredWhenMicDisabled() { mController.addCallback( new int[]{AppOpsManager.OP_PHONE_CALL_MICROPHONE, AppOpsManager.OP_CAMERA}, mCallback); int micOp = AppOpsManager.OP_PHONE_CALL_MICROPHONE; int nonMicOp = AppOpsManager.OP_CAMERA; // Add callbacks for the micOp and nonMicOp, called for the micOp active state change, // verify the micOp is the only active op returned. mController.addCallback(new int[]{micOp, nonMicOp}, mCallback); mTestableLooper.processAllMessages(); mController.onOpActiveChanged( AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE, TEST_UID_OTHER, TEST_PACKAGE_NAME, true); AppOpsManager.opToPublicName(micOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true); mTestableLooper.processAllMessages(); List<AppOpItem> list = mController.getActiveAppOps(); assertEquals(1, list.size()); assertEquals(AppOpsManager.OP_PHONE_CALL_MICROPHONE, list.get(0).getCode()); assertFalse(list.get(0).isDisabled()); verifySingleActiveOps(micOp); // Add a camera op, and disable the microphone. The camera op should be the only op returned // Add a non-mic op, and disable the microphone. The camera op should be the only active op // returned. mController.onSensorBlockedChanged(MICROPHONE, true); mController.onOpActiveChanged(AppOpsManager.opToPublicName(nonMicOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true); mTestableLooper.processAllMessages(); verifySingleActiveOps(nonMicOp); // Re-enable the microphone, and verify the active op returns. mController.onSensorBlockedChanged(MICROPHONE, false); mTestableLooper.processAllMessages(); verifyActiveOps(micOp, nonMicOp); } @Test public void testAmbientTriggerMicrophoneFilteredWhenMicDisabled() { int micOp = AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO; int nonMicOp = AppOpsManager.OP_CAMERA; // Add callbacks for the micOp and nonMicOp, called for the micOp active state change, // verify the micOp is the only active op returned. mController.addCallback(new int[]{micOp, nonMicOp}, mCallback); mTestableLooper.processAllMessages(); mController.onOpActiveChanged( AppOpsManager.OPSTR_CAMERA, TEST_UID_OTHER, TEST_PACKAGE_NAME, true); AppOpsManager.opToPublicName(micOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true); mTestableLooper.processAllMessages(); list = mController.getActiveAppOps(); assertEquals(1, list.size()); assertEquals(AppOpsManager.OP_CAMERA, list.get(0).getCode()); verifySingleActiveOps(micOp); // Add a non-mic op, and disable the microphone. The camera op should be the only active op // returned. mController.onSensorBlockedChanged(MICROPHONE, true); mController.onOpActiveChanged(AppOpsManager.opToPublicName(nonMicOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true); mTestableLooper.processAllMessages(); verifySingleActiveOps(nonMicOp); // Re enable the microphone, and verify the op returns // Re-enable the microphone, and verify the active op returns. mController.onSensorBlockedChanged(MICROPHONE, false); mTestableLooper.processAllMessages(); verifyActiveOps(micOp, nonMicOp); } list = mController.getActiveAppOps(); assertEquals(2, list.size()); int micIdx = list.get(0).getCode() == AppOpsManager.OP_CAMERA ? 1 : 0; assertEquals(AppOpsManager.OP_PHONE_CALL_MICROPHONE, list.get(micIdx).getCode()); @Test public void testSandboxTriggerMicrophoneFilteredWhenMicDisabled() { int micOp = AppOpsManager.OP_RECEIVE_SANDBOX_TRIGGER_AUDIO; int nonMicOp = AppOpsManager.OP_CAMERA; // Add callbacks for the micOp and nonMicOp, called for the micOp active state change, // verify the micOp is the only active op returned. mController.addCallback(new int[]{micOp, nonMicOp}, mCallback); mTestableLooper.processAllMessages(); mController.onOpActiveChanged( AppOpsManager.opToPublicName(micOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true); mTestableLooper.processAllMessages(); verifySingleActiveOps(micOp); // Add a non-mic op, and disable the microphone. The camera op should be the only active op // returned. mController.onSensorBlockedChanged(MICROPHONE, true); mController.onOpActiveChanged(AppOpsManager.opToPublicName(nonMicOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true); mTestableLooper.processAllMessages(); verifySingleActiveOps(nonMicOp); // Re-enable the microphone, and verify the active op returns. mController.onSensorBlockedChanged(MICROPHONE, false); mTestableLooper.processAllMessages(); verifyActiveOps(micOp, nonMicOp); } @Test Loading Loading @@ -708,6 +756,22 @@ public class AppOpsControllerTest extends SysuiTestCase { micOpCode, TEST_UID_OTHER, TEST_PACKAGE_NAME, false); } private void verifySingleActiveOps(int op) { List<AppOpItem> list = mController.getActiveAppOps(); assertEquals(1, list.size()); assertEquals(op, list.get(0).getCode()); assertFalse(list.get(0).isDisabled()); } private void verifyActiveOps(int micOp, int nonMicOp) { List<AppOpItem> list = mController.getActiveAppOps(); assertEquals(2, list.size()); List<Integer> codes = Arrays.asList(list.get(0).getCode(), list.get(1).getCode()); assertThat(codes).containsExactly(micOp, nonMicOp); assertFalse(list.get(0).isDisabled()); assertFalse(list.get(1).isDisabled()); } private class TestHandler extends AppOpsControllerImpl.H { TestHandler(Looper looper) { mController.super(looper); Loading
services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java +3 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import static android.app.AppOpsManager.OP_PHONE_CALL_CAMERA; import static android.app.AppOpsManager.OP_PHONE_CALL_MICROPHONE; import static android.app.AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO; import static android.app.AppOpsManager.OP_RECEIVE_EXPLICIT_USER_INTERACTION_AUDIO; import static android.app.AppOpsManager.OP_RECEIVE_SANDBOX_TRIGGER_AUDIO; import static android.app.AppOpsManager.OP_RECORD_AUDIO; import static android.content.Intent.EXTRA_PACKAGE_NAME; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; Loading Loading @@ -1125,6 +1126,8 @@ public final class SensorPrivacyService extends SystemService { case MICROPHONE: mAppOpsManagerInternal.setGlobalRestriction(OP_RECORD_AUDIO, enabled, mAppOpsRestrictionToken); mAppOpsManagerInternal.setGlobalRestriction( OP_RECEIVE_SANDBOX_TRIGGER_AUDIO, enabled, mAppOpsRestrictionToken); mAppOpsManagerInternal.setGlobalRestriction(OP_PHONE_CALL_MICROPHONE, enabled, mAppOpsRestrictionToken); // We don't show the dialog for RECEIVE_SOUNDTRIGGER_AUDIO, but still want to Loading