Add unit tests for native input and fix bugs identified.

Fixed a bug where we would lose the first touch point when swiping out of
the virtual key area.

Fixed a bug where we would not send an ACTION_MOVE event in cases where
individual pointers went down/up and the remaining pointers actually moved.
This is important since many applications do not handle pointer movements
during ACTION_POINTER_DOWN or ACTION_POINTER_UP.  In the case of
ACTION_POINTER_UP the movement was completely lost since all pointers were
dispatched using their old location rather than the new location.

Improved motion event validation to check for duplicate pointer ids.

Added an input source constant that was missing from the NDK api but
defined in the framework api.

Added a timestamp when reporting added/removed devices in EventHub.

Bug: 3070082
Change-Id: I3206a030f43b7616e2f48006e5a9d522c4d92e56
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index ce0d880..d167439 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -234,7 +234,7 @@
         break;
 
     case EventHubInterface::FINISHED_DEVICE_SCAN:
-        handleConfigurationChanged();
+        handleConfigurationChanged(rawEvent->when);
         break;
 
     default:
@@ -372,7 +372,7 @@
     } // release device registry reader lock
 }
 
-void InputReader::handleConfigurationChanged() {
+void InputReader::handleConfigurationChanged(nsecs_t when) {
     // Reset global meta state because it depends on the list of all configured devices.
     updateGlobalMetaState();
 
@@ -380,7 +380,6 @@
     updateInputConfiguration();
 
     // Enqueue configuration changed.
-    nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
     mDispatcher->notifyConfigurationChanged(when);
 }
 
@@ -2094,7 +2093,7 @@
                 mLocked.currentVirtualKey.down = false;
 #if DEBUG_VIRTUAL_KEYS
                 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
-                        mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
+                        mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
 #endif
                 keyEventAction = AKEY_EVENT_ACTION_UP;
                 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
@@ -2119,13 +2118,22 @@
             mLocked.currentVirtualKey.down = false;
 #if DEBUG_VIRTUAL_KEYS
             LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
-                    mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
+                    mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
 #endif
             keyEventAction = AKEY_EVENT_ACTION_UP;
             keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
                     | AKEY_EVENT_FLAG_CANCELED;
-            touchResult = DROP_STROKE;
-            goto DispatchVirtualKey;
+
+            // Check whether the pointer moved inside the display area where we should
+            // start a new stroke.
+            int32_t x = mCurrentTouch.pointers[0].x;
+            int32_t y = mCurrentTouch.pointers[0].y;
+            if (isPointInsideSurfaceLocked(x, y)) {
+                mLastTouch.clear();
+                touchResult = DISPATCH_TOUCH;
+            } else {
+                touchResult = DROP_STROKE;
+            }
         } else {
             if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
                 // Pointer just went down.  Handle off-screen touches, if needed.
@@ -2143,7 +2151,8 @@
                             mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
 #if DEBUG_VIRTUAL_KEYS
                             LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
-                                    mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
+                                    mLocked.currentVirtualKey.keyCode,
+                                    mLocked.currentVirtualKey.scanCode);
 #endif
                             keyEventAction = AKEY_EVENT_ACTION_DOWN;
                             keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
@@ -2190,14 +2199,35 @@
         dispatchTouch(when, policyFlags, & mCurrentTouch,
                 currentIdBits, -1, currentPointerCount, motionEventAction);
     } else {
-        // There may be pointers going up and pointers going down at the same time when pointer
-        // ids are reported by the device driver.
+        // There may be pointers going up and pointers going down and pointers moving
+        // all at the same time.
         BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
         BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
         BitSet32 activeIdBits(lastIdBits.value);
         uint32_t pointerCount = lastPointerCount;
 
-        while (! upIdBits.isEmpty()) {
+        // Produce an intermediate representation of the touch data that consists of the
+        // old location of pointers that have just gone up and the new location of pointers that
+        // have just moved but omits the location of pointers that have just gone down.
+        TouchData interimTouch;
+        interimTouch.copyFrom(mLastTouch);
+
+        BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
+        bool moveNeeded = false;
+        while (!moveIdBits.isEmpty()) {
+            uint32_t moveId = moveIdBits.firstMarkedBit();
+            moveIdBits.clearBit(moveId);
+
+            int32_t oldIndex = mLastTouch.idToIndex[moveId];
+            int32_t newIndex = mCurrentTouch.idToIndex[moveId];
+            if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
+                interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
+                moveNeeded = true;
+            }
+        }
+
+        // Dispatch pointer up events using the interim pointer locations.
+        while (!upIdBits.isEmpty()) {
             uint32_t upId = upIdBits.firstMarkedBit();
             upIdBits.clearBit(upId);
             BitSet32 oldActiveIdBits = activeIdBits;
@@ -2210,12 +2240,21 @@
                 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
             }
 
-            dispatchTouch(when, policyFlags, & mLastTouch,
+            dispatchTouch(when, policyFlags, &interimTouch,
                     oldActiveIdBits, upId, pointerCount, motionEventAction);
             pointerCount -= 1;
         }
 
-        while (! downIdBits.isEmpty()) {
+        // Dispatch move events if any of the remaining pointers moved from their old locations.
+        // Although applications receive new locations as part of individual pointer up
+        // events, they do not generally handle them except when presented in a move event.
+        if (moveNeeded) {
+            dispatchTouch(when, policyFlags, &mCurrentTouch,
+                    activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
+        }
+
+        // Dispatch pointer down events using the new pointer locations.
+        while (!downIdBits.isEmpty()) {
             uint32_t downId = downIdBits.firstMarkedBit();
             downIdBits.clearBit(downId);
             BitSet32 oldActiveIdBits = activeIdBits;
@@ -2230,7 +2269,7 @@
             }
 
             pointerCount += 1;
-            dispatchTouch(when, policyFlags, & mCurrentTouch,
+            dispatchTouch(when, policyFlags, &mCurrentTouch,
                     activeIdBits, downId, pointerCount, motionEventAction);
         }
     }
@@ -3339,8 +3378,8 @@
 
         if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
             if (inPointer.absMTPressure <= 0) {
-                // Some devices send sync packets with X / Y but with a 0 presure to indicate
-                // a pointer up.  Drop this finger.
+                // Some devices send sync packets with X / Y but with a 0 pressure to indicate
+                // a pointer going up.  Drop this finger.
                 continue;
             }
             outPointer.pressure = inPointer.absMTPressure;