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

Commit 0b998497 authored by Thomas Leu's avatar Thomas Leu Committed by Cherrypicker Worker
Browse files

Add the DPAD device flag when injecting accessibility DPAD events.

For the global DPAD actions GLOBAL_ACTION_DPAD_UP/DOWN/LEFT/RIGHT/CENTER, set the event source to both SOURCE_KEYBOARD and SOURCE_DPAD to match the event we would get with a real DPAD of a TV remote control.

Bug: b/273880258
Test: Locally tested on adt4-userdebug with the same sample accessibility service used in the video attached to b/273880258.
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:4df28baa74d2dbde690d5357f1807e59f4eadd6d)
Merged-In: Icc194345bca7220927f98ae67379c27a9e8c32ba
Change-Id: Icc194345bca7220927f98ae67379c27a9e8c32ba
parent f9e6314f
Loading
Loading
Loading
Loading
+21 −14
Original line number Diff line number Diff line
@@ -266,11 +266,11 @@ public class SystemActionPerformer {
            // actions.
            switch (actionId) {
                case AccessibilityService.GLOBAL_ACTION_BACK: {
                    sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK);
                    sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK, InputDevice.SOURCE_KEYBOARD);
                    return true;
                }
                case AccessibilityService.GLOBAL_ACTION_HOME: {
                    sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME);
                    sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME, InputDevice.SOURCE_KEYBOARD);
                    return true;
                }
                case AccessibilityService.GLOBAL_ACTION_RECENTS:
@@ -292,22 +292,28 @@ public class SystemActionPerformer {
                case AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT:
                    return takeScreenshot();
                case AccessibilityService.GLOBAL_ACTION_KEYCODE_HEADSETHOOK:
                    sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HEADSETHOOK);
                    sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HEADSETHOOK,
                            InputDevice.SOURCE_KEYBOARD);
                    return true;
                case AccessibilityService.GLOBAL_ACTION_DPAD_UP:
                    sendDownAndUpKeyEvents(KeyEvent.KEYCODE_DPAD_UP);
                    sendDownAndUpKeyEvents(KeyEvent.KEYCODE_DPAD_UP,
                            InputDevice.SOURCE_KEYBOARD | InputDevice.SOURCE_DPAD);
                    return true;
                case AccessibilityService.GLOBAL_ACTION_DPAD_DOWN:
                    sendDownAndUpKeyEvents(KeyEvent.KEYCODE_DPAD_DOWN);
                    sendDownAndUpKeyEvents(KeyEvent.KEYCODE_DPAD_DOWN,
                            InputDevice.SOURCE_KEYBOARD | InputDevice.SOURCE_DPAD);
                    return true;
                case AccessibilityService.GLOBAL_ACTION_DPAD_LEFT:
                    sendDownAndUpKeyEvents(KeyEvent.KEYCODE_DPAD_LEFT);
                    sendDownAndUpKeyEvents(KeyEvent.KEYCODE_DPAD_LEFT,
                            InputDevice.SOURCE_KEYBOARD | InputDevice.SOURCE_DPAD);
                    return true;
                case AccessibilityService.GLOBAL_ACTION_DPAD_RIGHT:
                    sendDownAndUpKeyEvents(KeyEvent.KEYCODE_DPAD_RIGHT);
                    sendDownAndUpKeyEvents(KeyEvent.KEYCODE_DPAD_RIGHT,
                            InputDevice.SOURCE_KEYBOARD | InputDevice.SOURCE_DPAD);
                    return true;
                case AccessibilityService.GLOBAL_ACTION_DPAD_CENTER:
                    sendDownAndUpKeyEvents(KeyEvent.KEYCODE_DPAD_CENTER);
                    sendDownAndUpKeyEvents(KeyEvent.KEYCODE_DPAD_CENTER,
                            InputDevice.SOURCE_KEYBOARD | InputDevice.SOURCE_DPAD);
                    return true;
                default:
                    Slog.e(TAG, "Invalid action id: " + actionId);
@@ -318,23 +324,24 @@ public class SystemActionPerformer {
        }
    }

    private void sendDownAndUpKeyEvents(int keyCode) {
    private void sendDownAndUpKeyEvents(int keyCode, int source) {
        final long token = Binder.clearCallingIdentity();
        try {
            // Inject down.
            final long downTime = SystemClock.uptimeMillis();
            sendKeyEventIdentityCleared(keyCode, KeyEvent.ACTION_DOWN, downTime, downTime);
            sendKeyEventIdentityCleared(keyCode, KeyEvent.ACTION_DOWN, downTime, downTime, source);
            sendKeyEventIdentityCleared(
                    keyCode, KeyEvent.ACTION_UP, downTime, SystemClock.uptimeMillis());
                    keyCode, KeyEvent.ACTION_UP, downTime, SystemClock.uptimeMillis(), source);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    private void sendKeyEventIdentityCleared(int keyCode, int action, long downTime, long time) {
    private void sendKeyEventIdentityCleared(int keyCode, int action, long downTime, long time,
            int source) {
        KeyEvent event = KeyEvent.obtain(downTime, time, action, keyCode, 0, 0,
                KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
                InputDevice.SOURCE_KEYBOARD, null);
                source, null);
        mContext.getSystemService(InputManager.class)
                .injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
        event.recycle();