diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 79695186ace7c..d405c0b5b24fb 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -255,17 +255,6 @@ public final class AccessibilityManager {
*/
public static final int FLAG_CONTENT_CONTROLS = 4;
-
- /**
- * {@link ComponentName} for the Accessibility Menu {@link AccessibilityService} as provided
- * inside the system build, used for automatic migration to this version of the service.
- * @hide
- */
- public static final ComponentName ACCESSIBILITY_MENU_IN_SYSTEM =
- new ComponentName("com.android.systemui.accessibility.accessibilitymenu",
- "com.android.systemui.accessibility.accessibilitymenu"
- + ".AccessibilityMenuService");
-
@UnsupportedAppUsage
static final Object sInstanceSync = new Object();
diff --git a/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java b/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
index 6a976efa5ef92..3a8f427d54bc5 100644
--- a/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
+++ b/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
@@ -19,11 +19,16 @@ package com.android.internal.accessibility.util;
import static com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType;
import static com.android.internal.accessibility.common.ShortcutConstants.SERVICES_SEPARATOR;
+import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.UserHandle;
import android.provider.Settings;
@@ -33,6 +38,8 @@ import android.text.TextUtils;
import android.util.ArraySet;
import android.view.accessibility.AccessibilityManager;
+import com.android.internal.annotations.VisibleForTesting;
+
import libcore.util.EmptyArray;
import java.lang.annotation.Retention;
@@ -40,6 +47,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
/**
@@ -66,6 +74,19 @@ public final class AccessibilityUtils {
/** Specifies some parcelable spans has been changed. */
public static final int PARCELABLE_SPAN = 2;
+ @VisibleForTesting
+ public static final String MENU_SERVICE_RELATIVE_CLASS_NAME = ".AccessibilityMenuService";
+
+ /**
+ * {@link ComponentName} for the Accessibility Menu {@link AccessibilityService} as provided
+ * inside the system build, used for automatic migration to this version of the service.
+ * @hide
+ */
+ public static final ComponentName ACCESSIBILITY_MENU_IN_SYSTEM =
+ new ComponentName("com.android.systemui.accessibility.accessibilitymenu",
+ "com.android.systemui.accessibility.accessibilitymenu"
+ + MENU_SERVICE_RELATIVE_CLASS_NAME);
+
/**
* Returns the set of enabled accessibility services for userId. If there are no
* services, it returns the unmodifiable {@link Collections#emptySet()}.
@@ -244,4 +265,54 @@ public final class AccessibilityUtils {
}
return true;
}
+
+ /**
+ * Finds the {@link ComponentName} of the AccessibilityMenu accessibility service that the
+ * device should be migrated off. Devices using this service should be migrated to
+ * {@link #ACCESSIBILITY_MENU_IN_SYSTEM}.
+ *
+ *
+ * Requirements:
+ *
There are exactly two installed accessibility service components with class name
+ * {@link #MENU_SERVICE_RELATIVE_CLASS_NAME}.
+ * Exactly one of these components is equal to {@link #ACCESSIBILITY_MENU_IN_SYSTEM}.
+ *
+ *
+ * @return The {@link ComponentName} of the service that is not {@link
+ * #ACCESSIBILITY_MENU_IN_SYSTEM},
+ * or null if the above requirements are not met.
+ */
+ @Nullable
+ public static ComponentName getAccessibilityMenuComponentToMigrate(
+ PackageManager packageManager, int userId) {
+ final Set menuComponentNames = findA11yMenuComponentNames(packageManager,
+ userId);
+ Optional menuOutsideSystem = menuComponentNames.stream().filter(
+ name -> !name.equals(ACCESSIBILITY_MENU_IN_SYSTEM)).findFirst();
+ final boolean shouldMigrateToMenuInSystem = menuComponentNames.size() == 2
+ && menuComponentNames.contains(ACCESSIBILITY_MENU_IN_SYSTEM)
+ && menuOutsideSystem.isPresent();
+ return shouldMigrateToMenuInSystem ? menuOutsideSystem.get() : null;
+ }
+
+ /**
+ * Returns all {@link ComponentName}s whose class name ends in {@link
+ * #MENU_SERVICE_RELATIVE_CLASS_NAME}.
+ **/
+ private static Set findA11yMenuComponentNames(
+ PackageManager packageManager, int userId) {
+ Set result = new ArraySet<>();
+ final PackageManager.ResolveInfoFlags flags = PackageManager.ResolveInfoFlags.of(
+ PackageManager.MATCH_DISABLED_COMPONENTS
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
+ for (ResolveInfo resolveInfo : packageManager.queryIntentServicesAsUser(
+ new Intent(AccessibilityService.SERVICE_INTERFACE), flags, userId)) {
+ final ComponentName componentName = resolveInfo.serviceInfo.getComponentName();
+ if (componentName.getClassName().endsWith(MENU_SERVICE_RELATIVE_CLASS_NAME)) {
+ result.add(componentName);
+ }
+ }
+ return result;
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityUtilsTest.java b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityUtilsTest.java
index 045b3a27456f6..3ea7f471e4bda 100644
--- a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityUtilsTest.java
@@ -16,8 +16,19 @@
package com.android.internal.accessibility;
-import static junit.framework.Assert.assertEquals;
+import static com.android.internal.accessibility.util.AccessibilityUtils.ACCESSIBILITY_MENU_IN_SYSTEM;
+import static com.android.internal.accessibility.util.AccessibilityUtils.MENU_SERVICE_RELATIVE_CLASS_NAME;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
import android.text.ParcelableSpan;
import android.text.SpannableString;
import android.text.style.LocaleSpan;
@@ -26,9 +37,13 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.accessibility.util.AccessibilityUtils;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import java.util.List;
import java.util.Locale;
/**
@@ -36,6 +51,15 @@ import java.util.Locale;
*/
@RunWith(AndroidJUnit4.class)
public class AccessibilityUtilsTest {
+ private static final int USER_ID = 123;
+ @Mock
+ private PackageManager mMockPackageManager;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
@Test
public void textOrSpanChanged_stringChange_returnTextChange() {
final CharSequence beforeText = "a";
@@ -44,7 +68,7 @@ public class AccessibilityUtilsTest {
@AccessibilityUtils.A11yTextChangeType int type = AccessibilityUtils.textOrSpanChanged(
beforeText, afterText);
- assertEquals(AccessibilityUtils.TEXT, type);
+ assertThat(type).isEqualTo(AccessibilityUtils.TEXT);
}
@Test
@@ -55,7 +79,7 @@ public class AccessibilityUtilsTest {
@AccessibilityUtils.A11yTextChangeType int type = AccessibilityUtils.textOrSpanChanged(
beforeText, afterText);
- assertEquals(AccessibilityUtils.NONE, type);
+ assertThat(type).isEqualTo(AccessibilityUtils.NONE);
}
@Test
@@ -68,7 +92,7 @@ public class AccessibilityUtilsTest {
@AccessibilityUtils.A11yTextChangeType int type = AccessibilityUtils.textOrSpanChanged(
beforeText, afterText);
- assertEquals(AccessibilityUtils.NONE, type);
+ assertThat(type).isEqualTo(AccessibilityUtils.NONE);
}
@Test
@@ -81,7 +105,7 @@ public class AccessibilityUtilsTest {
@AccessibilityUtils.A11yTextChangeType int type = AccessibilityUtils.textOrSpanChanged(
beforeText, afterText);
- assertEquals(AccessibilityUtils.PARCELABLE_SPAN, type);
+ assertThat(type).isEqualTo(AccessibilityUtils.PARCELABLE_SPAN);
}
@Test
@@ -96,7 +120,7 @@ public class AccessibilityUtilsTest {
@AccessibilityUtils.A11yTextChangeType int type = AccessibilityUtils.textOrSpanChanged(
beforeText, afterText);
- assertEquals(AccessibilityUtils.PARCELABLE_SPAN, type);
+ assertThat(type).isEqualTo(AccessibilityUtils.PARCELABLE_SPAN);
}
@Test
@@ -110,7 +134,7 @@ public class AccessibilityUtilsTest {
@AccessibilityUtils.A11yTextChangeType int type = AccessibilityUtils.textOrSpanChanged(
beforeText, afterText);
- assertEquals(AccessibilityUtils.NONE, type);
+ assertThat(type).isEqualTo(AccessibilityUtils.NONE);
}
@Test
@@ -124,6 +148,72 @@ public class AccessibilityUtilsTest {
@AccessibilityUtils.A11yTextChangeType int type = AccessibilityUtils.textOrSpanChanged(
beforeText, afterText);
- assertEquals(AccessibilityUtils.PARCELABLE_SPAN, type);
+ assertThat(type).isEqualTo(AccessibilityUtils.PARCELABLE_SPAN);
+ }
+
+ @Test
+ public void getAccessibilityMenuComponentToMigrate_isNull_whenNoMenuComponents() {
+ when(mMockPackageManager.queryIntentServicesAsUser(any(), any(),
+ eq(USER_ID))).thenReturn(List.of());
+
+ final ComponentName result = AccessibilityUtils.getAccessibilityMenuComponentToMigrate(
+ mMockPackageManager, USER_ID);
+
+ assertThat(result).isNull();
+ }
+
+ @Test
+ public void getAccessibilityMenuComponentToMigrate_isNull_whenTooManyMenuComponents() {
+ when(mMockPackageManager.queryIntentServicesAsUser(any(), any(),
+ eq(USER_ID))).thenReturn(List.of(
+ createResolveInfo(ComponentName.createRelative("external1",
+ MENU_SERVICE_RELATIVE_CLASS_NAME)),
+ createResolveInfo(ComponentName.createRelative("external2",
+ MENU_SERVICE_RELATIVE_CLASS_NAME)),
+ createResolveInfo(ComponentName.createRelative("external3",
+ MENU_SERVICE_RELATIVE_CLASS_NAME))));
+
+ final ComponentName result = AccessibilityUtils.getAccessibilityMenuComponentToMigrate(
+ mMockPackageManager, USER_ID);
+
+ assertThat(result).isNull();
+ }
+
+ @Test
+ public void getAccessibilityMenuComponentToMigrate_isNull_whenMenuInSystemNotFound() {
+ when(mMockPackageManager.queryIntentServicesAsUser(any(), any(),
+ eq(USER_ID))).thenReturn(List.of(
+ createResolveInfo(ComponentName.createRelative("external1",
+ MENU_SERVICE_RELATIVE_CLASS_NAME)),
+ createResolveInfo(ComponentName.createRelative("external2",
+ MENU_SERVICE_RELATIVE_CLASS_NAME))));
+
+ final ComponentName result = AccessibilityUtils.getAccessibilityMenuComponentToMigrate(
+ mMockPackageManager, USER_ID);
+
+ assertThat(result).isNull();
+ }
+
+ @Test
+ public void getAccessibilityMenuComponentToMigrate_returnsMenuOutsideSystem() {
+ ComponentName menuOutsideSystem = ComponentName.createRelative("external1",
+ MENU_SERVICE_RELATIVE_CLASS_NAME);
+ when(mMockPackageManager.queryIntentServicesAsUser(any(), any(),
+ eq(USER_ID))).thenReturn(List.of(
+ createResolveInfo(menuOutsideSystem),
+ createResolveInfo(ACCESSIBILITY_MENU_IN_SYSTEM)));
+
+ final ComponentName result = AccessibilityUtils.getAccessibilityMenuComponentToMigrate(
+ mMockPackageManager, USER_ID);
+
+ assertThat(result).isEqualTo(menuOutsideSystem);
+ }
+
+ private static ResolveInfo createResolveInfo(ComponentName componentName) {
+ ResolveInfo resolveInfo = new ResolveInfo();
+ resolveInfo.serviceInfo = new ServiceInfo();
+ resolveInfo.serviceInfo.packageName = componentName.getPackageName();
+ resolveInfo.serviceInfo.name = componentName.getClassName();
+ return resolveInfo;
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index a9c0f00788ae8..f1413e54f16de 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -33,6 +33,7 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
+import static com.android.internal.accessibility.util.AccessibilityUtils.ACCESSIBILITY_MENU_IN_SYSTEM;
import static com.android.providers.settings.SettingsState.FALLBACK_FILE_SUFFIX;
import android.Manifest;
@@ -107,6 +108,7 @@ import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.proto.ProtoOutputStream;
+import com.android.internal.accessibility.util.AccessibilityUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
@@ -3712,7 +3714,7 @@ public class SettingsProvider extends ContentProvider {
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 213;
+ private static final int SETTINGS_VERSION = 214;
private final int mUserId;
@@ -5646,6 +5648,27 @@ public class SettingsProvider extends ContentProvider {
currentVersion = 213;
}
+ if (currentVersion == 213) {
+ final ComponentName accessibilityMenuToMigrate =
+ AccessibilityUtils.getAccessibilityMenuComponentToMigrate(
+ getContext().getPackageManager(), userId);
+ if (accessibilityMenuToMigrate != null) {
+ final SettingsState secureSettings = getSecureSettingsLocked(userId);
+ final String toRemove = accessibilityMenuToMigrate.flattenToString();
+ final String toAdd = ACCESSIBILITY_MENU_IN_SYSTEM.flattenToString();
+ // Migrate the accessibility shortcuts and enabled state.
+ migrateColonDelimitedStringSettingLocked(secureSettings,
+ Secure.ACCESSIBILITY_BUTTON_TARGETS, toRemove, toAdd);
+ migrateColonDelimitedStringSettingLocked(secureSettings,
+ Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, toRemove, toAdd);
+ migrateColonDelimitedStringSettingLocked(secureSettings,
+ Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, toRemove, toAdd);
+ migrateColonDelimitedStringSettingLocked(secureSettings,
+ Secure.ENABLED_ACCESSIBILITY_SERVICES, toRemove, toAdd);
+ }
+ currentVersion = 214;
+ }
+
// vXXX: Add new settings above this point.
if (currentVersion != newVersion) {
@@ -5867,6 +5890,22 @@ public class SettingsProvider extends ContentProvider {
return items;
}
+ @GuardedBy("mLock")
+ private void migrateColonDelimitedStringSettingLocked(SettingsState settingsState,
+ String setting, String toRemove, String toAdd) {
+ final Set componentNames = transformColonDelimitedStringToSet(
+ settingsState.getSettingLocked(setting).getValue());
+ if (componentNames != null && componentNames.contains(toRemove)) {
+ componentNames.remove(toRemove);
+ componentNames.add(toAdd);
+ settingsState.insertSettingLocked(
+ setting,
+ TextUtils.join(":", componentNames),
+ null /* tag */, false /* makeDefault */,
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+ }
+
private boolean isAccessibilityButtonInNavigationBarOn(SettingsState secureSettings) {
return hasValueInA11yButtonTargets(secureSettings) && !isGestureNavigateEnabled();
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 03cf9b460b1e5..08e63bc5abcb7 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -28,7 +28,6 @@ import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MANAG
import static android.provider.Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED;
import static android.provider.Settings.Secure.CONTRAST_LEVEL;
import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_BUTTON;
-import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_MENU_IN_SYSTEM;
import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY;
import static android.view.accessibility.AccessibilityManager.CONTRAST_DEFAULT_VALUE;
import static android.view.accessibility.AccessibilityManager.CONTRAST_NOT_SET;
@@ -138,6 +137,7 @@ import com.android.internal.accessibility.AccessibilityShortcutController.Framew
import com.android.internal.accessibility.AccessibilityShortcutController.LaunchableFrameworkFeatureInfo;
import com.android.internal.accessibility.dialog.AccessibilityButtonChooserActivity;
import com.android.internal.accessibility.dialog.AccessibilityShortcutChooserActivity;
+import com.android.internal.accessibility.util.AccessibilityUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;
@@ -172,7 +172,6 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -218,9 +217,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
private static final String SET_PIP_ACTION_REPLACEMENT =
"setPictureInPictureActionReplacingConnection";
- @VisibleForTesting
- static final String MENU_SERVICE_RELATIVE_CLASS_NAME = ".AccessibilityMenuService";
-
private static final char COMPONENT_NAME_SEPARATOR = ':';
private static final int OWN_PROCESS_ID = android.os.Process.myPid();
@@ -484,6 +480,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
registerBroadcastReceivers();
new AccessibilityContentObserver(mMainHandler).register(
mContext.getContentResolver());
+ disableAccessibilityMenuToMigrateIfNeeded();
}
@Override
@@ -855,91 +852,27 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
/**
- * Migrates the Accessibility Menu to the version provided by the system build,
- * if necessary based on presence of the service on the device.
+ * Disables the component returned by
+ * {@link AccessibilityUtils#getAccessibilityMenuComponentToMigrate} so that it does not appear
+ * in Settings or other places that query for installed accessibility services.
+ *
+ *
+ * SettingsProvider is responsible for migrating users off of Menu-outside-system,
+ * which it performs in its initialization before AccessibilityManagerService is started.
+ *
*/
- @VisibleForTesting
- void migrateAccessibilityMenuIfNecessaryLocked(AccessibilityUserState userState) {
- final Set menuComponentNames = findA11yMenuComponentNamesLocked();
- final ComponentName menuOutsideSystem = getA11yMenuOutsideSystem(menuComponentNames);
- final boolean shouldMigrateToMenuInSystem = menuComponentNames.size() == 2
- && menuComponentNames.contains(ACCESSIBILITY_MENU_IN_SYSTEM)
- && menuOutsideSystem != null;
-
- if (!shouldMigrateToMenuInSystem) {
- if (menuComponentNames.size() == 1) {
- // If only one Menu package exists then reset its component to the default state.
- mPackageManager.setComponentEnabledSetting(
- menuComponentNames.stream().findFirst().get(),
- PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
- PackageManager.DONT_KILL_APP);
- }
- return;
+ private void disableAccessibilityMenuToMigrateIfNeeded() {
+ int userId;
+ synchronized (mLock) {
+ userId = mCurrentUserId;
}
-
- // Hide Menu-outside-system so that it does not appear in Settings.
- mPackageManager.setComponentEnabledSetting(
- menuOutsideSystem,
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP);
- // Migrate the accessibility shortcuts.
- migrateA11yMenuInSettingLocked(userState,
- Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, menuOutsideSystem);
- migrateA11yMenuInSettingLocked(userState,
- Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, menuOutsideSystem);
- migrateA11yMenuInSettingLocked(userState,
- Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, menuOutsideSystem);
- // If Menu-outside-system is currently enabled by the user then automatically
- // disable it and enable Menu-in-system.
- migrateA11yMenuInSettingLocked(userState,
- Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, menuOutsideSystem);
- }
-
- /**
- * Returns all {@link ComponentName}s whose class name ends in {@link
- * #MENU_SERVICE_RELATIVE_CLASS_NAME}.
- **/
- private Set findA11yMenuComponentNamesLocked() {
- Set result = new ArraySet<>();
- final var flags =
- PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_DISABLED_COMPONENTS
- | PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
- for (ResolveInfo resolveInfo : mPackageManager.queryIntentServicesAsUser(
- new Intent(AccessibilityService.SERVICE_INTERFACE), flags, mCurrentUserId)) {
- final ComponentName componentName = resolveInfo.serviceInfo.getComponentName();
- if (componentName.getClassName().endsWith(MENU_SERVICE_RELATIVE_CLASS_NAME)) {
- result.add(componentName);
- }
- }
- return result;
- }
-
- /**
- * Returns the first {@link ComponentName} in the provided set that is not equal to {@link
- * AccessibilityManager#ACCESSIBILITY_MENU_IN_SYSTEM}.
- */
- private static ComponentName getA11yMenuOutsideSystem(Set menuComponentNames) {
- Optional menuOutsideSystem = menuComponentNames.stream().filter(
- name -> !name.equals(ACCESSIBILITY_MENU_IN_SYSTEM)).findFirst();
- if (menuOutsideSystem.isEmpty()) {
- return null;
- }
- return menuOutsideSystem.get();
- }
-
- /**
- * Replaces toRemove with {@link AccessibilityManager#ACCESSIBILITY_MENU_IN_SYSTEM}
- * in the requested setting, if present already.
- */
- private void migrateA11yMenuInSettingLocked(AccessibilityUserState userState, String setting,
- ComponentName toRemove) {
- mTempComponentNameSet.clear();
- readComponentNamesFromSettingLocked(setting, userState.mUserId, mTempComponentNameSet);
- if (mTempComponentNameSet.contains(toRemove)) {
- mTempComponentNameSet.remove(toRemove);
- mTempComponentNameSet.add(ACCESSIBILITY_MENU_IN_SYSTEM);
- persistComponentNamesToSettingLocked(setting, mTempComponentNameSet, userState.mUserId);
+ final ComponentName menuToMigrate =
+ AccessibilityUtils.getAccessibilityMenuComponentToMigrate(mPackageManager, userId);
+ if (menuToMigrate != null) {
+ mPackageManager.setComponentEnabledSetting(
+ menuToMigrate,
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP);
}
}
@@ -1712,8 +1645,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
mCurrentUserId = userId;
AccessibilityUserState userState = getCurrentUserStateLocked();
- migrateAccessibilityMenuIfNecessaryLocked(userState);
-
readConfigurationForUserStateLocked(userState);
mSecurityPolicy.onSwitchUserLocked(mCurrentUserId, userState.mEnabledServices);
// Even if reading did not yield change, we have to update
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
index cc5c2f3154df0..424940567da53 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
@@ -16,19 +16,13 @@
package com.android.server.accessibility;
-import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS;
-import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
-import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
-import static android.provider.Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES;
-import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_MENU_IN_SYSTEM;
import static com.android.internal.accessibility.AccessibilityShortcutController.ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME;
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
-import static com.android.server.accessibility.AccessibilityManagerService.MENU_SERVICE_RELATIVE_CLASS_NAME;
import static com.google.common.truth.Truth.assertThat;
@@ -100,7 +94,6 @@ import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
-import java.util.List;
/**
* APCT tests for {@link AccessibilityManagerService}.
@@ -558,113 +551,6 @@ public class AccessibilityManagerServiceTest {
ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME.flattenToString());
}
- @Test
- public void testMigrateA11yMenu_ResetSingularComponentToDefaultState() {
- final ComponentName componentName =
- ComponentName.createRelative("external", MENU_SERVICE_RELATIVE_CLASS_NAME);
- when(mMockPackageManager.queryIntentServicesAsUser(any(), any(),
- eq(mA11yms.getCurrentUserIdLocked()))).thenReturn(
- List.of(createResolveInfo(componentName)));
-
- mA11yms.migrateAccessibilityMenuIfNecessaryLocked(mA11yms.getCurrentUserState());
-
- verify(mMockPackageManager).setComponentEnabledSetting(componentName,
- PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
- PackageManager.DONT_KILL_APP);
- }
-
- @Test
- public void testMigrateA11yMenu_DoNothing_WhenNoMenuComponents() {
- when(mMockPackageManager.queryIntentServicesAsUser(any(), any(),
- eq(mA11yms.getCurrentUserIdLocked()))).thenReturn(List.of());
-
- mA11yms.migrateAccessibilityMenuIfNecessaryLocked(mA11yms.getCurrentUserState());
-
- verify(mMockPackageManager, never()).setComponentEnabledSetting(any(),
- anyInt(), anyInt());
- }
-
- @Test
- public void testMigrateA11yMenu_DoNothing_WhenTooManyMenuComponents() {
- when(mMockPackageManager.queryIntentServicesAsUser(any(), any(),
- eq(mA11yms.getCurrentUserIdLocked()))).thenReturn(List.of(
- createResolveInfo(ComponentName.createRelative("external1",
- MENU_SERVICE_RELATIVE_CLASS_NAME)),
- createResolveInfo(ComponentName.createRelative("external2",
- MENU_SERVICE_RELATIVE_CLASS_NAME)),
- createResolveInfo(ComponentName.createRelative("external3",
- MENU_SERVICE_RELATIVE_CLASS_NAME))));
-
- mA11yms.migrateAccessibilityMenuIfNecessaryLocked(mA11yms.getCurrentUserState());
-
- verify(mMockPackageManager, never()).setComponentEnabledSetting(any(),
- anyInt(), anyInt());
- }
-
- @Test
- public void testMigrateA11yMenu_DoNothing_WhenNoMenuInSystem() {
- when(mMockPackageManager.queryIntentServicesAsUser(any(), any(),
- eq(mA11yms.getCurrentUserIdLocked()))).thenReturn(List.of(
- createResolveInfo(ComponentName.createRelative("external1",
- MENU_SERVICE_RELATIVE_CLASS_NAME)),
- createResolveInfo(ComponentName.createRelative("external2",
- MENU_SERVICE_RELATIVE_CLASS_NAME))));
-
- mA11yms.migrateAccessibilityMenuIfNecessaryLocked(mA11yms.getCurrentUserState());
-
- verify(mMockPackageManager, never()).setComponentEnabledSetting(any(),
- anyInt(), anyInt());
- }
-
- @Test
- public void testMigrateA11yMenu_PerformsMigration() {
- final ComponentName menuOutsideSystem =
- ComponentName.createRelative("external", MENU_SERVICE_RELATIVE_CLASS_NAME);
- final String[] migratedSettings = {
- ACCESSIBILITY_BUTTON_TARGETS,
- ACCESSIBILITY_BUTTON_TARGET_COMPONENT,
- ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
- ENABLED_ACCESSIBILITY_SERVICES
- };
- // Start the user with Menu-outside-system enabled,
- for (String setting : migratedSettings) {
- Settings.Secure.putStringForUser(
- mTestableContext.getContentResolver(),
- setting,
- menuOutsideSystem.flattenToShortString(),
- mA11yms.getCurrentUserIdLocked());
- }
- // and both Menu versions present.
- when(mMockPackageManager.queryIntentServicesAsUser(any(), any(),
- eq(mA11yms.getCurrentUserIdLocked()))).thenReturn(List.of(
- createResolveInfo(menuOutsideSystem),
- createResolveInfo(ACCESSIBILITY_MENU_IN_SYSTEM)));
-
- mA11yms.migrateAccessibilityMenuIfNecessaryLocked(mA11yms.getCurrentUserState());
-
- // Menu-outside-system should be disabled,
- verify(mMockPackageManager).setComponentEnabledSetting(menuOutsideSystem,
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP);
- // and all settings should migrated to Menu-in-system.
- for (String setting : migratedSettings) {
- ComponentName componentName = ComponentName.unflattenFromString(
- Settings.Secure.getStringForUser(
- mTestableContext.getContentResolver(),
- setting,
- mA11yms.getCurrentUserIdLocked()));
- assertThat(componentName).isEqualTo(ACCESSIBILITY_MENU_IN_SYSTEM);
- }
- }
-
- private static ResolveInfo createResolveInfo(ComponentName componentName) {
- ResolveInfo resolveInfo = new ResolveInfo();
- resolveInfo.serviceInfo = new ServiceInfo();
- resolveInfo.serviceInfo.packageName = componentName.getPackageName();
- resolveInfo.serviceInfo.name = componentName.getClassName();
- return resolveInfo;
- }
-
private void mockManageAccessibilityGranted(TestableContext context) {
context.getTestablePermissions().setPermission(Manifest.permission.MANAGE_ACCESSIBILITY,
PackageManager.PERMISSION_GRANTED);