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
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index ddce3ce..6378ffd 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -3372,11 +3372,11 @@
                         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 @@
                         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 d779628..1848a8f97 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4319,6 +4319,7 @@
      * 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 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 4d44787..70ff085 100644
--- a/libs/input/InputDispatcher.cpp
+++ b/libs/input/InputDispatcher.cpp
@@ -4105,18 +4105,39 @@
     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",