Fixed a bug where the header was positioned wrong

Also cleaned up some logic about the translation

Change-Id: I6bfcb36ac27d8d6280e8ffea62b597d3bc705121
Fixes: 29880654
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 4b82279..64f205d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -58,6 +58,7 @@
 import com.android.systemui.statusbar.KeyguardAffordanceView;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
@@ -78,7 +79,6 @@
     private static final int CAP_HEIGHT = 1456;
     private static final int FONT_HEIGHT = 2163;
 
-    private static final float HEADER_RUBBERBAND_FACTOR = 2.05f;
     private static final float LOCK_ICON_ACTIVE_SCALE = 1.2f;
 
     private static final String COUNTER_PANEL_OPEN = "panel_open";
@@ -1376,8 +1376,7 @@
         int min = mStatusBarMinHeight;
         if (mStatusBar.getBarState() != StatusBarState.KEYGUARD
                 && mNotificationStackScroller.getNotGoneChildCount() == 0) {
-            int minHeight = (int) ((mQsMinExpansionHeight + getOverExpansionAmount())
-                    * HEADER_RUBBERBAND_FACTOR);
+            int minHeight = (int) (mQsMinExpansionHeight + getOverExpansionAmount());
             min = Math.max(min, minHeight);
         }
         int maxHeight;
@@ -1552,15 +1551,8 @@
         if (mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
             return 0;
         }
-        if (mNotificationStackScroller.getNotGoneChildCount() == 0) {
-            return Math.min(0, mExpandedHeight / HEADER_RUBBERBAND_FACTOR - mQsMinExpansionHeight);
-        }
-        float stackTranslation = mNotificationStackScroller.getStackTranslation();
-        float translation = stackTranslation / HEADER_RUBBERBAND_FACTOR;
-        if (mHeadsUpManager.hasPinnedHeadsUp() || mIsExpansionFromHeadsUp) {
-            translation = mNotificationStackScroller.getTopPadding() + stackTranslation
-                    - mQsMinExpansionHeight;
-        }
+        float translation = NotificationUtils.interpolate(-mQsMinExpansionHeight, 0,
+                mNotificationStackScroller.getAppearFraction(mExpandedHeight));
         return Math.min(0, translation);
     }
 
@@ -1968,7 +1960,7 @@
         if (mNotificationStackScroller.getNotGoneChildCount() > 0) {
             return mNotificationStackScroller.getPeekHeight();
         } else {
-            return mQsMinExpansionHeight * HEADER_RUBBERBAND_FACTOR;
+            return mQsMinExpansionHeight;
         }
     }
 
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 e00674a..0165602 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -668,30 +668,74 @@
     public void setStackHeight(float height) {
         mLastSetStackHeight = height;
         setIsExpanded(height > 0.0f);
-        int newStackHeight = (int) height;
-        int minStackHeight = getLayoutMinHeight();
         int stackHeight;
-        float paddingOffset;
-        boolean trackingHeadsUp = mTrackingHeadsUp || mHeadsUpManager.hasPinnedHeadsUp();
-        int normalUnfoldPositionStart = trackingHeadsUp
-                ? mHeadsUpManager.getTopHeadsUpPinnedHeight()
-                : minStackHeight;
-        if (newStackHeight - mTopPadding - mTopPaddingOverflow >= normalUnfoldPositionStart
-                || getNotGoneChildCount() == 0) {
-            paddingOffset = mTopPaddingOverflow;
-            stackHeight = newStackHeight;
+        float translationY;
+        float appearEndPosition = getAppearEndPosition();
+        float appearStartPosition = getAppearStartPosition();
+        if (height >= appearEndPosition) {
+            translationY = mTopPaddingOverflow;
+            stackHeight = (int) height;
         } else {
-            int translationY;
-            translationY = newStackHeight - normalUnfoldPositionStart;
-            paddingOffset = translationY - mTopPadding;
-            stackHeight = (int) (height - (translationY - mTopPadding));
+            float appearFraction = getAppearFraction(height);
+            if (appearFraction >= 0) {
+                translationY = NotificationUtils.interpolate(getExpandTranslationStart(), 0,
+                        appearFraction);
+            } else {
+                // This may happen when pushing up a heads up. We linearly push it up from the
+                // start
+                translationY = height - appearStartPosition + getExpandTranslationStart();
+            }
+            stackHeight = (int) (height - translationY);
         }
         if (stackHeight != mCurrentStackHeight) {
             mCurrentStackHeight = stackHeight;
             updateAlgorithmHeightAndPadding();
             requestChildrenUpdate();
         }
-        setStackTranslation(paddingOffset);
+        setStackTranslation(translationY);
+    }
+
+    /**
+     * @return The translation at the beginning when expanding.
+     *         Measured relative to the resting position.
+     */
+    private float getExpandTranslationStart() {
+        int startPosition = mTrackingHeadsUp || mHeadsUpManager.hasPinnedHeadsUp()
+                ? 0 : -getFirstChildMinHeight();
+        return startPosition - mTopPadding;
+    }
+
+    /**
+     * @return the position from where the appear transition starts when expanding.
+     *         Measured in absolute height.
+     */
+    private float getAppearStartPosition() {
+        return mTrackingHeadsUp
+                ? mHeadsUpManager.getTopHeadsUpPinnedHeight()
+                : 0;
+    }
+
+    /**
+     * @return the position from where the appear transition ends when expanding.
+     *         Measured in absolute height.
+     */
+    private float getAppearEndPosition() {
+        int firstItemHeight = mTrackingHeadsUp || mHeadsUpManager.hasPinnedHeadsUp()
+                ? mHeadsUpManager.getTopHeadsUpPinnedHeight() + mBottomStackPeekSize
+                        + mBottomStackSlowDownHeight
+                : getLayoutMinHeight();
+        return firstItemHeight + mTopPadding + mTopPaddingOverflow;
+    }
+
+    /**
+     * @param height the height of the panel
+     * @return the fraction of the appear animation that has been performed
+     */
+    public float getAppearFraction(float height) {
+        float appearEndPosition = getAppearEndPosition();
+        float appearStartPosition = getAppearStartPosition();
+        return (height - appearStartPosition)
+                / (appearEndPosition - appearStartPosition);
     }
 
     public float getStackTranslation() {
@@ -2096,6 +2140,12 @@
     }
 
     public int getLayoutMinHeight() {
+        int firstChildMinHeight = getFirstChildMinHeight();
+        return Math.min(firstChildMinHeight + mBottomStackPeekSize + mBottomStackSlowDownHeight,
+                mMaxLayoutHeight - mTopPadding);
+    }
+
+    private int getFirstChildMinHeight() {
         final ExpandableView firstChild = getFirstChildNotGone();
         int firstChildMinHeight = firstChild != null
                 ? firstChild.getIntrinsicHeight()
@@ -2105,8 +2155,7 @@
         if (mOwnScrollY > 0) {
             firstChildMinHeight = Math.max(firstChildMinHeight - mOwnScrollY, mCollapsedSize);
         }
-        return Math.min(firstChildMinHeight + mBottomStackPeekSize + mBottomStackSlowDownHeight,
-                mMaxLayoutHeight - mTopPadding);
+        return firstChildMinHeight;
     }
 
     public float getTopPaddingOverflow() {