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: + *
null if the above requirements are not met.
+ */
+ @Nullable
+ public static ComponentName getAccessibilityMenuComponentToMigrate(
+ PackageManager packageManager, int userId) {
+ final Set+ * 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 SettoRemove 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 4d1d2b22ed345..77831dda9d9c9 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;
@@ -99,7 +93,6 @@ import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
-import java.util.List;
/**
* APCT tests for {@link AccessibilityManagerService}.
@@ -523,113 +516,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);