Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2ae61c92 authored by Caitlin Shkuratov's avatar Caitlin Shkuratov Committed by Android (Google) Code Review
Browse files

Merge "[SB][Privacy] Start listening for app ops on background thread." into main

parents 89b9417a 7dacad02
Loading
Loading
Loading
Loading
+40 −34
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;

import javax.inject.Inject;

@@ -84,6 +85,7 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
    private final SystemClock mClock;

    private H mBGHandler;
    private final Executor mBgExecutor;
    private final List<AppOpsController.Callback> mCallbacks = new ArrayList<>();
    private final SparseArray<Set<Callback>> mCallbacksByCode = new SparseArray<>();
    private boolean mListening;
@@ -153,6 +155,7 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
    public AppOpsControllerImpl(
            Context context,
            @Background Looper bgLooper,
            @Background Executor bgExecutor,
            DumpManager dumpManager,
            AudioManager audioManager,
            IndividualSensorPrivacyController sensorPrivacyController,
@@ -162,6 +165,7 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
        mDispatcher = dispatcher;
        mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
        mBGHandler = new H(bgLooper);
        mBgExecutor = bgExecutor;
        final int numOps = OPS.length;
        for (int i = 0; i < numOps; i++) {
            mCallbacksByCode.put(OPS[i], new ArraySet<>());
@@ -184,9 +188,11 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
    @VisibleForTesting
    protected void setListening(boolean listening) {
        mListening = listening;
        // Move IPCs to the background.
        mBgExecutor.execute(() -> {
            if (listening) {
            // System UI could be restarted while ops are active, so fetch the currently active ops
            // once System UI starts listening again.
                // System UI could be restarted while ops are active, so fetch the currently active
                // ops once System UI starts listening again -- see b/294104969.
                fetchCurrentActiveOps();

                mAppOps.startWatchingActive(OPS, this);
@@ -202,7 +208,6 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
                        mAudioManager.getActiveRecordingConfigurations()));
                mDispatcher.registerReceiverWithHandler(this,
                        new IntentFilter(ACTION_MICROPHONE_MUTE_CHANGED), mBGHandler);

            } else {
                mAppOps.stopWatchingActive(this);
                mAppOps.stopWatchingNoted(this);
@@ -219,6 +224,7 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
                    mNotedItems.clear();
                }
            }
        });
    }

    private void fetchCurrentActiveOps() {
+45 −0
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;

import org.junit.Before;
@@ -108,6 +109,7 @@ public class AppOpsControllerTest extends SysuiTestCase {

    private AppOpsControllerImpl mController;
    private TestableLooper mTestableLooper;
    private final FakeExecutor mBgExecutor = new FakeExecutor(new FakeSystemClock());

    private String mExemptedRolePkgName;

@@ -139,6 +141,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
        mController = new AppOpsControllerImpl(
                mContext,
                mTestableLooper.getLooper(),
                mBgExecutor,
                mDumpManager,
                mAudioManager,
                mSensorPrivacyController,
@@ -150,6 +153,8 @@ public class AppOpsControllerTest extends SysuiTestCase {
    @Test
    public void testOnlyListenForFewOps() {
        mController.setListening(true);
        mBgExecutor.runAllReady();

        verify(mAppOpsManager, times(1)).startWatchingActive(AppOpsControllerImpl.OPS, mController);
        verify(mDispatcher, times(1)).registerReceiverWithHandler(eq(mController), any(), any());
        verify(mSensorPrivacyController, times(1)).addCallback(mController);
@@ -158,6 +163,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
    @Test
    public void testStopListening() {
        mController.setListening(false);
        mBgExecutor.runAllReady();
        verify(mAppOpsManager, times(1)).stopWatchingActive(mController);
        verify(mDispatcher, times(1)).unregisterReceiver(mController);
        verify(mSensorPrivacyController, times(1)).removeCallback(mController);
@@ -169,6 +175,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
                .thenReturn(List.of());

        mController.setListening(true);
        mBgExecutor.runAllReady();

        assertThat(mController.getActiveAppOps()).isEmpty();
    }
@@ -186,6 +193,7 @@ public class AppOpsControllerTest extends SysuiTestCase {

        // WHEN we start listening
        mController.setListening(true);
        mBgExecutor.runAllReady();

        // THEN the active list has the op
        List<AppOpItem> list = mController.getActiveAppOps();
@@ -218,6 +226,7 @@ public class AppOpsControllerTest extends SysuiTestCase {

        // WHEN we start listening
        mController.setListening(true);
        mBgExecutor.runAllReady();

        // THEN the active list has the ops
        List<AppOpItem> list = mController.getActiveAppOps();
@@ -265,6 +274,7 @@ public class AppOpsControllerTest extends SysuiTestCase {

        // WHEN we start listening
        mController.setListening(true);
        mBgExecutor.runAllReady();

        // THEN the active list has the ops
        List<AppOpItem> list = mController.getActiveAppOps();
@@ -304,6 +314,7 @@ public class AppOpsControllerTest extends SysuiTestCase {

        // WHEN we start listening
        mController.setListening(true);
        mBgExecutor.runAllReady();

        // THEN the active list has the ops
        List<AppOpItem> list = mController.getActiveAppOps();
@@ -341,6 +352,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
        mController.addCallback(
                new int[]{AppOpsManager.OP_RECORD_AUDIO, AppOpsManager.OP_FINE_LOCATION},
                mCallback);
        mBgExecutor.runAllReady();
        mTestableLooper.processAllMessages();

        // THEN the callback is notified of the current active ops it cares about
@@ -366,11 +378,14 @@ public class AppOpsControllerTest extends SysuiTestCase {
        mController.addCallback(
                new int[]{AppOpsManager.OP_RECORD_AUDIO, AppOpsManager.OP_FINE_LOCATION},
                mCallback);
        mBgExecutor.runAllReady();

        mController.onOpActiveChanged(
                AppOpsManager.OPSTR_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
        mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
                TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
        mTestableLooper.processAllMessages();

        verify(mCallback).onActiveStateChanged(AppOpsManager.OP_RECORD_AUDIO,
                TEST_UID, TEST_PACKAGE_NAME, true);
    }
@@ -383,6 +398,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
    public void addCallback_partialIncludedCode() {
        mController.addCallback(new int[]{AppOpsManager.OP_RECEIVE_SANDBOX_TRIGGER_AUDIO,
                AppOpsManager.OP_FINE_LOCATION}, mCallback);
        mBgExecutor.runAllReady();
        mController.onOpActiveChanged(
                AppOpsManager.OPSTR_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
        mController.onOpActiveChanged(
@@ -400,9 +416,12 @@ public class AppOpsControllerTest extends SysuiTestCase {
    @Test
    public void addCallback_notIncludedCode() {
        mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback);
        mBgExecutor.runAllReady();

        mController.onOpActiveChanged(
                AppOpsManager.OPSTR_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
        mTestableLooper.processAllMessages();

        verify(mCallback, never()).onActiveStateChanged(
                anyInt(), anyInt(), anyString(), anyBoolean());
    }
@@ -410,7 +429,10 @@ public class AppOpsControllerTest extends SysuiTestCase {
    @Test
    public void removeCallback_sameCode() {
        mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback);
        mBgExecutor.runAllReady();

        mController.removeCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback);
        mBgExecutor.runAllReady();
        mController.onOpActiveChanged(
                AppOpsManager.OPSTR_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
        mTestableLooper.processAllMessages();
@@ -421,7 +443,10 @@ public class AppOpsControllerTest extends SysuiTestCase {
    @Test
    public void addCallback_notSameCode() {
        mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback);
        mBgExecutor.runAllReady();

        mController.removeCallback(new int[]{AppOpsManager.OP_CAMERA}, mCallback);
        mBgExecutor.runAllReady();
        mController.onOpActiveChanged(
                AppOpsManager.OPSTR_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
        mTestableLooper.processAllMessages();
@@ -484,6 +509,8 @@ public class AppOpsControllerTest extends SysuiTestCase {
        assumeFalse(mExemptedRolePkgName == null || mExemptedRolePkgName.equals(""));

        mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback);
        mBgExecutor.runAllReady();

        mController.onOpActiveChanged(AppOpsManager.OPSTR_RECORD_AUDIO,
                TEST_UID_NON_USER_SENSITIVE, mExemptedRolePkgName, true);

@@ -506,6 +533,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
        mController.setBGHandler(mMockHandler);

        mController.setListening(true);
        mBgExecutor.runAllReady();
        mController.onOpActiveChanged(AppOpsManager.OPSTR_FINE_LOCATION, TEST_UID,
                TEST_PACKAGE_NAME, true);
        mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
@@ -513,6 +541,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
        assertFalse(mController.getActiveAppOps().isEmpty());

        mController.setListening(false);
        mBgExecutor.runAllReady();

        verify(mMockHandler).removeCallbacksAndMessages(null);
        assertTrue(mController.getActiveAppOps().isEmpty());
@@ -583,6 +612,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
        TestHandler testHandler = new TestHandler(mTestableLooper.getLooper());

        mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback);
        mBgExecutor.runAllReady();
        mController.setBGHandler(testHandler);

        mController.onOpActiveChanged(
@@ -616,6 +646,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
    @Test
    public void testNotedNotRemovedAfterActive() {
        mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback);
        mBgExecutor.runAllReady();

        mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
                TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
@@ -645,6 +676,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
    @Test
    public void testNotedAndActiveOnlyOneCall() {
        mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback);
        mBgExecutor.runAllReady();

        mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
                TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
@@ -660,6 +692,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
    @Test
    public void testActiveAndNotedOnlyOneCall() {
        mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback);
        mBgExecutor.runAllReady();

        mController.onOpActiveChanged(
                AppOpsManager.OPSTR_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
@@ -675,6 +708,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
    @Test
    public void testPausedRecordingIsRetrievedOnCreation() {
        mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback);
        mBgExecutor.runAllReady();
        mTestableLooper.processAllMessages();

        mController.onOpActiveChanged(
@@ -688,6 +722,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
    @Test
    public void testPausedRecordingFilteredOut() {
        mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback);
        mBgExecutor.runAllReady();
        mTestableLooper.processAllMessages();

        mController.onOpActiveChanged(
@@ -700,6 +735,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
    @Test
    public void testPausedPhoneCallMicrophoneFilteredOut() {
        mController.addCallback(new int[]{AppOpsManager.OP_PHONE_CALL_MICROPHONE}, mCallback);
        mBgExecutor.runAllReady();
        mTestableLooper.processAllMessages();

        mController.onOpActiveChanged(
@@ -715,6 +751,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
                AppOpsManager.OP_RECORD_AUDIO,
                AppOpsManager.OP_CAMERA
        }, mCallback);
        mBgExecutor.runAllReady();
        mTestableLooper.processAllMessages();

        mController.onOpActiveChanged(
@@ -751,6 +788,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
        // 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);
        mBgExecutor.runAllReady();
        mTestableLooper.processAllMessages();
        mController.onOpActiveChanged(
                AppOpsManager.opToPublicName(micOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
@@ -779,6 +817,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
        // 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);
        mBgExecutor.runAllReady();
        mTestableLooper.processAllMessages();
        mController.onOpActiveChanged(
                AppOpsManager.opToPublicName(micOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
@@ -807,6 +846,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
        // 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);
        mBgExecutor.runAllReady();
        mTestableLooper.processAllMessages();
        mController.onOpActiveChanged(
                AppOpsManager.opToPublicName(micOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
@@ -835,6 +875,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
        // 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);
        mBgExecutor.runAllReady();
        mTestableLooper.processAllMessages();
        mController.onOpActiveChanged(
                AppOpsManager.opToPublicName(micOp), TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
@@ -859,6 +900,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
    public void testCameraFilteredWhenCameraDisabled() {
        mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO, AppOpsManager.OP_CAMERA},
                mCallback);
        mBgExecutor.runAllReady();
        mTestableLooper.processAllMessages();
        mController.onOpActiveChanged(
                AppOpsManager.OPSTR_CAMERA, TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
@@ -892,6 +934,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
        mController.addCallback(
                new int[]{AppOpsManager.OP_RECORD_AUDIO, AppOpsManager.OP_PHONE_CALL_CAMERA},
                mCallback);
        mBgExecutor.runAllReady();
        mTestableLooper.processAllMessages();
        mController.onOpActiveChanged(
                AppOpsManager.OPSTR_PHONE_CALL_CAMERA, TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
@@ -922,6 +965,7 @@ public class AppOpsControllerTest extends SysuiTestCase {

    private void verifyUnPausedSentActive(int micOpCode) {
        mController.addCallback(new int[]{micOpCode}, mCallback);
        mBgExecutor.runAllReady();
        mTestableLooper.processAllMessages();
        mController.onOpActiveChanged(AppOpsManager.opToPublicName(micOpCode), TEST_UID,
                TEST_PACKAGE_NAME, true);
@@ -936,6 +980,7 @@ public class AppOpsControllerTest extends SysuiTestCase {

    private void verifyAudioPausedSentInactive(int micOpCode) {
        mController.addCallback(new int[]{micOpCode}, mCallback);
        mBgExecutor.runAllReady();
        mTestableLooper.processAllMessages();
        mController.onOpActiveChanged(AppOpsManager.opToPublicName(micOpCode), TEST_UID_OTHER,
                TEST_PACKAGE_NAME, true);