Handle go to full shade motion for redacted case

Bug: 16291973
Change-Id: Idc5ea93548e17ef9cd2d7c36416b293950554703
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index e9989ab..df475d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -127,9 +127,7 @@
                 return true;
             case MotionEvent.ACTION_UP:
                 if (mDraggedFarEnough && mDragDownCallback.onDraggedDown(mStartingChild)) {
-                    if (mStartingChild != null) {
-                        mCallback.setUserLockedChild(mStartingChild, false);
-                    } else {
+                    if (mStartingChild == null) {
                         mDragDownCallback.setEmptyDragAmount(0f);
                     }
                     mDraggingDown = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index e6ffde0..8996197 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -47,7 +47,6 @@
     private StatusBarWindowManager mWindowManager;
     private KeyguardViewBase mKeyguardView;
     private ViewGroup mRoot;
-    private Interpolator mFadeOutInterpolator = new LinearInterpolator();
     private boolean mFadingOut;
 
     public KeyguardBouncer(Context context, ViewMediatorCallback callback,
@@ -101,7 +100,7 @@
 
                     // Make it disappear faster, as the focus should be on the activity behind.
                     .setDuration(duration / 2)
-                    .setInterpolator(mFadeOutInterpolator)
+                    .setInterpolator(PhoneStatusBar.ALPHA_OUT)
                     .setStartDelay(delay)
                     .withEndAction(new Runnable() {
                         @Override
@@ -109,7 +108,8 @@
                             mFadingOut = false;
                             hide(true /* destroyView */);
                         }
-                    });
+                    })
+                    .start();
         } else {
             hide(true /* destroyView */);
         }
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 4f9d4a3..c9c7703 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -19,6 +19,7 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -115,6 +116,7 @@
 
     private Interpolator mFastOutSlowInInterpolator;
     private Interpolator mFastOutLinearInterpolator;
+    private Interpolator mLinearOutSlowInInterpolator;
     private ObjectAnimator mClockAnimator;
     private int mClockAnimationTarget = -1;
     private int mTopPaddingAdjustment;
@@ -140,6 +142,8 @@
     private Runnable mLaunchAnimationEndRunnable;
     private boolean mOnlyAffordanceInThisMotion;
     private boolean mKeyguardStatusViewAnimating;
+    private boolean mHeaderAnimatingIn;
+    private ObjectAnimator mQsContainerAnimator;
 
     public NotificationPanelView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -172,6 +176,8 @@
                 android.R.interpolator.fast_out_slow_in);
         mFastOutLinearInterpolator = AnimationUtils.loadInterpolator(getContext(),
                 android.R.interpolator.fast_out_linear_in);
+        mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(),
+                android.R.interpolator.linear_out_slow_in);
         mKeyguardBottomArea = (KeyguardBottomAreaView) findViewById(R.id.keyguard_bottom_area);
         mAfforanceHelper = new KeyguardAffordanceHelper(this, getContext());
     }
@@ -292,9 +298,9 @@
         mKeyguardStatusView.setScaleY(scale);
     }
 
-    public void animateToFullShade() {
+    public void animateToFullShade(long delay) {
         mAnimateNextTopPaddingChange = true;
-        mNotificationStackScroller.goToFullShade();
+        mNotificationStackScroller.goToFullShade(delay);
         requestLayout();
     }
 
@@ -673,19 +679,28 @@
         }
     }
 
-    public void setBarState(int statusBarState, boolean keyguardFadingAway) {
+    public void setBarState(int statusBarState, boolean keyguardFadingAway,
+            boolean goingToFullShade) {
         boolean keyguardShowing = statusBarState == StatusBarState.KEYGUARD
                 || statusBarState == StatusBarState.SHADE_LOCKED;
-        mKeyguardStatusBar.setAlpha(1f);
-        mKeyguardStatusBar.setVisibility(keyguardShowing ? View.VISIBLE : View.INVISIBLE);
         if (!mKeyguardShowing && keyguardShowing) {
             setQsTranslation(mQsExpansionHeight);
             mHeader.setTranslationY(0f);
         }
-        setKeyguardStatusViewVisibility(statusBarState, keyguardFadingAway);
+        setKeyguardStatusViewVisibility(statusBarState, keyguardFadingAway, goingToFullShade);
+        setKeyguardBottomAreaVisibility(statusBarState, goingToFullShade);
+        if (goingToFullShade) {
+            animateKeyguardStatusBarOut();
+        } else {
+            mKeyguardStatusBar.setAlpha(1f);
+            mKeyguardStatusBar.setVisibility(keyguardShowing ? View.VISIBLE : View.INVISIBLE);
+        }
         mStatusBarState = statusBarState;
         mKeyguardShowing = keyguardShowing;
         updateQsState();
+        if (goingToFullShade) {
+            animateHeaderSlidingIn();
+        }
     }
 
     private final Runnable mAnimateKeyguardStatusViewInvisibleEndRunnable = new Runnable() {
@@ -703,16 +718,131 @@
         }
     };
 
-    private void setKeyguardStatusViewVisibility(int statusBarState, boolean keyguardFadingAway) {
-        if (!keyguardFadingAway && mStatusBarState == StatusBarState.KEYGUARD
-                && statusBarState != StatusBarState.KEYGUARD) {
+    private final Animator.AnimatorListener mAnimateHeaderSlidingInListener
+            = new AnimatorListenerAdapter() {
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            mHeaderAnimatingIn = false;
+            mQsContainerAnimator = null;
+            mQsContainer.removeOnLayoutChangeListener(mQsContainerAnimatorUpdater);
+        }
+    };
+
+    private final OnLayoutChangeListener mQsContainerAnimatorUpdater
+            = new OnLayoutChangeListener() {
+        @Override
+        public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
+                int oldTop, int oldRight, int oldBottom) {
+            int oldHeight = oldBottom - oldTop;
+            int height = bottom - top;
+            if (height != oldHeight && mQsContainerAnimator != null) {
+                PropertyValuesHolder[] values = mQsContainerAnimator.getValues();
+                float newEndValue = mHeader.getCollapsedHeight() + mQsPeekHeight - height - top;
+                float newStartValue = -height - top;
+                values[0].setFloatValues(newStartValue, newEndValue);
+                mQsContainerAnimator.setCurrentPlayTime(mQsContainerAnimator.getCurrentPlayTime());
+            }
+        }
+    };
+
+    private final ViewTreeObserver.OnPreDrawListener mStartHeaderSlidingIn
+            = new ViewTreeObserver.OnPreDrawListener() {
+        @Override
+        public boolean onPreDraw() {
+            getViewTreeObserver().removeOnPreDrawListener(this);
+            mHeader.setTranslationY(-mHeader.getCollapsedHeight() - mQsPeekHeight);
+            mHeader.animate()
+                    .translationY(0f)
+                    .setStartDelay(mStatusBar.calculateGoingToFullShadeDelay())
+                    .setDuration(StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE)
+                    .setInterpolator(mFastOutSlowInInterpolator)
+                    .start();
+            mQsContainer.setY(-mQsContainer.getHeight());
+            mQsContainerAnimator = ObjectAnimator.ofFloat(mQsContainer, View.TRANSLATION_Y,
+                    mQsContainer.getTranslationY(),
+                    mHeader.getCollapsedHeight() + mQsPeekHeight - mQsContainer.getHeight()
+                            - mQsContainer.getTop());
+            mQsContainerAnimator.setStartDelay(mStatusBar.calculateGoingToFullShadeDelay());
+            mQsContainerAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE);
+            mQsContainerAnimator.setInterpolator(mFastOutSlowInInterpolator);
+            mQsContainerAnimator.addListener(mAnimateHeaderSlidingInListener);
+            mQsContainerAnimator.start();
+            mQsContainer.addOnLayoutChangeListener(mQsContainerAnimatorUpdater);
+            return true;
+        }
+    };
+    
+    private void animateHeaderSlidingIn() {
+        mHeaderAnimatingIn = true;
+        getViewTreeObserver().addOnPreDrawListener(mStartHeaderSlidingIn);
+
+    }
+
+    private final Runnable mAnimateKeyguardStatusBarInvisibleEndRunnable = new Runnable() {
+        @Override
+        public void run() {
+            mKeyguardStatusBar.setVisibility(View.INVISIBLE);
+        }
+    };
+
+    private void animateKeyguardStatusBarOut() {
+        mKeyguardStatusBar.animate()
+                .alpha(0f)
+                .setStartDelay(mStatusBar.getKeyguardFadingAwayDelay())
+                .setDuration(mStatusBar.getKeyguardFadingAwayDuration()/2)
+                .setInterpolator(PhoneStatusBar.ALPHA_OUT)
+                .withEndAction(mAnimateKeyguardStatusBarInvisibleEndRunnable)
+                .start();
+    }
+
+    private final Runnable mAnimateKeyguardBottomAreaInvisibleEndRunnable = new Runnable() {
+        @Override
+        public void run() {
+            mKeyguardBottomArea.setVisibility(View.GONE);
+        }
+    };
+
+    private void setKeyguardBottomAreaVisibility(int statusBarState,
+            boolean goingToFullShade) {
+        if (goingToFullShade) {
+            mKeyguardBottomArea.animate().cancel();
+            mKeyguardBottomArea.animate()
+                    .alpha(0f)
+                    .setStartDelay(mStatusBar.getKeyguardFadingAwayDelay())
+                    .setDuration(mStatusBar.getKeyguardFadingAwayDuration()/2)
+                    .setInterpolator(PhoneStatusBar.ALPHA_OUT)
+                    .withEndAction(mAnimateKeyguardBottomAreaInvisibleEndRunnable)
+                    .start();
+        } else if (statusBarState == StatusBarState.KEYGUARD
+                || statusBarState == StatusBarState.SHADE_LOCKED) {
+            mKeyguardBottomArea.animate().cancel();
+            mKeyguardBottomArea.setVisibility(View.VISIBLE);
+            mKeyguardBottomArea.setAlpha(1f);
+        } else {
+            mKeyguardBottomArea.animate().cancel();
+            mKeyguardBottomArea.setVisibility(View.GONE);
+            mKeyguardBottomArea.setAlpha(1f);
+        }
+    }
+
+    private void setKeyguardStatusViewVisibility(int statusBarState, boolean keyguardFadingAway,
+            boolean goingToFullShade) {
+        if ((!keyguardFadingAway && mStatusBarState == StatusBarState.KEYGUARD
+                && statusBarState != StatusBarState.KEYGUARD) || goingToFullShade) {
             mKeyguardStatusView.animate().cancel();
             mKeyguardStatusViewAnimating = true;
             mKeyguardStatusView.animate()
                     .alpha(0f)
+                    .setStartDelay(0)
                     .setDuration(160)
                     .setInterpolator(PhoneStatusBar.ALPHA_OUT)
                     .withEndAction(mAnimateKeyguardStatusViewInvisibleEndRunnable);
+            if (keyguardFadingAway) {
+                mKeyguardStatusView.animate()
+                        .setStartDelay(mStatusBar.getKeyguardFadingAwayDelay())
+                        .setDuration(mStatusBar.getKeyguardFadingAwayDuration()/2)
+                        .start();
+            }
         } else if (mStatusBarState == StatusBarState.SHADE_LOCKED
                 && statusBarState == StatusBarState.KEYGUARD) {
             mKeyguardStatusView.animate().cancel();
@@ -721,6 +851,7 @@
             mKeyguardStatusView.setAlpha(0f);
             mKeyguardStatusView.animate()
                     .alpha(1f)
+                    .setStartDelay(0)
                     .setDuration(320)
                     .setInterpolator(PhoneStatusBar.ALPHA_IN)
                     .withEndAction(mAnimateKeyguardStatusViewVisibleEndRunnable);
@@ -791,7 +922,9 @@
     }
 
     private void setQsTranslation(float height) {
-        mQsContainer.setY(height - mQsContainer.getHeight() + getHeaderTranslation());
+        if (!mHeaderAnimatingIn) {
+            mQsContainer.setY(height - mQsContainer.getHeight() + getHeaderTranslation());
+        }
         if (mKeyguardShowing) {
             mHeader.setY(interpolate(getQsExpansionFraction(), -mHeader.getHeight(), 0));
         }
@@ -1089,7 +1222,9 @@
     }
 
     private void updateHeaderShade() {
-        mHeader.setTranslationY(getHeaderTranslation());
+        if (!mHeaderAnimatingIn) {
+            mHeader.setTranslationY(getHeaderTranslation());
+        }
         setQsTranslation(mQsExpansionHeight);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 2be3d5a..61b0eaa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -455,6 +455,7 @@
     private int mDrawCount;
     private Runnable mLaunchTransitionEndRunnable;
     private boolean mLaunchTransitionFadingAway;
+    private ExpandableNotificationRow mDraggedDownRow;
 
     private static final int VISIBLE_LOCATIONS = ViewState.LOCATION_FIRST_CARD
             | ViewState.LOCATION_TOP_STACK_PEEKING
@@ -3290,9 +3291,14 @@
 
     public void showKeyguard() {
         setBarState(StatusBarState.KEYGUARD);
-        updateKeyguardState();
+        updateKeyguardState(false /* goingToFullShade */);
         instantExpandNotificationsPanel();
         mLeaveOpenOnKeyguardHide = false;
+        if (mDraggedDownRow != null) {
+            mDraggedDownRow.setUserLocked(false);
+            mDraggedDownRow.notifyHeightChanged();
+            mDraggedDownRow = null;
+        }
     }
 
     public boolean isInLaunchTransition() {
@@ -3341,15 +3347,28 @@
         }
     }
 
-    public void hideKeyguard() {
+    /**
+     * @return true if we would like to stay in the shade, false if it should go away entirely
+     */
+    public boolean hideKeyguard() {
+        boolean staying = mLeaveOpenOnKeyguardHide;
         setBarState(StatusBarState.SHADE);
         if (mLeaveOpenOnKeyguardHide) {
             mLeaveOpenOnKeyguardHide = false;
-            mNotificationPanel.animateToFullShade();
+            mNotificationPanel.animateToFullShade(calculateGoingToFullShadeDelay());
+            if (mDraggedDownRow != null) {
+                mDraggedDownRow.setUserLocked(false);
+                mDraggedDownRow = null;
+            }
         } else {
             instantCollapseNotificationPanel();
         }
-        updateKeyguardState();
+        updateKeyguardState(staying);
+        return staying;
+    }
+
+    public long calculateGoingToFullShadeDelay() {
+        return mKeyguardFadingAwayDelay + mKeyguardFadingAwayDuration;
     }
 
     /**
@@ -3380,7 +3399,7 @@
                 && mStatusBarKeyguardViewManager.isSecure());
     }
 
-    private void updateKeyguardState() {
+    private void updateKeyguardState(boolean goingToFullShade) {
         if (mState == StatusBarState.KEYGUARD) {
             mKeyguardIndicationController.setVisible(true);
             mNotificationPanel.resetViews();
@@ -3390,13 +3409,11 @@
             mKeyguardUserSwitcher.setKeyguard(false);
         }
         if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
-            mKeyguardBottomArea.setVisibility(View.VISIBLE);
             mScrimController.setKeyguardShowing(true);
         } else {
-            mKeyguardBottomArea.setVisibility(View.GONE);
             mScrimController.setKeyguardShowing(false);
         }
-        mNotificationPanel.setBarState(mState, mKeyguardFadingAway);
+        mNotificationPanel.setBarState(mState, mKeyguardFadingAway, goingToFullShade);
         updateDozingState();
         updateStackScrollerState();
         updatePublicMode();
@@ -3609,17 +3626,22 @@
      * @param expandView The view to expand after going to the shade.
      */
     public void goToLockedShade(View expandView) {
+        ExpandableNotificationRow row = null;
         if (expandView instanceof ExpandableNotificationRow) {
-            ExpandableNotificationRow row = (ExpandableNotificationRow) expandView;
+            row = (ExpandableNotificationRow) expandView;
             row.setUserExpanded(true);
         }
         if (isLockscreenPublicMode() && !userAllowsPrivateNotificationsInPublic(mCurrentUserId)) {
             mLeaveOpenOnKeyguardHide = true;
             showBouncer();
+            mDraggedDownRow = row;
         } else {
-            mNotificationPanel.animateToFullShade();
+            mNotificationPanel.animateToFullShade(0 /* delay */);
             setBarState(StatusBarState.SHADE_LOCKED);
-            updateKeyguardState();
+            updateKeyguardState(false /* goingToFullShade */);
+            if (row != null) {
+                row.setUserLocked(false);
+            }
         }
     }
 
@@ -3629,7 +3651,7 @@
     public void goToKeyguard() {
         if (mState == StatusBarState.SHADE_LOCKED) {
             setBarState(StatusBarState.KEYGUARD);
-            updateKeyguardState();
+            updateKeyguardState(false /* goingToFullShade */);
         }
     }
 
@@ -3640,6 +3662,14 @@
         return mNotificationPanel;
     }
 
+    public long getKeyguardFadingAwayDelay() {
+        return mKeyguardFadingAwayDelay;
+    }
+
+    public long getKeyguardFadingAwayDuration() {
+        return mKeyguardFadingAwayDuration;
+    }
+
     public LinearLayout getSystemIcons() {
         return mSystemIcons;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index eb42401..7bce664 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -115,6 +115,13 @@
         scheduleUpdate();
     }
 
+    public void animateGoingToFullShade(long delay, long duration) {
+        mDurationOverride = duration;
+        mAnimationDelay = delay;
+        mAnimateChange = true;
+        scheduleUpdate();
+    }
+
     public void setDozing(boolean dozing) {
         if (mDozing == dozing) return;
         mDozing = dozing;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index af21f25..6831933 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -230,17 +230,22 @@
             });
         } else {
             mPhoneStatusBar.setKeyguardFadingAway(delay, fadeoutDuration);
-            mPhoneStatusBar.hideKeyguard();
-            mStatusBarWindowManager.setKeyguardFadingAway(true);
+            boolean staying = mPhoneStatusBar.hideKeyguard();
+            if (!staying) {
+                mStatusBarWindowManager.setKeyguardFadingAway(true);
+                mScrimController.animateKeyguardFadingOut(delay, fadeoutDuration, new Runnable() {
+                    @Override
+                    public void run() {
+                        mStatusBarWindowManager.setKeyguardFadingAway(false);
+                        mPhoneStatusBar.finishKeyguardFadingAway();
+                    }
+                });
+            } else {
+                mScrimController.animateGoingToFullShade(delay, fadeoutDuration);
+                mPhoneStatusBar.finishKeyguardFadingAway();
+            }
             mStatusBarWindowManager.setKeyguardShowing(false);
             mBouncer.animateHide(delay, fadeoutDuration);
-            mScrimController.animateKeyguardFadingOut(delay, fadeoutDuration, new Runnable() {
-                @Override
-                public void run() {
-                    mStatusBarWindowManager.setKeyguardFadingAway(false);
-                    mPhoneStatusBar.finishKeyguardFadingAway();
-                }
-            });
             mViewMediatorCallback.keyguardGone();
             updateStates();
         }
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 aa41b9c..c9bfc4e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -176,6 +176,7 @@
     private boolean mInterceptDelegateEnabled;
     private boolean mDelegateToScrollView;
     private boolean mDisallowScrollingInThisMotion;
+    private long mGoToFullShadeDelay;
 
     private ViewTreeObserver.OnPreDrawListener mChildrenUpdater
             = new ViewTreeObserver.OnPreDrawListener() {
@@ -1560,11 +1561,13 @@
             mNeedsAnimation = false;
         }
         if (!mAnimationEvents.isEmpty() || isCurrentlyAnimating()) {
-            mStateAnimator.startAnimationForEvents(mAnimationEvents, mCurrentStackScrollState);
+            mStateAnimator.startAnimationForEvents(mAnimationEvents, mCurrentStackScrollState,
+                    mGoToFullShadeDelay);
             mAnimationEvents.clear();
         } else {
             applyCurrentState();
         }
+        mGoToFullShadeDelay = 0;
     }
 
     private void generateChildHierarchyEvents() {
@@ -1939,10 +1942,11 @@
         }
     }
 
-    public void goToFullShade() {
+    public void goToFullShade(long delay) {
         updateSpeedBump(true /* visibility */);
         mDismissView.setInvisible();
         mGoToFullShadeNeedsAnimation = true;
+        mGoToFullShadeDelay = delay;
         mNeedsAnimation =  true;
         requestChildrenUpdate();
     }
@@ -2117,7 +2121,8 @@
 
                 // ANIMATION_TYPE_SNAP_BACK
                 new AnimationFilter()
-                        .animateAlpha(),
+                        .animateAlpha()
+                        .animateHeight(),
 
                 // ANIMATION_TYPE_ACTIVATED_CHILD
                 new AnimationFilter()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index edc669e..e21d52d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -77,6 +77,7 @@
     private Stack<AnimatorListenerAdapter> mAnimationListenerPool = new Stack<>();
     private AnimationFilter mAnimationFilter = new AnimationFilter();
     private long mCurrentLength;
+    private long mCurrentAdditionalDelay;
 
     /** The current index for the last child which was not added in this event set. */
     private int mCurrentLastNotAddedIndex;
@@ -99,12 +100,13 @@
 
     public void startAnimationForEvents(
             ArrayList<NotificationStackScrollLayout.AnimationEvent> mAnimationEvents,
-            StackScrollState finalState) {
+            StackScrollState finalState, long additionalDelay) {
 
         processAnimationEvents(mAnimationEvents, finalState);
 
         int childCount = mHostLayout.getChildCount();
         mAnimationFilter.applyCombination(mNewEvents);
+        mCurrentAdditionalDelay = additionalDelay;
         mCurrentLength = NotificationStackScrollLayout.AnimationEvent.combineLength(mNewEvents);
         mCurrentLastNotAddedIndex = findLastNotAddedIndex(finalState);
         for (int i = 0; i < childCount; i++) {
@@ -167,7 +169,7 @@
         long delay = 0;
         long duration = mCurrentLength;
         if (hasDelays && isDelayRelevant || wasAdded) {
-            delay = calculateChildAnimationDelay(viewState, finalState);
+            delay = mCurrentAdditionalDelay + calculateChildAnimationDelay(viewState, finalState);
         }
 
         if (wasAdded && mAnimationFilter.hasGoToFullShadeEvent) {