Merge "Add app window thresholds for transient taskbar." into tm-qpr-dev
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 45a2cf8..c0765ee 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -288,6 +288,10 @@
     <dimen name="transient_taskbar_margin">24dp</dimen>
     <dimen name="transient_taskbar_shadow_blur">40dp</dimen>
     <dimen name="transient_taskbar_key_shadow_distance">10dp</dimen>
+    <!-- Taskbar swipe up thresholds -->
+    <dimen name="taskbar_app_window_threshold">150dp</dimen>
+    <dimen name="taskbar_home_overview_threshold">225dp</dimen>
+    <dimen name="taskbar_catch_up_threshold">300dp</dimen>
 
     <!--  Taskbar 3 button spacing  -->
     <dimen name="taskbar_button_space_inbetween">24dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index 49dba95..9ec8cfe 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -97,6 +97,13 @@
         }
     }
 
+    /**
+     * Returns true iff taskbar is stashed.
+     */
+    public boolean isTaskbarStashed() {
+        return mControllers.taskbarStashController.isStashed();
+    }
+
     @CallSuper
     protected void dumpLogs(String prefix, PrintWriter pw) {
         pw.println(String.format(
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index ff7c668..2e06825 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -64,6 +64,7 @@
 import android.app.WindowConfiguration;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Resources;
 import android.graphics.Matrix;
 import android.graphics.PointF;
 import android.graphics.Rect;
@@ -101,6 +102,7 @@
 import com.android.launcher3.tracing.InputConsumerProto;
 import com.android.launcher3.tracing.SwipeHandlerProto;
 import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter;
+import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.TraceHelper;
 import com.android.launcher3.util.WindowBounds;
 import com.android.quickstep.BaseActivityInterface.AnimationFactory;
@@ -311,6 +313,10 @@
     // Interpolate RecentsView scale from start of quick switch scroll until this scroll threshold
     private final float mQuickSwitchScaleScrollThreshold;
 
+    private final int mTaskbarAppWindowThreshold;
+    private final int mTaskbarCatchUpThreshold;
+    private boolean mTaskbarAlreadyOpen;
+
     public AbsSwipeUpHandler(Context context, RecentsAnimationDeviceState deviceState,
             TaskAnimationManager taskAnimationManager, GestureState gestureState,
             long touchTimeMs, boolean continuingLastGesture,
@@ -331,11 +337,17 @@
         mTaskAnimationManager = taskAnimationManager;
         mTouchTimeMs = touchTimeMs;
         mContinuingLastGesture = continuingLastGesture;
-        mQuickSwitchScaleScrollThreshold = context.getResources().getDimension(
-                R.dimen.quick_switch_scaling_scroll_threshold);
 
-        mSplashMainWindowShiftLength = -context.getResources().getDimensionPixelSize(
-                R.dimen.starting_surface_exit_animation_window_shift_length);
+        Resources res = context.getResources();
+        mTaskbarAppWindowThreshold = res
+                .getDimensionPixelSize(R.dimen.taskbar_app_window_threshold);
+        mTaskbarCatchUpThreshold = res.getDimensionPixelSize(R.dimen.taskbar_catch_up_threshold);
+
+        mQuickSwitchScaleScrollThreshold = res
+                .getDimension(R.dimen.quick_switch_scaling_scroll_threshold);
+
+        mSplashMainWindowShiftLength = -res
+                .getDimensionPixelSize(R.dimen.starting_surface_exit_animation_window_shift_length);
 
         initAfterSubclassConstructor();
         initStateCallbacks();
@@ -824,7 +836,7 @@
             return;
         }
         mLauncherTransitionController.setProgress(
-                Math.max(mCurrentShift.value, getScaleProgressDueToScroll()), mDragLengthFactor);
+                Math.max(getTaskbarProgress(), getScaleProgressDueToScroll()), mDragLengthFactor);
     }
 
     /**
@@ -1170,7 +1182,7 @@
     }
 
     private boolean hasReachedOverviewThreshold() {
-        return mCurrentShift.value > MIN_PROGRESS_FOR_OVERVIEW;
+        return getTaskbarProgress() > MIN_PROGRESS_FOR_OVERVIEW;
     }
 
     @UiThread
@@ -2198,7 +2210,7 @@
             AnimatorControllerWithResistance playbackController =
                     remoteHandle.getPlaybackController();
             if (playbackController != null) {
-                playbackController.setProgress(Math.max(mCurrentShift.value,
+                playbackController.setProgress(Math.max(getTaskbarProgress(),
                         getScaleProgressDueToScroll()), mDragLengthFactor);
             }
 
@@ -2242,6 +2254,41 @@
         return scaleProgress;
     }
 
+    /**
+     * Updates the current status of taskbar during this swipe.
+     */
+    public void setTaskbarAlreadyOpen(boolean taskbarAlreadyOpen) {
+        mTaskbarAlreadyOpen = taskbarAlreadyOpen;
+    }
+
+    /**
+     * Overrides the current shift progress to keep the app window at the bottom of the screen
+     * while the transient taskbar is being swiped in.
+     *
+     * There is also a catch up period so that the window can start moving 1:1 with the swipe.
+     */
+    private float getTaskbarProgress() {
+        if (!DisplayController.isTransientTaskbar(mContext)) {
+            return mCurrentShift.value;
+        }
+
+        if (mTaskbarAlreadyOpen) {
+            return mCurrentShift.value;
+        }
+
+        if (mCurrentDisplacement < mTaskbarAppWindowThreshold) {
+            return 0;
+        }
+
+        // "Catch up" with `mCurrentShift.value`.
+        if (mCurrentDisplacement < mTaskbarCatchUpThreshold) {
+            return Utilities.mapToRange(mCurrentDisplacement, mTaskbarAppWindowThreshold,
+                    mTaskbarCatchUpThreshold, 0, mCurrentShift.value, ACCEL_DEACCEL);
+        }
+
+        return mCurrentShift.value;
+    }
+
     private void setDividerShown(boolean shown, boolean immediate) {
         if (mDividerAnimator != null) {
             mDividerAnimator.cancel();
diff --git a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
index f591a1c..ddb06ce 100644
--- a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
+++ b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
@@ -65,6 +65,7 @@
     // 1 => preview snapShot is completely aligned with the recents view and hotseat is completely
     // visible.
     protected final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift);
+    protected float mCurrentDisplacement;
 
     // The distance needed to drag to reach the task size in recents.
     protected int mTransitionDragLength;
@@ -116,6 +117,8 @@
     public void updateDisplacement(float displacement) {
         // We are moving in the negative x/y direction
         displacement = -displacement;
+        mCurrentDisplacement = displacement;
+
         float shift;
         if (displacement > mTransitionDragLength * mDragLengthFactor && mTransitionDragLength > 0) {
             shift = mDragLengthFactor;
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 60d5ba4..9d269fb 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -37,6 +37,7 @@
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.Intent;
+import android.content.res.Resources;
 import android.graphics.PointF;
 import android.os.Build;
 import android.util.Log;
@@ -48,13 +49,16 @@
 
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.taskbar.TaskbarUIController;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.TestProtocol;
 import com.android.launcher3.tracing.InputConsumerProto;
+import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.Preconditions;
 import com.android.launcher3.util.TraceHelper;
 import com.android.quickstep.AbsSwipeUpHandler;
 import com.android.quickstep.AbsSwipeUpHandler.Factory;
+import com.android.quickstep.BaseActivityInterface;
 import com.android.quickstep.GestureState;
 import com.android.quickstep.InputConsumer;
 import com.android.quickstep.RecentsAnimationCallbacks;
@@ -97,6 +101,7 @@
     private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
     private final InputMonitorCompat mInputMonitorCompat;
     private final InputEventReceiver mInputEventReceiver;
+    private final BaseActivityInterface mActivityInterface;
 
     private final AbsSwipeUpHandler.Factory mHandlerFactory;
 
@@ -131,6 +136,10 @@
     // Might be displacement in X or Y, depending on the direction we are swiping from the nav bar.
     private float mStartDisplacement;
 
+    private final boolean mIsTransientTaskbar;
+    private final boolean mTaskbarAlreadyOpen;
+    private final int mTaskbarHomeOverviewThreshold;
+
     public OtherActivityInputConsumer(Context base, RecentsAnimationDeviceState deviceState,
             TaskAnimationManager taskAnimationManager, GestureState gestureState,
             boolean isDeferredDownTarget, Consumer<OtherActivityInputConsumer> onCompleteCallback,
@@ -142,6 +151,11 @@
         mTaskAnimationManager = taskAnimationManager;
         mGestureState = gestureState;
         mHandlerFactory = handlerFactory;
+        mActivityInterface = mGestureState.getActivityInterface();
+
+        Resources res = base.getResources();
+        mTaskbarHomeOverviewThreshold = res
+                .getDimensionPixelSize(R.dimen.taskbar_home_overview_threshold);
 
         mMotionPauseDetector = new MotionPauseDetector(base, false,
                 mNavBarPosition.isLeftEdge() || mNavBarPosition.isRightEdge()
@@ -153,6 +167,10 @@
         mInputMonitorCompat = inputMonitorCompat;
         mInputEventReceiver = inputEventReceiver;
 
+        TaskbarUIController controller = mActivityInterface.getTaskbarController();
+        mTaskbarAlreadyOpen = controller != null && !controller.isTaskbarStashed();
+        mIsTransientTaskbar = DisplayController.isTransientTaskbar(base);
+
         boolean continuingPreviousGesture = mTaskAnimationManager.isRecentsAnimationRunning();
         mIsDeferredDownTarget = !continuingPreviousGesture && isDeferredDownTarget;
 
@@ -279,6 +297,7 @@
                 float upDist = -displacement;
                 boolean passedSlop = squaredHypot(displacementX, displacementY)
                         >= mSquaredTouchSlop;
+
                 if (!mPassedSlopOnThisGesture && passedSlop) {
                     mPassedSlopOnThisGesture = true;
                 }
@@ -323,7 +342,13 @@
                     }
 
                     if (mDeviceState.isFullyGesturalNavMode()) {
-                        mMotionPauseDetector.setDisallowPause(upDist < mMotionPauseMinDisplacement
+                        float minDisplacement = mMotionPauseMinDisplacement;
+
+                        if (mIsTransientTaskbar && !mTaskbarAlreadyOpen) {
+                            minDisplacement += mTaskbarHomeOverviewThreshold;
+                        }
+
+                        mMotionPauseDetector.setDisallowPause(upDist < minDisplacement
                                 || isLikelyToStartNewTask);
                         mMotionPauseDetector.addPosition(ev);
                         mInteractionHandler.setIsLikelyToStartNewTask(isLikelyToStartNewTask);
@@ -357,6 +382,8 @@
 
         // Notify the handler that the gesture has actually started
         mInteractionHandler.onGestureStarted(isLikelyToStartNewTask);
+
+        mInteractionHandler.setTaskbarAlreadyOpen(mTaskbarAlreadyOpen);
     }
 
     private void startTouchTrackingForWindowAnimation(long touchTimeMs) {
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 0a28b6c..afdb071 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -380,6 +380,11 @@
     <dimen name="taskbar_button_margin_6_5">0dp</dimen>
     <dimen name="taskbar_button_margin_4_5">0dp</dimen>
     <dimen name="taskbar_button_margin_4_4">0dp</dimen>
+    <!-- Taskbar swipe up thresholds threshold -->
+    <dimen name="taskbar_nav_threshold">0dp</dimen>
+    <dimen name="taskbar_app_window_threshold">0dp</dimen>
+    <dimen name="taskbar_home_overview_threshold">0dp</dimen>
+    <dimen name="taskbar_catch_up_threshold">0dp</dimen>
 
     <!-- Size of the maximum radius for the enforced rounded rectangles. -->
     <dimen name="enforced_rounded_corner_max_radius">16dp</dimen>