Merge "Cancel touches as well as pointer gestures." into mnc-dev
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index f3cb0e6..bd74b02 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -3860,6 +3860,7 @@
     mPointerUsage = POINTER_USAGE_NONE;
     mSentHoverEnter = false;
     mHavePointerIds = false;
+    mCurrentMotionAborted = false;
     mDownTime = 0;
 
     mCurrentVirtualKey.down = false;
@@ -4087,11 +4088,17 @@
                     mCurrentCookedState.cookedPointerData.touchingIdBits);
         }
 
-        dispatchButtonRelease(when, policyFlags);
-        dispatchHoverExit(when, policyFlags);
-        dispatchTouches(when, policyFlags);
-        dispatchHoverEnterAndMove(when, policyFlags);
-        dispatchButtonPress(when, policyFlags);
+        if (!mCurrentMotionAborted) {
+            dispatchButtonRelease(when, policyFlags);
+            dispatchHoverExit(when, policyFlags);
+            dispatchTouches(when, policyFlags);
+            dispatchHoverEnterAndMove(when, policyFlags);
+            dispatchButtonPress(when, policyFlags);
+        }
+
+        if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
+            mCurrentMotionAborted = false;
+        }
     }
 
     // Synthesize key up from raw buttons if needed.
@@ -4316,6 +4323,22 @@
     getListener()->notifyKey(&args);
 }
 
+void TouchInputMapper::abortTouches(nsecs_t when, uint32_t policyFlags) {
+    BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
+    if (!currentIdBits.isEmpty()) {
+        int32_t metaState = getContext()->getGlobalMetaState();
+        int32_t buttonState = mCurrentCookedState.buttonState;
+        dispatchMotion(when, policyFlags, mSource, AMOTION_EVENT_ACTION_CANCEL, 0, 0,
+                metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+                mCurrentCookedState.cookedPointerData.pointerProperties,
+                mCurrentCookedState.cookedPointerData.pointerCoords,
+                mCurrentCookedState.cookedPointerData.idToIndex,
+                currentIdBits, -1,
+                mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+        mCurrentMotionAborted = true;
+    }
+}
+
 void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
     BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
     BitSet32 lastIdBits = mLastCookedState.cookedPointerData.touchingIdBits;
@@ -6089,6 +6112,7 @@
 
 void TouchInputMapper::cancelTouch(nsecs_t when) {
     abortPointerUsage(when, 0 /*policyFlags*/);
+    abortTouches(when, 0 /* policyFlags*/);
 }
 
 bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index 4062ec7..7cb4680 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -1469,6 +1469,9 @@
     // Have we assigned pointer IDs for this stream
     bool mHavePointerIds;
 
+    // Is the current stream of direct touch events aborted
+    bool mCurrentMotionAborted;
+
     // The time the primary pointer last went down.
     nsecs_t mDownTime;
 
@@ -1802,6 +1805,7 @@
     void dispatchButtonPress(nsecs_t when, uint32_t policyFlags);
     const BitSet32& findActiveIdBits(const CookedPointerData& cookedPointerData);
     void cookPointerData();
+    void abortTouches(nsecs_t when, uint32_t policyFlags);
 
     void dispatchPointerUsage(nsecs_t when, uint32_t policyFlags, PointerUsage pointerUsage);
     void abortPointerUsage(nsecs_t when, uint32_t policyFlags);