Merge "Cancelling previous touch interaction when a new touch starts" into ub-launcher3-master
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index b9f95cc..cded799 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -19,7 +19,7 @@
 import static android.view.MotionEvent.ACTION_DOWN;
 import static android.view.MotionEvent.ACTION_MOVE;
 import static android.view.MotionEvent.ACTION_POINTER_DOWN;
-import static android.view.MotionEvent.ACTION_POINTER_UP;
+import static android.view.MotionEvent.ACTION_POINTER_INDEX_SHIFT;
 import static android.view.MotionEvent.ACTION_UP;
 
 import static com.android.systemui.shared.system.ActivityManagerWrapper
@@ -52,6 +52,7 @@
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.ChoreographerCompat;
 import com.android.systemui.shared.system.NavigationBarCompat.HitTarget;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
@@ -299,7 +300,7 @@
             mActivityHelper = activityHelper;
             mActivity = activity;
             mTarget = activity.getDragLayer();
-            mTouchSlop = ViewConfiguration.get(mTarget.getContext()).getScaledTouchSlop();
+            mTouchSlop = ViewConfiguration.get(mActivity).getScaledTouchSlop();
             mStartingInActivityBounds = startingInActivityBounds;
 
             mQuickScrubController = mActivity.<RecentsView>getOverviewPanel()
@@ -324,12 +325,6 @@
                 mDownPos.set(ev.getX(), ev.getY());
             } else if (!mTrackingStarted) {
                 switch (action) {
-                    case ACTION_POINTER_UP:
-                    case ACTION_POINTER_DOWN:
-                        if (!mTrackingStarted) {
-                            mInvalidated = true;
-                        }
-                        break;
                     case ACTION_CANCEL:
                     case ACTION_UP:
                         startTouchTracking(ev, true /* updateLocationOffset */);
@@ -359,15 +354,26 @@
             }
 
             // Send down touch event
-            MotionEvent down = MotionEvent.obtain(ev);
+            MotionEvent down = MotionEvent.obtainNoHistory(ev);
             down.setAction(ACTION_DOWN);
             sendEvent(down);
-            down.recycle();
 
             mTrackingStarted = true;
+            // Send pointer down for remaining pointers.
+            int pointerCount = ev.getPointerCount();
+            for (int i = 1; i < pointerCount; i++) {
+                down.setAction(ACTION_POINTER_DOWN | (i << ACTION_POINTER_INDEX_SHIFT));
+                sendEvent(down);
+            }
+
+            down.recycle();
         }
 
         private void sendEvent(MotionEvent ev) {
+            if (!mTarget.verifyTouchDispatch(this, ev)) {
+                mInvalidated = true;
+                return;
+            }
             int flags = ev.getEdgeFlags();
             ev.setEdgeFlags(flags | TouchInteractionService.EDGE_NAV_BAR);
             ev.offsetLocation(-mLocationOnScreen[0], -mLocationOnScreen[1]);
diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java
index 1faca15..5b8df13 100644
--- a/src/com/android/launcher3/views/BaseDragLayer.java
+++ b/src/com/android/launcher3/views/BaseDragLayer.java
@@ -16,6 +16,10 @@
 
 package com.android.launcher3.views;
 
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_UP;
+
 import static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
 
 import android.content.Context;
@@ -79,6 +83,9 @@
     protected TouchController mActiveController;
     private TouchCompleteListener mTouchCompleteListener;
 
+    // Object controlling the current touch interaction
+    private Object mCurrentTouchOwner;
+
     public BaseDragLayer(Context context, AttributeSet attrs, int alphaChannelCount) {
         super(context, attrs);
         mActivity = (T) ActivityContext.lookupContext(context);
@@ -94,7 +101,7 @@
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         int action = ev.getAction();
 
-        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+        if (action == ACTION_UP || action == ACTION_CANCEL) {
             if (mTouchCompleteListener != null) {
                 mTouchCompleteListener.onTouchComplete();
             }
@@ -177,7 +184,7 @@
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         int action = ev.getAction();
-        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+        if (action == ACTION_UP || action == ACTION_CANCEL) {
             if (mTouchCompleteListener != null) {
                 mTouchCompleteListener.onTouchComplete();
             }
@@ -192,6 +199,37 @@
         }
     }
 
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        return verifyTouchDispatch(this, ev) && super.dispatchTouchEvent(ev);
+    }
+
+    /**
+     * Returns true if the {@param caller} is allowed to dispatch {@param ev} on this view,
+     * false otherwise.
+     */
+    public boolean verifyTouchDispatch(Object caller, MotionEvent ev) {
+        int action = ev.getAction();
+        if (action == ACTION_DOWN) {
+            if (mCurrentTouchOwner != null) {
+                // Another touch in progress.
+                ev.setAction(ACTION_CANCEL);
+                super.dispatchTouchEvent(ev);
+                ev.setAction(action);
+            }
+            mCurrentTouchOwner = caller;
+            return true;
+        }
+        if (mCurrentTouchOwner != caller) {
+            // Someone else is controlling the touch
+            return false;
+        }
+        if (action == ACTION_UP || action == ACTION_CANCEL) {
+            mCurrentTouchOwner = null;
+        }
+        return true;
+    }
+
     /**
      * Determine the rect of the descendant in this DragLayer's coordinates
      *