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
This commit is contained in:
Thomas Leu
2023-03-16 14:45:51 +01:00
committed by Cherrypicker Worker
parent f9e6314f1d
commit 0b99849797

View File

@@ -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:
@@ -291,23 +291,29 @@ public class SystemActionPerformer {
return lockScreen();
case AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT:
return takeScreenshot();
case AccessibilityService.GLOBAL_ACTION_KEYCODE_HEADSETHOOK :
sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HEADSETHOOK);
case AccessibilityService.GLOBAL_ACTION_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();