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
This commit is contained in:
Phil Weaver
2016-04-20 13:08:35 -07:00
parent b1dea03f0a
commit 698c96dbd2

View File

@@ -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;
}
}
}