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

Commit d9b80187 authored by Riley Jones's avatar Riley Jones Committed by Android (Google) Code Review
Browse files

Merge "Fix for a11yManager package force stop" into main

parents e8492539 7628589c
Loading
Loading
Loading
Loading
+17 −14
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.provider.Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED;
import static android.view.accessibility.AccessibilityManager.FlashNotificationReason;

import static com.android.hardware.input.Flags.keyboardA11yMouseKeys;
import static com.android.internal.accessibility.AccessibilityShortcutController.ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME;
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_COMPONENT_NAME;
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
@@ -57,7 +58,6 @@ import static com.android.internal.accessibility.util.AccessibilityStatsLogUtils
import static com.android.internal.util.FunctionalUtils.ignoreRemoteException;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import static com.android.server.accessibility.AccessibilityUserState.doesShortcutTargetsStringContain;
import static com.android.hardware.input.Flags.keyboardA11yMouseKeys;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;

import android.accessibilityservice.AccessibilityGestureEvent;
@@ -825,25 +825,27 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
    @VisibleForTesting
    boolean onPackagesForceStoppedLocked(
            String[] packages, AccessibilityUserState userState) {
        final List<String> continuousServicePackages =
        final Set<String> packageSet = new HashSet<>(List.of(packages));
        final ArrayList<ComponentName> continuousServices = new ArrayList<>(
                userState.mInstalledServices.stream().filter(service ->
                        (service.flags & FLAG_REQUEST_ACCESSIBILITY_BUTTON)
                                == FLAG_REQUEST_ACCESSIBILITY_BUTTON
                ).map(service -> service.getComponentName().flattenToString()).toList();
                ).map(AccessibilityServiceInfo::getComponentName).toList());

        // Filter out continuous packages that are not from the array of stopped packages.
        continuousServices.removeIf(
                continuousName -> !packageSet.contains(continuousName.getPackageName()));

        boolean enabledServicesChanged = false;
        final Iterator<ComponentName> it = userState.mEnabledServices.iterator();
        while (it.hasNext()) {
            final ComponentName comp = it.next();
            final String compPkg = comp.getPackageName();
            for (String pkg : packages) {
                if (compPkg.equals(pkg)) {
            if (packageSet.contains(compPkg)) {
                it.remove();
                userState.getBindingServicesLocked().remove(comp);
                userState.getCrashedServicesLocked().remove(comp);
                enabledServicesChanged = true;
                    break;
                }
            }
        }
        if (enabledServicesChanged) {
@@ -855,8 +857,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        // Remove any button targets that match any stopped continuous services
        Set<String> buttonTargets = userState.getShortcutTargetsLocked(SOFTWARE);
        boolean buttonTargetsChanged = buttonTargets.removeIf(
                target -> continuousServicePackages.stream().anyMatch(
                        pkg -> Objects.equals(target, pkg)));
                target -> continuousServices.stream().anyMatch(
                        continuousName -> continuousName.flattenToString().equals(target)));
        if (buttonTargetsChanged) {
            userState.updateShortcutTargetsLocked(buttonTargets, SOFTWARE);
            persistColonDelimitedSetToSettingLocked(
@@ -2641,7 +2643,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        }
    }

    private <T> void persistColonDelimitedSetToSettingLocked(String settingName, int userId,
    @VisibleForTesting
    <T> void persistColonDelimitedSetToSettingLocked(String settingName, int userId,
            Set<T> set, Function<T, String> toString) {
        persistColonDelimitedSetToSettingLocked(settingName, userId, set,
                toString, /* defaultEmptyString= */ null);
+59 −7
Original line number Diff line number Diff line
@@ -840,6 +840,10 @@ public class AccessibilityManagerServiceTest {
        info_a.setComponentName(COMPONENT_NAME);
        final AccessibilityServiceInfo info_b = new AccessibilityServiceInfo();
        info_b.setComponentName(new ComponentName("package", "class"));
        writeStringsToSetting(Set.of(
                info_a.getComponentName().flattenToString(),
                info_b.getComponentName().flattenToString()),
                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);

        AccessibilityUserState userState = mA11yms.getCurrentUserState();
        userState.mInstalledServices.clear();
@@ -858,10 +862,9 @@ public class AccessibilityManagerServiceTest {
        userState = mA11yms.getCurrentUserState();
        assertThat(userState.mEnabledServices).containsExactly(info_b.getComponentName());
        //Assert setting change
        final Set<ComponentName> componentsFromSetting = new ArraySet<>();
        mA11yms.readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
                userState.mUserId, componentsFromSetting);
        assertThat(componentsFromSetting).containsExactly(info_b.getComponentName());
        final Set<String> enabledServices =
                readStringsFromSetting(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
        assertThat(enabledServices).containsExactly(info_b.getComponentName().flattenToString());
    }

    @Test
@@ -880,6 +883,10 @@ public class AccessibilityManagerServiceTest {
                        info_a.getComponentName().flattenToString(),
                        info_b.getComponentName().flattenToString()),
                SOFTWARE);
        writeStringsToSetting(Set.of(
                        info_a.getComponentName().flattenToString(),
                        info_b.getComponentName().flattenToString()),
                ShortcutUtils.convertToKey(SOFTWARE));

        // despite force stopping both packages, only the first service has the relevant flag,
        // so only the first should be removed.
@@ -896,12 +903,52 @@ public class AccessibilityManagerServiceTest {
        assertThat(userState.getShortcutTargetsLocked(SOFTWARE)).containsExactly(
                info_b.getComponentName().flattenToString());
        //Assert setting change
        final Set<String> targetsFromSetting = new ArraySet<>();
        mA11yms.readColonDelimitedSettingToSet(ShortcutUtils.convertToKey(SOFTWARE),
                userState.mUserId, str -> str, targetsFromSetting);
        final Set<String> targetsFromSetting = readStringsFromSetting(
                ShortcutUtils.convertToKey(SOFTWARE));
        assertThat(targetsFromSetting).containsExactly(info_b.getComponentName().flattenToString());
    }

    @Test
    public void testPackagesForceStopped_otherServiceStopped_doesNotRemoveContinuousTarget() {
        final AccessibilityServiceInfo info_a = new AccessibilityServiceInfo();
        info_a.setComponentName(COMPONENT_NAME);
        info_a.flags = FLAG_REQUEST_ACCESSIBILITY_BUTTON;
        final AccessibilityServiceInfo info_b = new AccessibilityServiceInfo();
        info_b.setComponentName(new ComponentName("package", "class"));
        writeStringsToSetting(Set.of(
                        info_a.getComponentName().flattenToString(),
                        info_b.getComponentName().flattenToString()),
                ShortcutUtils.convertToKey(SOFTWARE));

        AccessibilityUserState userState = mA11yms.getCurrentUserState();
        userState.mInstalledServices.clear();
        userState.mInstalledServices.add(info_a);
        userState.mInstalledServices.add(info_b);
        userState.updateShortcutTargetsLocked(Set.of(
                        info_a.getComponentName().flattenToString(),
                        info_b.getComponentName().flattenToString()),
                SOFTWARE);

        // Force stopping a service should not disable unrelated continuous services.
        synchronized (mA11yms.getLock()) {
            mA11yms.onPackagesForceStoppedLocked(
                    new String[]{info_b.getComponentName().getPackageName()},
                    userState);
        }

        //Assert user state change
        userState = mA11yms.getCurrentUserState();
        assertThat(userState.getShortcutTargetsLocked(SOFTWARE)).containsExactly(
                info_a.getComponentName().flattenToString(),
                info_b.getComponentName().flattenToString());
        //Assert setting unchanged
        final Set<String> targetsFromSetting = readStringsFromSetting(
                ShortcutUtils.convertToKey(SOFTWARE));
        assertThat(targetsFromSetting).containsExactly(
                info_a.getComponentName().flattenToString(),
                info_b.getComponentName().flattenToString());
    }

    @Test
    public void testPackageMonitorScanPackages_scansWithoutHoldingLock() {
        setupAccessibilityServiceConnection(0);
@@ -1844,6 +1891,11 @@ public class AccessibilityManagerServiceTest {
        return result;
    }

    private void writeStringsToSetting(Set<String> strings, String setting) {
        mA11yms.persistColonDelimitedSetToSettingLocked(
                setting, UserHandle.USER_SYSTEM, strings, str -> str);
    }

    private void broadcastSettingRestored(String setting, String newValue) {
        Intent intent = new Intent(Intent.ACTION_SETTING_RESTORED)
                .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)