Fixed more heads up bugs

Change-Id: Ibfb6656deb3bc588fc9292a672a5e4d4d1de4d23
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index b759684..fa1ec0f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -643,9 +643,10 @@
         }
         mMaxExpandHeight = expandedChild.getHeight();
         View headsUpChild = mPrivateLayout.getHeadsUpChild();
-        if (headsUpChild != null) {
-            mHeadsUpHeight = headsUpChild.getHeight();
+        if (headsUpChild == null) {
+            headsUpChild = mPrivateLayout.getContractedChild();
         }
+        mHeadsUpHeight = headsUpChild.getHeight();
         if (intrinsicBefore != getIntrinsicHeight()) {
             notifyHeightChanged(false  /* needsAnimation */);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 7403f93..964d75f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -51,8 +51,8 @@
 
     private NotificationViewWrapper mContractedWrapper;
 
-    private int mSmallHeight;
-    private int mHeadsUpHeight;
+    private final int mSmallHeight;
+    private final int mHeadsUpHeight;
     private int mClipTopAmount;
 
     private int mContentHeight;
@@ -77,6 +77,8 @@
     public NotificationContentView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mFadePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
+        mSmallHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
+        mHeadsUpHeight = getResources().getDimensionPixelSize(R.dimen.notification_mid_height);
         reset(true);
     }
 
@@ -150,8 +152,7 @@
         removeAllViews();
         mContractedChild = null;
         mExpandedChild = null;
-        mSmallHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
-        mHeadsUpHeight = getResources().getDimensionPixelSize(R.dimen.notification_mid_height);
+        mHeadsUpChild = null;
         mVisibleView = CONTRACTED;
         if (resetActualHeight) {
             mContentHeight = mSmallHeight;
@@ -175,7 +176,6 @@
             mContractedChild.animate().cancel();
             removeView(mContractedChild);
         }
-        sanitizeLayoutParams(child, mSmallHeight);
         addView(child);
         mContractedChild = child;
         mContractedWrapper = NotificationViewWrapper.wrap(getContext(), child);
@@ -259,12 +259,6 @@
         setClipBounds(mClipBounds);
     }
 
-    private void sanitizeLayoutParams(View contractedChild, int height) {
-        LayoutParams lp = (LayoutParams) contractedChild.getLayoutParams();
-        lp.height = height;
-        contractedChild.setLayoutParams(lp);
-    }
-
     private void selectLayout(boolean animate, boolean force) {
         if (mContractedChild == null) {
             return;
@@ -337,8 +331,8 @@
 
     private int calculateVisibleView() {
         boolean noExpandedChild = mExpandedChild == null;
-        if (mIsHeadsUp) {
-            if (mContentHeight <= mHeadsUpHeight || noExpandedChild) {
+        if (mIsHeadsUp && mHeadsUpChild != null) {
+            if (mContentHeight <= mHeadsUpChild.getHeight() || noExpandedChild) {
                 return HEADSUP;
             } else {
                 return EXPANDED;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
index 386be7e..3997807 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
@@ -89,7 +89,6 @@
                     mCollapseSnoozes = h < 0;
                     mInitialTouchX = x;
                     mInitialTouchY = y;
-                    mHeadsUpManager.releaseAllToShade();
                     int expandedHeight = mPickedChild.getActualHeight();
                     mPanel.startExpandMotion(x, y, true /* startTracking */, expandedHeight);
                     return true;
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 f0e8b20..ade1a33 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -45,6 +45,7 @@
 import com.android.systemui.R;
 import com.android.systemui.qs.QSContainer;
 import com.android.systemui.qs.QSPanel;
+import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.ExpandableView;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.statusbar.GestureRecorder;
@@ -1445,7 +1446,7 @@
         updateHeader();
         updateUnlockIcon();
         updateNotificationTranslucency();
-        mHeadsUpManager.setIsExpanded(!isShadeCollapsed());
+        mHeadsUpManager.setIsExpanded(expandedHeight != 0);
         mNotificationStackScroller.setShadeExpanded(!isShadeCollapsed());
         if (DEBUG) {
             invalidate();
@@ -2154,6 +2155,11 @@
     }
 
     @Override
+    public void OnHeadsUpPinned(ExpandableNotificationRow headsUp) {
+        mNotificationStackScroller.generateHeadsUpAnimation(headsUp, true);
+    }
+
+    @Override
     public void OnHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) {
         mNotificationStackScroller.generateHeadsUpAnimation(entry.row, isHeadsUp);
     }
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 c40a0c1..3b02911 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1845,6 +1845,10 @@
     }
 
     @Override
+    public void OnHeadsUpPinned(ExpandableNotificationRow headsUp) {
+    }
+
+    @Override
     public void OnHeadsUpStateChanged(Entry entry, boolean isHeadsUp) {
         if (!isHeadsUp && mHeadsUpEntriesToRemoveOnSwitch.contains(entry)) {
             removeNotification(entry.key, mLatestRankingMap);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index 85ff59a..d226014 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -156,7 +156,7 @@
         if (alert) {
             HeadsUpEntry headsUpEntry = mHeadsUpEntries.get(headsUp.key);
             headsUpEntry.updateEntry();
-            headsUpEntry.entry.row.setInShade(mIsExpanded);
+            setEntryToShade(headsUpEntry, mIsExpanded);
         }
     }
 
@@ -168,22 +168,35 @@
         mHeadsUpEntries.put(entry.key, headsUpEntry);
         entry.row.setHeadsUp(true);
         if (!entry.row.isInShade() && mIsExpanded) {
-            headsUpEntry.entry.row.setInShade(true);
+            setEntryToShade(headsUpEntry, true);
         }
-        updatePinnedHeadsUpState(false);
+        updatePinnedHeadsUpState(false /*forceImmediate */);
         for (OnHeadsUpChangedListener listener : mListeners) {
             listener.OnHeadsUpStateChanged(entry, true);
         }
         entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
     }
 
+    private void setEntryToShade(HeadsUpEntry headsUpEntry, boolean inShade) {
+        ExpandableNotificationRow row = headsUpEntry.entry.row;
+        if (row.isInShade() != inShade) {
+            row.setInShade(inShade);
+            updatePinnedHeadsUpState(false /* forceImmediate */);
+            if (!inShade) {
+                for (OnHeadsUpChangedListener listener :mListeners) {
+                    listener.OnHeadsUpPinned(row);
+                }
+            }
+        }
+    }
+
     private void removeHeadsUpEntry(NotificationData.Entry entry) {
         HeadsUpEntry remove = mHeadsUpEntries.remove(entry.key);
         mSortedEntries.remove(remove);
         mEntryPool.release(remove);
         entry.row.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
         entry.row.setHeadsUp(false);
-        updatePinnedHeadsUpState(false);
+        updatePinnedHeadsUpState(false /* forceImmediate */);
         for (OnHeadsUpChangedListener listener : mListeners) {
             listener.OnHeadsUpStateChanged(entry, false);
         }
@@ -392,7 +405,7 @@
             HeadsUpEntry entry = mHeadsUpEntries.get(key);
             entry.entry.row.setInShade(true);
         }
-        updatePinnedHeadsUpState(true);
+        updatePinnedHeadsUpState(true /* forceImmediate */);
     }
 
     public void onExpandingFinished() {
@@ -412,7 +425,12 @@
     }
 
     public void setIsExpanded(boolean isExpanded) {
-        mIsExpanded = isExpanded;
+        if (isExpanded != mIsExpanded) {
+            mIsExpanded = isExpanded;
+            if (isExpanded) {
+                releaseAllToShade();
+            }
+        }
     }
 
     public int getTopHeadsUpHeight() {
@@ -495,6 +513,7 @@
 
     public interface OnHeadsUpChangedListener {
         void OnPinnedHeadsUpExistChanged(boolean exist, boolean changeImmediatly);
+        void OnHeadsUpPinned(ExpandableNotificationRow headsUp);
         void OnHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp);
     }
 }
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 da4cc7e..4d7f8c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -621,7 +621,7 @@
         requestChildrenUpdate();
     }
 
-    private boolean isPinnedHeadsUp(View v) {
+    public boolean isPinnedHeadsUp(View v) {
         if (v instanceof ExpandableNotificationRow) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) v;
             return row.isHeadsUp() && !row.isInShade();
@@ -1875,7 +1875,7 @@
             boolean onBottom = false;
             if (!row.isInShade() && !isHeadsUp) {
                 type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR;
-            } else if (mAddedHeadsUpChildren.contains(row)) {
+            } else if (mAddedHeadsUpChildren.contains(row) || (!row.isInShade() && !mIsExpanded)) {
                 if (!row.isInShade() || shouldHunAppearFromBottom(row)) {
                     // Our custom add animation
                     type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_APPEAR;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 5dbcce8..54ed04c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -515,17 +515,29 @@
         for (HeadsUpManager.HeadsUpEntry entry: headsUpEntries) {
             ExpandableNotificationRow row = entry.entry.row;
             StackViewState childState = resultState.getViewStateForView(row);
+            ExpandableNotificationRow topHeadsUpEntry = ambientState.getTopHeadsUpEntry();
+            boolean isTopEntry = topHeadsUpEntry == row;
             if (!row.isInShade()) {
                 childState.yTranslation = 0;
+                childState.height = row.getHeadsUpHeight();
+                if (!isTopEntry) {
+                    // Ensure that a headsUp is never below the topmost headsUp
+                    StackViewState topState = resultState.getViewStateForView(topHeadsUpEntry);
+                    childState.height = row.getHeadsUpHeight();
+                    childState.yTranslation = Math.min(childState.yTranslation,
+                            topState.yTranslation + topState.height - childState.height);
+                }
+            } else if (mIsExpanded) {
+                if (isTopEntry) {
+                    childState.height += row.getHeadsUpHeight() - mCollapsedSize;
+                }
+                childState.height = Math.max(childState.height, row.getHeadsUpHeight());
+                // Ensure that the heads up is always visible even when scrolled of from the bottom
+                float bottomPosition = ambientState.getMaxHeadsUpTranslation() - childState.height;
+                childState.yTranslation = Math.min(childState.yTranslation,
+                        bottomPosition);
             }
-            if (ambientState.getTopHeadsUpEntry() == row) {
-                childState.height += row.getHeadsUpHeight() - mCollapsedSize;
-            }
-            childState.height = Math.max(childState.height, row.getHeadsUpHeight());
 
-            // Ensure that the heads up is always visible even when scrolled of from the bottom
-            childState.yTranslation = Math.min(childState.yTranslation,
-                    ambientState.getMaxHeadsUpTranslation() - childState.height);
         }
     }
 
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 75b4117..4a705b5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -183,6 +183,10 @@
             // This is a heads up animation
             return false;
         }
+        if (mHostLayout.isPinnedHeadsUp(child)) {
+            // This is another headsUp which might move. Let's animate!
+            return false;
+        }
         finalState.applyState(child, viewState);
         return true;
     }