Limit notification scroll up to status bar

Fixes: 186916207
Test: open shade, scroll
      => notifications clipped right below status bar
      => scrim positioned right below status bar
Test: close shade from scrolled state
      => notification clipping and scrim position
         move up, in sync with decreasing expansion fraction

Change-Id: Ifc150444e68f0ce871e5b90ea08c05adf849ac7a
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index 66d2347..a189177 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -75,6 +75,7 @@
     private int mExpandAnimationTopChange;
     private ExpandableNotificationRow mExpandingNotification;
     private float mHideAmount;
+    private float mNotificationScrimTop;
     private boolean mAppearing;
     private float mPulseHeight = MAX_PULSE_HEIGHT;
     private float mDozeAmount = 0.0f;
@@ -255,6 +256,20 @@
         return mHideAmount;
     }
 
+    /**
+     * Set y position of top of notifications background scrim, relative to top of screen.
+     */
+    public void setNotificationScrimTop(float notificationScrimTop) {
+        mNotificationScrimTop = notificationScrimTop;
+    }
+
+    /**
+     * @return Y position of top of notifications background scrim, relative to top of screen.
+     */
+    public float getNotificationScrimTop() {
+        return mNotificationScrimTop;
+    }
+
     public void setHideSensitive(boolean hideSensitive) {
         mHideSensitive = hideSensitive;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index a804ae6..ab4e0da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -1009,9 +1009,7 @@
 
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void updateClippingToTopRoundedCorner() {
-        Float clipStart = (float) mTopPadding
-                + mStackTranslation
-                + mAmbientState.getExpandAnimationTopChange();
+        Float clipStart = mAmbientState.getNotificationScrimTop();
         Float clipEnd = clipStart + mCornerRadius;
         boolean first = true;
         for (int i = 0; i < getChildCount(); i++) {
@@ -1024,7 +1022,8 @@
             boolean clip = clipStart > start && clipStart < end
                     || clipEnd >= start && clipEnd <= end;
             clip &= !(first && mScrollAdapter.isScrolledToTop());
-            child.setDistanceToTopRoundness(ExpandableView.NO_ROUNDNESS);
+            child.setDistanceToTopRoundness(clip ? Math.max(start - clipStart, 0)
+                    : ExpandableView.NO_ROUNDNESS);
             first = false;
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index e931ec4..5c8cc9f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -156,9 +156,9 @@
 
     private void updateClipping(StackScrollAlgorithmState algorithmState,
             AmbientState ambientState) {
-        float drawStart = !ambientState.isOnKeyguard()
-                ? ambientState.getStackY() - ambientState.getScrollY() : 0;
-        float clipStart = 0;
+        float drawStart = ambientState.isOnKeyguard() ? 0
+                : ambientState.getStackY() - ambientState.getScrollY();
+        float clipStart = ambientState.getNotificationScrimTop();
         int childCount = algorithmState.visibleChildren.size();
         boolean firstHeadsUp = true;
         for (int i = 0; i < childCount; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 9d8a9bf..5fb29fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -331,7 +331,7 @@
     private LockIconViewController mLockIconViewController;
     private NotificationsQuickSettingsContainer mNotificationContainerParent;
     private boolean mAnimateNextPositionUpdate;
-
+    private float mQuickQsOffsetHeight;
     private int mTrackingPointer;
     private VelocityTracker mQsVelocityTracker;
     private boolean mQsTracking;
@@ -942,6 +942,8 @@
     }
 
     public void updateResources() {
+        mQuickQsOffsetHeight = mResources.getDimensionPixelSize(
+                com.android.internal.R.dimen.quick_qs_offset_height);
         mSplitShadeNotificationsTopPadding =
                 mResources.getDimensionPixelSize(R.dimen.notifications_top_padding_split_shade);
         int qsWidth = mResources.getDimensionPixelSize(R.dimen.qs_panel_width);
@@ -2170,7 +2172,8 @@
                 // can be wrong during transitions when waiting for the keyguard to unlock
                 top = mTransitionToFullShadeQSPosition;
             } else {
-                float notificationTop = getQSEdgePosition();
+                final float notificationTop = getQSEdgePosition();
+                mAmbientState.setNotificationScrimTop(notificationTop);
                 top = (int) (isOnKeyguard() ? Math.min(qsPanelBottomY, notificationTop)
                         : notificationTop);
             }
@@ -2252,7 +2255,8 @@
 
     private float getQSEdgePosition() {
         // TODO: replace StackY with unified calculation
-        return mAmbientState.getStackY() - mAmbientState.getScrollY();
+        return Math.max(mQuickQsOffsetHeight * mAmbientState.getExpansionFraction(),
+                mAmbientState.getStackY() - mAmbientState.getScrollY());
     }
 
     private int calculateQsBottomPosition(float qsExpansionFraction) {