Merge "Move logic that overrides MotionPauseDetector to callers" into ub-launcher3-qt-dev
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
index bab215b..6358109 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
@@ -28,6 +28,7 @@
 import android.animation.AnimatorSet;
 import android.view.HapticFeedbackConstants;
 import android.view.MotionEvent;
+import android.view.ViewConfiguration;
 
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
@@ -44,12 +45,14 @@
     private static final long PEEK_ANIM_DURATION = 100;
 
     private final MotionPauseDetector mMotionPauseDetector;
+    private final float mMotionPauseMinDisplacement;
 
     private AnimatorSet mPeekAnim;
 
     public FlingAndHoldTouchController(Launcher l) {
         super(l, false /* allowDragToOverview */);
         mMotionPauseDetector = new MotionPauseDetector(l);
+        mMotionPauseMinDisplacement = ViewConfiguration.get(l).getScaledTouchSlop();
     }
 
     @Override
@@ -98,7 +101,8 @@
 
     @Override
     public boolean onDrag(float displacement, MotionEvent event) {
-        mMotionPauseDetector.addPosition(displacement, 0, event.getEventTime());
+        mMotionPauseDetector.setDisallowPause(-displacement < mMotionPauseMinDisplacement);
+        mMotionPauseDetector.addPosition(displacement, event.getEventTime());
         return super.onDrag(displacement, event);
     }
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/AssistantTouchConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/AssistantTouchConsumer.java
index abd7c03..a76ecd5 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/AssistantTouchConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/AssistantTouchConsumer.java
@@ -21,14 +21,14 @@
 import static android.view.MotionEvent.ACTION_MOVE;
 import static android.view.MotionEvent.ACTION_POINTER_UP;
 import static android.view.MotionEvent.ACTION_UP;
-import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.SWIPE;
-import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.SWIPE_NOOP;
+
 import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction.UPLEFT;
 import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction.UPRIGHT;
+import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.SWIPE;
+import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.SWIPE_NOOP;
 import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType.NAVBAR;
 
 import android.animation.ValueAnimator;
-import android.app.Activity;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.PointF;
@@ -40,10 +40,10 @@
 import android.view.MotionEvent;
 
 import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.R;
 import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.logging.UserEventDispatcher;
 import com.android.systemui.shared.recents.ISystemUiProxy;
-import com.android.launcher3.R;
 import com.android.systemui.shared.system.InputMonitorCompat;
 import com.android.systemui.shared.system.NavigationBarCompat;
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java
index 36afdef..44ba515 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java
@@ -21,9 +21,9 @@
 import static android.view.MotionEvent.ACTION_POINTER_UP;
 import static android.view.MotionEvent.ACTION_UP;
 import static android.view.MotionEvent.INVALID_POINTER_ID;
+import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
 import static com.android.launcher3.util.RaceConditionTracker.ENTER;
 import static com.android.launcher3.util.RaceConditionTracker.EXIT;
-import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
 import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
 import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
@@ -45,6 +45,9 @@
 import android.view.ViewConfiguration;
 import android.view.WindowManager;
 
+import androidx.annotation.UiThread;
+
+import com.android.launcher3.R;
 import com.android.launcher3.util.Preconditions;
 import com.android.launcher3.util.RaceConditionTracker;
 import com.android.launcher3.util.TraceHelper;
@@ -62,8 +65,6 @@
 
 import java.util.function.Consumer;
 
-import androidx.annotation.UiThread;
-
 /**
  * Input consumer for handling events originating from an activity other than Launcher
  */
@@ -90,6 +91,7 @@
 
     private final Consumer<OtherActivityInputConsumer> mOnCompleteCallback;
     private final MotionPauseDetector mMotionPauseDetector;
+    private final float mMotionPauseMinDisplacement;
     private VelocityTracker mVelocityTracker;
 
     private WindowTransformSwipeHandler mInteractionHandler;
@@ -107,8 +109,9 @@
     // Slop used to determine when we say that the gesture has started.
     private boolean mPassedTouchSlop;
 
-    // TODO: Start displacement should have both x and y
+    // Might be displacement in X or Y, depending on the direction we are swiping from the nav bar.
     private float mStartDisplacement;
+    private float mStartDisplacementX;
 
     private Handler mMainThreadHandler;
     private Runnable mCancelRecentsAnimationRunnable = () -> {
@@ -131,6 +134,8 @@
         mMode = SysUINavigationMode.getMode(base);
 
         mMotionPauseDetector = new MotionPauseDetector(base);
+        mMotionPauseMinDisplacement = base.getResources().getDimension(
+                R.dimen.motion_pause_detector_min_displacement_from_app);
         mOnCompleteCallback = onCompleteCallback;
         mVelocityTracker = VelocityTracker.obtain();
         mInputMonitorCompat = inputMonitorCompat;
@@ -219,6 +224,7 @@
                 }
                 mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
                 float displacement = getDisplacement(ev);
+                float displacementX = mLastPos.x - mDownPos.x;
 
                 if (!mPassedDragSlop) {
                     if (!mIsDeferredDownTarget) {
@@ -227,13 +233,13 @@
                         if (Math.abs(displacement) > mDragSlop) {
                             mPassedDragSlop = true;
                             mStartDisplacement = displacement;
+                            mStartDisplacementX = displacementX;
                         }
                     }
                 }
 
                 if (!mPassedTouchSlop) {
-                    if (Math.hypot(mLastPos.x - mDownPos.x, mLastPos.y - mDownPos.y) >=
-                            mTouchSlop) {
+                    if (Math.hypot(displacementX, mLastPos.y - mDownPos.y) >= mTouchSlop) {
                         mPassedTouchSlop = true;
 
                         if (mIsDeferredDownTarget) {
@@ -244,6 +250,7 @@
                         if (!mPassedDragSlop) {
                             mPassedDragSlop = true;
                             mStartDisplacement = displacement;
+                            mStartDisplacementX = displacementX;
                         }
                         notifyGestureStarted();
                     }
@@ -254,12 +261,12 @@
                     mInteractionHandler.updateDisplacement(displacement - mStartDisplacement);
 
                     if (mMode == Mode.NO_BUTTON) {
-                        boolean isLandscape = isNavBarOnLeft() || isNavBarOnRight();
-                        float orthogonalDisplacement = !isLandscape
-                                ? ev.getX() - mDownPos.x
-                                : ev.getY() - mDownPos.y;
-                        mMotionPauseDetector.addPosition(displacement, orthogonalDisplacement,
-                                ev.getEventTime());
+                        float horizontalDist = Math.abs(displacementX - mStartDisplacementX);
+                        float upDist = -(displacement - mStartDisplacement);
+                        boolean isLikelyToStartNewTask = horizontalDist > upDist;
+                        mMotionPauseDetector.setDisallowPause(upDist < mMotionPauseMinDisplacement
+                                || isLikelyToStartNewTask);
+                        mMotionPauseDetector.addPosition(displacement, ev.getEventTime());
                     }
                 }
                 break;
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 13a0435..32f312f 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -38,7 +38,7 @@
     <dimen name="motion_pause_detector_speed_very_slow">0.0285dp</dimen>
     <dimen name="motion_pause_detector_speed_somewhat_fast">0.285dp</dimen>
     <dimen name="motion_pause_detector_speed_fast">0.5dp</dimen>
-    <dimen name="motion_pause_detector_min_displacement">48dp</dimen>
+    <dimen name="motion_pause_detector_min_displacement_from_app">36dp</dimen>
 
     <!-- Launcher app transition -->
     <dimen name="content_trans_y">50dp</dimen>
diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
index ae5f390..4b24a2f 100644
--- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
+++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
@@ -38,28 +38,26 @@
     private final float mSpeedVerySlow;
     private final float mSpeedSomewhatFast;
     private final float mSpeedFast;
-    private final float mMinDisplacementForPause;
     private final Alarm mForcePauseTimeout;
 
     private Long mPreviousTime = null;
     private Float mPreviousPosition = null;
     private Float mPreviousVelocity = null;
 
-    private TotalDisplacement mTotalDisplacement = new TotalDisplacement();
     private Float mFirstPosition = null;
-    private Float mFirstOrthogonalPosition = null;
 
     private OnMotionPauseListener mOnMotionPauseListener;
     private boolean mIsPaused;
     // Bias more for the first pause to make it feel extra responsive.
     private boolean mHasEverBeenPaused;
+    /** @see #setDisallowPause(boolean) */
+    private boolean mDisallowPause;
 
     public MotionPauseDetector(Context context) {
         Resources res = context.getResources();
         mSpeedVerySlow = res.getDimension(R.dimen.motion_pause_detector_speed_very_slow);
         mSpeedSomewhatFast = res.getDimension(R.dimen.motion_pause_detector_speed_somewhat_fast);
         mSpeedFast = res.getDimension(R.dimen.motion_pause_detector_speed_fast);
-        mMinDisplacementForPause = res.getDimension(R.dimen.motion_pause_detector_min_displacement);
         mForcePauseTimeout = new Alarm();
         mForcePauseTimeout.setOnAlarmListener(alarm -> updatePaused(true /* isPaused */));
     }
@@ -73,28 +71,30 @@
     }
 
     /**
+     * @param disallowPause If true, we will not detect any pauses until this is set to false again.
+     */
+    public void setDisallowPause(boolean disallowPause) {
+        mDisallowPause = disallowPause;
+        updatePaused(false);
+    }
+
+    /**
      * Computes velocity and acceleration to determine whether the motion is paused.
      * @param position The x or y component of the motion being tracked.
-     * @param orthogonalPosition The x or y component (opposite of {@param position}) of the motion.
      *
      * TODO: Use historical positions as well, e.g. {@link MotionEvent#getHistoricalY(int, int)}.
      */
-    public void addPosition(float position, float orthogonalPosition, long time) {
+    public void addPosition(float position, long time) {
         if (mFirstPosition == null) {
             mFirstPosition = position;
         }
-        if (mFirstOrthogonalPosition == null) {
-            mFirstOrthogonalPosition = orthogonalPosition;
-        }
         mForcePauseTimeout.setAlarm(FORCE_PAUSE_TIMEOUT);
         if (mPreviousTime != null && mPreviousPosition != null) {
             long changeInTime = Math.max(1, time - mPreviousTime);
             float changeInPosition = position - mPreviousPosition;
             float velocity = changeInPosition / changeInTime;
             if (mPreviousVelocity != null) {
-                mTotalDisplacement.set(Math.abs(position - mFirstPosition),
-                        Math.abs(orthogonalPosition - mFirstOrthogonalPosition));
-                checkMotionPaused(velocity, mPreviousVelocity, mTotalDisplacement);
+                checkMotionPaused(velocity, mPreviousVelocity);
             }
             mPreviousVelocity = velocity;
         }
@@ -102,8 +102,7 @@
         mPreviousPosition = position;
     }
 
-    private void checkMotionPaused(float velocity, float prevVelocity,
-            TotalDisplacement totalDisplacement) {
+    private void checkMotionPaused(float velocity, float prevVelocity) {
         float speed = Math.abs(velocity);
         float previousSpeed = Math.abs(prevVelocity);
         boolean isPaused;
@@ -125,16 +124,13 @@
                 }
             }
         }
-        boolean passedMinDisplacement = totalDisplacement.primary >= mMinDisplacementForPause;
-        boolean isDisplacementOrthogonal = totalDisplacement.orthogonal > totalDisplacement.primary;
-        if (!passedMinDisplacement || isDisplacementOrthogonal) {
-            mForcePauseTimeout.cancelAlarm();
-            isPaused = false;
-        }
         updatePaused(isPaused);
     }
 
     private void updatePaused(boolean isPaused) {
+        if (mDisallowPause) {
+            isPaused = false;
+        }
         if (mIsPaused != isPaused) {
             mIsPaused = isPaused;
             if (mIsPaused) {
@@ -151,8 +147,6 @@
         mPreviousPosition = null;
         mPreviousVelocity = null;
         mFirstPosition = null;
-        mFirstOrthogonalPosition = null;
-        mTotalDisplacement.set(0, 0);
         setOnMotionPauseListener(null);
         mIsPaused = mHasEverBeenPaused = false;
         mForcePauseTimeout.cancelAlarm();
@@ -165,18 +159,4 @@
     public interface OnMotionPauseListener {
         void onMotionPauseChanged(boolean isPaused);
     }
-
-    /**
-     * Contains the displacement from the first tracked position,
-     * along both the primary and orthogonal axes.
-     */
-    private class TotalDisplacement {
-        public float primary;
-        public float orthogonal;
-
-        public void set(float primaryDisplacement, float orthogonalDisplacement) {
-            this.primary = primaryDisplacement;
-            this.orthogonal = orthogonalDisplacement;
-        }
-    }
 }