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

Commit 0f50a52d authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Turn off the Always-on a11y service with correct user id" into main

parents 0d6db406 d8684cf6
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -126,7 +126,7 @@ public final class AccessibilityUtils {
    }

    /**
     * Changes an accessibility component's state.
     * Changes an accessibility component's state for the calling process userId
     */
    public static void setAccessibilityServiceState(Context context, ComponentName componentName,
            boolean enabled) {
+3 −1
Original line number Diff line number Diff line
@@ -224,7 +224,9 @@ public final class ShortcutUtils {
                boolean enableA11yService = servicesWithShortcuts.contains(componentName);
                AccessibilityUtils.setAccessibilityServiceState(
                        context,
                        ComponentName.unflattenFromString(componentName), enableA11yService);
                        ComponentName.unflattenFromString(componentName),
                        enableA11yService,
                        userId);
            }
        }
    }
+101 −71
Original line number Diff line number Diff line
@@ -25,33 +25,28 @@ import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.ParceledListSlice;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.testing.TestableContext;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IAccessibilityManager;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import com.android.internal.accessibility.AccessibilityShortcutController;
import com.android.internal.accessibility.TestUtils;
import com.android.internal.accessibility.common.ShortcutConstants;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.internal.util.test.FakeSettingsProviderRule;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -79,39 +74,33 @@ public class ShortcutUtilsTest {
    private static final String STANDARD_SERVICE_COMPONENT_NAME =
            "fake.package/fake.standard.service.name";
    private static final String SERVICE_NAME_SUMMARY = "Summary";

    @Rule
    public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
    @Mock
    private IAccessibilityManager mAccessibilityManagerService;
    private ContextWrapper mContextSpy;
    private TestableContext mContext;
    @UserIdInt
    private int mDefaultUserId;

    @Before
    public void setUp() throws RemoteException {
        MockitoAnnotations.initMocks(this);
        mContextSpy = spy(
                new ContextWrapper(InstrumentationRegistry.getInstrumentation().getContext()));

        ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy);
        when(mContextSpy.getContentResolver()).thenReturn(contentResolver);
        mContext = new TestableContext(InstrumentationRegistry.getInstrumentation().getContext());
        mDefaultUserId = mContext.getContentResolver().getUserId();

        AccessibilityManager accessibilityManager =
                new AccessibilityManager(
                        mContextSpy, mock(Handler.class),
                        mAccessibilityManagerService, UserHandle.myUserId(),
                        mContext, mock(Handler.class),
                        mAccessibilityManagerService, mDefaultUserId,
                        /* serviceConnect= */ true);
        when(mContextSpy.getSystemService(Context.ACCESSIBILITY_SERVICE))
                .thenReturn(accessibilityManager);

        setupFakeA11yServiceInfos();
        mContext.addMockSystemService(Context.ACCESSIBILITY_SERVICE, accessibilityManager);
        setupFakeInstalledA11yServiceInfos();
    }

    @Test
    public void getShortcutTargets_softwareShortcutNoService_emptyResult() {
        assertThat(
                ShortcutUtils.getShortcutTargetsFromSettings(
                        mContextSpy,
                        ShortcutConstants.UserShortcutType.SOFTWARE, UserHandle.myUserId())
                        mContext,
                        ShortcutConstants.UserShortcutType.SOFTWARE, mDefaultUserId)
        ).isEmpty();
    }

@@ -119,8 +108,8 @@ public class ShortcutUtilsTest {
    public void getShortcutTargets_volumeKeyShortcutNoService_emptyResult() {
        assertThat(
                ShortcutUtils.getShortcutTargetsFromSettings(
                        mContextSpy, ShortcutConstants.UserShortcutType.HARDWARE,
                        UserHandle.myUserId())
                        mContext, ShortcutConstants.UserShortcutType.HARDWARE,
                        mDefaultUserId)
        ).isEmpty();
    }

@@ -131,8 +120,8 @@ public class ShortcutUtilsTest {

        assertThat(
                ShortcutUtils.getShortcutTargetsFromSettings(
                        mContextSpy, ShortcutConstants.UserShortcutType.SOFTWARE,
                        UserHandle.myUserId())
                        mContext, ShortcutConstants.UserShortcutType.SOFTWARE,
                        mDefaultUserId)
        ).containsExactlyElementsIn(ONE_COMPONENT);
    }

@@ -143,8 +132,8 @@ public class ShortcutUtilsTest {

        assertThat(
                ShortcutUtils.getShortcutTargetsFromSettings(
                        mContextSpy, ShortcutConstants.UserShortcutType.HARDWARE,
                        UserHandle.myUserId())
                        mContext, ShortcutConstants.UserShortcutType.HARDWARE,
                        mDefaultUserId)
        ).containsExactlyElementsIn(TWO_COMPONENTS);
    }

@@ -156,8 +145,8 @@ public class ShortcutUtilsTest {

        assertThat(
                ShortcutUtils.getShortcutTargetsFromSettings(
                        mContextSpy, ShortcutConstants.UserShortcutType.TRIPLETAP,
                        UserHandle.myUserId())
                        mContext, ShortcutConstants.UserShortcutType.TRIPLETAP,
                        mDefaultUserId)
        ).isEmpty();
    }

@@ -169,8 +158,8 @@ public class ShortcutUtilsTest {

        assertThat(
                ShortcutUtils.getShortcutTargetsFromSettings(
                        mContextSpy, ShortcutConstants.UserShortcutType.TRIPLETAP,
                        UserHandle.myUserId())
                        mContext, ShortcutConstants.UserShortcutType.TRIPLETAP,
                        mDefaultUserId)
        ).containsExactly(ACCESSIBILITY_SHORTCUT_TARGET_MAGNIFICATION_CONTROLLER);
    }

@@ -180,23 +169,46 @@ public class ShortcutUtilsTest {
                ALWAYS_ON_SERVICE_COMPONENT_NAME, /* serviceOn= */ true, /* shortcutOn= */ false);

        ShortcutUtils.updateInvisibleToggleAccessibilityServiceEnableState(
                mContextSpy,
                mContext,
                Set.of(ALWAYS_ON_SERVICE_COMPONENT_NAME),
                UserHandle.myUserId()
                mDefaultUserId
        );

        assertA11yServiceState(ALWAYS_ON_SERVICE_COMPONENT_NAME, /* enabled= */ false);
    }

    @Test
    public void updateAccessibilityServiceStateIfNeeded_alwaysOnServiceOnForBothUsers_noShortcutsForGuestUser_serviceTurnedOffForGuestUserOnly() {
        // setup arbitrary userId by add 10 to the default user id
        final int guestUserId = mDefaultUserId + 10;
        setupA11yServiceAndShortcutStateForUser(
                ALWAYS_ON_SERVICE_COMPONENT_NAME, /* serviceOn= */ true,
                /* shortcutOn= */ true, mDefaultUserId);
        setupA11yServiceAndShortcutStateForUser(
                ALWAYS_ON_SERVICE_COMPONENT_NAME, /* serviceOn= */ true,
                /* shortcutOn= */ false, guestUserId);

        ShortcutUtils.updateInvisibleToggleAccessibilityServiceEnableState(
                mContext,
                Set.of(ALWAYS_ON_SERVICE_COMPONENT_NAME),
                guestUserId
        );

        assertA11yServiceStateForUser(
                ALWAYS_ON_SERVICE_COMPONENT_NAME, /* enabled= */ false, guestUserId);
        assertA11yServiceStateForUser(
                ALWAYS_ON_SERVICE_COMPONENT_NAME, /* enabled= */ true, mDefaultUserId);
    }

    @Test
    public void updateAccessibilityServiceStateIfNeeded_alwaysOnServiceOn_hasShortcut_serviceKeepsOn() {
        setupA11yServiceAndShortcutState(
                ALWAYS_ON_SERVICE_COMPONENT_NAME, /* serviceOn= */ true, /* shortcutOn= */ true);

        ShortcutUtils.updateInvisibleToggleAccessibilityServiceEnableState(
                mContextSpy,
                mContext,
                Set.of(ALWAYS_ON_SERVICE_COMPONENT_NAME),
                UserHandle.myUserId()
                mDefaultUserId
        );

        assertA11yServiceState(ALWAYS_ON_SERVICE_COMPONENT_NAME, /* enabled= */ true);
@@ -208,9 +220,9 @@ public class ShortcutUtilsTest {
                ALWAYS_ON_SERVICE_COMPONENT_NAME, /* serviceOn= */ false, /* shortcutOn= */ false);

        ShortcutUtils.updateInvisibleToggleAccessibilityServiceEnableState(
                mContextSpy,
                mContext,
                Set.of(ALWAYS_ON_SERVICE_COMPONENT_NAME),
                UserHandle.myUserId()
                mDefaultUserId
        );

        assertA11yServiceState(ALWAYS_ON_SERVICE_COMPONENT_NAME, /* enabled= */ false);
@@ -222,9 +234,9 @@ public class ShortcutUtilsTest {
                ALWAYS_ON_SERVICE_COMPONENT_NAME, /* serviceOn= */ false, /* shortcutOn= */ true);

        ShortcutUtils.updateInvisibleToggleAccessibilityServiceEnableState(
                mContextSpy,
                mContext,
                Set.of(ALWAYS_ON_SERVICE_COMPONENT_NAME),
                UserHandle.myUserId()
                mDefaultUserId
        );

        assertA11yServiceState(ALWAYS_ON_SERVICE_COMPONENT_NAME, /* enabled= */ true);
@@ -236,9 +248,9 @@ public class ShortcutUtilsTest {
                STANDARD_SERVICE_COMPONENT_NAME, /* serviceOn= */ true, /* shortcutOn= */ false);

        ShortcutUtils.updateInvisibleToggleAccessibilityServiceEnableState(
                mContextSpy,
                mContext,
                Set.of(STANDARD_SERVICE_COMPONENT_NAME),
                UserHandle.myUserId()
                mDefaultUserId
        );

        assertA11yServiceState(STANDARD_SERVICE_COMPONENT_NAME, /* enabled= */ true);
@@ -250,9 +262,9 @@ public class ShortcutUtilsTest {
                STANDARD_SERVICE_COMPONENT_NAME, /* serviceOn= */ true, /* shortcutOn= */ true);

        ShortcutUtils.updateInvisibleToggleAccessibilityServiceEnableState(
                mContextSpy,
                mContext,
                Set.of(STANDARD_SERVICE_COMPONENT_NAME),
                UserHandle.myUserId()
                mDefaultUserId
        );

        assertA11yServiceState(STANDARD_SERVICE_COMPONENT_NAME, /* enabled= */ true);
@@ -264,9 +276,9 @@ public class ShortcutUtilsTest {
                STANDARD_SERVICE_COMPONENT_NAME, /* serviceOn= */ false, /* shortcutOn= */ false);

        ShortcutUtils.updateInvisibleToggleAccessibilityServiceEnableState(
                mContextSpy,
                mContext,
                Set.of(STANDARD_SERVICE_COMPONENT_NAME),
                UserHandle.myUserId()
                mDefaultUserId
        );

        assertA11yServiceState(STANDARD_SERVICE_COMPONENT_NAME, /* enabled= */ false);
@@ -278,9 +290,9 @@ public class ShortcutUtilsTest {
                STANDARD_SERVICE_COMPONENT_NAME, /* serviceOn= */ false, /* shortcutOn= */ true);

        ShortcutUtils.updateInvisibleToggleAccessibilityServiceEnableState(
                mContextSpy,
                mContext,
                Set.of(STANDARD_SERVICE_COMPONENT_NAME),
                UserHandle.myUserId()
                mDefaultUserId
        );

        assertA11yServiceState(STANDARD_SERVICE_COMPONENT_NAME, /* enabled= */ false);
@@ -292,18 +304,18 @@ public class ShortcutUtilsTest {
            stringJoiner.add(target);
        }
        Settings.Secure.putStringForUser(
                mContextSpy.getContentResolver(), shortcutSettingsKey,
                mContext.getContentResolver(), shortcutSettingsKey,
                stringJoiner.toString(),
                UserHandle.myUserId());
                mDefaultUserId);
    }

    private void enableTripleTapShortcutForMagnification(boolean enable) {
        Settings.Secure.putInt(
                mContextSpy.getContentResolver(),
                mContext.getContentResolver(),
                ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, enable ? 1 : 0);
    }

    private void setupFakeA11yServiceInfos() throws RemoteException {
    private void setupFakeInstalledA11yServiceInfos() throws RemoteException {
        List<AccessibilityServiceInfo> serviceInfos = List.of(
                TestUtils.createFakeServiceInfo(
                        ALWAYS_ON_SERVICE_PACKAGE_LABEL,
@@ -322,37 +334,55 @@ public class ShortcutUtilsTest {

    private void setupA11yServiceAndShortcutState(
            String a11yServiceComponentName, boolean serviceOn, boolean shortcutOn) {
        enableA11yService(a11yServiceComponentName, serviceOn);
        addShortcutForA11yService(a11yServiceComponentName, shortcutOn);
        setupA11yServiceAndShortcutStateForUser(
                a11yServiceComponentName, serviceOn, shortcutOn, mDefaultUserId);
    }

    private void setupA11yServiceAndShortcutStateForUser(
            String a11yServiceComponentName, boolean serviceOn,
            boolean shortcutOn, @UserIdInt int userId) {
        enableA11yServiceForUser(a11yServiceComponentName, serviceOn, userId);
        addShortcutForA11yServiceForUser(a11yServiceComponentName, shortcutOn, userId);
    }

    private void assertA11yServiceState(String a11yServiceComponentName, boolean enabled) {
        assertA11yServiceStateForUser(a11yServiceComponentName, enabled, mDefaultUserId);
    }

    private void assertA11yServiceStateForUser(
            String a11yServiceComponentName, boolean enabled, @UserIdInt int userId) {
        if (enabled) {
            assertThat(
                    Settings.Secure.getString(
                            mContextSpy.getContentResolver(),
                            Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES)
                    Settings.Secure.getStringForUser(
                            mContext.getContentResolver(),
                            Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
                            userId)
            ).contains(a11yServiceComponentName);
        } else {
            assertThat(
                    Settings.Secure.getString(
                            mContextSpy.getContentResolver(),
                            Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES)
                    Settings.Secure.getStringForUser(
                            mContext.getContentResolver(),
                            Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
                            userId)
            ).doesNotContain(a11yServiceComponentName);
        }
    }

    private void enableA11yService(String a11yServiceComponentName, boolean enable) {
        Settings.Secure.putString(
                mContextSpy.getContentResolver(),
    private void enableA11yServiceForUser(
            String a11yServiceComponentName, boolean enable, @UserIdInt int userId) {
        Settings.Secure.putStringForUser(
                mContext.getContentResolver(),
                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
                enable ? a11yServiceComponentName : "");
                enable ? a11yServiceComponentName : "",
                userId);
    }

    private void addShortcutForA11yService(String a11yServiceComponentName, boolean add) {
        Settings.Secure.putString(
                mContextSpy.getContentResolver(),
    private void addShortcutForA11yServiceForUser(
            String a11yServiceComponentName, boolean add, @UserIdInt int userId) {
        Settings.Secure.putStringForUser(
                mContext.getContentResolver(),
                Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
                add ? a11yServiceComponentName : "");
                add ? a11yServiceComponentName : "",
                userId);
    }
}