From 1b10869f39978a864cfcc4efc73aefc312d8ed79 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 19 Mar 2014 11:51:26 -0700 Subject: [PATCH] Generate and respect ACTION_CANCEL for joystick fallbacks. DO NOT MERGE Also change MotionEvent.PointerCoords bit packing and unpacking methods to be consistent with BitSets which are now used on the native PointerCoords object. Bug: 11480300 Change-Id: Ib18c99b94ac555104c69eac526860aa501e89e03 --- core/java/android/view/MotionEvent.java | 8 +++--- core/java/android/view/ViewRootImpl.java | 16 ++++++++++-- libs/input/InputDispatcher.cpp | 33 +++++++++++++++++++----- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index ddce3ceef753e..6378ffd99749d 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -3372,11 +3372,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { throw new IllegalArgumentException("Axis out of range."); } final long bits = mPackedAxisBits; - final long axisBit = 1L << axis; + final long axisBit = 0x8000000000000000L >>> axis; if ((bits & axisBit) == 0) { return 0; } - final int index = Long.bitCount(bits & (axisBit - 1L)); + final int index = Long.bitCount(bits & ~(0xFFFFFFFFFFFFFFFFL >>> axis)); return mPackedAxisValues[index]; } } @@ -3425,8 +3425,8 @@ public final class MotionEvent extends InputEvent implements Parcelable { throw new IllegalArgumentException("Axis out of range."); } final long bits = mPackedAxisBits; - final long axisBit = 1L << axis; - final int index = Long.bitCount(bits & (axisBit - 1L)); + final long axisBit = 0x8000000000000000L >>> axis; + final int index = Long.bitCount(bits & ~(0xFFFFFFFFFFFFFFFFL >>> axis)); float[] values = mPackedAxisValues; if ((bits & axisBit) == 0) { if (values == null) { diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index d779628571bff..1848a8f976af7 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -4319,6 +4319,7 @@ public final class ViewRootImpl implements ViewParent, * Creates dpad events from unhandled joystick movements. */ final class SyntheticJoystickHandler extends Handler { + private final static String TAG = "SyntheticJoystickHandler"; private final static int MSG_ENQUEUE_X_AXIS_KEY_REPEAT = 1; private final static int MSG_ENQUEUE_Y_AXIS_KEY_REPEAT = 2; @@ -4351,10 +4352,21 @@ public final class ViewRootImpl implements ViewParent, } public void process(MotionEvent event) { - update(event, true); + switch(event.getActionMasked()) { + case MotionEvent.ACTION_CANCEL: + cancel(event); + break; + case MotionEvent.ACTION_MOVE: + update(event, true); + break; + default: + Log.w(TAG, "Unexpected action: " + event.getActionMasked()); + } } - public void cancel(MotionEvent event) { + private void cancel(MotionEvent event) { + removeMessages(MSG_ENQUEUE_X_AXIS_KEY_REPEAT); + removeMessages(MSG_ENQUEUE_Y_AXIS_KEY_REPEAT); update(event, false); } diff --git a/libs/input/InputDispatcher.cpp b/libs/input/InputDispatcher.cpp index 4d447878da4b6..70ff0851b1f89 100644 --- a/libs/input/InputDispatcher.cpp +++ b/libs/input/InputDispatcher.cpp @@ -4105,18 +4105,39 @@ bool InputDispatcher::InputState::trackMotion(const MotionEntry* entry, case AMOTION_EVENT_ACTION_POINTER_UP: case AMOTION_EVENT_ACTION_POINTER_DOWN: case AMOTION_EVENT_ACTION_MOVE: { + if (entry->source & AINPUT_SOURCE_CLASS_NAVIGATION) { + // Trackballs can send MOVE events with a corresponding DOWN or UP. There's no need to + // generate cancellation events for these since they're based in relative rather than + // absolute units. + return true; + } + ssize_t index = findMotionMemento(entry, false /*hovering*/); + + if (entry->source & AINPUT_SOURCE_CLASS_JOYSTICK) { + // Joysticks can send MOVE events without a corresponding DOWN or UP. Since all + // joystick axes are normalized to [-1, 1] we can trust that 0 means it's neutral. Any + // other value and we need to track the motion so we can send cancellation events for + // anything generating fallback events (e.g. DPad keys for joystick movements). + if (index >= 0) { + if (entry->pointerCoords[0].isEmpty()) { + mMotionMementos.removeAt(index); + } else { + MotionMemento& memento = mMotionMementos.editItemAt(index); + memento.setPointers(entry); + } + } else if (!entry->pointerCoords[0].isEmpty()) { + addMotionMemento(entry, flags, false /*hovering*/); + } + + // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP. + return true; + } if (index >= 0) { MotionMemento& memento = mMotionMementos.editItemAt(index); memento.setPointers(entry); return true; } - if (actionMasked == AMOTION_EVENT_ACTION_MOVE - && (entry->source & (AINPUT_SOURCE_CLASS_JOYSTICK - | AINPUT_SOURCE_CLASS_NAVIGATION))) { - // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP. - return true; - } #if DEBUG_OUTBOUND_EVENT_DETAILS ALOGD("Dropping inconsistent motion pointer up/down or move event: " "deviceId=%d, source=%08x, actionMasked=%d",