Merge "Fixing disabled filter is not applied to the foregound layer when dragging an icon" into ub-launcher3-edmonton
diff --git a/quickstep/src/com/android/quickstep/OverviewInteractionState.java b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
index 9416a29..ad4af62 100644
--- a/quickstep/src/com/android/quickstep/OverviewInteractionState.java
+++ b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
@@ -203,7 +203,12 @@
     }
 
     private boolean shouldIgnoreSwipeUpEnabledSettings() {
-        String sdkInt = getSystemProperty("ro.product.first_api_level", "0");
+        int deviceApiLevel = Build.VERSION.SDK_INT;
+
+        // Note: on factory ROM devices, this first_api_level property is intentionally not set.
+        // deviceApiLevel is used in these case.
+        String sdkInt = getSystemProperty("ro.product.first_api_level",
+                Integer.toString(deviceApiLevel));
         try {
             return Integer.parseInt(sdkInt) >= Build.VERSION_CODES.P;
         } catch (Exception e) {
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewDrawable.java b/quickstep/src/com/android/quickstep/util/TaskViewDrawable.java
index 34f580b..48b07a7 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewDrawable.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewDrawable.java
@@ -15,7 +15,9 @@
  */
 package com.android.quickstep.util;
 
-import android.animation.TimeInterpolator;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
 import android.graphics.PixelFormat;
@@ -30,7 +32,7 @@
 
 public class TaskViewDrawable extends Drawable {
 
-    public static FloatProperty<TaskViewDrawable> PROGRESS =
+    public static final FloatProperty<TaskViewDrawable> PROGRESS =
             new FloatProperty<TaskViewDrawable>("progress") {
                 @Override
                 public void setValue(TaskViewDrawable taskViewDrawable, float v) {
@@ -43,8 +45,10 @@
                 }
             };
 
-    private static final TimeInterpolator ICON_SIZE_INTERPOLATOR =
-            (t) -> (Math.max(t, 0.3f) - 0.3f) / 0.7f;
+    /**
+     * The progress at which we play the atomic icon scale animation.
+     */
+    private static final float ICON_SCALE_THRESHOLD = 0.95f;
 
     private final RecentsView mParent;
     private final View mIconView;
@@ -55,11 +59,15 @@
     private final ClipAnimationHelper mClipAnimationHelper;
 
     private float mProgress = 1;
+    private boolean mPassedIconScaleThreshold;
+    private ValueAnimator mIconScaleAnimator;
+    private float mIconScale;
 
     public TaskViewDrawable(TaskView tv, RecentsView parent) {
         mParent = parent;
         mIconView = tv.getIconView();
         mIconPos = new int[2];
+        mIconScale = mIconView.getScaleX();
         Utilities.getDescendantCoordRelativeToAncestor(mIconView, parent, mIconPos, true);
 
         mThumbnailView = tv.getThumbnail();
@@ -70,6 +78,37 @@
     public void setProgress(float progress) {
         mProgress = progress;
         mParent.invalidate();
+        boolean passedIconScaleThreshold = progress <= ICON_SCALE_THRESHOLD;
+        if (mPassedIconScaleThreshold != passedIconScaleThreshold) {
+            mPassedIconScaleThreshold = passedIconScaleThreshold;
+            animateIconScale(mPassedIconScaleThreshold ? 0 : 1);
+        }
+    }
+
+    private void animateIconScale(float toScale) {
+        if (mIconScaleAnimator != null) {
+            mIconScaleAnimator.cancel();
+        }
+        mIconScaleAnimator = ValueAnimator.ofFloat(mIconScale, toScale);
+        mIconScaleAnimator.addUpdateListener(valueAnimator -> {
+            mIconScale = (float) valueAnimator.getAnimatedValue();
+            if (mProgress > ICON_SCALE_THRESHOLD) {
+                // Speed up the icon scale to ensure it is 1 when progress is 1.
+                float iconProgress = (mProgress - ICON_SCALE_THRESHOLD) / (1 - ICON_SCALE_THRESHOLD);
+                if (iconProgress > mIconScale) {
+                    mIconScale = iconProgress;
+                }
+            }
+            invalidateSelf();
+        });
+        mIconScaleAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mIconScaleAnimator = null;
+            }
+        });
+        mIconScaleAnimator.setDuration(TaskView.SCALE_ICON_DURATION);
+        mIconScaleAnimator.start();
     }
 
     @Override
@@ -81,8 +120,7 @@
 
         canvas.save();
         canvas.translate(mIconPos[0], mIconPos[1]);
-        float scale = ICON_SIZE_INTERPOLATOR.getInterpolation(mProgress);
-        canvas.scale(scale, scale, mIconView.getWidth() / 2, mIconView.getHeight() / 2);
+        canvas.scale(mIconScale, mIconScale, mIconView.getWidth() / 2, mIconView.getHeight() / 2);
         mIconView.draw(canvas);
         canvas.restore();
     }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 8c3e1a2..2b70219 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -22,6 +22,7 @@
 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.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
@@ -960,15 +961,13 @@
         if (currTask == null) {
             return;
         }
-        currTask.setScaleX(mAdjacentScale);
-        currTask.setScaleY(mAdjacentScale);
+        currTask.setZoomScale(mAdjacentScale);
 
         if (mCurrentPage - 1 >= 0) {
             TaskView adjacentTask = getPageAt(mCurrentPage - 1);
             float[] scaleAndTranslation = getAdjacentScaleAndTranslation(currTask, adjacentTask,
                     mAdjacentScale, 0);
-            adjacentTask.setScaleX(scaleAndTranslation[0]);
-            adjacentTask.setScaleY(scaleAndTranslation[0]);
+            adjacentTask.setZoomScale(scaleAndTranslation[0]);
             adjacentTask.setTranslationX(-scaleAndTranslation[1]);
             adjacentTask.setTranslationY(scaleAndTranslation[2]);
         }
@@ -976,8 +975,7 @@
             TaskView adjacentTask = getPageAt(mCurrentPage + 1);
             float[] scaleAndTranslation = getAdjacentScaleAndTranslation(currTask, adjacentTask,
                     mAdjacentScale, 0);
-            adjacentTask.setScaleX(scaleAndTranslation[0]);
-            adjacentTask.setScaleY(scaleAndTranslation[0]);
+            adjacentTask.setZoomScale(scaleAndTranslation[0]);
             adjacentTask.setTranslationX(scaleAndTranslation[1]);
             adjacentTask.setTranslationY(scaleAndTranslation[2]);
         }
@@ -986,7 +984,7 @@
     private float[] getAdjacentScaleAndTranslation(TaskView currTask, TaskView adjacentTask,
             float currTaskToScale, float currTaskToTranslationY) {
         float displacement = currTask.getWidth() * (currTaskToScale - currTask.getCurveScale());
-        sTempFloatArray[0] = currTaskToScale * adjacentTask.getCurveScale();
+        sTempFloatArray[0] = currTaskToScale;
         sTempFloatArray[1] = mIsRtl ? -displacement : displacement;
         sTempFloatArray[2] = currTaskToTranslationY;
         return sTempFloatArray;
@@ -1127,13 +1125,15 @@
         return anim;
     }
 
-    private ObjectAnimator createAnimForChild(View child, float[] toScaleAndTranslation) {
-        return ObjectAnimator.ofPropertyValuesHolder(child,
+    private Animator createAnimForChild(TaskView child, float[] toScaleAndTranslation) {
+        AnimatorSet anim = new AnimatorSet();
+        anim.play(ObjectAnimator.ofFloat(child, TaskView.ZOOM_SCALE, toScaleAndTranslation[0]));
+        anim.play(ObjectAnimator.ofPropertyValuesHolder(child,
                         new PropertyListBuilder()
-                                .scale(child.getScaleX() * toScaleAndTranslation[0])
                                 .translationX(toScaleAndTranslation[1])
                                 .translationY(toScaleAndTranslation[2])
-                                .build());
+                                .build()));
+        return anim;
     }
 
     public PendingAnimation createTaskLauncherAnimation(TaskView tv, long duration) {
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index b8b9196..4f447b1 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -30,14 +30,15 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.util.AttributeSet;
+import android.util.FloatProperty;
 import android.util.Log;
+import android.util.Property;
 import android.view.View;
 import android.view.ViewOutlineProvider;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.FrameLayout;
-import android.widget.ImageView;
-
 import android.widget.Toast;
+
 import com.android.launcher3.BaseActivity;
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.R;
@@ -76,12 +77,26 @@
      */
     private static final float EDGE_SCALE_DOWN_FACTOR = 0.03f;
 
-    private static final long SCALE_ICON_DURATION = 120;
+    public static final long SCALE_ICON_DURATION = 120;
+
+    public static final Property<TaskView, Float> ZOOM_SCALE =
+            new FloatProperty<TaskView>("zoomScale") {
+                @Override
+                public void setValue(TaskView taskView, float v) {
+                    taskView.setZoomScale(v);
+                }
+
+                @Override
+                public Float get(TaskView taskView) {
+                    return taskView.mZoomScale;
+                }
+            };
 
     private Task mTask;
     private TaskThumbnailView mSnapshotView;
     private IconView mIconView;
     private float mCurveScale;
+    private float mZoomScale;
     private float mCurveDimAlpha;
     private Animator mDimAlphaAnim;
 
@@ -207,8 +222,7 @@
     }
 
     public void resetVisualProperties() {
-        setScaleX(1f);
-        setScaleY(1f);
+        setZoomScale(1);
         setTranslationX(0f);
         setTranslationY(0f);
         setTranslationZ(0);
@@ -226,9 +240,7 @@
             mSnapshotView.setDimAlpha(mCurveDimAlpha);
         }
 
-        mCurveScale = getCurveScaleForCurveInterpolation(curveInterpolation);
-        setScaleX(mCurveScale);
-        setScaleY(mCurveScale);
+        setCurveScale(getCurveScaleForCurveInterpolation(curveInterpolation));
     }
 
     @Override
@@ -247,10 +259,26 @@
         return 1 - curveInterpolation * EDGE_SCALE_DOWN_FACTOR;
     }
 
+    private void setCurveScale(float curveScale) {
+        mCurveScale = curveScale;
+        onScaleChanged();
+    }
+
     public float getCurveScale() {
         return mCurveScale;
     }
 
+    public void setZoomScale(float adjacentScale) {
+        mZoomScale = adjacentScale;
+        onScaleChanged();
+    }
+
+    private void onScaleChanged() {
+        float scale = mCurveScale * mZoomScale;
+        setScaleX(scale);
+        setScaleY(scale);
+    }
+
     @Override
     public boolean hasOverlappingRendering() {
         // TODO: Clip-out the icon region from the thumbnail, since they are overlapping.
diff --git a/res/animator-v23/discovery_bounce.xml b/res/animator-v23/discovery_bounce.xml
index 8d0e8fd..f554853 100644
--- a/res/animator-v23/discovery_bounce.xml
+++ b/res/animator-v23/discovery_bounce.xml
@@ -26,14 +26,14 @@
             android:fraction="0"
             android:value="1f" />
         <keyframe
-            android:fraction="0.346"
+            android:fraction="0.246"
             android:value="1f" />
         <keyframe
             android:fraction=".423"
             android:interpolator="@interpolator/disco_bounce"
-            android:value="0.9438f" />
+            android:value="0.9738f" />
         <keyframe
-            android:fraction="0.654"
+            android:fraction="0.754"
             android:interpolator="@interpolator/disco_bounce"
             android:value="1f" />
         <keyframe
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5dc7844..65fffd3 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -310,7 +310,7 @@
 
     <!-- Accessibility action to show quick actions menu for an icon. [CHAR_LIMIT=30] -->
     <string name="action_deep_shortcut">Shortcuts</string>
-    <!-- Accessibility description when the shortcuts menu has notifications as well as shortcuts. [CHAR_LIMIT=50] -->
+    <!-- Accessibility description when the context menu of a launcher icon that has notifications as well as shortcuts (providing quick access to app's actions). The "shortcuts" translation should be consistent with the one for action_deep_shortcut. [CHAR_LIMIT=50] -->
     <string name="shortcuts_menu_with_notifications_description">Shortcuts and notifications
     </string>
 
diff --git a/src/com/android/launcher3/allapps/DiscoveryBounce.java b/src/com/android/launcher3/allapps/DiscoveryBounce.java
index 8f1c8df..e8c5f15 100644
--- a/src/com/android/launcher3/allapps/DiscoveryBounce.java
+++ b/src/com/android/launcher3/allapps/DiscoveryBounce.java
@@ -156,14 +156,14 @@
         float verticalProgress = OVERVIEW.getVerticalProgress(launcher);
 
         TimeInterpolator pathInterpolator = new PathInterpolator(0.35f, 0, 0.5f, 1);
-        Keyframe keyframe3 = Keyframe.ofFloat(0.423f, verticalProgress - (1 - 0.9438f));
+        Keyframe keyframe3 = Keyframe.ofFloat(0.423f, verticalProgress - (1 - 0.9738f));
         keyframe3.setInterpolator(pathInterpolator);
-        Keyframe keyframe4 = Keyframe.ofFloat(0.654f, verticalProgress);
+        Keyframe keyframe4 = Keyframe.ofFloat(0.754f, verticalProgress);
         keyframe4.setInterpolator(pathInterpolator);
 
         PropertyValuesHolder propertyValuesHolder = PropertyValuesHolder.ofKeyframe("progress",
                 Keyframe.ofFloat(0, verticalProgress),
-                Keyframe.ofFloat(0.346f, verticalProgress), keyframe3, keyframe4,
+                Keyframe.ofFloat(0.246f, verticalProgress), keyframe3, keyframe4,
                 Keyframe.ofFloat(1f, verticalProgress));
         ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(null,
                 new PropertyValuesHolder[]{propertyValuesHolder});