Passing all events to RecentsView instead of passing the calculated velocity

Velocity tracker is able to calculate the velocity using cached copy of motionEvent
as long as the event as correct timeStamp

Change-Id: I2b0f612e010fdfcf144d5bed928c5a96b36f3ac7
diff --git a/quickstep/libs/sysui_shared.jar b/quickstep/libs/sysui_shared.jar
index 16d2b67..5ec699c 100644
--- a/quickstep/libs/sysui_shared.jar
+++ b/quickstep/libs/sysui_shared.jar
Binary files differ
diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
index 0c20bd1..77f900f 100644
--- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
+++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
@@ -24,6 +24,7 @@
 
 import static com.android.launcher3.util.RaceConditionTracker.ENTER;
 import static com.android.launcher3.util.RaceConditionTracker.EXIT;
+import static com.android.quickstep.TouchInteractionService.EDGE_NAV_BAR;
 import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
 
@@ -35,7 +36,6 @@
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.os.Build;
-import android.os.Bundle;
 import android.view.Display;
 import android.view.MotionEvent;
 import android.view.Surface;
@@ -43,7 +43,6 @@
 import android.view.ViewConfiguration;
 import android.view.WindowManager;
 
-import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
 
 import com.android.launcher3.config.FeatureFlags;
@@ -51,10 +50,10 @@
 import com.android.launcher3.util.RaceConditionTracker;
 import com.android.launcher3.util.TraceHelper;
 import com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget;
+import com.android.quickstep.util.CachedEventDispatcher;
 import com.android.quickstep.util.MotionPauseDetector;
 import com.android.quickstep.util.RecentsAnimationListenerSet;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.AssistDataReceiver;
 import com.android.systemui.shared.system.BackgroundExecutor;
 import com.android.systemui.shared.system.InputConsumerController;
 import com.android.systemui.shared.system.NavigationBarCompat;
@@ -71,6 +70,7 @@
     public static final String DOWN_EVT = "OtherActivityTouchConsumer.DOWN";
     private static final String UP_EVT = "OtherActivityTouchConsumer.UP";
 
+    private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
     private final RunningTaskInfo mRunningTask;
     private final RecentsModel mRecentsModel;
     private final Intent mHomeIntent;
@@ -143,6 +143,19 @@
         if (mVelocityTracker == null) {
             return;
         }
+
+        // Proxy events to recents view
+        if (!isNavBarOnLeft() && !isNavBarOnRight()) {
+            if (mPassedDragSlop && mInteractionHandler != null
+                    && !mRecentsViewDispatcher.hasConsumer()) {
+                mRecentsViewDispatcher.setConsumer(mInteractionHandler.getRecentsViewDispatcher());
+            }
+            int edgeFlags = ev.getEdgeFlags();
+            ev.setEdgeFlags(edgeFlags | EDGE_NAV_BAR);
+            mRecentsViewDispatcher.dispatchEvent(ev);
+            ev.setEdgeFlags(edgeFlags);
+        }
+
         mVelocityTracker.addMovement(ev);
         if (ev.getActionMasked() == ACTION_POINTER_UP) {
             mVelocityTracker.clear();
@@ -177,7 +190,6 @@
                     mLastPos.set(ev.getX(newPointerIdx), ev.getY(newPointerIdx));
                     mActivePointerId = ev.getPointerId(newPointerIdx);
                 }
-                dispatchMotion(ev, null, null);
                 break;
             }
             case ACTION_MOVE: {
@@ -220,7 +232,7 @@
 
                 if (mPassedDragSlop && mInteractionHandler != null) {
                     // Move
-                    dispatchMotion(ev, displacement - mStartDisplacement, null);
+                    mInteractionHandler.updateDisplacement(displacement - mStartDisplacement);
 
                     if (FeatureFlags.SWIPE_HOME.get()) {
                         boolean isLandscape = isNavBarOnLeft() || isNavBarOnRight();
@@ -245,17 +257,6 @@
         }
     }
 
-    private void dispatchMotion(MotionEvent ev, @Nullable Float displacement,
-            @Nullable Float velocityX) {
-        if (displacement != null) {
-            mInteractionHandler.updateDisplacement(displacement);
-        }
-        boolean isLandscape = isNavBarOnLeft() || isNavBarOnRight();
-        if (!isLandscape) {
-            mInteractionHandler.dispatchMotionEventToRecentsView(ev, velocityX);
-        }
-    }
-
     private void notifyGestureStarted() {
         if (mInteractionHandler == null) {
             return;
@@ -319,8 +320,7 @@
                     : isNavBarOnLeft() ? -velocityX
                             : mVelocityTracker.getYVelocity(mActivePointerId);
 
-            dispatchMotion(ev, getDisplacement(ev) - mStartDisplacement, velocityX);
-
+            mInteractionHandler.updateDisplacement(getDisplacement(ev) - mStartDisplacement);
             mInteractionHandler.onGestureEnded(velocity, velocityX);
         } else {
             // Since we start touch tracking on DOWN, we may reach this state without actually
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 8d90813..f578149 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -56,6 +56,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.SystemClock;
+import android.util.Log;
 import android.view.HapticFeedbackConstants;
 import android.view.MotionEvent;
 import android.view.View;
@@ -103,9 +104,9 @@
 import com.android.systemui.shared.system.WindowCallbacksCompat;
 
 import java.util.function.BiFunction;
+import java.util.function.Consumer;
 
 import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
 
 @TargetApi(Build.VERSION_CODES.O)
@@ -522,24 +523,8 @@
         return TaskView.getCurveScaleForInterpolation(interpolation);
     }
 
-    @UiThread
-    public void dispatchMotionEventToRecentsView(MotionEvent event, @Nullable Float velocityX) {
-        if (mRecentsView == null) {
-            return;
-        }
-        // Pass the motion events to RecentsView to allow scrolling during swipe up.
-        if (!mDispatchedDownEvent) {
-            // The first event we dispatch should be ACTION_DOWN.
-            mDispatchedDownEvent = true;
-            MotionEvent downEvent = MotionEvent.obtain(event);
-            downEvent.setAction(MotionEvent.ACTION_DOWN);
-            int flags = downEvent.getEdgeFlags();
-            downEvent.setEdgeFlags(flags | TouchInteractionService.EDGE_NAV_BAR);
-            mRecentsView.simulateTouchEvent(downEvent, velocityX);
-            downEvent.recycle();
-        }
-
-        mRecentsView.simulateTouchEvent(event, velocityX);
+    public Consumer<MotionEvent> getRecentsViewDispatcher() {
+        return mRecentsView != null ? mRecentsView::dispatchTouchEvent : null;
     }
 
     @UiThread
diff --git a/quickstep/src/com/android/quickstep/util/CachedEventDispatcher.java b/quickstep/src/com/android/quickstep/util/CachedEventDispatcher.java
new file mode 100644
index 0000000..194c7d4
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/CachedEventDispatcher.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.util;
+
+import static com.android.systemui.shared.system.InputChannelCompat.mergeMotionEvent;
+
+import android.view.MotionEvent;
+
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
+/**
+ * Utility class to dispatch touch events to a different class. It stores the events locally
+ * until a valid dispatcher is available.
+ */
+public class CachedEventDispatcher {
+
+    private Consumer<MotionEvent> mConsumer;
+
+    private ArrayList<MotionEvent> mCache;
+    private MotionEvent mLastEvent;
+
+    public void dispatchEvent(MotionEvent event) {
+        if (mConsumer != null) {
+            mConsumer.accept(event);
+        } else {
+            if (mLastEvent == null || !mergeMotionEvent(event, mLastEvent)) {
+                // Queue event.
+                if (mCache == null) {
+                    mCache = new ArrayList<>();
+                }
+                mLastEvent = MotionEvent.obtain(event);
+                mCache.add(mLastEvent);
+            }
+        }
+    }
+
+    public void setConsumer(Consumer<MotionEvent> consumer) {
+        if (consumer == null) {
+            return;
+        }
+        mConsumer = consumer;
+        int cacheCount = mCache == null ? 0 : mCache.size();
+        for (int i = 0; i < cacheCount; i++) {
+            MotionEvent ev = mCache.get(i);
+            mConsumer.accept(ev);
+            ev.recycle();
+        }
+        mCache = null;
+        mLastEvent = null;
+    }
+
+    public boolean hasConsumer() {
+        return mConsumer != null;
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 5465a0c..8faf95d 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -166,8 +166,6 @@
 
     private final ViewPool<TaskView> mTaskViewPool;
 
-    @Nullable Float mSimulatedVelocityX = null;
-
     /**
      * TODO: Call reloadIdNeeded in onTaskStackChanged.
      */
@@ -1626,18 +1624,4 @@
             }
         }
     }
-
-    public void simulateTouchEvent(MotionEvent event, @Nullable Float velocityX) {
-        mSimulatedVelocityX = velocityX;
-        dispatchTouchEvent(event);
-        mSimulatedVelocityX = null;
-    }
-
-    @Override
-    protected int computeXVelocity() {
-        if (mSimulatedVelocityX != null) {
-            return mSimulatedVelocityX.intValue();
-        }
-        return super.computeXVelocity();
-    }
 }
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 018ec5f..4b7d8b4 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -1134,7 +1134,9 @@
                 final int activePointerId = mActivePointerId;
                 final int pointerIndex = ev.findPointerIndex(activePointerId);
                 final float x = ev.getX(pointerIndex);
-                int velocityX = computeXVelocity();
+                final VelocityTracker velocityTracker = mVelocityTracker;
+                velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+                int velocityX = (int) velocityTracker.getXVelocity(mActivePointerId);
                 final int deltaX = (int) (x - mDownMotionX);
                 final int pageWidth = getPageAt(mCurrentPage).getMeasuredWidth();
                 boolean isSignificantMove = Math.abs(deltaX) > pageWidth *
@@ -1238,12 +1240,6 @@
         return true;
     }
 
-    protected int computeXVelocity() {
-        final VelocityTracker velocityTracker = mVelocityTracker;
-        velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
-        return (int) velocityTracker.getXVelocity(mActivePointerId);
-    }
-
     protected boolean shouldFlingForVelocity(int velocityX) {
         return Math.abs(velocityX) > mFlingThresholdVelocity;
     }