Loading packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +2 −10 Original line number Original line Diff line number Diff line Loading @@ -4692,24 +4692,16 @@ public class SettingsProvider extends ContentProvider { if (currentVersion == 185) { if (currentVersion == 185) { // Deprecate ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, and migrate it // Deprecate ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, and migrate it // to ACCESSIBILITY_BUTTON_TARGET_COMPONENT. // to ACCESSIBILITY_BUTTON_TARGETS. final SettingsState secureSettings = getSecureSettingsLocked(userId); final SettingsState secureSettings = getSecureSettingsLocked(userId); final Setting magnifyNavbarEnabled = secureSettings.getSettingLocked( final Setting magnifyNavbarEnabled = secureSettings.getSettingLocked( Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED); Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED); if ("1".equals(magnifyNavbarEnabled.getValue())) { if ("1".equals(magnifyNavbarEnabled.getValue())) { secureSettings.insertSettingLocked( secureSettings.insertSettingLocked( Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, Secure.ACCESSIBILITY_BUTTON_TARGETS, ACCESSIBILITY_SHORTCUT_TARGET_MAGNIFICATION_CONTROLLER, ACCESSIBILITY_SHORTCUT_TARGET_MAGNIFICATION_CONTROLLER, null /* tag */, false /* makeDefault */, null /* tag */, false /* makeDefault */, SettingsState.SYSTEM_PACKAGE_NAME); SettingsState.SYSTEM_PACKAGE_NAME); } else { // Clear a11y button targets list setting. A11yManagerService will end up // adding all legacy enabled services that want the button to the list, so // there's no need to keep tracking them. secureSettings.insertSettingLocked( Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, null, null /* tag */, false /* makeDefault */, SettingsState.SYSTEM_PACKAGE_NAME); } } secureSettings.deleteSettingLocked( secureSettings.deleteSettingLocked( Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED); Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED); Loading services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java +1 −0 Original line number Original line Diff line number Diff line Loading @@ -1081,6 +1081,7 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ pw.append(", eventTypes=" pw.append(", eventTypes=" + AccessibilityEvent.eventTypeToString(mEventTypes)); + AccessibilityEvent.eventTypeToString(mEventTypes)); pw.append(", notificationTimeout=" + mNotificationTimeout); pw.append(", notificationTimeout=" + mNotificationTimeout); pw.append(", requestA11yBtn=" + mRequestAccessibilityButton); pw.append("]"); pw.append("]"); } } } } Loading services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +72 −23 Original line number Original line Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.view.accessibility.AccessibilityManager.ShortcutType; import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME; import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME; import static com.android.internal.util.FunctionalUtils.ignoreRemoteException; import static com.android.internal.util.FunctionalUtils.ignoreRemoteException; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import static com.android.server.accessibility.AccessibilityUserState.doesShortcutTargetsStringContain; import android.Manifest; import android.Manifest; import android.accessibilityservice.AccessibilityGestureEvent; import android.accessibilityservice.AccessibilityGestureEvent; Loading Loading @@ -876,6 +877,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub throw new SecurityException("Caller does not hold permission " throw new SecurityException("Caller does not hold permission " + android.Manifest.permission.STATUS_BAR_SERVICE); + android.Manifest.permission.STATUS_BAR_SERVICE); } } if (targetName == null) { synchronized (mLock) { final AccessibilityUserState userState = getCurrentUserStateLocked(); targetName = userState.getTargetAssignedToAccessibilityButton(); } } mMainHandler.sendMessage(obtainMessage( mMainHandler.sendMessage(obtainMessage( AccessibilityManagerService::performAccessibilityShortcutInternal, this, AccessibilityManagerService::performAccessibilityShortcutInternal, this, displayId, ACCESSIBILITY_BUTTON, targetName)); displayId, ACCESSIBILITY_BUTTON, targetName)); Loading Loading @@ -1828,7 +1835,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub somethingChanged |= readMagnificationEnabledSettingsLocked(userState); somethingChanged |= readMagnificationEnabledSettingsLocked(userState); somethingChanged |= readAutoclickEnabledSettingLocked(userState); somethingChanged |= readAutoclickEnabledSettingLocked(userState); somethingChanged |= readAccessibilityShortcutKeySettingLocked(userState); somethingChanged |= readAccessibilityShortcutKeySettingLocked(userState); somethingChanged |= readAccessibilityButtonSettingsLocked(userState); somethingChanged |= readAccessibilityButtonTargetsLocked(userState); somethingChanged |= readAccessibilityButtonTargetComponentLocked(userState); somethingChanged |= readUserRecommendedUiTimeoutSettingsLocked(userState); somethingChanged |= readUserRecommendedUiTimeoutSettingsLocked(userState); return somethingChanged; return somethingChanged; } } Loading Loading @@ -1948,9 +1956,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return true; return true; } } private boolean readAccessibilityButtonSettingsLocked(AccessibilityUserState userState) { private boolean readAccessibilityButtonTargetsLocked(AccessibilityUserState userState) { final Set<String> targetsFromSetting = new ArraySet<>(); final Set<String> targetsFromSetting = new ArraySet<>(); readColonDelimitedSettingToSet(Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, readColonDelimitedSettingToSet(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, userState.mUserId, targetsFromSetting, str -> str); userState.mUserId, targetsFromSetting, str -> str); final Set<String> currentTargets = final Set<String> currentTargets = Loading @@ -1964,6 +1972,23 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return true; return true; } } private boolean readAccessibilityButtonTargetComponentLocked(AccessibilityUserState userState) { final String componentId = Settings.Secure.getStringForUser(mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, userState.mUserId); if (TextUtils.isEmpty(componentId)) { if (userState.getTargetAssignedToAccessibilityButton() == null) { return false; } userState.setTargetAssignedToAccessibilityButton(null); return true; } if (componentId.equals(userState.getTargetAssignedToAccessibilityButton())) { return false; } userState.setTargetAssignedToAccessibilityButton(componentId); return true; } private boolean readUserRecommendedUiTimeoutSettingsLocked(AccessibilityUserState userState) { private boolean readUserRecommendedUiTimeoutSettingsLocked(AccessibilityUserState userState) { final int nonInteractiveUiTimeout = Settings.Secure.getIntForUser( final int nonInteractiveUiTimeout = Settings.Secure.getIntForUser( mContext.getContentResolver(), mContext.getContentResolver(), Loading @@ -1984,7 +2009,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } /** /** * Check if the targets that will be enabled by the accessibility shortcut key is installed. * Check if the target that will be enabled by the accessibility shortcut key is installed. * If it isn't, remove it from the list and associated setting so a side loaded service can't * If it isn't, remove it from the list and associated setting so a side loaded service can't * spoof the package name of the default service. * spoof the package name of the default service. */ */ Loading Loading @@ -2145,7 +2170,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub /** /** * 1) Update accessibility button availability to accessibility services. * 1) Update accessibility button availability to accessibility services. * 2) Check if the targets that will be enabled by the accessibility button is installed. * 2) Check if the target that will be enabled by the accessibility button is installed. * If it isn't, remove it from the list and associated setting so a side loaded service can't * If it isn't, remove it from the list and associated setting so a side loaded service can't * spoof the package name of the default service. * spoof the package name of the default service. */ */ Loading @@ -2172,8 +2197,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } // Update setting key with new value. // Update setting key with new value. persistColonDelimitedSetToSettingLocked( persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, userState.mUserId, currentTargets, str -> str); userState.mUserId, currentTargets, str -> str); scheduleNotifyClientsOfServicesStateChangeLocked(userState); scheduleNotifyClientsOfServicesStateChangeLocked(userState); } } Loading @@ -2182,7 +2206,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub * 1) Check if the service assigned to accessibility button target sdk version > Q. * 1) Check if the service assigned to accessibility button target sdk version > Q. * If it isn't, remove it from the list and associated setting. * If it isn't, remove it from the list and associated setting. * (It happens when an accessibility service package is downgraded.) * (It happens when an accessibility service package is downgraded.) * 2) Check if an enabled service targeting sdk version > Q and requesting a11y button is * 2) For a service targeting sdk version > Q and requesting a11y button, it should be in the * enabled list if's assigned to a11y button. * (It happens when an accessibility service package is same graded, and updated requesting * a11y button flag) * 3) Check if an enabled service targeting sdk version > Q and requesting a11y button is * assigned to a shortcut. If it isn't, assigns it to the accessibility button. * assigned to a shortcut. If it isn't, assigns it to the accessibility button. * (It happens when an enabled accessibility service package is upgraded.) * (It happens when an enabled accessibility service package is upgraded.) * * Loading @@ -2207,11 +2235,22 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return false; return false; } } if (serviceInfo.getResolveInfo().serviceInfo.applicationInfo if (serviceInfo.getResolveInfo().serviceInfo.applicationInfo .targetSdkVersion > Build.VERSION_CODES.Q) { .targetSdkVersion <= Build.VERSION_CODES.Q) { return false; } // A11y services targeting sdk version <= Q should not be in the list. // A11y services targeting sdk version <= Q should not be in the list. Slog.v(LOG_TAG, "Legacy service " + componentName + " should not in the button"); return true; } final boolean requestA11yButton = (serviceInfo.flags & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0; if (requestA11yButton && !userState.mEnabledServices.contains(componentName)) { // An a11y service targeting sdk version > Q and request A11y button and is assigned // to a11y btn should be in the enabled list. Slog.v(LOG_TAG, "Service requesting a11y button and be assigned to the button" + componentName + " should be enabled state"); return true; return true; } return false; }); }); boolean changed = (lastSize != buttonTargets.size()); boolean changed = (lastSize != buttonTargets.size()); lastSize = buttonTargets.size(); lastSize = buttonTargets.size(); Loading @@ -2234,15 +2273,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub .targetSdkVersion > Build.VERSION_CODES.Q && requestA11yButton)) { .targetSdkVersion > Build.VERSION_CODES.Q && requestA11yButton)) { return; return; } } final String serviceName = serviceInfo.getComponentName().flattenToString(); final String serviceName = componentName.flattenToString(); if (TextUtils.isEmpty(serviceName)) { if (TextUtils.isEmpty(serviceName)) { return; return; } } if (shortcutKeyTargets.contains(serviceName) || buttonTargets.contains(serviceName)) { if (doesShortcutTargetsStringContain(buttonTargets, serviceName) || doesShortcutTargetsStringContain(shortcutKeyTargets, serviceName)) { return; return; } } // For enabled a11y services targeting sdk version > Q and requesting a11y button should // For enabled a11y services targeting sdk version > Q and requesting a11y button should // be assigned to a shortcut. // be assigned to a shortcut. Slog.v(LOG_TAG, "A enabled service requesting a11y button " + componentName + " should be assign to the button or shortcut."); buttonTargets.add(serviceName); buttonTargets.add(serviceName); }); }); changed |= (lastSize != buttonTargets.size()); changed |= (lastSize != buttonTargets.size()); Loading @@ -2251,8 +2293,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } // Update setting key with new value. // Update setting key with new value. persistColonDelimitedSetToSettingLocked( persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, userState.mUserId, buttonTargets, str -> str); userState.mUserId, buttonTargets, str -> str); scheduleNotifyClientsOfServicesStateChangeLocked(userState); scheduleNotifyClientsOfServicesStateChangeLocked(userState); } } Loading Loading @@ -2353,12 +2394,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return; return; } } // In case the caller specified a target name // In case the caller specified a target name if (targetName != null) { if (targetName != null && !doesShortcutTargetsStringContain(shortcutTargets, targetName)) { if (!shortcutTargets.contains(targetName)) { Slog.v(LOG_TAG, "Perform shortcut failed, invalid target name:" + targetName); Slog.d(LOG_TAG, "Perform shortcut failed, invalid target name:" + targetName); targetName = null; return; } } } else { if (targetName == null) { // In case there are many targets assigned to the given shortcut. // In case there are many targets assigned to the given shortcut. if (shortcutTargets.size() > 1) { if (shortcutTargets.size() > 1) { showAccessibilityTargetsSelection(displayId, shortcutType); showAccessibilityTargetsSelection(displayId, shortcutType); Loading Loading @@ -2983,6 +3023,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub private final Uri mAccessibilityButtonComponentIdUri = Settings.Secure.getUriFor( private final Uri mAccessibilityButtonComponentIdUri = Settings.Secure.getUriFor( Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT); Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT); private final Uri mAccessibilityButtonTargetsUri = Settings.Secure.getUriFor( Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS); private final Uri mUserNonInteractiveUiTimeoutUri = Settings.Secure.getUriFor( private final Uri mUserNonInteractiveUiTimeoutUri = Settings.Secure.getUriFor( Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS); Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS); Loading Loading @@ -3015,6 +3058,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub mAccessibilityShortcutServiceIdUri, false, this, UserHandle.USER_ALL); mAccessibilityShortcutServiceIdUri, false, this, UserHandle.USER_ALL); contentResolver.registerContentObserver( contentResolver.registerContentObserver( mAccessibilityButtonComponentIdUri, false, this, UserHandle.USER_ALL); mAccessibilityButtonComponentIdUri, false, this, UserHandle.USER_ALL); contentResolver.registerContentObserver( mAccessibilityButtonTargetsUri, false, this, UserHandle.USER_ALL); contentResolver.registerContentObserver( contentResolver.registerContentObserver( mUserNonInteractiveUiTimeoutUri, false, this, UserHandle.USER_ALL); mUserNonInteractiveUiTimeoutUri, false, this, UserHandle.USER_ALL); contentResolver.registerContentObserver( contentResolver.registerContentObserver( Loading Loading @@ -3061,7 +3106,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub onUserStateChangedLocked(userState); onUserStateChangedLocked(userState); } } } else if (mAccessibilityButtonComponentIdUri.equals(uri)) { } else if (mAccessibilityButtonComponentIdUri.equals(uri)) { if (readAccessibilityButtonSettingsLocked(userState)) { if (readAccessibilityButtonTargetComponentLocked(userState)) { onUserStateChangedLocked(userState); } } else if (mAccessibilityButtonTargetsUri.equals(uri)) { if (readAccessibilityButtonTargetsLocked(userState)) { onUserStateChangedLocked(userState); onUserStateChangedLocked(userState); } } } else if (mUserNonInteractiveUiTimeoutUri.equals(uri) } else if (mUserNonInteractiveUiTimeoutUri.equals(uri) Loading services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java +58 −0 Original line number Original line Diff line number Diff line Loading @@ -49,6 +49,7 @@ import com.android.internal.accessibility.AccessibilityShortcutController; import java.io.FileDescriptor; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashMap; import java.util.HashSet; import java.util.HashSet; import java.util.Iterator; import java.util.Iterator; Loading Loading @@ -96,6 +97,8 @@ class AccessibilityUserState { private ComponentName mServiceChangingSoftKeyboardMode; private ComponentName mServiceChangingSoftKeyboardMode; private String mTargetAssignedToAccessibilityButton; private boolean mBindInstantServiceAllowed; private boolean mBindInstantServiceAllowed; private boolean mIsAutoclickEnabled; private boolean mIsAutoclickEnabled; private boolean mIsDisplayMagnificationEnabled; private boolean mIsDisplayMagnificationEnabled; Loading Loading @@ -152,6 +155,7 @@ class AccessibilityUserState { mTouchExplorationGrantedServices.clear(); mTouchExplorationGrantedServices.clear(); mAccessibilityShortcutKeyTargets.clear(); mAccessibilityShortcutKeyTargets.clear(); mAccessibilityButtonTargets.clear(); mAccessibilityButtonTargets.clear(); mTargetAssignedToAccessibilityButton = null; mIsTouchExplorationEnabled = false; mIsTouchExplorationEnabled = false; mServiceHandlesDoubleTap = false; mServiceHandlesDoubleTap = false; mRequestMultiFingerGestures = false; mRequestMultiFingerGestures = false; Loading Loading @@ -469,6 +473,8 @@ class AccessibilityUserState { } } } } pw.println("}"); pw.println("}"); pw.append(" button target:{").append(mTargetAssignedToAccessibilityButton); pw.println("}"); pw.append(" Bound services:{"); pw.append(" Bound services:{"); final int serviceCount = mBoundServices.size(); final int serviceCount = mBoundServices.size(); for (int j = 0; j < serviceCount; j++) { for (int j = 0; j < serviceCount; j++) { Loading Loading @@ -716,4 +722,56 @@ class AccessibilityUserState { public void setUserNonInteractiveUiTimeoutLocked(int timeout) { public void setUserNonInteractiveUiTimeoutLocked(int timeout) { mUserNonInteractiveUiTimeout = timeout; mUserNonInteractiveUiTimeout = timeout; } } /** * Gets a shortcut target which is assigned to the accessibility button by the chooser * activity. * * @return The flattened component name or the system class name of the shortcut target. */ public String getTargetAssignedToAccessibilityButton() { return mTargetAssignedToAccessibilityButton; } /** * Sets a shortcut target which is assigned to the accessibility button by the chooser * activity. * * @param target The flattened component name or the system class name of the shortcut target. */ public void setTargetAssignedToAccessibilityButton(String target) { mTargetAssignedToAccessibilityButton = target; } /** * Whether or not the given target name is contained in the shortcut collection. Since the * component name string format could be short or long, this function un-flatten the component * name from the string in {@code shortcutTargets} and compared with the given target name. * * @param shortcutTargets The shortcut type. * @param targetName The target name. * @return {@code true} if the target is in the shortcut collection. */ public static boolean doesShortcutTargetsStringContain(Collection<String> shortcutTargets, String targetName) { if (shortcutTargets == null || targetName == null) { return false; } // Some system features, such as magnification, don't have component name. Using string // compare first. if (shortcutTargets.contains(targetName)) { return true; } final ComponentName targetComponentName = ComponentName.unflattenFromString(targetName); if (targetComponentName == null) { return false; } for (String stringName : shortcutTargets) { if (!TextUtils.isEmpty(stringName) && targetComponentName.equals(ComponentName.unflattenFromString(stringName))) { return true; } } return false; } } } services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java +36 −0 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,8 @@ import static android.view.accessibility.AccessibilityManager.STATE_FLAG_ACCESSI import static android.view.accessibility.AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED; import static android.view.accessibility.AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED; import static android.view.accessibility.AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED; import static android.view.accessibility.AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED; import static com.android.server.accessibility.AccessibilityUserState.doesShortcutTargetsStringContain; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertNull; Loading @@ -41,6 +43,7 @@ import android.content.Context; import android.provider.Settings; import android.provider.Settings; import android.test.mock.MockContentResolver; import android.test.mock.MockContentResolver; import android.testing.DexmakerShareClassLoaderRule; import android.testing.DexmakerShareClassLoaderRule; import android.util.ArraySet; import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.util.test.FakeSettingsProvider; Loading @@ -56,6 +59,12 @@ public class AccessibilityUserStateTest { private static final ComponentName COMPONENT_NAME = private static final ComponentName COMPONENT_NAME = new ComponentName("com.android.server.accessibility", "AccessibilityUserStateTest"); new ComponentName("com.android.server.accessibility", "AccessibilityUserStateTest"); private static final ComponentName COMPONENT_NAME1 = new ComponentName("com.android.server.accessibility", "com.android.server.accessibility.AccessibilityUserStateTest1"); private static final ComponentName COMPONENT_NAME2 = new ComponentName("com.android.server.accessibility", "com.android.server.accessibility.AccessibilityUserStateTest2"); // Values of setting key SHOW_IME_WITH_HARD_KEYBOARD // Values of setting key SHOW_IME_WITH_HARD_KEYBOARD private static final int STATE_HIDE_IME = 0; private static final int STATE_HIDE_IME = 0; Loading Loading @@ -111,6 +120,7 @@ public class AccessibilityUserStateTest { mUserState.mTouchExplorationGrantedServices.add(COMPONENT_NAME); mUserState.mTouchExplorationGrantedServices.add(COMPONENT_NAME); mUserState.mAccessibilityShortcutKeyTargets.add(COMPONENT_NAME.flattenToString()); mUserState.mAccessibilityShortcutKeyTargets.add(COMPONENT_NAME.flattenToString()); mUserState.mAccessibilityButtonTargets.add(COMPONENT_NAME.flattenToString()); mUserState.mAccessibilityButtonTargets.add(COMPONENT_NAME.flattenToString()); mUserState.setTargetAssignedToAccessibilityButton(COMPONENT_NAME.flattenToString()); mUserState.setTouchExplorationEnabledLocked(true); mUserState.setTouchExplorationEnabledLocked(true); mUserState.setDisplayMagnificationEnabledLocked(true); mUserState.setDisplayMagnificationEnabledLocked(true); mUserState.setAutoclickEnabledLocked(true); mUserState.setAutoclickEnabledLocked(true); Loading @@ -129,6 +139,7 @@ public class AccessibilityUserStateTest { assertTrue(mUserState.mTouchExplorationGrantedServices.isEmpty()); assertTrue(mUserState.mTouchExplorationGrantedServices.isEmpty()); assertTrue(mUserState.mAccessibilityShortcutKeyTargets.isEmpty()); assertTrue(mUserState.mAccessibilityShortcutKeyTargets.isEmpty()); assertTrue(mUserState.mAccessibilityButtonTargets.isEmpty()); assertTrue(mUserState.mAccessibilityButtonTargets.isEmpty()); assertNull(mUserState.getTargetAssignedToAccessibilityButton()); assertFalse(mUserState.isTouchExplorationEnabledLocked()); assertFalse(mUserState.isTouchExplorationEnabledLocked()); assertFalse(mUserState.isDisplayMagnificationEnabledLocked()); assertFalse(mUserState.isDisplayMagnificationEnabledLocked()); assertFalse(mUserState.isAutoclickEnabledLocked()); assertFalse(mUserState.isAutoclickEnabledLocked()); Loading Loading @@ -285,6 +296,31 @@ public class AccessibilityUserStateTest { verify(mMockConnection).notifySoftKeyboardShowModeChangedLocked(eq(SHOW_MODE_HIDDEN)); verify(mMockConnection).notifySoftKeyboardShowModeChangedLocked(eq(SHOW_MODE_HIDDEN)); } } @Test public void doesShortcutTargetsStringContain_returnFalse() { assertFalse(doesShortcutTargetsStringContain(null, null)); assertFalse(doesShortcutTargetsStringContain(null, COMPONENT_NAME.flattenToShortString())); assertFalse(doesShortcutTargetsStringContain(new ArraySet<>(), null)); final ArraySet<String> shortcutTargets = new ArraySet<>(); shortcutTargets.add(COMPONENT_NAME.flattenToString()); assertFalse(doesShortcutTargetsStringContain(shortcutTargets, COMPONENT_NAME1.flattenToString())); } @Test public void isAssignedToShortcutLocked_withDifferentTypeComponentString_returnTrue() { final ArraySet<String> shortcutTargets = new ArraySet<>(); shortcutTargets.add(COMPONENT_NAME1.flattenToShortString()); shortcutTargets.add(COMPONENT_NAME2.flattenToString()); assertTrue(doesShortcutTargetsStringContain(shortcutTargets, COMPONENT_NAME1.flattenToString())); assertTrue(doesShortcutTargetsStringContain(shortcutTargets, COMPONENT_NAME2.flattenToShortString())); } @Test @Test public void isShortcutTargetInstalledLocked_returnTrue() { public void isShortcutTargetInstalledLocked_returnTrue() { mUserState.mInstalledServices.add(mMockServiceInfo); mUserState.mInstalledServices.add(mMockServiceInfo); Loading Loading
packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +2 −10 Original line number Original line Diff line number Diff line Loading @@ -4692,24 +4692,16 @@ public class SettingsProvider extends ContentProvider { if (currentVersion == 185) { if (currentVersion == 185) { // Deprecate ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, and migrate it // Deprecate ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, and migrate it // to ACCESSIBILITY_BUTTON_TARGET_COMPONENT. // to ACCESSIBILITY_BUTTON_TARGETS. final SettingsState secureSettings = getSecureSettingsLocked(userId); final SettingsState secureSettings = getSecureSettingsLocked(userId); final Setting magnifyNavbarEnabled = secureSettings.getSettingLocked( final Setting magnifyNavbarEnabled = secureSettings.getSettingLocked( Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED); Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED); if ("1".equals(magnifyNavbarEnabled.getValue())) { if ("1".equals(magnifyNavbarEnabled.getValue())) { secureSettings.insertSettingLocked( secureSettings.insertSettingLocked( Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, Secure.ACCESSIBILITY_BUTTON_TARGETS, ACCESSIBILITY_SHORTCUT_TARGET_MAGNIFICATION_CONTROLLER, ACCESSIBILITY_SHORTCUT_TARGET_MAGNIFICATION_CONTROLLER, null /* tag */, false /* makeDefault */, null /* tag */, false /* makeDefault */, SettingsState.SYSTEM_PACKAGE_NAME); SettingsState.SYSTEM_PACKAGE_NAME); } else { // Clear a11y button targets list setting. A11yManagerService will end up // adding all legacy enabled services that want the button to the list, so // there's no need to keep tracking them. secureSettings.insertSettingLocked( Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, null, null /* tag */, false /* makeDefault */, SettingsState.SYSTEM_PACKAGE_NAME); } } secureSettings.deleteSettingLocked( secureSettings.deleteSettingLocked( Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED); Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED); Loading
services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java +1 −0 Original line number Original line Diff line number Diff line Loading @@ -1081,6 +1081,7 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ pw.append(", eventTypes=" pw.append(", eventTypes=" + AccessibilityEvent.eventTypeToString(mEventTypes)); + AccessibilityEvent.eventTypeToString(mEventTypes)); pw.append(", notificationTimeout=" + mNotificationTimeout); pw.append(", notificationTimeout=" + mNotificationTimeout); pw.append(", requestA11yBtn=" + mRequestAccessibilityButton); pw.append("]"); pw.append("]"); } } } } Loading
services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +72 −23 Original line number Original line Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.view.accessibility.AccessibilityManager.ShortcutType; import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME; import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME; import static com.android.internal.util.FunctionalUtils.ignoreRemoteException; import static com.android.internal.util.FunctionalUtils.ignoreRemoteException; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import static com.android.server.accessibility.AccessibilityUserState.doesShortcutTargetsStringContain; import android.Manifest; import android.Manifest; import android.accessibilityservice.AccessibilityGestureEvent; import android.accessibilityservice.AccessibilityGestureEvent; Loading Loading @@ -876,6 +877,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub throw new SecurityException("Caller does not hold permission " throw new SecurityException("Caller does not hold permission " + android.Manifest.permission.STATUS_BAR_SERVICE); + android.Manifest.permission.STATUS_BAR_SERVICE); } } if (targetName == null) { synchronized (mLock) { final AccessibilityUserState userState = getCurrentUserStateLocked(); targetName = userState.getTargetAssignedToAccessibilityButton(); } } mMainHandler.sendMessage(obtainMessage( mMainHandler.sendMessage(obtainMessage( AccessibilityManagerService::performAccessibilityShortcutInternal, this, AccessibilityManagerService::performAccessibilityShortcutInternal, this, displayId, ACCESSIBILITY_BUTTON, targetName)); displayId, ACCESSIBILITY_BUTTON, targetName)); Loading Loading @@ -1828,7 +1835,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub somethingChanged |= readMagnificationEnabledSettingsLocked(userState); somethingChanged |= readMagnificationEnabledSettingsLocked(userState); somethingChanged |= readAutoclickEnabledSettingLocked(userState); somethingChanged |= readAutoclickEnabledSettingLocked(userState); somethingChanged |= readAccessibilityShortcutKeySettingLocked(userState); somethingChanged |= readAccessibilityShortcutKeySettingLocked(userState); somethingChanged |= readAccessibilityButtonSettingsLocked(userState); somethingChanged |= readAccessibilityButtonTargetsLocked(userState); somethingChanged |= readAccessibilityButtonTargetComponentLocked(userState); somethingChanged |= readUserRecommendedUiTimeoutSettingsLocked(userState); somethingChanged |= readUserRecommendedUiTimeoutSettingsLocked(userState); return somethingChanged; return somethingChanged; } } Loading Loading @@ -1948,9 +1956,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return true; return true; } } private boolean readAccessibilityButtonSettingsLocked(AccessibilityUserState userState) { private boolean readAccessibilityButtonTargetsLocked(AccessibilityUserState userState) { final Set<String> targetsFromSetting = new ArraySet<>(); final Set<String> targetsFromSetting = new ArraySet<>(); readColonDelimitedSettingToSet(Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, readColonDelimitedSettingToSet(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, userState.mUserId, targetsFromSetting, str -> str); userState.mUserId, targetsFromSetting, str -> str); final Set<String> currentTargets = final Set<String> currentTargets = Loading @@ -1964,6 +1972,23 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return true; return true; } } private boolean readAccessibilityButtonTargetComponentLocked(AccessibilityUserState userState) { final String componentId = Settings.Secure.getStringForUser(mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, userState.mUserId); if (TextUtils.isEmpty(componentId)) { if (userState.getTargetAssignedToAccessibilityButton() == null) { return false; } userState.setTargetAssignedToAccessibilityButton(null); return true; } if (componentId.equals(userState.getTargetAssignedToAccessibilityButton())) { return false; } userState.setTargetAssignedToAccessibilityButton(componentId); return true; } private boolean readUserRecommendedUiTimeoutSettingsLocked(AccessibilityUserState userState) { private boolean readUserRecommendedUiTimeoutSettingsLocked(AccessibilityUserState userState) { final int nonInteractiveUiTimeout = Settings.Secure.getIntForUser( final int nonInteractiveUiTimeout = Settings.Secure.getIntForUser( mContext.getContentResolver(), mContext.getContentResolver(), Loading @@ -1984,7 +2009,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } /** /** * Check if the targets that will be enabled by the accessibility shortcut key is installed. * Check if the target that will be enabled by the accessibility shortcut key is installed. * If it isn't, remove it from the list and associated setting so a side loaded service can't * If it isn't, remove it from the list and associated setting so a side loaded service can't * spoof the package name of the default service. * spoof the package name of the default service. */ */ Loading Loading @@ -2145,7 +2170,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub /** /** * 1) Update accessibility button availability to accessibility services. * 1) Update accessibility button availability to accessibility services. * 2) Check if the targets that will be enabled by the accessibility button is installed. * 2) Check if the target that will be enabled by the accessibility button is installed. * If it isn't, remove it from the list and associated setting so a side loaded service can't * If it isn't, remove it from the list and associated setting so a side loaded service can't * spoof the package name of the default service. * spoof the package name of the default service. */ */ Loading @@ -2172,8 +2197,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } // Update setting key with new value. // Update setting key with new value. persistColonDelimitedSetToSettingLocked( persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, userState.mUserId, currentTargets, str -> str); userState.mUserId, currentTargets, str -> str); scheduleNotifyClientsOfServicesStateChangeLocked(userState); scheduleNotifyClientsOfServicesStateChangeLocked(userState); } } Loading @@ -2182,7 +2206,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub * 1) Check if the service assigned to accessibility button target sdk version > Q. * 1) Check if the service assigned to accessibility button target sdk version > Q. * If it isn't, remove it from the list and associated setting. * If it isn't, remove it from the list and associated setting. * (It happens when an accessibility service package is downgraded.) * (It happens when an accessibility service package is downgraded.) * 2) Check if an enabled service targeting sdk version > Q and requesting a11y button is * 2) For a service targeting sdk version > Q and requesting a11y button, it should be in the * enabled list if's assigned to a11y button. * (It happens when an accessibility service package is same graded, and updated requesting * a11y button flag) * 3) Check if an enabled service targeting sdk version > Q and requesting a11y button is * assigned to a shortcut. If it isn't, assigns it to the accessibility button. * assigned to a shortcut. If it isn't, assigns it to the accessibility button. * (It happens when an enabled accessibility service package is upgraded.) * (It happens when an enabled accessibility service package is upgraded.) * * Loading @@ -2207,11 +2235,22 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return false; return false; } } if (serviceInfo.getResolveInfo().serviceInfo.applicationInfo if (serviceInfo.getResolveInfo().serviceInfo.applicationInfo .targetSdkVersion > Build.VERSION_CODES.Q) { .targetSdkVersion <= Build.VERSION_CODES.Q) { return false; } // A11y services targeting sdk version <= Q should not be in the list. // A11y services targeting sdk version <= Q should not be in the list. Slog.v(LOG_TAG, "Legacy service " + componentName + " should not in the button"); return true; } final boolean requestA11yButton = (serviceInfo.flags & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0; if (requestA11yButton && !userState.mEnabledServices.contains(componentName)) { // An a11y service targeting sdk version > Q and request A11y button and is assigned // to a11y btn should be in the enabled list. Slog.v(LOG_TAG, "Service requesting a11y button and be assigned to the button" + componentName + " should be enabled state"); return true; return true; } return false; }); }); boolean changed = (lastSize != buttonTargets.size()); boolean changed = (lastSize != buttonTargets.size()); lastSize = buttonTargets.size(); lastSize = buttonTargets.size(); Loading @@ -2234,15 +2273,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub .targetSdkVersion > Build.VERSION_CODES.Q && requestA11yButton)) { .targetSdkVersion > Build.VERSION_CODES.Q && requestA11yButton)) { return; return; } } final String serviceName = serviceInfo.getComponentName().flattenToString(); final String serviceName = componentName.flattenToString(); if (TextUtils.isEmpty(serviceName)) { if (TextUtils.isEmpty(serviceName)) { return; return; } } if (shortcutKeyTargets.contains(serviceName) || buttonTargets.contains(serviceName)) { if (doesShortcutTargetsStringContain(buttonTargets, serviceName) || doesShortcutTargetsStringContain(shortcutKeyTargets, serviceName)) { return; return; } } // For enabled a11y services targeting sdk version > Q and requesting a11y button should // For enabled a11y services targeting sdk version > Q and requesting a11y button should // be assigned to a shortcut. // be assigned to a shortcut. Slog.v(LOG_TAG, "A enabled service requesting a11y button " + componentName + " should be assign to the button or shortcut."); buttonTargets.add(serviceName); buttonTargets.add(serviceName); }); }); changed |= (lastSize != buttonTargets.size()); changed |= (lastSize != buttonTargets.size()); Loading @@ -2251,8 +2293,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } // Update setting key with new value. // Update setting key with new value. persistColonDelimitedSetToSettingLocked( persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, userState.mUserId, buttonTargets, str -> str); userState.mUserId, buttonTargets, str -> str); scheduleNotifyClientsOfServicesStateChangeLocked(userState); scheduleNotifyClientsOfServicesStateChangeLocked(userState); } } Loading Loading @@ -2353,12 +2394,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return; return; } } // In case the caller specified a target name // In case the caller specified a target name if (targetName != null) { if (targetName != null && !doesShortcutTargetsStringContain(shortcutTargets, targetName)) { if (!shortcutTargets.contains(targetName)) { Slog.v(LOG_TAG, "Perform shortcut failed, invalid target name:" + targetName); Slog.d(LOG_TAG, "Perform shortcut failed, invalid target name:" + targetName); targetName = null; return; } } } else { if (targetName == null) { // In case there are many targets assigned to the given shortcut. // In case there are many targets assigned to the given shortcut. if (shortcutTargets.size() > 1) { if (shortcutTargets.size() > 1) { showAccessibilityTargetsSelection(displayId, shortcutType); showAccessibilityTargetsSelection(displayId, shortcutType); Loading Loading @@ -2983,6 +3023,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub private final Uri mAccessibilityButtonComponentIdUri = Settings.Secure.getUriFor( private final Uri mAccessibilityButtonComponentIdUri = Settings.Secure.getUriFor( Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT); Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT); private final Uri mAccessibilityButtonTargetsUri = Settings.Secure.getUriFor( Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS); private final Uri mUserNonInteractiveUiTimeoutUri = Settings.Secure.getUriFor( private final Uri mUserNonInteractiveUiTimeoutUri = Settings.Secure.getUriFor( Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS); Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS); Loading Loading @@ -3015,6 +3058,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub mAccessibilityShortcutServiceIdUri, false, this, UserHandle.USER_ALL); mAccessibilityShortcutServiceIdUri, false, this, UserHandle.USER_ALL); contentResolver.registerContentObserver( contentResolver.registerContentObserver( mAccessibilityButtonComponentIdUri, false, this, UserHandle.USER_ALL); mAccessibilityButtonComponentIdUri, false, this, UserHandle.USER_ALL); contentResolver.registerContentObserver( mAccessibilityButtonTargetsUri, false, this, UserHandle.USER_ALL); contentResolver.registerContentObserver( contentResolver.registerContentObserver( mUserNonInteractiveUiTimeoutUri, false, this, UserHandle.USER_ALL); mUserNonInteractiveUiTimeoutUri, false, this, UserHandle.USER_ALL); contentResolver.registerContentObserver( contentResolver.registerContentObserver( Loading Loading @@ -3061,7 +3106,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub onUserStateChangedLocked(userState); onUserStateChangedLocked(userState); } } } else if (mAccessibilityButtonComponentIdUri.equals(uri)) { } else if (mAccessibilityButtonComponentIdUri.equals(uri)) { if (readAccessibilityButtonSettingsLocked(userState)) { if (readAccessibilityButtonTargetComponentLocked(userState)) { onUserStateChangedLocked(userState); } } else if (mAccessibilityButtonTargetsUri.equals(uri)) { if (readAccessibilityButtonTargetsLocked(userState)) { onUserStateChangedLocked(userState); onUserStateChangedLocked(userState); } } } else if (mUserNonInteractiveUiTimeoutUri.equals(uri) } else if (mUserNonInteractiveUiTimeoutUri.equals(uri) Loading
services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java +58 −0 Original line number Original line Diff line number Diff line Loading @@ -49,6 +49,7 @@ import com.android.internal.accessibility.AccessibilityShortcutController; import java.io.FileDescriptor; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashMap; import java.util.HashSet; import java.util.HashSet; import java.util.Iterator; import java.util.Iterator; Loading Loading @@ -96,6 +97,8 @@ class AccessibilityUserState { private ComponentName mServiceChangingSoftKeyboardMode; private ComponentName mServiceChangingSoftKeyboardMode; private String mTargetAssignedToAccessibilityButton; private boolean mBindInstantServiceAllowed; private boolean mBindInstantServiceAllowed; private boolean mIsAutoclickEnabled; private boolean mIsAutoclickEnabled; private boolean mIsDisplayMagnificationEnabled; private boolean mIsDisplayMagnificationEnabled; Loading Loading @@ -152,6 +155,7 @@ class AccessibilityUserState { mTouchExplorationGrantedServices.clear(); mTouchExplorationGrantedServices.clear(); mAccessibilityShortcutKeyTargets.clear(); mAccessibilityShortcutKeyTargets.clear(); mAccessibilityButtonTargets.clear(); mAccessibilityButtonTargets.clear(); mTargetAssignedToAccessibilityButton = null; mIsTouchExplorationEnabled = false; mIsTouchExplorationEnabled = false; mServiceHandlesDoubleTap = false; mServiceHandlesDoubleTap = false; mRequestMultiFingerGestures = false; mRequestMultiFingerGestures = false; Loading Loading @@ -469,6 +473,8 @@ class AccessibilityUserState { } } } } pw.println("}"); pw.println("}"); pw.append(" button target:{").append(mTargetAssignedToAccessibilityButton); pw.println("}"); pw.append(" Bound services:{"); pw.append(" Bound services:{"); final int serviceCount = mBoundServices.size(); final int serviceCount = mBoundServices.size(); for (int j = 0; j < serviceCount; j++) { for (int j = 0; j < serviceCount; j++) { Loading Loading @@ -716,4 +722,56 @@ class AccessibilityUserState { public void setUserNonInteractiveUiTimeoutLocked(int timeout) { public void setUserNonInteractiveUiTimeoutLocked(int timeout) { mUserNonInteractiveUiTimeout = timeout; mUserNonInteractiveUiTimeout = timeout; } } /** * Gets a shortcut target which is assigned to the accessibility button by the chooser * activity. * * @return The flattened component name or the system class name of the shortcut target. */ public String getTargetAssignedToAccessibilityButton() { return mTargetAssignedToAccessibilityButton; } /** * Sets a shortcut target which is assigned to the accessibility button by the chooser * activity. * * @param target The flattened component name or the system class name of the shortcut target. */ public void setTargetAssignedToAccessibilityButton(String target) { mTargetAssignedToAccessibilityButton = target; } /** * Whether or not the given target name is contained in the shortcut collection. Since the * component name string format could be short or long, this function un-flatten the component * name from the string in {@code shortcutTargets} and compared with the given target name. * * @param shortcutTargets The shortcut type. * @param targetName The target name. * @return {@code true} if the target is in the shortcut collection. */ public static boolean doesShortcutTargetsStringContain(Collection<String> shortcutTargets, String targetName) { if (shortcutTargets == null || targetName == null) { return false; } // Some system features, such as magnification, don't have component name. Using string // compare first. if (shortcutTargets.contains(targetName)) { return true; } final ComponentName targetComponentName = ComponentName.unflattenFromString(targetName); if (targetComponentName == null) { return false; } for (String stringName : shortcutTargets) { if (!TextUtils.isEmpty(stringName) && targetComponentName.equals(ComponentName.unflattenFromString(stringName))) { return true; } } return false; } } }
services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java +36 −0 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,8 @@ import static android.view.accessibility.AccessibilityManager.STATE_FLAG_ACCESSI import static android.view.accessibility.AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED; import static android.view.accessibility.AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED; import static android.view.accessibility.AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED; import static android.view.accessibility.AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED; import static com.android.server.accessibility.AccessibilityUserState.doesShortcutTargetsStringContain; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertNull; Loading @@ -41,6 +43,7 @@ import android.content.Context; import android.provider.Settings; import android.provider.Settings; import android.test.mock.MockContentResolver; import android.test.mock.MockContentResolver; import android.testing.DexmakerShareClassLoaderRule; import android.testing.DexmakerShareClassLoaderRule; import android.util.ArraySet; import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.util.test.FakeSettingsProvider; Loading @@ -56,6 +59,12 @@ public class AccessibilityUserStateTest { private static final ComponentName COMPONENT_NAME = private static final ComponentName COMPONENT_NAME = new ComponentName("com.android.server.accessibility", "AccessibilityUserStateTest"); new ComponentName("com.android.server.accessibility", "AccessibilityUserStateTest"); private static final ComponentName COMPONENT_NAME1 = new ComponentName("com.android.server.accessibility", "com.android.server.accessibility.AccessibilityUserStateTest1"); private static final ComponentName COMPONENT_NAME2 = new ComponentName("com.android.server.accessibility", "com.android.server.accessibility.AccessibilityUserStateTest2"); // Values of setting key SHOW_IME_WITH_HARD_KEYBOARD // Values of setting key SHOW_IME_WITH_HARD_KEYBOARD private static final int STATE_HIDE_IME = 0; private static final int STATE_HIDE_IME = 0; Loading Loading @@ -111,6 +120,7 @@ public class AccessibilityUserStateTest { mUserState.mTouchExplorationGrantedServices.add(COMPONENT_NAME); mUserState.mTouchExplorationGrantedServices.add(COMPONENT_NAME); mUserState.mAccessibilityShortcutKeyTargets.add(COMPONENT_NAME.flattenToString()); mUserState.mAccessibilityShortcutKeyTargets.add(COMPONENT_NAME.flattenToString()); mUserState.mAccessibilityButtonTargets.add(COMPONENT_NAME.flattenToString()); mUserState.mAccessibilityButtonTargets.add(COMPONENT_NAME.flattenToString()); mUserState.setTargetAssignedToAccessibilityButton(COMPONENT_NAME.flattenToString()); mUserState.setTouchExplorationEnabledLocked(true); mUserState.setTouchExplorationEnabledLocked(true); mUserState.setDisplayMagnificationEnabledLocked(true); mUserState.setDisplayMagnificationEnabledLocked(true); mUserState.setAutoclickEnabledLocked(true); mUserState.setAutoclickEnabledLocked(true); Loading @@ -129,6 +139,7 @@ public class AccessibilityUserStateTest { assertTrue(mUserState.mTouchExplorationGrantedServices.isEmpty()); assertTrue(mUserState.mTouchExplorationGrantedServices.isEmpty()); assertTrue(mUserState.mAccessibilityShortcutKeyTargets.isEmpty()); assertTrue(mUserState.mAccessibilityShortcutKeyTargets.isEmpty()); assertTrue(mUserState.mAccessibilityButtonTargets.isEmpty()); assertTrue(mUserState.mAccessibilityButtonTargets.isEmpty()); assertNull(mUserState.getTargetAssignedToAccessibilityButton()); assertFalse(mUserState.isTouchExplorationEnabledLocked()); assertFalse(mUserState.isTouchExplorationEnabledLocked()); assertFalse(mUserState.isDisplayMagnificationEnabledLocked()); assertFalse(mUserState.isDisplayMagnificationEnabledLocked()); assertFalse(mUserState.isAutoclickEnabledLocked()); assertFalse(mUserState.isAutoclickEnabledLocked()); Loading Loading @@ -285,6 +296,31 @@ public class AccessibilityUserStateTest { verify(mMockConnection).notifySoftKeyboardShowModeChangedLocked(eq(SHOW_MODE_HIDDEN)); verify(mMockConnection).notifySoftKeyboardShowModeChangedLocked(eq(SHOW_MODE_HIDDEN)); } } @Test public void doesShortcutTargetsStringContain_returnFalse() { assertFalse(doesShortcutTargetsStringContain(null, null)); assertFalse(doesShortcutTargetsStringContain(null, COMPONENT_NAME.flattenToShortString())); assertFalse(doesShortcutTargetsStringContain(new ArraySet<>(), null)); final ArraySet<String> shortcutTargets = new ArraySet<>(); shortcutTargets.add(COMPONENT_NAME.flattenToString()); assertFalse(doesShortcutTargetsStringContain(shortcutTargets, COMPONENT_NAME1.flattenToString())); } @Test public void isAssignedToShortcutLocked_withDifferentTypeComponentString_returnTrue() { final ArraySet<String> shortcutTargets = new ArraySet<>(); shortcutTargets.add(COMPONENT_NAME1.flattenToShortString()); shortcutTargets.add(COMPONENT_NAME2.flattenToString()); assertTrue(doesShortcutTargetsStringContain(shortcutTargets, COMPONENT_NAME1.flattenToString())); assertTrue(doesShortcutTargetsStringContain(shortcutTargets, COMPONENT_NAME2.flattenToShortString())); } @Test @Test public void isShortcutTargetInstalledLocked_returnTrue() { public void isShortcutTargetInstalledLocked_returnTrue() { mUserState.mInstalledServices.add(mMockServiceInfo); mUserState.mInstalledServices.add(mMockServiceInfo); Loading