Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2b361b73 authored by David Padlipsky's avatar David Padlipsky Committed by Android (Google) Code Review
Browse files

Merge "Implement toggle talkback shortcut" into main

parents e0947f5d 736e8955
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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);
        }
+12 −0
Original line number Diff line number Diff line
@@ -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()
+25 −1
Original line number Diff line number Diff line
@@ -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;
    }
+9 −4
Original line number Diff line number Diff line
@@ -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);
            }
        }
+24 −0
Original line number Diff line number Diff line
@@ -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);
    }
}
Loading