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

Commit 4df28baa authored by Thomas Leu's avatar Thomas Leu
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.
Change-Id: Icc194345bca7220927f98ae67379c27a9e8c32ba
parent 96889485
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();