Merge "Fix jump in animation for hotseat while re-arranging icons" into tm-dev
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index 75cf5cb..bd7e5de 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -22,7 +22,7 @@
 import static com.android.launcher3.LauncherState.HINT_STATE_TWO_BUTTON;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.WorkspaceStateTransitionAnimation.getSpringScaleAnimator;
+import static com.android.launcher3.WorkspaceStateTransitionAnimation.getWorkspaceSpringScaleAnimator;
 import static com.android.launcher3.anim.Interpolators.ACCEL;
 import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
 import static com.android.launcher3.anim.Interpolators.DEACCEL;
@@ -172,7 +172,8 @@
         } else if (fromState == HINT_STATE && toState == NORMAL) {
             config.setInterpolator(ANIM_DEPTH, DEACCEL_3);
             if (mHintToNormalDuration == -1) {
-                ValueAnimator va = getSpringScaleAnimator(mActivity, mActivity.getWorkspace(),
+                ValueAnimator va = getWorkspaceSpringScaleAnimator(mActivity,
+                        mActivity.getWorkspace(),
                         toState.getWorkspaceScaleAndTranslation(mActivity).scale);
                 mHintToNormalDuration = (int) va.getDuration();
             }
diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
index 333df10..3b58046 100644
--- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
+++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
@@ -15,14 +15,14 @@
  */
 package com.android.quickstep.util;
 
+import static com.android.launcher3.LauncherAnimUtils.HOTSEAT_SCALE_PROPERTY_FACTORY;
 import static com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_UNFOLD_ANIMATION;
-import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY_FACTORY;
+import static com.android.launcher3.LauncherAnimUtils.WORKSPACE_SCALE_PROPERTY_FACTORY;
 import static com.android.launcher3.Utilities.comp;
 
 import android.annotation.Nullable;
 import android.util.FloatProperty;
 import android.util.MathUtils;
-import android.view.View;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 
@@ -30,6 +30,7 @@
 
 import com.android.launcher3.Hotseat;
 import com.android.launcher3.Launcher;
+import com.android.launcher3.Workspace;
 import com.android.launcher3.util.HorizontalInsettableView;
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener;
@@ -44,8 +45,10 @@
     // Percentage of the width of the quick search bar that will be reduced
     // from the both sides of the bar when progress is 0
     private static final float MAX_WIDTH_INSET_FRACTION = 0.15f;
-    private static final FloatProperty<View> UNFOLD_SCALE_PROPERTY =
-            SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_UNFOLD_ANIMATION);
+    private static final FloatProperty<Workspace> WORKSPACE_SCALE_PROPERTY =
+            WORKSPACE_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_UNFOLD_ANIMATION);
+    private static final FloatProperty<Hotseat> HOTSEAT_SCALE_PROPERTY =
+            HOTSEAT_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_UNFOLD_ANIMATION);
 
     private final Launcher mLauncher;
 
@@ -147,8 +150,8 @@
         }
 
         private void setScale(float value) {
-            UNFOLD_SCALE_PROPERTY.setValue(mLauncher.getWorkspace(), value);
-            UNFOLD_SCALE_PROPERTY.setValue(mLauncher.getHotseat(), value);
+            WORKSPACE_SCALE_PROPERTY.setValue(mLauncher.getWorkspace(), value);
+            HOTSEAT_SCALE_PROPERTY.setValue(mLauncher.getHotseat(), value);
         }
     }
 }
diff --git a/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java b/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java
index 8659b68..5326d2b 100644
--- a/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java
+++ b/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java
@@ -15,8 +15,9 @@
  */
 package com.android.quickstep.util;
 
+import static com.android.launcher3.LauncherAnimUtils.HOTSEAT_SCALE_PROPERTY_FACTORY;
 import static com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_REVEAL_ANIM;
-import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY_FACTORY;
+import static com.android.launcher3.LauncherAnimUtils.WORKSPACE_SCALE_PROPERTY_FACTORY;
 import static com.android.launcher3.LauncherState.BACKGROUND_APP;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
@@ -32,6 +33,7 @@
 import android.view.View;
 
 import com.android.launcher3.BaseQuickstepLauncher;
+import com.android.launcher3.Hotseat;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
 import com.android.launcher3.Workspace;
@@ -51,8 +53,11 @@
 
     // Should be used for animations running alongside this WorkspaceRevealAnim.
     public static final int DURATION_MS = 350;
-    private static final FloatProperty<View> REVEAL_SCALE_PROPERTY =
-            SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_REVEAL_ANIM);
+    private static final FloatProperty<Workspace> WORKSPACE_SCALE_PROPERTY =
+            WORKSPACE_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_REVEAL_ANIM);
+
+    private static final FloatProperty<Hotseat> HOTSEAT_SCALE_PROPERTY =
+            HOTSEAT_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_REVEAL_ANIM);
 
     private final float mScaleStart;
     private final AnimatorSet mAnimators = new AnimatorSet();
@@ -67,8 +72,8 @@
         workspace.setPivotToScaleWithSelf(launcher.getHotseat());
 
         // Add reveal animations.
-        addRevealAnimatorsForView(workspace);
-        addRevealAnimatorsForView(launcher.getHotseat());
+        addRevealAnimatorsForView(workspace, WORKSPACE_SCALE_PROPERTY);
+        addRevealAnimatorsForView(launcher.getHotseat(), HOTSEAT_SCALE_PROPERTY);
 
         // Add overview scrim animation.
         if (animateOverviewScrim) {
@@ -93,8 +98,8 @@
         mAnimators.setInterpolator(Interpolators.DECELERATED_EASE);
     }
 
-    private void addRevealAnimatorsForView(View v) {
-        ObjectAnimator scale = ObjectAnimator.ofFloat(v, REVEAL_SCALE_PROPERTY, mScaleStart, 1f);
+    private <T extends View>  void addRevealAnimatorsForView(T v, FloatProperty<T> scaleProperty) {
+        ObjectAnimator scale = ObjectAnimator.ofFloat(v, scaleProperty, mScaleStart, 1f);
         scale.setDuration(DURATION_MS);
         scale.setInterpolator(Interpolators.DECELERATED_EASE);
         mAnimators.play(scale);
@@ -107,7 +112,7 @@
         mAnimators.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                REVEAL_SCALE_PROPERTY.set(v, 1f);
+                scaleProperty.set(v, 1f);
                 v.setAlpha(1f);
             }
         });
diff --git a/src/com/android/launcher3/LauncherAnimUtils.java b/src/com/android/launcher3/LauncherAnimUtils.java
index 4300392..c43172c 100644
--- a/src/com/android/launcher3/LauncherAnimUtils.java
+++ b/src/com/android/launcher3/LauncherAnimUtils.java
@@ -67,18 +67,16 @@
             };
 
     /**
-     * Property to set the scale of workspace and hotseat. The value is based on a combination
+     * Property to set the scale of workspace. The value is based on a combination
      * of all the ones set, to have a smooth experience even in the case of overlapping scaling
      * animation.
      */
-    public static final MultiScalePropertyFactory<View> SCALE_PROPERTY_FACTORY =
-            new MultiScalePropertyFactory<View>("scale_property") {
-                @Override
-                protected void apply(View view, float scale) {
-                    view.setScaleX(scale);
-                    view.setScaleY(scale);
-                }
-            };
+    public static final MultiScalePropertyFactory<Workspace> WORKSPACE_SCALE_PROPERTY_FACTORY =
+            new MultiScalePropertyFactory<Workspace>("workspace_scale_property");
+
+    /** Property to set the scale of hotseat. */
+    public static final MultiScalePropertyFactory<Hotseat> HOTSEAT_SCALE_PROPERTY_FACTORY =
+            new MultiScalePropertyFactory<Hotseat>("hotseat_scale_property");
 
     public static final int SCALE_INDEX_UNFOLD_ANIMATION = 1;
     public static final int SCALE_INDEX_UNLOCK_ANIMATION = 2;
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index 98e785f..d94e84c 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -18,11 +18,12 @@
 
 import static androidx.dynamicanimation.animation.DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE;
 
+import static com.android.launcher3.LauncherAnimUtils.HOTSEAT_SCALE_PROPERTY_FACTORY;
 import static com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_WORKSPACE_STATE;
-import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY_FACTORY;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
+import static com.android.launcher3.LauncherAnimUtils.WORKSPACE_SCALE_PROPERTY_FACTORY;
 import static com.android.launcher3.LauncherState.FLAG_HAS_SYS_UI_SCRIM;
 import static com.android.launcher3.LauncherState.HINT_STATE;
 import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
@@ -64,8 +65,11 @@
  */
 public class WorkspaceStateTransitionAnimation {
 
-    private static final FloatProperty<View> WORKSPACE_STATE_SCALE_PROPERTY =
-            SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_WORKSPACE_STATE);
+    private static final FloatProperty<Workspace> WORKSPACE_SCALE_PROPERTY =
+            WORKSPACE_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_WORKSPACE_STATE);
+
+    private static final FloatProperty<Hotseat> HOTSEAT_SCALE_PROPERTY =
+            HOTSEAT_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_WORKSPACE_STATE);
 
     private final Launcher mLauncher;
     private final Workspace mWorkspace;
@@ -120,9 +124,9 @@
                 && fromState == HINT_STATE && state == NORMAL;
         if (shouldSpring) {
             ((PendingAnimation) propertySetter).add(getSpringScaleAnimator(mLauncher,
-                    mWorkspace, mNewScale));
+                    mWorkspace, mNewScale, WORKSPACE_SCALE_PROPERTY));
         } else {
-            propertySetter.setFloat(mWorkspace, WORKSPACE_STATE_SCALE_PROPERTY, mNewScale,
+            propertySetter.setFloat(mWorkspace, WORKSPACE_SCALE_PROPERTY, mNewScale,
                     scaleInterpolator);
         }
 
@@ -130,11 +134,12 @@
         float hotseatScale = hotseatScaleAndTranslation.scale;
         if (shouldSpring) {
             PendingAnimation pa = (PendingAnimation) propertySetter;
-            pa.add(getSpringScaleAnimator(mLauncher, hotseat, hotseatScale));
+            pa.add(getSpringScaleAnimator(mLauncher, hotseat, hotseatScale,
+                    HOTSEAT_SCALE_PROPERTY));
         } else {
             Interpolator hotseatScaleInterpolator = config.getInterpolator(ANIM_HOTSEAT_SCALE,
                     scaleInterpolator);
-            propertySetter.setFloat(hotseat, WORKSPACE_STATE_SCALE_PROPERTY, hotseatScale,
+            propertySetter.setFloat(hotseat, HOTSEAT_SCALE_PROPERTY, hotseatScale,
                     hotseatScaleInterpolator);
         }
 
@@ -198,9 +203,18 @@
     }
 
     /**
+     * Returns a spring based animator for the scale property of {@param workspace}.
+     */
+    public static ValueAnimator getWorkspaceSpringScaleAnimator(Launcher launcher,
+            Workspace workspace, float scale) {
+        return getSpringScaleAnimator(launcher, workspace, scale, WORKSPACE_SCALE_PROPERTY);
+    }
+
+    /**
      * Returns a spring based animator for the scale property of {@param v}.
      */
-    public static ValueAnimator getSpringScaleAnimator(Launcher launcher, View v, float scale) {
+    public static <T extends View> ValueAnimator getSpringScaleAnimator(Launcher launcher, T v,
+            float scale, FloatProperty<T> property) {
         ResourceProvider rp = DynamicResource.provider(launcher);
         float damping = rp.getFloat(R.dimen.hint_scale_damping_ratio);
         float stiffness = rp.getFloat(R.dimen.hint_scale_stiffness);
@@ -211,9 +225,9 @@
                 .setDampingRatio(damping)
                 .setMinimumVisibleChange(MIN_VISIBLE_CHANGE_SCALE)
                 .setEndValue(scale)
-                .setStartValue(WORKSPACE_STATE_SCALE_PROPERTY.get(v))
+                .setStartValue(property.get(v))
                 .setStartVelocity(velocityPxPerS)
-                .build(v, WORKSPACE_STATE_SCALE_PROPERTY);
+                .build(v, property);
 
     }
 }
\ No newline at end of file
diff --git a/src/com/android/launcher3/util/MultiScalePropertyFactory.java b/src/com/android/launcher3/util/MultiScalePropertyFactory.java
index f27d0f0..a7e6cc8 100644
--- a/src/com/android/launcher3/util/MultiScalePropertyFactory.java
+++ b/src/com/android/launcher3/util/MultiScalePropertyFactory.java
@@ -18,6 +18,8 @@
 
 import android.util.ArrayMap;
 import android.util.FloatProperty;
+import android.util.Log;
+import android.view.View;
 
 import com.android.launcher3.Utilities;
 
@@ -33,8 +35,10 @@
  *
  * @param <T> Type where to apply the property.
  */
-public abstract class MultiScalePropertyFactory<T> {
+public class MultiScalePropertyFactory<T extends View> {
 
+    private static final boolean DEBUG = false;
+    private static final String TAG = "MultiScaleProperty";
     private final String mName;
     private final ArrayMap<Integer, MultiScaleProperty> mProperties =
             new ArrayMap<Integer, MultiScaleProperty>();
@@ -56,7 +60,6 @@
                 (k) -> new MultiScaleProperty(index, mName + "_" + index));
     }
 
-
     /**
      * Each [setValue] will be aggregated with the other properties values created by the
      * corresponding factory.
@@ -91,11 +94,22 @@
             mLastAggregatedValue = Utilities.boundToRange(multValue, minValue, maxValue);
             mValue = newValue;
             apply(obj, mLastAggregatedValue);
+
+            if (DEBUG) {
+                Log.d(TAG, "name=" + mName
+                        + " newValue=" + newValue + " mInx=" + mInx
+                        + " aggregated=" + mLastAggregatedValue + " others= " + mProperties);
+            }
         }
 
         @Override
-        public Float get(T t) {
-            return mLastAggregatedValue;
+        public Float get(T view) {
+            // The scale of the view should match mLastAggregatedValue. Still, if it has been
+            // changed without using this property, it can differ. As this get method is usually
+            // used to set the starting point on an animation, this would result in some jumps
+            // when the view scale is different than the last aggregated value. To stay on the
+            // safe side, let's return the real view scale.
+            return view.getScaleX();
         }
 
         @Override
@@ -104,6 +118,8 @@
         }
     }
 
-    /** Applies value to object after setValue method is called. */
-    protected abstract void apply(T obj, float value);
+    protected void apply(View view, float value) {
+        view.setScaleX(value);
+        view.setScaleY(value);
+    }
 }
diff --git a/tests/src/com/android/launcher3/util/MultiScalePropertyTest.kt b/tests/src/com/android/launcher3/util/MultiScalePropertyTest.kt
index c4a8db6..6099987 100644
--- a/tests/src/com/android/launcher3/util/MultiScalePropertyTest.kt
+++ b/tests/src/com/android/launcher3/util/MultiScalePropertyTest.kt
@@ -1,5 +1,6 @@
 package com.android.launcher3.util
 
+import android.view.View
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.google.common.truth.Truth.assertThat
@@ -14,8 +15,8 @@
     private val received = mutableListOf<Float>()
 
     private val factory =
-        object : MultiScalePropertyFactory<Int?>("Test") {
-            override fun apply(obj: Int?, value: Float) {
+        object : MultiScalePropertyFactory<View?>("Test") {
+            override fun apply(obj: View?, value: Float) {
                 received.add(value)
             }
         }