summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author fayey <fayey@google.com> 2023-08-08 18:46:44 +0000
committer fayey <fayey@google.com> 2023-08-16 16:47:51 +0000
commit42f1565e340d3b9500e3913c202c43d2f5a6c35c (patch)
tree8218f29e700b401ef5277b39f1662b146b35086b
parent4db2da9c66f2c3cb5a5de1fc393fc1824d8d5081 (diff)
Ambient Activation p2.3
This change set global restriction on the OP_RECEIVE_SANDBOX_TRIGGER_AUDIO to make sure if the mic is blocked when user toggled, 1) no voice activation of the assistant app and 2) no microphone privacy indicator would be turned on. Bug: 287264308 Bug: 293930248 Test: atest com.android.systemui.appops.AppOpsControllerTest Test-manual: when test.apk is intalled(to provide voiceinternactionservice attribution tag), and voice activation op is not enabled:(AppOpsPolicy.IS_VOICE_ACTIVATION_OP_ENABLED = false && AbstractDetector.IS_IDENTITY_WITH_ATTRIBUTION_TAG = false), no OP_RECEIVE_SANDBOX_TRIGGER_AUDIO is noted. https://paste.googleplex.com/5609810593579008 When test.apk is intalled, and voice activation op is enabled (AppOpsPolicy.IS_VOICE_ACTIVATION_OP_ENABLED = true && AbstractDetector.IS_IDENTITY_WITH_ATTRIBUTION_TAG = true): https://paste.googleplex.com/5178429057007616 Change-Id: Idd066e1809b34b5209c66c3324fd6932f1ea9671
-rw-r--r--packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java140
-rw-r--r--services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java3
3 files changed, 106 insertions, 41 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index c28a9ebb98e9..1aa1c59e9443 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -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;
@@ -122,8 +121,7 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
AppOpsManager.OP_RECEIVE_EXPLICIT_USER_INTERACTION_AUDIO
};
-
- protected static final int[] OPS = concatOps(OPS_MIC, OPS_CAMERA, OPS_LOC, OPS_OTHERS);
+ protected static final int[] OPS = concatOps(OPS_MIC, OPS_CAMERA, OPS_LOC, OPS_OTHERS);
/**
* @param opArrays the given op arrays.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
index b23f7f2db01e..b100336b602f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
@@ -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;
@@ -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;
@@ -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
@@ -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);
diff --git a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java
index 76126df14bfd..87809916bcaf 100644
--- a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java
+++ b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java
@@ -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;
@@ -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