Making the dismiss animation feel smoother.

Bug: 27154882
Change-Id: Idbabfe396bc75b598861fd12b78c846f08243a90
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index e838191..9a6fa9c 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -51,11 +51,9 @@
     private float SWIPE_ESCAPE_VELOCITY = 100f; // dp/sec
     private int DEFAULT_ESCAPE_ANIMATION_DURATION = 200; // ms
     private int MAX_ESCAPE_ANIMATION_DURATION = 400; // ms
-    private int MAX_DISMISS_VELOCITY = 2000; // dp/sec
+    private int MAX_DISMISS_VELOCITY = 4000; // dp/sec
     private static final int SNAP_ANIM_LEN = SLOW_ANIMATIONS ? 1000 : 150; // ms
 
-    public static float SWIPE_PROGRESS_FADE_START = 0f; // fraction of thumbnail width
-                                                 // where fade starts
     static final float SWIPE_PROGRESS_FADE_END = 0.5f; // fraction of thumbnail width
                                               // beyond which swipe progress->0
     private float mMinSwipeProgress = 0f;
@@ -102,8 +100,7 @@
         mFalsingThreshold = context.getResources().getDimensionPixelSize(
                 R.dimen.swipe_helper_falsing_threshold);
         mFalsingManager = FalsingManager.getInstance(context);
-        mFlingAnimationUtils = new FlingAnimationUtils(context,
-                MAX_ESCAPE_ANIMATION_DURATION / 1000f /* maxLengthSeconds */);
+        mFlingAnimationUtils = new FlingAnimationUtils(context, getMaxEscapeAnimDuration() / 1000f);
     }
 
     public void setLongPressListener(LongPressListener listener) {
@@ -183,21 +180,23 @@
         mMaxSwipeProgress = maxSwipeProgress;
     }
 
-    private float getSwipeProgressForOffset(View view) {
+    private float getSwipeProgressForOffset(View view, float translation) {
         float viewSize = getSize(view);
-        final float fadeSize = SWIPE_PROGRESS_FADE_END * viewSize;
-        float result = 1.0f;
-        float pos = getTranslation(view);
-        if (pos >= viewSize * SWIPE_PROGRESS_FADE_START) {
-            result = 1.0f - (pos - viewSize * SWIPE_PROGRESS_FADE_START) / fadeSize;
-        } else if (pos < viewSize * (1.0f - SWIPE_PROGRESS_FADE_START)) {
-            result = 1.0f + (viewSize * SWIPE_PROGRESS_FADE_START + pos) / fadeSize;
-        }
+        float result = Math.abs(translation / viewSize);
         return Math.min(Math.max(mMinSwipeProgress, result), mMaxSwipeProgress);
     }
 
+    private float getSwipeAlpha(float progress) {
+        return Math.min(0, Math.max(1, progress / SWIPE_PROGRESS_FADE_END));
+    }
+
     private void updateSwipeProgressFromOffset(View animView, boolean dismissable) {
-        float swipeProgress = getSwipeProgressForOffset(animView);
+        updateSwipeProgressFromOffset(animView, dismissable, getTranslation(animView));
+    }
+
+    private void updateSwipeProgressFromOffset(View animView, boolean dismissable,
+            float translation) {
+        float swipeProgress = getSwipeProgressForOffset(animView, translation);
         if (!mCallback.updateSwipeProgress(animView, dismissable, swipeProgress)) {
             if (FADE_OUT_DURING_SWIPE && dismissable) {
                 float alpha = swipeProgress;
@@ -208,7 +207,7 @@
                         animView.setLayerType(View.LAYER_TYPE_NONE, null);
                     }
                 }
-                animView.setAlpha(getSwipeProgressForOffset(animView));
+                animView.setAlpha(getSwipeAlpha(swipeProgress));
             }
         }
         invalidateGlobalRegion(animView);
@@ -485,7 +484,7 @@
      * view is being animated to dismiss or snap.
      */
     public void onTranslationUpdate(View animView, float value, boolean canBeDismissed) {
-        updateSwipeProgressFromOffset(animView, canBeDismissed);
+        updateSwipeProgressFromOffset(animView, canBeDismissed, value);
     }
 
     private void snapChildInstantly(final View view) {
@@ -600,7 +599,15 @@
     }
 
     protected float getEscapeVelocity() {
-        return SWIPE_ESCAPE_VELOCITY * mDensityScale;
+        return getUnscaledEscapeVelocity() * mDensityScale;
+    }
+
+    protected float getUnscaledEscapeVelocity() {
+        return SWIPE_ESCAPE_VELOCITY;
+    }
+
+    protected long getMaxEscapeAnimDuration() {
+        return MAX_ESCAPE_ANIMATION_DURATION;
     }
 
     protected boolean swipedFarEnough() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 4441ddc..9edf9d6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -60,8 +60,7 @@
 class TaskStackViewTouchHandler implements SwipeHelper.Callback {
 
     private static final int INACTIVE_POINTER_ID = -1;
-    private static final Interpolator STACK_TRANSFORM_INTERPOLATOR =
-            new PathInterpolator(0.73f, 0.33f, 0.42f, 0.85f);
+    private static final float CHALLENGING_SWIPE_ESCAPE_VELOCITY = 800f; // dp/sec
     // The min overscroll is the amount of task progress overscroll we want / the max overscroll
     // curve value below
     private static final float MAX_OVERSCROLL = 0.7f / 0.3f;
@@ -125,7 +124,7 @@
         mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, context) {
             @Override
             protected float getSize(View v) {
-                return mSv.getWidth();
+                return getScaledDismissSize();
             }
 
             @Override
@@ -138,6 +137,16 @@
                 anim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
                 mSwipeHelperAnimations.put(v, anim);
             }
+
+            @Override
+            protected float getUnscaledEscapeVelocity() {
+                return CHALLENGING_SWIPE_ESCAPE_VELOCITY;
+            }
+
+            @Override
+            protected long getMaxEscapeAnimDuration() {
+                return 700;
+            }
         };
         mSwipeHelper.setDisableHardwareLayers(true);
     }
@@ -500,7 +509,7 @@
 
     @Override
     public boolean updateSwipeProgress(View v, boolean dismissable, float swipeProgress) {
-        updateTaskViewTransforms(getDismissFraction(v));
+        updateTaskViewTransforms(Interpolators.FAST_OUT_SLOW_IN.getInterpolation(swipeProgress));
         return true;
     }
 
@@ -616,13 +625,9 @@
     }
 
     /**
-     * Returns the fraction which we should interpolate the other task views based on the dismissal
-     * of this given task.
-     *
-     * TODO: We can interpolate this to adjust when the other tasks should respond to the dismissal
+     * Returns the scaled size used to calculate the dismiss fraction.
      */
-    private float getDismissFraction(View v) {
-        float fraction = Math.min(1f, Math.abs(v.getTranslationX() / mSv.getWidth()));
-        return STACK_TRANSFORM_INTERPOLATOR.getInterpolation(fraction);
+    private float getScaledDismissSize() {
+        return 1.5f * Math.max(mSv.getWidth(), mSv.getHeight());
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 8b52bf6..4986740 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -747,7 +747,7 @@
     public boolean updateSwipeProgress(View animView, boolean dismissable, float swipeProgress) {
         if (!mIsExpanded && isPinnedHeadsUp(animView) && canChildBeDismissed(animView)) {
             mScrimController.setTopHeadsUpDragAmount(animView,
-                    Math.min(Math.abs(swipeProgress - 1.0f), 1.0f));
+                    Math.min(Math.abs(swipeProgress / 2f - 1.0f), 1.0f));
         }
         return true; // Don't fade out the notification
     }