Animating task icon scale when using long swipe

> Separating the task icon animation and setter into 2 separate methods and calling each appropriately
> Using taskId instead of TaskView for ignoreSet as taskView can be reassigned

Bug: 110893730
Change-Id: I7bc958e53becffdf633766373b257ead2eeef2ad
diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
index 8fa6c49..d37ac49 100644
--- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java
+++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
@@ -134,7 +134,7 @@
     /**
      * Must return a non-null controller is supportsLongSwipe was true.
      */
-    LongSwipeHelper getLongSwipeController(T activity, RemoteAnimationTargetSet targetSet);
+    LongSwipeHelper getLongSwipeController(T activity, int runningTaskId);
 
     /**
      * Used for containerType in {@link com.android.launcher3.logging.UserEventDispatcher}
@@ -384,12 +384,11 @@
         }
 
         @Override
-        public LongSwipeHelper getLongSwipeController(Launcher activity,
-                RemoteAnimationTargetSet targetSet) {
+        public LongSwipeHelper getLongSwipeController(Launcher activity, int runningTaskId) {
             if (activity.getDeviceProfile().isVerticalBarLayout()) {
                 return null;
             }
-            return new LongSwipeHelper(activity, targetSet);
+            return new LongSwipeHelper(activity, runningTaskId);
         }
 
         @Override
@@ -571,8 +570,7 @@
         }
 
         @Override
-        public LongSwipeHelper getLongSwipeController(RecentsActivity activity,
-                RemoteAnimationTargetSet targetSet) {
+        public LongSwipeHelper getLongSwipeController(RecentsActivity activity, int runningTaskId) {
             return null;
         }
 
diff --git a/quickstep/src/com/android/quickstep/LongSwipeHelper.java b/quickstep/src/com/android/quickstep/LongSwipeHelper.java
index 6b66ec8..2fe7a11 100644
--- a/quickstep/src/com/android/quickstep/LongSwipeHelper.java
+++ b/quickstep/src/com/android/quickstep/LongSwipeHelper.java
@@ -26,7 +26,6 @@
 import android.view.animation.Interpolator;
 
 import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAnimUtils;
 import com.android.launcher3.LauncherStateManager;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
@@ -41,7 +40,6 @@
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
 import com.android.launcher3.util.FlingBlockCheck;
-import com.android.quickstep.util.RemoteAnimationTargetSet;
 import com.android.quickstep.views.RecentsView;
 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
 
@@ -56,15 +54,15 @@
             Math.min(1 / MIN_PROGRESS_TO_ALL_APPS, 1 / (1 - MIN_PROGRESS_TO_ALL_APPS));
 
     private final Launcher mLauncher;
-    private final RemoteAnimationTargetSet mTargetSet;
+    private final int mRunningTaskId;
 
     private float mMaxSwipeDistance = 1;
     private AnimatorPlaybackController mAnimator;
     private FlingBlockCheck mFlingBlockCheck = new FlingBlockCheck();
 
-    LongSwipeHelper(Launcher launcher, RemoteAnimationTargetSet targetSet) {
+    LongSwipeHelper(Launcher launcher, int runningTaskId) {
         mLauncher = launcher;
-        mTargetSet = targetSet;
+        mRunningTaskId = runningTaskId;
         init();
     }
 
@@ -151,10 +149,16 @@
     }
 
     private void onSwipeAnimationComplete(boolean toAllApps, boolean isFling, Runnable callback) {
+        RecentsView rv = mLauncher.getOverviewPanel();
+        if (!toAllApps) {
+            rv.setIgnoreResetTask(mRunningTaskId);
+        }
+
         mLauncher.getStateManager().goToState(toAllApps ? ALL_APPS : OVERVIEW, false);
         if (!toAllApps) {
             DiscoveryBounce.showForOverviewIfNeeded(mLauncher);
-            mLauncher.<RecentsView>getOverviewPanel().setSwipeDownShouldLaunchApp(true);
+            rv.animateUpRunningTaskIconScale();
+            rv.setSwipeDownShouldLaunchApp(true);
         }
 
         mLauncher.getUserEventDispatcher().logStateChangeAction(
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 7094a53..5d4d2c8 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -285,7 +285,7 @@
             }
             mActivity = activity;
             mRecentsView = mActivity.getOverviewPanel();
-            mRecentsView.setRunningTaskIconScaledDown(true /* isScaledDown */, false /* animate */);
+            mRecentsView.setRunningTaskIconScaledDown(true);
             if (!mUserEventLogged) {
                 activity.getUserEventDispatcher().logActionCommand(Action.Command.RECENTS_BUTTON,
                         mHelper.getContainerType(), ContainerType.TASKSWITCHER);
@@ -308,8 +308,7 @@
                 @Override
                 public void onAnimationSuccess(Animator animator) {
                     if (mRecentsView != null) {
-                        mRecentsView.setRunningTaskIconScaledDown(false /* isScaledDown */,
-                                true /* animate */);
+                        mRecentsView.animateUpRunningTaskIconScale();
                     }
                 }
             });
diff --git a/quickstep/src/com/android/quickstep/TaskSystemShortcut.java b/quickstep/src/com/android/quickstep/TaskSystemShortcut.java
index 5a6312d..d9da002 100644
--- a/quickstep/src/com/android/quickstep/TaskSystemShortcut.java
+++ b/quickstep/src/com/android/quickstep/TaskSystemShortcut.java
@@ -133,7 +133,7 @@
                             public void onLayoutChange(View v, int l, int t, int r, int b,
                                     int oldL, int oldT, int oldR, int oldB) {
                                 taskView.getRootView().removeOnLayoutChangeListener(this);
-                                recentsView.removeIgnoreResetTask(taskView);
+                                recentsView.clearIgnoreResetTask(taskId);
 
                                 // Start animating in the side pages once launcher has been resized
                                 recentsView.dismissTask(taskView, false, false);
@@ -178,7 +178,7 @@
                         // Hide the task view and wait for the window to be resized
                         // TODO: Consider animating in launcher and do an in-place start activity
                         //       afterwards
-                        recentsView.addIgnoreResetTask(taskView);
+                        recentsView.setIgnoreResetTask(taskId);
                         taskView.setAlpha(0f);
                     };
 
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 3662633..793def9 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -436,7 +436,7 @@
 
         mRecentsView.showTask(mRunningTaskId);
         mRecentsView.setRunningTaskHidden(true);
-        mRecentsView.setRunningTaskIconScaledDown(true /* isScaledDown */, false /* animate */);
+        mRecentsView.setRunningTaskIconScaledDown(true);
         mLayoutListener.open();
         mStateCallback.setState(STATE_LAUNCHER_STARTED);
     }
@@ -841,7 +841,7 @@
         mActivityControlHelper.getAlphaProperty(mActivity).setValue(1);
 
         mRecentsView.setRunningTaskHidden(false);
-        mRecentsView.setRunningTaskIconScaledDown(false /* isScaledDown */, false /* animate */);
+        mRecentsView.setRunningTaskIconScaledDown(false);
         mQuickScrubController.cancelActiveQuickscrub();
     }
 
@@ -907,7 +907,7 @@
         mActivityControlHelper.onSwipeUpComplete(mActivity);
 
         // Animate the first icon.
-        mRecentsView.setRunningTaskIconScaledDown(false /* isScaledDown */, true /* animate */);
+        mRecentsView.animateUpRunningTaskIconScale();
         mRecentsView.setSwipeDownShouldLaunchApp(true);
 
         RecentsModel.getInstance(mContext).onOverviewShown(false, TAG);
@@ -939,7 +939,7 @@
         }
         mQuickScrubController.onFinishedTransitionToQuickScrub();
 
-        mRecentsView.setRunningTaskIconScaledDown(false /* isScaledDown */, true /* animate */);
+        mRecentsView.animateUpRunningTaskIconScale();
         RecentsModel.getInstance(mContext).onOverviewShown(false, TAG);
     }
 
@@ -1044,7 +1044,7 @@
         }
 
         mLongSwipeController = mActivityControlHelper.getLongSwipeController(
-                mActivity, mRecentsAnimationWrapper.targetSet);
+                mActivity, mRunningTaskId);
         onLongSwipeDisplacementUpdated();
         setTargetAlphaProvider(mLongSwipeController::getTargetAlpha);
     }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index b763099..2680a26 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -48,7 +48,6 @@
 import android.text.Layout;
 import android.text.StaticLayout;
 import android.text.TextPaint;
-import android.util.ArraySet;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
 import android.util.SparseBooleanArray;
@@ -249,8 +248,8 @@
     @ViewDebug.ExportedProperty(category = "launcher")
     private float mContentAlpha = 1;
 
-    // Keeps track of task views whose visual state should not be reset
-    private ArraySet<TaskView> mIgnoreResetTaskViews = new ArraySet<>();
+    // Keeps track of task id whose visual state should not be reset
+    private int mIgnoreResetTaskId = -1;
 
     // Variables for empty state
     private final Drawable mEmptyIcon;
@@ -457,18 +456,19 @@
         // Unload existing visible task data
         unloadVisibleTaskData();
 
+        TaskView ignoreRestTaskView =
+                mIgnoreResetTaskId == -1 ? null : getTaskView(mIgnoreResetTaskId);
+
         final int requiredTaskCount = tasks.size();
         if (getTaskViewCount() != requiredTaskCount) {
             if (oldChildCount > 0) {
                 removeView(mClearAllButton);
             }
             for (int i = getChildCount(); i < requiredTaskCount; i++) {
-                final TaskView taskView = (TaskView) inflater.inflate(R.layout.task, this, false);
-                addView(taskView, 0);
+                addView(inflater.inflate(R.layout.task, this, false));
             }
             while (getChildCount() > requiredTaskCount) {
-                final TaskView taskView = (TaskView) getChildAt(getChildCount() - 1);
-                removeView(taskView);
+                removeView(getChildAt(getChildCount() - 1));
             }
             if (requiredTaskCount > 0) {
                 addView(mClearAllButton);
@@ -482,6 +482,12 @@
             final TaskView taskView = (TaskView) getChildAt(pageIndex);
             taskView.bind(task);
         }
+        if (mIgnoreResetTaskId != -1 && getTaskView(mIgnoreResetTaskId) != ignoreRestTaskView) {
+            // If the taskView mapping is changing, do not preserve the visuals. Since we are
+            // mostly preserving the first task, and new taskViews are added to the end, it should
+            // generally map to the same task.
+            mIgnoreResetTaskId = -1;
+        }
         resetTaskVisuals();
 
         if (oldChildCount != getChildCount()) {
@@ -501,14 +507,18 @@
     public void resetTaskVisuals() {
         for (int i = getTaskViewCount() - 1; i >= 0; i--) {
             TaskView taskView = (TaskView) getChildAt(i);
-            if (!mIgnoreResetTaskViews.contains(taskView)) {
+            if (mIgnoreResetTaskId != taskView.getTask().key.id) {
                 taskView.resetVisualProperties();
             }
         }
         if (mRunningTaskTileHidden) {
             setRunningTaskHidden(mRunningTaskTileHidden);
         }
-        applyIconScale(false /* animate */);
+
+        // Force apply the scale.
+        if (mIgnoreResetTaskId != mRunningTaskId) {
+            applyRunningTaskIconScale();
+        }
 
         updateCurveProperties();
         // Update the set of visible task's data
@@ -660,6 +670,7 @@
     public void reset() {
         mRunningTaskId = -1;
         mRunningTaskTileHidden = false;
+        mIgnoreResetTaskId = -1;
 
         unloadVisibleTaskData();
         setCurrentPage(0);
@@ -721,10 +732,10 @@
         boolean runningTaskTileHidden = mRunningTaskTileHidden;
         boolean runningTaskIconScaledDown = mRunningTaskIconScaledDown;
 
-        setRunningTaskIconScaledDown(false, false);
+        setRunningTaskIconScaledDown(false);
         setRunningTaskHidden(false);
         mRunningTaskId = runningTaskId;
-        setRunningTaskIconScaledDown(runningTaskIconScaledDown, false);
+        setRunningTaskIconScaledDown(runningTaskIconScaledDown);
         setRunningTaskHidden(runningTaskTileHidden);
 
         setCurrentPage(0);
@@ -754,23 +765,25 @@
         return mQuickScrubController;
     }
 
-    public void setRunningTaskIconScaledDown(boolean isScaledDown, boolean animate) {
-        if (mRunningTaskIconScaledDown == isScaledDown) {
-            return;
+    public void setRunningTaskIconScaledDown(boolean isScaledDown) {
+        if (mRunningTaskIconScaledDown != isScaledDown) {
+            mRunningTaskIconScaledDown = isScaledDown;
+            applyRunningTaskIconScale();
         }
-        mRunningTaskIconScaledDown = isScaledDown;
-        applyIconScale(animate);
     }
 
-    private void applyIconScale(boolean animate) {
-        float scale = mRunningTaskIconScaledDown ? 0 : 1;
+    private void applyRunningTaskIconScale() {
         TaskView firstTask = getTaskView(mRunningTaskId);
         if (firstTask != null) {
-            if (animate) {
-                firstTask.animateIconToScaleAndDim(scale);
-            } else {
-                firstTask.setIconScaleAndDim(scale);
-            }
+            firstTask.setIconScaleAndDim(mRunningTaskIconScaledDown ? 0 : 1);
+        }
+    }
+
+    public void animateUpRunningTaskIconScale() {
+        mRunningTaskIconScaledDown = false;
+        TaskView firstTask = getTaskView(mRunningTaskId);
+        if (firstTask != null) {
+            firstTask.animateIconScaleAndDimIntoView();
         }
     }
 
@@ -836,12 +849,14 @@
         public float scrollFromEdge;
     }
 
-    public void addIgnoreResetTask(TaskView taskView) {
-        mIgnoreResetTaskViews.add(taskView);
+    public void setIgnoreResetTask(int taskId) {
+        mIgnoreResetTaskId = taskId;
     }
 
-    public void removeIgnoreResetTask(TaskView taskView) {
-        mIgnoreResetTaskViews.remove(taskView);
+    public void clearIgnoreResetTask(int taskId) {
+        if (mIgnoreResetTaskId == taskId) {
+            mIgnoreResetTaskId = -1;
+        }
     }
 
     private void addDismissedTaskAnimations(View taskView, AnimatorSet anim, long duration) {
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index fb653cf..7223f97 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -54,19 +54,6 @@
     private static final LightingColorFilter[] sDimFilterCache = new LightingColorFilter[256];
     private static final LightingColorFilter[] sHighlightFilterCache = new LightingColorFilter[256];
 
-    public static final Property<TaskThumbnailView, Float> DIM_ALPHA_MULTIPLIER =
-            new FloatProperty<TaskThumbnailView>("dimAlphaMultiplier") {
-                @Override
-                public void setValue(TaskThumbnailView thumbnail, float dimAlphaMultiplier) {
-                    thumbnail.setDimAlphaMultipler(dimAlphaMultiplier);
-                }
-
-                @Override
-                public Float get(TaskThumbnailView thumbnailView) {
-                    return thumbnailView.mDimAlphaMultiplier;
-                }
-            };
-
     public static final Property<TaskThumbnailView, Float> DIM_ALPHA =
             new FloatProperty<TaskThumbnailView>("dimAlpha") {
                 @Override
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 508e5bb..88c81cf 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -18,7 +18,8 @@
 
 import static android.widget.Toast.LENGTH_SHORT;
 
-import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA_MULTIPLIER;
+import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -43,6 +44,7 @@
 import com.android.launcher3.BaseActivity;
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
 import com.android.quickstep.TaskSystemShortcut;
@@ -94,12 +96,27 @@
                 }
             };
 
+    private static FloatProperty<TaskView> FOCUS_TRANSITION =
+            new FloatProperty<TaskView>("focusTransition") {
+        @Override
+        public void setValue(TaskView taskView, float v) {
+            taskView.setIconAndDimTransitionProgress(v);
+        }
+
+        @Override
+        public Float get(TaskView taskView) {
+            return taskView.mFocusTransitionProgress;
+        }
+    };
+
     private Task mTask;
     private TaskThumbnailView mSnapshotView;
     private IconView mIconView;
     private float mCurveScale;
     private float mZoomScale;
-    private Animator mDimAlphaAnim;
+
+    private Animator mIconAndDimAnimator;
+    private float mFocusTransitionProgress = 1;
 
     public TaskView(Context context) {
         this(context, null);
@@ -201,28 +218,35 @@
         // Do nothing
     }
 
-    public void animateIconToScaleAndDim(float scale) {
-        mIconView.animate().scaleX(scale).scaleY(scale).setDuration(SCALE_ICON_DURATION).start();
-        mDimAlphaAnim = ObjectAnimator.ofFloat(mSnapshotView, DIM_ALPHA_MULTIPLIER, 1 - scale,
-                scale);
-        mDimAlphaAnim.setDuration(DIM_ANIM_DURATION);
-        mDimAlphaAnim.addListener(new AnimatorListenerAdapter() {
+    private void setIconAndDimTransitionProgress(float progress) {
+        mFocusTransitionProgress = progress;
+        mSnapshotView.setDimAlphaMultipler(progress);
+        float scale = FAST_OUT_SLOW_IN.getInterpolation(Utilities.boundToRange(
+                progress * DIM_ANIM_DURATION / SCALE_ICON_DURATION,  0, 1));
+        mIconView.setScaleX(scale);
+        mIconView.setScaleY(scale);
+    }
+
+    public void animateIconScaleAndDimIntoView() {
+        if (mIconAndDimAnimator != null) {
+            mIconAndDimAnimator.cancel();
+        }
+        mIconAndDimAnimator = ObjectAnimator.ofFloat(this, FOCUS_TRANSITION, 1);
+        mIconAndDimAnimator.setDuration(DIM_ANIM_DURATION).setInterpolator(LINEAR);
+        mIconAndDimAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                mDimAlphaAnim = null;
+                mIconAndDimAnimator = null;
             }
         });
-        mDimAlphaAnim.start();
+        mIconAndDimAnimator.start();
     }
 
     protected void setIconScaleAndDim(float iconScale) {
-        mIconView.animate().cancel();
-        mIconView.setScaleX(iconScale);
-        mIconView.setScaleY(iconScale);
-        if (mDimAlphaAnim != null) {
-            mDimAlphaAnim.cancel();
+        if (mIconAndDimAnimator != null) {
+            mIconAndDimAnimator.cancel();
         }
-        mSnapshotView.setDimAlphaMultipler(iconScale);
+        setIconAndDimTransitionProgress(iconScale);
     }
 
     public void resetVisualProperties() {