Merge "Ensure that the task is always clipped to match the tile aspect ratio" into ub-launcher3-master
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
index 13c99f9..dbff20a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
@@ -35,6 +35,7 @@
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.graphics.OverviewScrim;
 import com.android.launcher3.statemanager.StateManager;
+import com.android.launcher3.states.StateAnimationConfig;
 import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
 import com.android.launcher3.util.VibratorWrapper;
@@ -215,7 +216,7 @@
             new OverviewToHomeAnim(mLauncher, ()-> onSwipeInteractionCompleted(NORMAL, Touch.FLING))
                     .animateWithVelocity(velocity);
         }
-        if (mReachedOverview && !goToHomeInsteadOfOverview) {
+        if (mReachedOverview) {
             float distanceDp = dpiFromPx(Math.max(
                     Math.abs(mRecentsView.getTranslationX()),
                     Math.abs(mRecentsView.getTranslationY())));
@@ -224,11 +225,18 @@
             mRecentsView.animate()
                     .translationX(0)
                     .translationY(0)
-                    .scaleX(1)
-                    .scaleY(1)
                     .setInterpolator(ACCEL_DEACCEL)
                     .setDuration(duration)
-                    .withEndAction(this::maybeSwipeInteractionToOverviewComplete);
+                    .withEndAction(goToHomeInsteadOfOverview
+                            ? null
+                            : this::maybeSwipeInteractionToOverviewComplete);
+            if (!goToHomeInsteadOfOverview) {
+                // Return to normal properties for the overview state.
+                StateAnimationConfig config = new StateAnimationConfig();
+                config.duration = duration;
+                LauncherState state = mLauncher.getStateManager().getState();
+                mLauncher.getStateManager().createAtomicAnimation(state, state, config).start();
+            }
         }
     }
 
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index fce019b..3586b4f 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -24,6 +24,7 @@
 import android.animation.AnimatorListenerAdapter;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.animation.Interpolator;
 
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.BaseDraggingActivity;
@@ -205,14 +206,19 @@
         long maxDuration = 2 * secondaryLayerDimension;
         int verticalFactor = orientationHandler.getTaskDragDisplacementFactor(mIsRtl);
         int secondaryTaskDimension = orientationHandler.getSecondaryDimension(mTaskBeingDragged);
+        // The interpolator controlling the most prominent visual movement. We use this to determine
+        // whether we passed SUCCESS_TRANSITION_PROGRESS.
+        final Interpolator currentInterpolator;
         if (goingUp) {
+            currentInterpolator = Interpolators.LINEAR;
             mPendingAnimation = mRecentsView.createTaskDismissAnimation(mTaskBeingDragged,
                     true /* animateTaskView */, true /* removeTask */, maxDuration);
 
             mEndDisplacement = -secondaryTaskDimension;
         } else {
+            currentInterpolator = Interpolators.ZOOM_IN;
             mPendingAnimation = mRecentsView.createTaskLaunchAnimation(
-                    mTaskBeingDragged, maxDuration, Interpolators.ZOOM_IN);
+                    mTaskBeingDragged, maxDuration, currentInterpolator);
 
             // Since the thumbnail is what is filling the screen, based the end displacement on it.
             View thumbnailView = mTaskBeingDragged.getThumbnail();
@@ -227,6 +233,9 @@
         }
         mCurrentAnimation = mPendingAnimation.createPlaybackController()
                 .setOnCancelRunnable(this::clearState);
+        // Setting this interpolator doesn't affect the visual motion, but is used to determine
+        // whether we successfully reached the target state in onDragEnd().
+        mCurrentAnimation.getTarget().setInterpolator(currentInterpolator);
         onUserControlledAnimationCreated(mCurrentAnimation);
         mCurrentAnimation.getTarget().addListener(this);
         mCurrentAnimation.dispatchOnStart();
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/AbsSwipeUpHandler.java
index b6d44eb..d2fee30 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -525,6 +525,20 @@
             recentsAttachedToAppWindow = mIsShelfPeeking || mIsLikelyToStartNewTask;
         }
         mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate);
+
+        // Reapply window transform throughout the attach animation, as the animation affects how
+        // much the window is bound by overscroll (vs moving freely).
+        if (animate) {
+            ValueAnimator reapplyWindowTransformAnim = ValueAnimator.ofFloat(0, 1);
+            reapplyWindowTransformAnim.addUpdateListener(anim -> {
+                if (mRunningWindowAnim == null) {
+                    applyWindowTransform();
+                }
+            });
+            reapplyWindowTransformAnim.setDuration(RECENTS_ATTACH_DURATION).start();
+        } else {
+            applyWindowTransform();
+        }
     }
 
     public void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java
index 084692e..d2e1ded 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java
@@ -30,6 +30,7 @@
 import android.animation.Animator;
 import android.animation.AnimatorSet;
 import android.util.Log;
+import android.view.animation.Interpolator;
 
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
@@ -97,19 +98,18 @@
                 numPagesToScroll * PER_PAGE_SCROLL_DURATION);
         int duration = Math.max(scrollDuration, startState.getTransitionDuration(mLauncher));
 
-        StateAnimationConfig config = new StateAnimationConfig();
+        StateAnimationConfig config = new UseFirstInterpolatorStateAnimConfig();
         config.duration = duration;
         config.animFlags = playStaggeredWorkspaceAnim
                 // StaggeredWorkspaceAnim doesn't animate overview, so we handle it here.
                 ? PLAY_ATOMIC_OVERVIEW_PEEK
                 : ANIM_ALL_COMPONENTS;
+        config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, DEACCEL);
+        config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, FINAL_FRAME);
+        config.setInterpolator(ANIM_OVERVIEW_SCALE, FINAL_FRAME);
+        config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, INSTANT);
         AnimatorSet anim = stateManager.createAtomicAnimation(
-                startState, NORMAL, config, overrideConfig -> {
-                    overrideConfig.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, DEACCEL);
-                    overrideConfig.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, FINAL_FRAME);
-                    overrideConfig.setInterpolator(ANIM_OVERVIEW_SCALE, FINAL_FRAME);
-                    overrideConfig.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, INSTANT);
-                });
+                startState, NORMAL, config);
         anim.addListener(new AnimationSuccessListener() {
             @Override
             public void onAnimationSuccess(Animator animator) {
@@ -127,4 +127,17 @@
             mOnReachedHome.run();
         }
     }
+
+    /**
+     * Wrapper around StateAnimationConfig that doesn't allow interpolators to be set if they are
+     * already set. This ensures they aren't overridden before being used.
+     */
+    private static class UseFirstInterpolatorStateAnimConfig extends StateAnimationConfig {
+        @Override
+        public void setInterpolator(int animId, Interpolator interpolator) {
+            if (mInterpolators[animId] == null || interpolator == null) {
+                super.setInterpolator(animId, interpolator);
+            }
+        }
+    }
 }
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java
index ede2b70..1bf2fbf 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java
@@ -33,7 +33,6 @@
 
 import com.android.launcher3.Insettable;
 import com.android.launcher3.R;
-import com.android.launcher3.anim.AlphaUpdateListener;
 import com.android.launcher3.util.MultiValueAlpha;
 import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
 import com.android.quickstep.SysUINavigationMode;
@@ -106,6 +105,7 @@
     public OverviewActionsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr, 0);
         mMultiValueAlpha = new MultiValueAlpha(this, 4);
+        mMultiValueAlpha.setUpdateVisibility(true);
     }
 
     @Override
@@ -143,13 +143,6 @@
     }
 
     @Override
-    public void setAlpha(float alpha) {
-        super.setAlpha(alpha);
-        // Ensure actions don't consume clicks when alpha is 0.
-        AlphaUpdateListener.updateVisibility(this);
-    }
-
-    @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         updateHiddenFlags(HIDDEN_DISABLED_FEATURE, !ENABLE_OVERVIEW_ACTIONS.get());
diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java
index d93c6e6..6ff1254 100644
--- a/src/com/android/launcher3/statemanager/StateManager.java
+++ b/src/com/android/launcher3/statemanager/StateManager.java
@@ -28,9 +28,6 @@
 import android.os.Looper;
 import android.util.Log;
 
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AnimationSuccessListener;
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.anim.PendingAnimation;
@@ -40,7 +37,6 @@
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.function.Consumer;
 
 /**
  * Class to manage transitions between different states for a StatefulActivity based on different
@@ -266,23 +262,9 @@
      */
     public AnimatorSet createAtomicAnimation(
             STATE_TYPE fromState, STATE_TYPE toState, StateAnimationConfig config) {
-        return createAtomicAnimation(fromState, toState, config, null);
-    }
-
-    /**
-     * @see #createAtomicAnimation(BaseState, BaseState, StateAnimationConfig)
-     * @param overrideConfig Optional callback to override some config params that were populated
-     *                       by {{@link #prepareForAtomicAnimation}} before creating the animation.
-     */
-    public AnimatorSet createAtomicAnimation(STATE_TYPE fromState, STATE_TYPE toState,
-            StateAnimationConfig config, @Nullable Consumer<StateAnimationConfig> overrideConfig) {
         PendingAnimation builder = new PendingAnimation(config.duration);
         prepareForAtomicAnimation(fromState, toState, config);
 
-        if (overrideConfig != null) {
-            overrideConfig.accept(config);
-        }
-
         for (StateHandler handler : mActivity.getStateManager().getStateHandlers()) {
             handler.setStateWithAnimation(toState, config, builder);
         }
diff --git a/src/com/android/launcher3/states/StateAnimationConfig.java b/src/com/android/launcher3/states/StateAnimationConfig.java
index 4e8b30c..8b72177 100644
--- a/src/com/android/launcher3/states/StateAnimationConfig.java
+++ b/src/com/android/launcher3/states/StateAnimationConfig.java
@@ -94,7 +94,7 @@
 
     private static final int ANIM_TYPES_COUNT = 16;
 
-    private final Interpolator[] mInterpolators = new Interpolator[ANIM_TYPES_COUNT];
+    protected final Interpolator[] mInterpolators = new Interpolator[ANIM_TYPES_COUNT];
 
     public StateAnimationConfig() { }
 
diff --git a/src/com/android/launcher3/util/MultiValueAlpha.java b/src/com/android/launcher3/util/MultiValueAlpha.java
index a8642b0..5be9529 100644
--- a/src/com/android/launcher3/util/MultiValueAlpha.java
+++ b/src/com/android/launcher3/util/MultiValueAlpha.java
@@ -19,6 +19,8 @@
 import android.util.FloatProperty;
 import android.view.View;
 
+import com.android.launcher3.anim.AlphaUpdateListener;
+
 import java.util.Arrays;
 
 /**
@@ -44,6 +46,8 @@
     private final AlphaProperty[] mMyProperties;
 
     private int mValidMask;
+    // Whether we should change from INVISIBLE to VISIBLE and vice versa at low alpha values.
+    private boolean mUpdateVisibility;
 
     public MultiValueAlpha(View view, int size) {
         mView = view;
@@ -66,6 +70,11 @@
         return mMyProperties[index];
     }
 
+    /** Sets whether we should update between INVISIBLE and VISIBLE based on alpha. */
+    public void setUpdateVisibility(boolean updateVisibility) {
+        mUpdateVisibility = updateVisibility;
+    }
+
     public class AlphaProperty {
 
         private final int mMyMask;
@@ -99,6 +108,9 @@
             mValue = value;
 
             mView.setAlpha(mOthers * mValue);
+            if (mUpdateVisibility) {
+                AlphaUpdateListener.updateVisibility(mView);
+            }
         }
 
         public float getValue() {