Merge changes from topic "A11yShortcut_NeedWithUi"
* changes:
Accessibility shortcut improvement (10/n)
Accessibility shortcut improvement (9/n)
Accessibility shortcut improvement (8/n)
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 089122d..e2b33e0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6420,6 +6420,15 @@
"accessibility_button_target_component";
/**
+ * The system class name of magnification controller which is a target to be toggled via
+ * accessibility shortcut or accessibility button.
+ *
+ * @hide
+ */
+ public static final String ACCESSIBILITY_SHORTCUT_TARGET_MAGNIFICATION_CONTROLLER =
+ "com.android.server.accessibility.MagnificationController";
+
+ /**
* If touch exploration is enabled.
*/
public static final String TOUCH_EXPLORATION_ENABLED = "touch_exploration_enabled";
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 2e5a4b5..3dfeffb 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -1195,6 +1195,19 @@
@TestApi
@RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
public void performAccessibilityShortcut() {
+ performAccessibilityShortcut(null);
+ }
+
+ /**
+ * Perform the accessibility shortcut for the given target which is assigned to the shortcut.
+ *
+ * @param targetName The flattened {@link ComponentName} string or the class name of a system
+ * class implementing a supported accessibility feature, or {@code null} if there's no
+ * specified target.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
+ public void performAccessibilityShortcut(@Nullable String targetName) {
final IAccessibilityManager service;
synchronized (mLock) {
service = getServiceLocked();
@@ -1203,7 +1216,7 @@
}
}
try {
- service.performAccessibilityShortcut();
+ service.performAccessibilityShortcut(targetName);
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error performing accessibility shortcut. ", re);
}
@@ -1270,7 +1283,22 @@
* @param displayId The logical display id.
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE)
public void notifyAccessibilityButtonClicked(int displayId) {
+ notifyAccessibilityButtonClicked(displayId, null);
+ }
+
+ /**
+ * Perform the accessibility button for the given target which is assigned to the button.
+ *
+ * @param displayId displayId The logical display id.
+ * @param targetName The flattened {@link ComponentName} string or the class name of a system
+ * class implementing a supported accessibility feature, or {@code null} if there's no
+ * specified target.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE)
+ public void notifyAccessibilityButtonClicked(int displayId, @Nullable String targetName) {
final IAccessibilityManager service;
synchronized (mLock) {
service = getServiceLocked();
@@ -1279,7 +1307,7 @@
}
}
try {
- service.notifyAccessibilityButtonClicked(displayId);
+ service.notifyAccessibilityButtonClicked(displayId, targetName);
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error while dispatching accessibility button click", re);
}
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index 392db57..fcaaa2e 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -66,12 +66,12 @@
// Used by UiAutomation
IBinder getWindowToken(int windowId, int userId);
- void notifyAccessibilityButtonClicked(int displayId);
+ void notifyAccessibilityButtonClicked(int displayId, String targetName);
void notifyAccessibilityButtonVisibilityChanged(boolean available);
// Requires Manifest.permission.MANAGE_ACCESSIBILITY
- void performAccessibilityShortcut();
+ void performAccessibilityShortcut(String targetName);
// Requires Manifest.permission.MANAGE_ACCESSIBILITY
List<String> getAccessibilityShortcutTargets(int shortcutType);
diff --git a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
index 82854e5..6784ede 100644
--- a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
+++ b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
@@ -348,7 +348,7 @@
verify(mAlertDialog).show();
verify(mAccessibilityManagerService, atLeastOnce()).getInstalledAccessibilityServiceList(
anyInt());
- verify(mAccessibilityManagerService, times(0)).performAccessibilityShortcut();
+ verify(mAccessibilityManagerService, times(0)).performAccessibilityShortcut(null);
verify(mFrameworkObjectProvider, times(0)).getTextToSpeech(any(), any());
}
@@ -365,7 +365,7 @@
assertEquals(WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS,
mLayoutParams.privateFlags
& WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS);
- verify(mAccessibilityManagerService, times(1)).performAccessibilityShortcut();
+ verify(mAccessibilityManagerService, times(1)).performAccessibilityShortcut(null);
}
@Test
@@ -433,7 +433,7 @@
verifyZeroInteractions(mAlertDialogBuilder, mAlertDialog);
verify(mToast).show();
- verify(mAccessibilityManagerService).performAccessibilityShortcut();
+ verify(mAccessibilityManagerService).performAccessibilityShortcut(null);
}
@Test
@@ -459,7 +459,7 @@
when(mServiceInfo.loadSummary(any())).thenReturn(null);
Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 1);
getController().performAccessibilityShortcut();
- verify(mAccessibilityManagerService).performAccessibilityShortcut();
+ verify(mAccessibilityManagerService).performAccessibilityShortcut(null);
}
@Test
@@ -471,7 +471,7 @@
getController().performAccessibilityShortcut();
verifyZeroInteractions(mToast);
- verify(mAccessibilityManagerService).performAccessibilityShortcut();
+ verify(mAccessibilityManagerService).performAccessibilityShortcut(null);
}
@Test
@@ -485,7 +485,7 @@
getController().performAccessibilityShortcut();
verifyZeroInteractions(mToast);
- verify(mAccessibilityManagerService).performAccessibilityShortcut();
+ verify(mAccessibilityManagerService).performAccessibilityShortcut(null);
}
@Test
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 1e0c1d8..4443524 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -20,6 +20,7 @@
import static android.os.Process.ROOT_UID;
import static android.os.Process.SHELL_UID;
import static android.os.Process.SYSTEM_UID;
+import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_MAGNIFICATION_CONTROLLER;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY;
import android.Manifest;
@@ -3304,7 +3305,7 @@
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 185;
+ private static final int SETTINGS_VERSION = 186;
private final int mUserId;
@@ -4547,6 +4548,32 @@
currentVersion = 185;
}
+ if (currentVersion == 185) {
+ // Deprecate ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, and migrate it
+ // to ACCESSIBILITY_BUTTON_TARGET_COMPONENT.
+ final SettingsState secureSettings = getSecureSettingsLocked(userId);
+ final Setting magnifyNavbarEnabled = secureSettings.getSettingLocked(
+ Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED);
+ if ("1".equals(magnifyNavbarEnabled.getValue())) {
+ secureSettings.insertSettingLocked(
+ Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT,
+ ACCESSIBILITY_SHORTCUT_TARGET_MAGNIFICATION_CONTROLLER,
+ null /* tag */, false /* makeDefault */,
+ 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(
+ Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED);
+ currentVersion = 186;
+ }
+
// vXXX: Add new settings above this point.
if (currentVersion != newVersion) {
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 7278225..1a1a480 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -734,7 +734,8 @@
Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE,
Settings.Secure.FACE_UNLOCK_RE_ENROLL,
Settings.Secure.TAP_GESTURE,
- Settings.Secure.WINDOW_MAGNIFICATION);
+ Settings.Secure.WINDOW_MAGNIFICATION,
+ Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_MAGNIFICATION_CONTROLLER);
@Test
public void systemSettingsBackedUpOrBlacklisted() {
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 2a1e74e..df77b5b 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -211,6 +211,7 @@
<!-- accessibility -->
<uses-permission android:name="android.permission.MODIFY_ACCESSIBILITY_DATA" />
+ <uses-permission android:name="android.permission.MANAGE_ACCESSIBILITY" />
<!-- to control accessibility volume -->
<uses-permission android:name="android.permission.CHANGE_ACCESSIBILITY_VOLUME" />
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index a6842ba..4f56f56 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -157,7 +157,6 @@
private int mNavigationIconHints = 0;
private @TransitionMode int mNavigationBarMode;
private AccessibilityManager mAccessibilityManager;
- private MagnificationContentObserver mMagnificationObserver;
private ContentResolver mContentResolver;
private boolean mAssistantAvailable;
@@ -303,11 +302,6 @@
mWindowManager = getContext().getSystemService(WindowManager.class);
mAccessibilityManager = getContext().getSystemService(AccessibilityManager.class);
mContentResolver = getContext().getContentResolver();
- mMagnificationObserver = new MagnificationContentObserver(
- getContext().getMainThreadHandler());
- mContentResolver.registerContentObserver(Settings.Secure.getUriFor(
- Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED), false,
- mMagnificationObserver, UserHandle.USER_ALL);
mContentResolver.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.ASSISTANT),
false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL);
@@ -329,7 +323,6 @@
super.onDestroy();
mNavigationModeController.removeListener(this);
mAccessibilityManagerWrapper.removeCallback(mAccessibilityListener);
- mContentResolver.unregisterContentObserver(mMagnificationObserver);
mContentResolver.unregisterContentObserver(mAssistContentObserver);
}
@@ -969,28 +962,18 @@
* @param outFeedbackEnabled if non-null, sets it to true if accessibility feedback is enabled.
*/
public int getA11yButtonState(@Nullable boolean[] outFeedbackEnabled) {
- int requestingServices = 0;
- try {
- if (Settings.Secure.getIntForUser(mContentResolver,
- Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED,
- UserHandle.USER_CURRENT) == 1) {
- requestingServices++;
- }
- } catch (Settings.SettingNotFoundException e) {
- }
-
boolean feedbackEnabled = false;
// AccessibilityManagerService resolves services for the current user since the local
// AccessibilityManager is created from a Context with the INTERACT_ACROSS_USERS permission
final List<AccessibilityServiceInfo> services =
mAccessibilityManager.getEnabledAccessibilityServiceList(
AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
+ final List<String> a11yButtonTargets =
+ mAccessibilityManager.getAccessibilityShortcutTargets(
+ AccessibilityManager.ACCESSIBILITY_BUTTON);
+ final int requestingServices = a11yButtonTargets.size();
for (int i = services.size() - 1; i >= 0; --i) {
AccessibilityServiceInfo info = services.get(i);
- if ((info.flags & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0) {
- requestingServices++;
- }
-
if (info.feedbackType != 0 && info.feedbackType !=
AccessibilityServiceInfo.FEEDBACK_GENERIC) {
feedbackEnabled = true;
@@ -1114,18 +1097,6 @@
private final AccessibilityServicesStateChangeListener mAccessibilityListener =
this::updateAccessibilityServicesState;
- private class MagnificationContentObserver extends ContentObserver {
-
- public MagnificationContentObserver(Handler handler) {
- super(handler);
- }
-
- @Override
- public void onChange(boolean selfChange) {
- NavigationBarFragment.this.updateAccessibilityServicesState(mAccessibilityManager);
- }
- }
-
private final Consumer<Integer> mRotationWatcher = rotation -> {
if (mNavigationBarView != null
&& mNavigationBarView.needsReorient(rotation)) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 58d3489..36a9e0eb 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -411,6 +411,7 @@
if (reboundAService) {
onUserStateChangedLocked(userState);
}
+ migrateAccessibilityButtonSettingsIfNecessaryLocked(userState, packageName);
}
}
@@ -811,9 +812,7 @@
userState.setTouchExplorationEnabledLocked(touchExplorationEnabled);
userState.setDisplayMagnificationEnabledLocked(false);
- userState.setNavBarMagnificationEnabledLocked(false);
userState.disableShortcutMagnificationLocked();
-
userState.setAutoclickEnabledLocked(false);
userState.mEnabledServices.clear();
userState.mEnabledServices.add(service);
@@ -853,17 +852,20 @@
* navigation area has been clicked.
*
* @param displayId The logical display id.
+ * @param targetName The flattened {@link ComponentName} string or the class name of a system
+ * class implementing a supported accessibility feature, or {@code null} if there's no
+ * specified target.
*/
@Override
- public void notifyAccessibilityButtonClicked(int displayId) {
+ public void notifyAccessibilityButtonClicked(int displayId, String targetName) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Caller does not hold permission "
+ android.Manifest.permission.STATUS_BAR_SERVICE);
}
- synchronized (mLock) {
- notifyAccessibilityButtonClickedLocked(displayId);
- }
+ mMainHandler.sendMessage(obtainMessage(
+ AccessibilityManagerService::performAccessibilityShortcutInternal, this,
+ displayId, ACCESSIBILITY_BUTTON, targetName));
}
/**
@@ -1023,6 +1025,7 @@
// the state since the context in which the current user
// state was used has changed since it was inactive.
onUserStateChangedLocked(userState);
+ migrateAccessibilityButtonSettingsIfNecessaryLocked(userState, null);
if (announceNewUser) {
// Schedule announcement of the current user if needed.
@@ -1132,66 +1135,6 @@
}
}
- // TODO(a11y shortcut): Remove this function and Use #performAccessibilityShortcutInternal(
- // ACCESSIBILITY_BUTTON) instead, after the new Settings shortcut Ui merged.
- private void notifyAccessibilityButtonClickedLocked(int displayId) {
- final AccessibilityUserState state = getCurrentUserStateLocked();
-
- int potentialTargets = state.isNavBarMagnificationEnabledLocked() ? 1 : 0;
- for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
- final AccessibilityServiceConnection service = state.mBoundServices.get(i);
- if (service.mRequestAccessibilityButton) {
- potentialTargets++;
- }
- }
-
- if (potentialTargets == 0) {
- return;
- }
- if (potentialTargets == 1) {
- if (state.isNavBarMagnificationEnabledLocked()) {
- mMainHandler.sendMessage(obtainMessage(
- AccessibilityManagerService::sendAccessibilityButtonToInputFilter, this,
- displayId));
- return;
- } else {
- for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
- final AccessibilityServiceConnection service = state.mBoundServices.get(i);
- if (service.mRequestAccessibilityButton) {
- service.notifyAccessibilityButtonClickedLocked(displayId);
- return;
- }
- }
- }
- } else {
- if (state.getServiceAssignedToAccessibilityButtonLocked() == null
- && !state.isNavBarMagnificationAssignedToAccessibilityButtonLocked()) {
- mMainHandler.sendMessage(obtainMessage(
- AccessibilityManagerService::showAccessibilityTargetsSelection, this,
- displayId, ACCESSIBILITY_BUTTON));
- } else if (state.isNavBarMagnificationEnabledLocked()
- && state.isNavBarMagnificationAssignedToAccessibilityButtonLocked()) {
- mMainHandler.sendMessage(obtainMessage(
- AccessibilityManagerService::sendAccessibilityButtonToInputFilter, this,
- displayId));
- return;
- } else {
- for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
- final AccessibilityServiceConnection service = state.mBoundServices.get(i);
- if (service.mRequestAccessibilityButton && (service.mComponentName.equals(
- state.getServiceAssignedToAccessibilityButtonLocked()))) {
- service.notifyAccessibilityButtonClickedLocked(displayId);
- return;
- }
- }
- }
- // The user may have turned off the assigned service or feature
- mMainHandler.sendMessage(obtainMessage(
- AccessibilityManagerService::showAccessibilityTargetsSelection, this,
- displayId, ACCESSIBILITY_BUTTON));
- }
- }
-
private void sendAccessibilityButtonToInputFilter(int displayId) {
synchronized (mLock) {
if (mHasInputFilter && mInputFilter != null) {
@@ -1635,8 +1578,7 @@
if (userState.isDisplayMagnificationEnabledLocked()) {
flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER;
}
- if (userState.isNavBarMagnificationEnabledLocked()
- || userState.isShortcutKeyMagnificationEnabledLocked()) {
+ if (userState.isShortcutMagnificationEnabledLocked()) {
flags |= AccessibilityInputFilter.FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER;
}
if (userHasMagnificationServicesLocked(userState)) {
@@ -1886,14 +1828,8 @@
mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
0, userState.mUserId) == 1;
- final boolean navBarMagnificationEnabled = Settings.Secure.getIntForUser(
- mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED,
- 0, userState.mUserId) == 1;
- if ((displayMagnificationEnabled != userState.isDisplayMagnificationEnabledLocked())
- || (navBarMagnificationEnabled != userState.isNavBarMagnificationEnabledLocked())) {
+ if ((displayMagnificationEnabled != userState.isDisplayMagnificationEnabledLocked())) {
userState.setDisplayMagnificationEnabledLocked(displayMagnificationEnabled);
- userState.setNavBarMagnificationEnabledLocked(navBarMagnificationEnabled);
return true;
}
return false;
@@ -2088,8 +2024,7 @@
// displays in one display. It's not a real display and there's no input events for it.
final ArrayList<Display> displays = getValidDisplayList();
if (userState.isDisplayMagnificationEnabledLocked()
- || userState.isNavBarMagnificationEnabledLocked()
- || userState.isShortcutKeyMagnificationEnabledLocked()) {
+ || userState.isShortcutMagnificationEnabledLocked()) {
for (int i = 0; i < displays.size(); i++) {
final Display display = displays.get(i);
getMagnificationController().register(display.getDisplayId());
@@ -2208,6 +2143,85 @@
scheduleNotifyClientsOfServicesStateChangeLocked(userState);
}
+ /**
+ * 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.
+ * (It happens when an accessibility service package is downgraded.)
+ * 2) 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.
+ * (It happens when an enabled accessibility service package is upgraded.)
+ *
+ * @param packageName The package name to check, or {@code null} to check all services.
+ */
+ private void migrateAccessibilityButtonSettingsIfNecessaryLocked(
+ AccessibilityUserState userState, @Nullable String packageName) {
+ final Set<String> buttonTargets =
+ userState.getShortcutTargetsLocked(ACCESSIBILITY_BUTTON);
+ int lastSize = buttonTargets.size();
+ buttonTargets.removeIf(name -> {
+ if (packageName != null && name != null && !name.contains(packageName)) {
+ return false;
+ }
+ final ComponentName componentName = ComponentName.unflattenFromString(name);
+ if (componentName == null) {
+ return false;
+ }
+ final AccessibilityServiceInfo serviceInfo =
+ userState.getInstalledServiceInfoLocked(componentName);
+ if (serviceInfo == null) {
+ return false;
+ }
+ if (serviceInfo.getResolveInfo().serviceInfo.applicationInfo
+ .targetSdkVersion > Build.VERSION_CODES.Q) {
+ return false;
+ }
+ // A11y services targeting sdk version <= Q should not be in the list.
+ return true;
+ });
+ boolean changed = (lastSize != buttonTargets.size());
+ lastSize = buttonTargets.size();
+
+ final Set<String> shortcutKeyTargets =
+ userState.getShortcutTargetsLocked(ACCESSIBILITY_SHORTCUT_KEY);
+ userState.mEnabledServices.forEach(componentName -> {
+ if (packageName != null && componentName != null
+ && !packageName.equals(componentName.getPackageName())) {
+ return;
+ }
+ final AccessibilityServiceInfo serviceInfo =
+ userState.getInstalledServiceInfoLocked(componentName);
+ if (serviceInfo == null) {
+ return;
+ }
+ final boolean requestA11yButton = (serviceInfo.flags
+ & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
+ if (!(serviceInfo.getResolveInfo().serviceInfo.applicationInfo
+ .targetSdkVersion > Build.VERSION_CODES.Q && requestA11yButton)) {
+ return;
+ }
+ final String serviceName = serviceInfo.getComponentName().flattenToString();
+ if (TextUtils.isEmpty(serviceName)) {
+ return;
+ }
+ if (shortcutKeyTargets.contains(serviceName) || buttonTargets.contains(serviceName)) {
+ return;
+ }
+ // For enabled a11y services targeting sdk version > Q and requesting a11y button should
+ // be assigned to a shortcut.
+ buttonTargets.add(serviceName);
+ });
+ changed |= (lastSize != buttonTargets.size());
+ if (!changed) {
+ return;
+ }
+
+ // Update setting key with new value.
+ persistColonDelimitedSetToSettingLocked(
+ Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT,
+ userState.mUserId, buttonTargets, str -> str);
+ scheduleNotifyClientsOfServicesStateChangeLocked(userState);
+ }
+
private void updateRecommendedUiTimeoutLocked(AccessibilityUserState userState) {
int newNonInteractiveUiTimeout = userState.getUserNonInteractiveUiTimeoutLocked();
int newInteractiveUiTimeout = userState.getUserInteractiveUiTimeoutLocked();
@@ -2269,9 +2283,13 @@
* AIDL-exposed method to be called when the accessibility shortcut key is enabled. Requires
* permission to write secure settings, since someone with that permission can enable
* accessibility services themselves.
+ *
+ * @param targetName The flattened {@link ComponentName} string or the class name of a system
+ * class implementing a supported accessibility feature, or {@code null} if there's no
+ * specified target.
*/
@Override
- public void performAccessibilityShortcut() {
+ public void performAccessibilityShortcut(String targetName) {
if ((UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID)
&& (mContext.checkCallingPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
!= PackageManager.PERMISSION_GRANTED)) {
@@ -2280,7 +2298,7 @@
}
mMainHandler.sendMessage(obtainMessage(
AccessibilityManagerService::performAccessibilityShortcutInternal, this,
- Display.DEFAULT_DISPLAY, ACCESSIBILITY_SHORTCUT_KEY));
+ Display.DEFAULT_DISPLAY, ACCESSIBILITY_SHORTCUT_KEY, targetName));
}
/**
@@ -2288,20 +2306,31 @@
*
* @param shortcutType The shortcut type.
* @param displayId The display id of the accessibility button.
+ * @param targetName The flattened {@link ComponentName} string or the class name of a system
+ * class implementing a supported accessibility feature, or {@code null} if there's no
+ * specified target.
*/
private void performAccessibilityShortcutInternal(int displayId,
- @ShortcutType int shortcutType) {
+ @ShortcutType int shortcutType, @Nullable String targetName) {
final List<String> shortcutTargets = getAccessibilityShortcutTargetsInternal(shortcutType);
if (shortcutTargets.isEmpty()) {
Slog.d(LOG_TAG, "No target to perform shortcut, shortcutType=" + shortcutType);
return;
}
- // In case there are many targets assigned to the given shortcut.
- if (shortcutTargets.size() > 1) {
- showAccessibilityTargetsSelection(displayId, shortcutType);
- return;
+ // In case the caller specified a target name
+ if (targetName != null) {
+ if (!shortcutTargets.contains(targetName)) {
+ Slog.d(LOG_TAG, "Perform shortcut failed, invalid target name:" + targetName);
+ return;
+ }
+ } else {
+ // In case there are many targets assigned to the given shortcut.
+ if (shortcutTargets.size() > 1) {
+ showAccessibilityTargetsSelection(displayId, shortcutType);
+ return;
+ }
+ targetName = shortcutTargets.get(0);
}
- final String targetName = shortcutTargets.get(0);
// In case user assigned magnification to the given shortcut.
if (targetName.equals(MAGNIFICATION_CONTROLLER_NAME)) {
sendAccessibilityButtonToInputFilter(displayId);
@@ -2844,11 +2873,6 @@
private final Uri mDisplayMagnificationEnabledUri = Settings.Secure.getUriFor(
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
- // TODO(a11y shortcut): Remove this setting key, and have a migrate function in
- // Setting provider after new shortcut UI merged.
- private final Uri mNavBarMagnificationEnabledUri = Settings.Secure.getUriFor(
- Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED);
-
private final Uri mAutoclickEnabledUri = Settings.Secure.getUriFor(
Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED);
@@ -2888,8 +2912,6 @@
false, this, UserHandle.USER_ALL);
contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri,
false, this, UserHandle.USER_ALL);
- contentResolver.registerContentObserver(mNavBarMagnificationEnabledUri,
- false, this, UserHandle.USER_ALL);
contentResolver.registerContentObserver(mAutoclickEnabledUri,
false, this, UserHandle.USER_ALL);
contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri,
@@ -2924,8 +2946,7 @@
if (readTouchExplorationEnabledSettingLocked(userState)) {
onUserStateChangedLocked(userState);
}
- } else if (mDisplayMagnificationEnabledUri.equals(uri)
- || mNavBarMagnificationEnabledUri.equals(uri)) {
+ } else if (mDisplayMagnificationEnabledUri.equals(uri)) {
if (readMagnificationEnabledSettingsLocked(userState)) {
onUserStateChangedLocked(userState);
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index 37ac3ec..edb4445 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -313,48 +313,16 @@
}
}
- // TODO(a11y shortcut): Refactoring the logic here, after the new Settings shortcut Ui merged.
public boolean isAccessibilityButtonAvailableLocked(AccessibilityUserState userState) {
// If the service does not request the accessibility button, it isn't available
if (!mRequestAccessibilityButton) {
return false;
}
-
// If the accessibility button isn't currently shown, it cannot be available to services
if (!mSystemSupport.isAccessibilityButtonShown()) {
return false;
}
-
- // If magnification is on and assigned to the accessibility button, services cannot be
- if (userState.isNavBarMagnificationEnabledLocked()
- && userState.isNavBarMagnificationAssignedToAccessibilityButtonLocked()) {
- return false;
- }
-
- int requestingServices = 0;
- for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
- final AccessibilityServiceConnection service = userState.mBoundServices.get(i);
- if (service.mRequestAccessibilityButton) {
- requestingServices++;
- }
- }
-
- if (requestingServices == 1) {
- // If only a single service is requesting, it must be this service, and the
- // accessibility button is available to it
- return true;
- } else {
- // With more than one active service, we derive the target from the user's settings
- if (userState.getServiceAssignedToAccessibilityButtonLocked() == null) {
- // If the user has not made an assignment, we treat the button as available to
- // all services until the user interacts with the button to make an assignment
- return true;
- } else {
- // If an assignment was made, it defines availability
- return mComponentName.equals(
- userState.getServiceAssignedToAccessibilityButtonLocked());
- }
- }
+ return true;
}
@Override
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
index a163f74..ebe2af6 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -100,7 +100,6 @@
private boolean mIsAutoclickEnabled;
private boolean mIsDisplayMagnificationEnabled;
private boolean mIsFilterKeyEventsEnabled;
- private boolean mIsNavBarMagnificationEnabled;
private boolean mIsPerformGesturesEnabled;
private boolean mIsTextHighContrastEnabled;
private boolean mIsTouchExplorationEnabled;
@@ -153,7 +152,6 @@
mAccessibilityButtonTargets.clear();
mIsTouchExplorationEnabled = false;
mIsDisplayMagnificationEnabled = false;
- mIsNavBarMagnificationEnabled = false;
mIsAutoclickEnabled = false;
mUserNonInteractiveUiTimeout = 0;
mUserInteractiveUiTimeout = 0;
@@ -435,8 +433,6 @@
pw.append(", touchExplorationEnabled=").append(String.valueOf(mIsTouchExplorationEnabled));
pw.append(", displayMagnificationEnabled=").append(String.valueOf(
mIsDisplayMagnificationEnabled));
- pw.append(", navBarMagnificationEnabled=").append(String.valueOf(
- mIsNavBarMagnificationEnabled));
pw.append(", autoclickEnabled=").append(String.valueOf(mIsAutoclickEnabled));
pw.append(", nonInteractiveUiTimeout=").append(String.valueOf(mNonInteractiveUiTimeout));
pw.append(", interactiveUiTimeout=").append(String.valueOf(mInteractiveUiTimeout));
@@ -553,8 +549,12 @@
mLastSentClientState = state;
}
- public boolean isShortcutKeyMagnificationEnabledLocked() {
- return mAccessibilityShortcutKeyTargets.contains(MAGNIFICATION_CONTROLLER_NAME);
+ /**
+ * Returns true if navibar magnification or shortcut key magnification is enabled.
+ */
+ public boolean isShortcutMagnificationEnabledLocked() {
+ return mAccessibilityShortcutKeyTargets.contains(MAGNIFICATION_CONTROLLER_NAME)
+ || mAccessibilityButtonTargets.contains(MAGNIFICATION_CONTROLLER_NAME);
}
/**
@@ -690,28 +690,4 @@
public void setUserNonInteractiveUiTimeoutLocked(int timeout) {
mUserNonInteractiveUiTimeout = timeout;
}
-
- // TODO(a11y shortcut): These functions aren't necessary, after the new Settings shortcut Ui
- // is merged.
- boolean isNavBarMagnificationEnabledLocked() {
- return mIsNavBarMagnificationEnabled;
- }
-
- void setNavBarMagnificationEnabledLocked(boolean enabled) {
- mIsNavBarMagnificationEnabled = enabled;
- }
-
- boolean isNavBarMagnificationAssignedToAccessibilityButtonLocked() {
- return mAccessibilityButtonTargets.contains(MAGNIFICATION_CONTROLLER_NAME);
- }
-
- ComponentName getServiceAssignedToAccessibilityButtonLocked() {
- final String targetName = mAccessibilityButtonTargets.isEmpty() ? null
- : mAccessibilityButtonTargets.valueAt(0);
- if (targetName == null) {
- return null;
- }
- return ComponentName.unflattenFromString(targetName);
- }
- // TODO(a11y shortcut): End
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
index 96d9c47..ac5169c 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
@@ -113,7 +113,6 @@
mUserState.mAccessibilityButtonTargets.add(COMPONENT_NAME.flattenToString());
mUserState.setTouchExplorationEnabledLocked(true);
mUserState.setDisplayMagnificationEnabledLocked(true);
- mUserState.setNavBarMagnificationEnabledLocked(true);
mUserState.setAutoclickEnabledLocked(true);
mUserState.setUserNonInteractiveUiTimeoutLocked(30);
mUserState.setUserInteractiveUiTimeoutLocked(30);
@@ -132,7 +131,6 @@
assertTrue(mUserState.mAccessibilityButtonTargets.isEmpty());
assertFalse(mUserState.isTouchExplorationEnabledLocked());
assertFalse(mUserState.isDisplayMagnificationEnabledLocked());
- assertFalse(mUserState.isNavBarMagnificationEnabledLocked());
assertFalse(mUserState.isAutoclickEnabledLocked());
assertEquals(0, mUserState.getUserNonInteractiveUiTimeoutLocked());
assertEquals(0, mUserState.getUserInteractiveUiTimeoutLocked());