diff options
| author | 2024-10-16 18:44:45 +0000 | |
|---|---|---|
| committer | 2024-10-22 20:51:33 +0000 | |
| commit | 736e8955eca6b7a367c6b1611202e14b0dc11b10 (patch) | |
| tree | 33e33e11b0301774823a348e3441b0d51cd56d3b | |
| parent | 49cf41db6203179d24062a73796e654282a3d324 (diff) | |
Implement toggle talkback shortcut
Bug: 373458181
Test: atest WmTests
Flag: com.android.hardware.input.keyboard_a11y_shortcut_control
Change-Id: I42d61f620b7b15e0e4d215d6b99b090b9862b15d
6 files changed, 75 insertions, 6 deletions
diff --git a/core/java/android/hardware/input/KeyGestureEvent.java b/core/java/android/hardware/input/KeyGestureEvent.java index 2df541818e3d..71d17ebc40e3 100644 --- a/core/java/android/hardware/input/KeyGestureEvent.java +++ b/core/java/android/hardware/input/KeyGestureEvent.java @@ -100,6 +100,7 @@ public final class KeyGestureEvent { public static final int KEY_GESTURE_TYPE_ACCESSIBILITY_SHORTCUT = 60; public static final int KEY_GESTURE_TYPE_CLOSE_ALL_DIALOGS = 61; public static final int KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY = 62; + public static final int KEY_GESTURE_TYPE_TOGGLE_TALKBACK = 63; public static final int FLAG_CANCELLED = 1; @@ -177,6 +178,7 @@ public final class KeyGestureEvent { KEY_GESTURE_TYPE_ACCESSIBILITY_SHORTCUT, KEY_GESTURE_TYPE_CLOSE_ALL_DIALOGS, KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY, + KEY_GESTURE_TYPE_TOGGLE_TALKBACK, }) @Retention(RetentionPolicy.SOURCE) public @interface KeyGestureType { @@ -597,6 +599,8 @@ public final class KeyGestureEvent { return "KEY_GESTURE_TYPE_ACCESSIBILITY_SHORTCUT"; case KEY_GESTURE_TYPE_CLOSE_ALL_DIALOGS: return "KEY_GESTURE_TYPE_CLOSE_ALL_DIALOGS"; + case KEY_GESTURE_TYPE_TOGGLE_TALKBACK: + return "KEY_GESTURE_TYPE_TOGGLE_TALKBACK"; default: return Integer.toHexString(value); } diff --git a/services/core/java/com/android/server/input/KeyGestureController.java b/services/core/java/com/android/server/input/KeyGestureController.java index 2f5236f51c48..bd1625ea6d3e 100644 --- a/services/core/java/com/android/server/input/KeyGestureController.java +++ b/services/core/java/com/android/server/input/KeyGestureController.java @@ -20,6 +20,7 @@ import static android.content.pm.PackageManager.FEATURE_LEANBACK; import static android.content.pm.PackageManager.FEATURE_WATCH; import static android.view.WindowManagerPolicyConstants.FLAG_INTERACTIVE; +import static com.android.hardware.input.Flags.keyboardA11yShortcutControl; import static com.android.hardware.input.Flags.useKeyGestureEventHandler; import static com.android.hardware.input.Flags.useKeyGestureEventHandlerMultiPressGestures; import static com.android.server.flags.Flags.newBugreportKeyboardShortcut; @@ -577,6 +578,17 @@ final class KeyGestureController { focusedToken, /* flags = */0); } break; + case KeyEvent.KEYCODE_T: + if (keyboardA11yShortcutControl()) { + if (firstDown && event.isMetaPressed() && event.isAltPressed()) { + return handleKeyGesture(deviceId, new int[]{keyCode}, + KeyEvent.META_META_ON | KeyEvent.META_ALT_ON, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_TALKBACK, + KeyGestureEvent.ACTION_GESTURE_COMPLETE, displayId, + focusedToken, /* flags = */0); + } + } + break; case KeyEvent.KEYCODE_DEL: if (newBugreportKeyboardShortcut()) { if (firstDown && mEnableBugReportKeyboardShortcut && event.isMetaPressed() diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index ad5c84026aa6..0b5b0d2a0b26 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -84,6 +84,7 @@ import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED; import static android.view.contentprotection.flags.Flags.createAccessibilityOverlayAppOpEnabled; import static com.android.hardware.input.Flags.emojiAndScreenshotKeycodesAvailable; +import static com.android.hardware.input.Flags.keyboardA11yShortcutControl; import static com.android.hardware.input.Flags.modifierShortcutDump; import static com.android.hardware.input.Flags.useKeyGestureEventHandler; import static com.android.hardware.input.Flags.useKeyGestureEventHandlerMultiPressGestures; @@ -1615,7 +1616,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { case TRIPLE_PRESS_PRIMARY_NOTHING: break; case TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY: - mTalkbackShortcutController.toggleTalkback(mCurrentUserId); + mTalkbackShortcutController.toggleTalkback(mCurrentUserId, + TalkbackShortcutController.ShortcutSource.GESTURE); if (mTalkbackShortcutController.isTalkBackShortcutGestureEnabled()) { performHapticFeedback(HapticFeedbackConstants.CONFIRM, "Stem primary - Triple Press - Toggle Accessibility"); @@ -3603,6 +3605,17 @@ public class PhoneWindowManager implements WindowManagerPolicy { return true; } break; + case KeyEvent.KEYCODE_T: + if (keyboardA11yShortcutControl()) { + if (firstDown && event.isMetaPressed() && event.isAltPressed()) { + mTalkbackShortcutController.toggleTalkback(mCurrentUserId, + TalkbackShortcutController.ShortcutSource.KEYBOARD); + notifyKeyGestureCompleted(event, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_TALKBACK); + return true; + } + } + break; case KeyEvent.KEYCODE_DEL: if (newBugreportKeyboardShortcut()) { if (mEnableBugReportKeyboardShortcut && firstDown @@ -4034,6 +4047,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyGestureEvent.KEY_GESTURE_TYPE_TV_ACCESSIBILITY_SHORTCUT_CHORD: return mDefaultDisplayPolicy.isAwake() && mAccessibilityShortcutController .isAccessibilityShortcutAvailable(false); + case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_TALKBACK: + return keyboardA11yShortcutControl(); default: return false; } @@ -4251,6 +4266,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { mContext.closeSystemDialogs(); } return true; + case KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_TALKBACK: + if (keyboardA11yShortcutControl()) { + if (complete) { + mTalkbackShortcutController.toggleTalkback(mCurrentUserId, + TalkbackShortcutController.ShortcutSource.KEYBOARD); + } + return true; + } + break; } return false; } diff --git a/services/core/java/com/android/server/policy/TalkbackShortcutController.java b/services/core/java/com/android/server/policy/TalkbackShortcutController.java index e544ae64521c..9e16a7d5e83a 100644 --- a/services/core/java/com/android/server/policy/TalkbackShortcutController.java +++ b/services/core/java/com/android/server/policy/TalkbackShortcutController.java @@ -44,6 +44,11 @@ class TalkbackShortcutController { private final Context mContext; private final PackageManager mPackageManager; + public enum ShortcutSource { + GESTURE, + KEYBOARD, + } + TalkbackShortcutController(Context context) { mContext = context; mPackageManager = mContext.getPackageManager(); @@ -55,7 +60,7 @@ class TalkbackShortcutController { * @return talkback state after toggle. {@code true} if talkback is enabled, {@code false} if * talkback is disabled */ - boolean toggleTalkback(int userId) { + boolean toggleTalkback(int userId, ShortcutSource source) { final Set<ComponentName> enabledServices = AccessibilityUtils.getEnabledServicesFromSettings(mContext, userId); ComponentName componentName = getTalkbackComponent(); @@ -65,13 +70,13 @@ class TalkbackShortcutController { boolean isTalkbackAlreadyEnabled = enabledServices.contains(componentName); - if (isTalkBackShortcutGestureEnabled()) { + if (source == ShortcutSource.KEYBOARD || isTalkBackShortcutGestureEnabled()) { isTalkbackAlreadyEnabled = !isTalkbackAlreadyEnabled; AccessibilityUtils.setAccessibilityServiceState(mContext, componentName, - isTalkbackAlreadyEnabled); + isTalkbackAlreadyEnabled, userId); // log stem triple press telemetry if it's a talkback enabled event. - if (isTalkbackAlreadyEnabled) { + if (source == ShortcutSource.GESTURE && isTalkbackAlreadyEnabled) { logStemTriplePressAccessibilityTelemetry(componentName); } } diff --git a/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java b/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java index cdb45423c11a..d83ffd15ff71 100644 --- a/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java +++ b/services/tests/wmtests/src/com/android/server/policy/KeyGestureEventTests.java @@ -35,6 +35,7 @@ import android.view.KeyEvent; import androidx.test.filters.MediumTest; +import com.android.hardware.input.Flags; import com.android.internal.annotations.Keep; import junit.framework.Assert; @@ -393,6 +394,17 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase { META_ON | CTRL_ON); } + @Test + @EnableFlags(Flags.FLAG_KEYBOARD_A11Y_SHORTCUT_CONTROL) + @DisableFlags(com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER) + public void testToggleTalkbackPress() { + testShortcutInternal("Meta + Alt + T -> Toggle talkback", + new int[]{META_KEY, ALT_KEY, KeyEvent.KEYCODE_T}, + KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_TALKBACK, + KeyEvent.KEYCODE_T, + META_ON | ALT_ON); + } + private void testShortcutInternal(String testName, int[] testKeys, @KeyGestureEvent.KeyGestureType int expectedKeyGestureType, int expectedKey, int expectedModifierState) { @@ -699,4 +711,16 @@ public class KeyGestureEventTests extends ShortcutKeyTestBase { sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_CLOSE_ALL_DIALOGS)); mPhoneWindowManager.assertCloseAllDialogs(); } + + @Test + @EnableFlags(com.android.hardware.input.Flags.FLAG_KEYBOARD_A11Y_SHORTCUT_CONTROL) + public void testKeyGestureToggleTalkback() { + Assert.assertTrue( + sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_TALKBACK)); + mPhoneWindowManager.assertTalkBack(true); + + Assert.assertTrue( + sendKeyGestureEventComplete(KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_TALKBACK)); + mPhoneWindowManager.assertTalkBack(false); + } } diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java index a85f8666d2e1..62670b49b6d2 100644 --- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java +++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java @@ -197,7 +197,7 @@ class TestPhoneWindowManager { } @Override - boolean toggleTalkback(int currentUserId) { + boolean toggleTalkback(int currentUserId, ShortcutSource source) { mIsTalkBackEnabled = !mIsTalkBackEnabled; return mIsTalkBackEnabled; } |