Merge "NotificationStackScroller: Fix scrollTo for notification groups" into nyc-dev
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 88c1503..6e9e830 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -1486,6 +1486,13 @@
         updateBackground();
     }
 
+    public int getPositionOfChild(ExpandableNotificationRow childRow) {
+        if (mIsSummaryWithChildren) {
+            return mChildrenContainer.getPositionInLinearLayout(childRow);
+        }
+        return 0;
+    }
+
     public void setExpansionLogger(ExpansionLogger logger, String key) {
         mLogger = logger;
         mLoggingKey = key;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 2f522f0..40ff051 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -47,6 +47,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.ExpandableView;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.stack.ScrollContainer;
@@ -284,11 +285,17 @@
 
     private void findScrollContainer() {
         if (mScrollContainer == null) {
+            mScrollContainerChild = null;
             ViewParent p = this;
             while (p != null) {
+                if (mScrollContainerChild == null && p instanceof ExpandableView) {
+                    mScrollContainerChild = (View) p;
+                }
                 if (p.getParent() instanceof ScrollContainer) {
                     mScrollContainer = (ScrollContainer) p.getParent();
-                    mScrollContainerChild = (View) p;
+                    if (mScrollContainerChild == null) {
+                        mScrollContainerChild = (View) p;
+                    }
                     break;
                 }
                 p = p.getParent();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index cb0b848..a0f1bc2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -677,6 +677,10 @@
         mHeaderUtil = new NotificationHeaderUtil(mNotificationParent);
     }
 
+    public ExpandableNotificationRow getNotificationParent() {
+        return mNotificationParent;
+    }
+
     public NotificationHeaderView getHeaderView() {
         return mNotificationHeader;
     }
@@ -854,4 +858,23 @@
             child.setRemoved();
         }
     }
+
+    public int getPositionInLinearLayout(View childInGroup) {
+        int position = mNotificationHeaderMargin + mNotificatonTopPadding;
+
+        for (int i = 0; i < mChildren.size(); i++) {
+            ExpandableNotificationRow child = mChildren.get(i);
+            boolean notGone = child.getVisibility() != View.GONE;
+            if (notGone) {
+                position += mDividerHeight;
+            }
+            if (child == childInGroup) {
+                return position;
+            }
+            if (notGone) {
+                position += child.getIntrinsicHeight();
+            }
+        }
+        return 0;
+    }
 }
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 cab2534..b58538d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -610,9 +610,13 @@
             ExpandableView expandableView = (ExpandableView) mForcedScroll;
             int positionInLinearLayout = getPositionInLinearLayout(expandableView);
             int targetScroll = targetScrollForView(expandableView, positionInLinearLayout);
+            int outOfViewScroll = positionInLinearLayout + expandableView.getIntrinsicHeight();
 
             targetScroll = Math.max(0, Math.min(targetScroll, getScrollRange()));
-            if (mOwnScrollY < targetScroll || positionInLinearLayout < mOwnScrollY) {
+
+            // Only apply the scroll if we're scrolling the view upwards, or the view is so far up
+            // that it is not visible anymore.
+            if (mOwnScrollY < targetScroll || outOfViewScroll < mOwnScrollY) {
                 mOwnScrollY = targetScroll;
             }
         }
@@ -1034,9 +1038,13 @@
     @Override
     public boolean scrollTo(View v) {
         ExpandableView expandableView = (ExpandableView) v;
-        int targetScroll = targetScrollForView(expandableView, getPositionInLinearLayout(v));
+        int positionInLinearLayout = getPositionInLinearLayout(v);
+        int targetScroll = targetScrollForView(expandableView, positionInLinearLayout);
+        int outOfViewScroll = positionInLinearLayout + expandableView.getIntrinsicHeight();
 
-        if (mOwnScrollY < targetScroll) {
+        // Only apply the scroll if we're scrolling the view upwards, or the view is so far up
+        // that it is not visible anymore.
+        if (mOwnScrollY < targetScroll || outOfViewScroll < mOwnScrollY) {
             mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScroll - mOwnScrollY);
             mDontReportNextOverScroll = true;
             postInvalidateOnAnimation();
@@ -1064,6 +1072,10 @@
             // animating away. To work around that we'll wait until things have settled.
             removeCallbacks(mReclamp);
             postDelayed(mReclamp, 50);
+        } else if (mForcedScroll != null) {
+            // The scroll was requested before we got the actual inset - in case we need
+            // to scroll up some more do so now.
+            scrollTo(mForcedScroll);
         }
         return insets;
     }
@@ -2363,7 +2375,15 @@
         return view.getHeight();
     }
 
-    private int getPositionInLinearLayout(View requestedChild) {
+    private int getPositionInLinearLayout(View requestedView) {
+        ExpandableNotificationRow childInGroup = null;
+        ExpandableNotificationRow requestedRow = null;
+        if (isChildInGroup(requestedView)) {
+            // We're asking for a child in a group. Calculate the position of the parent first,
+            // then within the parent.
+            childInGroup = (ExpandableNotificationRow) requestedView;
+            requestedView = requestedRow = childInGroup.getNotificationParent();
+        }
         int position = 0;
         float previousIncreasedAmount = 0.0f;
         for (int i = 0; i < getChildCount(); i++) {
@@ -2379,7 +2399,10 @@
                 }
                 previousIncreasedAmount = increasedPaddingAmount;
             }
-            if (child == requestedChild) {
+            if (child == requestedView) {
+                if (requestedRow != null) {
+                    position += requestedRow.getPositionOfChild(childInGroup);
+                }
                 return position;
             }
             if (notGone) {