Merge "Use Animator cancel instead of end" into ub-launcher3-qt-dev
diff --git a/go/quickstep/src/com/android/quickstep/RecentsActivity.java b/go/quickstep/src/com/android/quickstep/RecentsActivity.java
index 078f3a5..7f813ce 100644
--- a/go/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/go/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -67,8 +67,8 @@
     }
 
     @Override
-    protected void onStart() {
+    protected void onResume() {
         mIconRecentsView.onBeginTransitionToOverview();
-        super.onStart();
+        super.onResume();
     }
 }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsAnimationWrapper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsAnimationWrapper.java
index 96d2dca..5eecf17 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsAnimationWrapper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsAnimationWrapper.java
@@ -24,6 +24,7 @@
 import android.view.MotionEvent;
 
 import com.android.launcher3.util.Preconditions;
+import com.android.quickstep.inputconsumers.InputConsumer;
 import com.android.quickstep.util.SwipeAnimationTargetSet;
 import com.android.systemui.shared.system.InputConsumerController;
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
index e20ef52..2c919b3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
@@ -296,10 +296,6 @@
             if (sysUiProxy == null) {
                 return null;
             }
-            if (SysUINavigationMode.getMode(activity) == SysUINavigationMode.Mode.NO_BUTTON) {
-                // TODO(b/130225926): Temporarily disable pinning while gesture nav is enabled
-                return null;
-            }
             if (!ActivityManagerWrapper.getInstance().isScreenPinningEnabled()) {
                 return null;
             }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index ee9876a..128fd45 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -66,6 +66,13 @@
 import com.android.launcher3.util.UiThreadHelper;
 import com.android.quickstep.SysUINavigationMode.Mode;
 import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
+import com.android.quickstep.inputconsumers.AccessibilityInputConsumer;
+import com.android.quickstep.inputconsumers.AssistantTouchConsumer;
+import com.android.quickstep.inputconsumers.DeviceLockedInputConsumer;
+import com.android.quickstep.inputconsumers.InputConsumer;
+import com.android.quickstep.inputconsumers.OtherActivityInputConsumer;
+import com.android.quickstep.inputconsumers.OverviewInputConsumer;
+import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -460,6 +467,12 @@
                         mInputMonitorCompat);
             }
 
+            if (ActivityManagerWrapper.getInstance().isScreenPinningActive()) {
+                // Note: we only allow accessibility to wrap this, and it replaces the previous
+                // base input consumer (which should be NO_OP anyway since topTaskLocked == true).
+                base = new ScreenPinnedInputConsumer(this, mISystemUiProxy, activityControl);
+            }
+
             if ((mSystemUiStateFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0) {
                 base = new AccessibilityInputConsumer(this, mISystemUiProxy,
                         (mSystemUiStateFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0, base,
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 58ae5eb..49c95f1 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -67,6 +67,7 @@
 import android.view.animation.Interpolator;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
 
 import com.android.launcher3.AbstractFloatingView;
@@ -91,6 +92,8 @@
 import com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState;
 import com.android.quickstep.ActivityControlHelper.HomeAnimationFactory;
 import com.android.quickstep.SysUINavigationMode.Mode;
+import com.android.quickstep.inputconsumers.InputConsumer;
+import com.android.quickstep.inputconsumers.OverviewInputConsumer;
 import com.android.quickstep.util.ClipAnimationHelper;
 import com.android.quickstep.util.RectFSpringAnim;
 import com.android.quickstep.util.RemoteAnimationTargetSet;
@@ -166,7 +169,7 @@
     private static final int LAUNCHER_UI_STATES =
             STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_LAUNCHER_STARTED;
 
-    enum GestureEndTarget {
+    public enum GestureEndTarget {
         HOME(1, STATE_SCALED_CONTROLLER_HOME, true, false, ContainerType.WORKSPACE, false),
 
         RECENTS(1, STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT
@@ -220,8 +223,8 @@
     private final ClipAnimationHelper mClipAnimationHelper;
     private final ClipAnimationHelper.TransformParams mTransformParams;
 
-    protected Runnable mGestureEndCallback;
-    protected GestureEndTarget mGestureEndTarget;
+    private Runnable mGestureEndCallback;
+    private GestureEndTarget mGestureEndTarget;
     // Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise
     private RunningWindowAnim mRunningWindowAnim;
     private boolean mIsShelfPeeking;
@@ -273,7 +276,7 @@
     private final long mTouchTimeMs;
     private long mLauncherFrameDrawnTime;
 
-    WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context,
+    public WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context,
             long touchTimeMs, ActivityControlHelper<T> controller, boolean continuingLastGesture,
             InputConsumerController inputConsumer) {
         mContext = context;
@@ -1125,6 +1128,13 @@
         return anim;
     }
 
+    /**
+     * @return The GestureEndTarget if the gesture has ended, else null.
+     */
+    public @Nullable GestureEndTarget getGestureEndTarget() {
+        return mGestureEndTarget;
+    }
+
     @UiThread
     private void resumeLastTask() {
         mRecentsAnimationWrapper.finish(false /* toRecents */, null);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/AccessibilityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
similarity index 98%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/AccessibilityInputConsumer.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
index 8f8cd18..f8475ca 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/AccessibilityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.quickstep;
+package com.android.quickstep.inputconsumers;
 
 import static android.view.MotionEvent.ACTION_CANCEL;
 import static android.view.MotionEvent.ACTION_DOWN;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/AssistantTouchConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantTouchConsumer.java
similarity index 98%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/AssistantTouchConsumer.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantTouchConsumer.java
index 335e8b1..0448fd1 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/AssistantTouchConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantTouchConsumer.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.quickstep;
+package com.android.quickstep.inputconsumers;
 
 import static android.view.MotionEvent.ACTION_CANCEL;
 import static android.view.MotionEvent.ACTION_DOWN;
@@ -43,6 +43,7 @@
 import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.logging.UserEventDispatcher;
 import com.android.launcher3.touch.SwipeDetector;
+import com.android.quickstep.ActivityControlHelper;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 import com.android.systemui.shared.system.InputMonitorCompat;
 import com.android.systemui.shared.system.QuickStepContract;
@@ -236,7 +237,7 @@
         }
     }
 
-    static boolean withinTouchRegion(Context context, MotionEvent ev) {
+    public static boolean withinTouchRegion(Context context, MotionEvent ev) {
         final Resources res = context.getResources();
         final int width = res.getDisplayMetrics().widthPixels;
         final int height = res.getDisplayMetrics().heightPixels;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/DelegateInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java
similarity index 96%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/DelegateInputConsumer.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java
index d36162f..311ddd2 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/DelegateInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java
@@ -1,4 +1,4 @@
-package com.android.quickstep;
+package com.android.quickstep.inputconsumers;
 
 import android.view.MotionEvent;
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/DeviceLockedInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
similarity index 97%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/DeviceLockedInputConsumer.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
index 7fd09f7..b1d175d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/DeviceLockedInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.quickstep;
+package com.android.quickstep.inputconsumers;
 
 import android.content.Context;
 import android.content.Intent;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/InputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java
similarity index 95%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/InputConsumer.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java
index 37b7288..2e8880d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/InputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/InputConsumer.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.quickstep;
+package com.android.quickstep.inputconsumers;
 
 import android.annotation.TargetApi;
 import android.os.Build;
@@ -30,6 +30,7 @@
     int TYPE_ASSISTANT = 1 << 3;
     int TYPE_DEVICE_LOCKED = 1 << 4;
     int TYPE_ACCESSIBILITY = 1 << 5;
+    int TYPE_SCREEN_PINNED = 1 << 6;
 
     InputConsumer NO_OP = () -> TYPE_NO_OP;
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
similarity index 97%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index db377b0..e862fa6 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.quickstep;
+package com.android.quickstep.inputconsumers;
 
 import static android.view.MotionEvent.ACTION_CANCEL;
 import static android.view.MotionEvent.ACTION_DOWN;
@@ -50,7 +50,13 @@
 import com.android.launcher3.util.Preconditions;
 import com.android.launcher3.util.RaceConditionTracker;
 import com.android.launcher3.util.TraceHelper;
+import com.android.quickstep.ActivityControlHelper;
+import com.android.quickstep.OverviewCallbacks;
+import com.android.quickstep.RecentsModel;
+import com.android.quickstep.SwipeSharedState;
+import com.android.quickstep.SysUINavigationMode;
 import com.android.quickstep.SysUINavigationMode.Mode;
+import com.android.quickstep.WindowTransformSwipeHandler;
 import com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget;
 import com.android.quickstep.util.CachedEventDispatcher;
 import com.android.quickstep.util.MotionPauseDetector;
@@ -376,7 +382,7 @@
             // The consumer is being switched while we are active. Set up the shared state to be
             // used by the next animation
             removeListener();
-            GestureEndTarget endTarget = mInteractionHandler.mGestureEndTarget;
+            GestureEndTarget endTarget = mInteractionHandler.getGestureEndTarget();
             mSwipeSharedState.canGestureBeContinued = endTarget != null && endTarget.canBeContinued;
             mSwipeSharedState.goingToLauncher = endTarget != null && endTarget.isLauncher;
             if (mSwipeSharedState.canGestureBeContinued) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
similarity index 96%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewInputConsumer.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
index bafc367..bab3c71 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.quickstep;
+package com.android.quickstep.inputconsumers;
 
 import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
 import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
@@ -27,6 +27,8 @@
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.views.BaseDragLayer;
+import com.android.quickstep.ActivityControlHelper;
+import com.android.quickstep.OverviewCallbacks;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.InputMonitorCompat;
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
new file mode 100644
index 0000000..a0e20f2
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
@@ -0,0 +1,88 @@
+/*
+ * 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.inputconsumers;
+
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.HapticFeedbackConstants;
+import android.view.MotionEvent;
+
+import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.R;
+import com.android.quickstep.ActivityControlHelper;
+import com.android.quickstep.util.MotionPauseDetector;
+import com.android.systemui.shared.recents.ISystemUiProxy;
+
+/**
+ * An input consumer that detects swipe up and hold to exit screen pinning mode.
+ */
+public class ScreenPinnedInputConsumer implements InputConsumer {
+
+    private static final String TAG = "ScreenPinnedConsumer";
+
+    private final float mMotionPauseMinDisplacement;
+    private final MotionPauseDetector mMotionPauseDetector;
+
+    private float mTouchDownY;
+
+    public ScreenPinnedInputConsumer(Context context, ISystemUiProxy sysuiProxy,
+            ActivityControlHelper activityControl) {
+        mMotionPauseMinDisplacement = context.getResources().getDimension(
+                R.dimen.motion_pause_detector_min_displacement_from_app);
+        mMotionPauseDetector = new MotionPauseDetector(context, true /* makePauseHarderToTrigger*/);
+        mMotionPauseDetector.setOnMotionPauseListener(isPaused -> {
+            if (isPaused) {
+                try {
+                    sysuiProxy.stopScreenPinning();
+                    BaseDraggingActivity launcherActivity = activityControl.getCreatedActivity();
+                    if (launcherActivity != null) {
+                        launcherActivity.getRootView().performHapticFeedback(
+                                HapticFeedbackConstants.LONG_PRESS,
+                                HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
+                    }
+                    mMotionPauseDetector.clear();
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Unable to stop screen pinning ", e);
+                }
+            }
+        });
+    }
+
+    @Override
+    public int getType() {
+        return TYPE_SCREEN_PINNED;
+    }
+
+    @Override
+    public void onMotionEvent(MotionEvent ev) {
+        float y = ev.getY();
+        switch (ev.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                mTouchDownY = y;
+                break;
+            case MotionEvent.ACTION_MOVE:
+                float displacement = mTouchDownY - y;
+                mMotionPauseDetector.setDisallowPause(displacement < mMotionPauseMinDisplacement);
+                mMotionPauseDetector.addPosition(y, ev.getEventTime());
+                break;
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP:
+                mMotionPauseDetector.clear();
+                break;
+        }
+    }
+}
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 32f312f..82d1aa6 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -36,6 +36,7 @@
 
     <!-- These speeds are in dp / ms -->
     <dimen name="motion_pause_detector_speed_very_slow">0.0285dp</dimen>
+    <dimen name="motion_pause_detector_speed_slow">0.15dp</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_from_app">36dp</dimen>
diff --git a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
index f58f0d4..893c053 100644
--- a/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
+++ b/quickstep/src/com/android/quickstep/util/MotionPauseDetector.java
@@ -35,10 +35,18 @@
     /** If no motion is added for this amount of time, assume the motion has paused. */
     private static final long FORCE_PAUSE_TIMEOUT = 300;
 
+    /**
+     * After {@link #makePauseHarderToTrigger()}, must
+     * move slowly for this long to trigger a pause.
+     */
+    private static final long HARDER_TRIGGER_TIMEOUT = 400;
+
     private final float mSpeedVerySlow;
+    private final float mSpeedSlow;
     private final float mSpeedSomewhatFast;
     private final float mSpeedFast;
     private final Alarm mForcePauseTimeout;
+    private final boolean mMakePauseHarderToTrigger;
 
     private Long mPreviousTime = null;
     private Float mPreviousPosition = null;
@@ -52,19 +60,29 @@
     private boolean mHasEverBeenPaused;
     /** @see #setDisallowPause(boolean) */
     private boolean mDisallowPause;
+    // Time at which speed became < mSpeedSlow (only used if mMakePauseHarderToTrigger == true).
+    private long mSlowStartTime;
 
     public MotionPauseDetector(Context context) {
+        this(context, false);
+    }
+
+    /**
+     * @param makePauseHarderToTrigger Used for gestures that require a more explicit pause.
+     */
+    public MotionPauseDetector(Context context, boolean makePauseHarderToTrigger) {
         Resources res = context.getResources();
         mSpeedVerySlow = res.getDimension(R.dimen.motion_pause_detector_speed_very_slow);
+        mSpeedSlow = res.getDimension(R.dimen.motion_pause_detector_speed_slow);
         mSpeedSomewhatFast = res.getDimension(R.dimen.motion_pause_detector_speed_somewhat_fast);
         mSpeedFast = res.getDimension(R.dimen.motion_pause_detector_speed_fast);
         mForcePauseTimeout = new Alarm();
         mForcePauseTimeout.setOnAlarmListener(alarm -> updatePaused(true /* isPaused */));
+        mMakePauseHarderToTrigger = makePauseHarderToTrigger;
     }
 
     /**
-     * Get callbacks for when motion pauses and resumes, including an
-     * immediate callback with the current pause state.
+     * Get callbacks for when motion pauses and resumes.
      */
     public void setOnMotionPauseListener(OnMotionPauseListener listener) {
         mOnMotionPauseListener = listener;
@@ -88,13 +106,15 @@
         if (mFirstPosition == null) {
             mFirstPosition = position;
         }
-        mForcePauseTimeout.setAlarm(FORCE_PAUSE_TIMEOUT);
+        mForcePauseTimeout.setAlarm(mMakePauseHarderToTrigger
+                ? HARDER_TRIGGER_TIMEOUT
+                : 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) {
-                checkMotionPaused(velocity, mPreviousVelocity);
+                checkMotionPaused(velocity, mPreviousVelocity, time);
             }
             mPreviousVelocity = velocity;
         }
@@ -102,7 +122,7 @@
         mPreviousPosition = position;
     }
 
-    private void checkMotionPaused(float velocity, float prevVelocity) {
+    private void checkMotionPaused(float velocity, float prevVelocity, long time) {
         float speed = Math.abs(velocity);
         float previousSpeed = Math.abs(prevVelocity);
         boolean isPaused;
@@ -122,6 +142,17 @@
                     boolean isRapidDeceleration = speed < previousSpeed * RAPID_DECELERATION_FACTOR;
                     isPaused = isRapidDeceleration && speed < mSpeedSomewhatFast;
                 }
+                if (mMakePauseHarderToTrigger) {
+                    if (speed < mSpeedSlow) {
+                        if (mSlowStartTime == 0) {
+                            mSlowStartTime = time;
+                        }
+                        isPaused = time - mSlowStartTime >= HARDER_TRIGGER_TIMEOUT;
+                    } else {
+                        mSlowStartTime = 0;
+                        isPaused = false;
+                    }
+                }
             }
         }
         updatePaused(isPaused);
@@ -149,6 +180,7 @@
         mFirstPosition = null;
         setOnMotionPauseListener(null);
         mIsPaused = mHasEverBeenPaused = false;
+        mSlowStartTime = 0;
         mForcePauseTimeout.cancelAlarm();
     }
 
diff --git a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
index 8bdb90d..2111e2c 100644
--- a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
+++ b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
@@ -28,6 +28,7 @@
 import com.android.launcher3.util.RaceConditionReproducer;
 import com.android.quickstep.NavigationModeSwitchRule.Mode;
 import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
+import com.android.quickstep.inputconsumers.OtherActivityInputConsumer;
 
 import org.junit.Before;
 import org.junit.Ignore;
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index e2a5160..41252aa 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -604,4 +604,18 @@
 
         return super.performAccessibilityAction(action, arguments);
     }
+
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        switch (ev.getActionMasked()) {
+            case MotionEvent.ACTION_DOWN:
+                mAllAppsStore.setDeferUpdates(true);
+                break;
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL:
+                mAllAppsStore.setDeferUpdates(false);
+                break;
+        }
+        return super.dispatchTouchEvent(ev);
+    }
 }