From 698c96dbd261c6f5c2be618d7ca206ef9c8cbd51 Mon Sep 17 00:00:00 2001 From: Phil Weaver Date: Wed, 20 Apr 2016 13:08:35 -0700 Subject: [PATCH] Fix a11y key event handling from multiple devices. For M, we ignored device type entirely, but with ag/760625 we started paying attention to it, which rejects events when keys from different devices are pressed simultaneously. Since the volume keys show up as different devices, the new behavior disrupted the event stream when both volume keys were pressed. Now tracking each device separately, which restores the old behavior but still takes the device id into account. Holding down two keys when enabling an accessibility service, however, always has and still can produce an invalid event stream. It doesn't seem worth the overhead, however, to track each key separately. Bug: 28091773 Change-Id: I8d30de1f5e05f779b6fe305856d42f209ff8b038 --- .../AccessibilityInputFilter.java | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java index 4d7f82d4158ef..2a7d945c1311c 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java @@ -20,6 +20,7 @@ import android.content.Context; import android.os.PowerManager; import android.util.Pools.SimplePool; import android.util.Slog; +import android.util.SparseBooleanArray; import android.view.Choreographer; import android.view.InputDevice; import android.view.InputEvent; @@ -637,10 +638,10 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo } /** - * Keeps state of stream of events from a keyboard device. + * Keeps state of streams of events from all keyboard devices. */ private static class KeyboardEventStreamState extends EventStreamState { - private boolean mEventSequenceStarted; + private SparseBooleanArray mEventSequenceStartedMap = new SparseBooleanArray(); public KeyboardEventStreamState() { reset(); @@ -649,17 +650,35 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo @Override final public void reset() { super.reset(); - mEventSequenceStarted = false; + mEventSequenceStartedMap.clear(); } + /* + * Key events from different devices may be interleaved. For example, the volume up and + * down keys can come from different device IDs. + */ + @Override + public boolean updateDeviceId(int deviceId) { + return false; + } + + // We manage all device ids simultaneously; there is no concept of validity. + @Override + public boolean deviceIdValid() { + return true; + } + + @Override final public boolean shouldProcessKeyEvent(KeyEvent event) { - // Wait for a down key event to start processing. - if (mEventSequenceStarted) { + // For each keyboard device, wait for a down event from a device to start processing + int deviceId = event.getDeviceId(); + if (mEventSequenceStartedMap.get(deviceId, false)) { return true; } - mEventSequenceStarted = event.getAction() == KeyEvent.ACTION_DOWN; - return mEventSequenceStarted; + boolean shouldProcess = event.getAction() == KeyEvent.ACTION_DOWN; + mEventSequenceStartedMap.put(deviceId, shouldProcess); + return shouldProcess; } } }