Only allow touch events from one device at a time.

Reject movements from other devices when one device is already down.
This fixes jittery behavior when the user moves the mouse and touches
the screen at the same time.

Change-Id: I99151c8f2596a3139720f776bcbc559d4b314878
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 3675021..89a7751 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -1060,14 +1060,26 @@
     // Update the touch state as needed based on the properties of the touch event.
     int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING;
     InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
+    bool isSplit, wrongDevice;
     if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
         mTempTouchState.reset();
         mTempTouchState.down = true;
+        mTempTouchState.deviceId = entry->deviceId;
+        isSplit = false;
+        wrongDevice = false;
     } else {
         mTempTouchState.copyFrom(mTouchState);
+        isSplit = mTempTouchState.split;
+        wrongDevice = mTempTouchState.down && mTempTouchState.deviceId != entry->deviceId;
+        if (wrongDevice) {
+#if DEBUG_INPUT_DISPATCHER_POLICY
+            LOGD("Dropping event because a pointer for a different device is already down.");
+#endif
+            injectionResult = INPUT_EVENT_INJECTION_FAILED;
+            goto Failed;
+        }
     }
 
-    bool isSplit = mTempTouchState.split && mTempTouchState.down;
     if (maskedAction == AMOTION_EVENT_ACTION_DOWN
             || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
         /* Case 1: New splittable pointer going down. */
@@ -1279,39 +1291,41 @@
 
     // Update final pieces of touch state if the injector had permission.
     if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
-        if (maskedAction == AMOTION_EVENT_ACTION_UP
-                || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
-            // All pointers up or canceled.
-            mTempTouchState.reset();
-        } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
-            // First pointer went down.
-            if (mTouchState.down) {
+        if (!wrongDevice) {
+            if (maskedAction == AMOTION_EVENT_ACTION_UP
+                    || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
+                // All pointers up or canceled.
+                mTempTouchState.reset();
+            } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
+                // First pointer went down.
+                if (mTouchState.down) {
 #if DEBUG_FOCUS
-                LOGD("Pointer down received while already down.");
+                    LOGD("Pointer down received while already down.");
 #endif
-            }
-        } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
-            // One pointer went up.
-            if (isSplit) {
-                int32_t pointerIndex = getMotionEventActionPointerIndex(action);
-                uint32_t pointerId = entry->pointerIds[pointerIndex];
+                }
+            } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
+                // One pointer went up.
+                if (isSplit) {
+                    int32_t pointerIndex = getMotionEventActionPointerIndex(action);
+                    uint32_t pointerId = entry->pointerIds[pointerIndex];
 
-                for (size_t i = 0; i < mTempTouchState.windows.size(); ) {
-                    TouchedWindow& touchedWindow = mTempTouchState.windows.editItemAt(i);
-                    if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
-                        touchedWindow.pointerIds.clearBit(pointerId);
-                        if (touchedWindow.pointerIds.isEmpty()) {
-                            mTempTouchState.windows.removeAt(i);
-                            continue;
+                    for (size_t i = 0; i < mTempTouchState.windows.size(); ) {
+                        TouchedWindow& touchedWindow = mTempTouchState.windows.editItemAt(i);
+                        if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
+                            touchedWindow.pointerIds.clearBit(pointerId);
+                            if (touchedWindow.pointerIds.isEmpty()) {
+                                mTempTouchState.windows.removeAt(i);
+                                continue;
+                            }
                         }
+                        i += 1;
                     }
-                    i += 1;
                 }
             }
-        }
 
-        // Save changes to touch state.
-        mTouchState.copyFrom(mTempTouchState);
+            // Save changes to touch state.
+            mTouchState.copyFrom(mTempTouchState);
+        }
     } else {
 #if DEBUG_FOCUS
         LOGD("Not updating touch focus because injection was denied.");
@@ -2768,6 +2782,7 @@
 
     dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down));
     dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split));
+    dump.appendFormat(INDENT "TouchDeviceId: %d\n", mTouchState.deviceId);
     if (!mTouchState.windows.isEmpty()) {
         dump.append(INDENT "TouchedWindows:\n");
         for (size_t i = 0; i < mTouchState.windows.size(); i++) {
@@ -3642,7 +3657,7 @@
 // --- InputDispatcher::TouchState ---
 
 InputDispatcher::TouchState::TouchState() :
-    down(false), split(false) {
+    down(false), split(false), deviceId(-1) {
 }
 
 InputDispatcher::TouchState::~TouchState() {
@@ -3651,12 +3666,14 @@
 void InputDispatcher::TouchState::reset() {
     down = false;
     split = false;
+    deviceId = -1;
     windows.clear();
 }
 
 void InputDispatcher::TouchState::copyFrom(const TouchState& other) {
     down = other.down;
     split = other.split;
+    deviceId = other.deviceId;
     windows.clear();
     windows.appendVector(other.windows);
 }