Continued low-priority group implementation

Adapting the low-priority group implementation
according to spec. Expanding a group takes 2 taps now.

Test: add low-priority group observe behavior
Change-Id: Ic563a8fe0e71df746b9b548adc8d1698940b1a83
Fixes: 35125708
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 8274b9a7..bc79070 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -39,7 +39,6 @@
 import android.view.NotificationHeaderView;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewParent;
 import android.view.ViewStub;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -159,14 +158,15 @@
     private OnClickListener mExpandClickListener = new OnClickListener() {
         @Override
         public void onClick(View v) {
-            if (!mShowingPublic && mGroupManager.isSummaryOfGroup(mStatusBarNotification)) {
+            if (!mShowingPublic && (!mIsLowPriority || isExpanded())
+                    && mGroupManager.isSummaryOfGroup(mStatusBarNotification)) {
                 mGroupExpansionChanging = true;
                 final boolean wasExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
                 boolean nowExpanded = mGroupManager.toggleGroupExpansion(mStatusBarNotification);
                 mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
                 MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTIFICATION_GROUP_EXPANDER,
                         nowExpanded);
-                logExpansionEvent(true /* userAction */, wasExpanded);
+                onExpansionChanged(true /* userAction */, wasExpanded);
             } else {
                 if (v.isAccessibilityFocused()) {
                     mPrivateLayout.setFocusOnVisibilityChange();
@@ -253,6 +253,7 @@
         }
         if (mIsSummaryWithChildren) {
             setIconAnimationRunningForChild(running, mChildrenContainer.getHeaderView());
+            setIconAnimationRunningForChild(running, mChildrenContainer.getLowPriorityHeaderView());
             List<ExpandableNotificationRow> notificationChildren =
                     mChildrenContainer.getNotificationChildren();
             for (int i = 0; i < notificationChildren.size(); i++) {
@@ -320,8 +321,7 @@
         mShowingPublicInitialized = false;
         updateNotificationColor();
         if (mIsSummaryWithChildren) {
-            mChildrenContainer.recreateNotificationHeader(mExpandClickListener,
-                    mEntry.notification);
+            mChildrenContainer.recreateNotificationHeader(mExpandClickListener);
             mChildrenContainer.onNotificationUpdated();
         }
         if (mIconAnimationRunning) {
@@ -687,9 +687,13 @@
         return mPrivateLayout.getNotificationHeader();
     }
 
-    private NotificationHeaderView getVisibleNotificationHeader() {
+    /**
+     * @return the currently visible notification header. This can be different from
+     * {@link #getNotificationHeader()} in case it is a low-priority group.
+     */
+    public NotificationHeaderView getVisibleNotificationHeader() {
         if (mIsSummaryWithChildren && !mShowingPublic) {
-            return mChildrenContainer.getHeaderView();
+            return mChildrenContainer.getVisibleHeader();
         }
         return getShowingLayout().getVisibleNotificationHeader();
     }
@@ -909,7 +913,7 @@
     }
 
     public View getNotificationIcon() {
-        NotificationHeaderView notificationHeader = getNotificationHeader();
+        NotificationHeaderView notificationHeader = getVisibleNotificationHeader();
         if (notificationHeader != null) {
             return notificationHeader.getIcon();
         }
@@ -1032,6 +1036,10 @@
         }
     }
 
+    public boolean isLowPriority() {
+        return mIsLowPriority;
+    }
+
     public void setUseIncreasedCollapsedHeight(boolean use) {
         mUseIncreasedCollapsedHeight = use;
         mNotificationInflater.setUsesIncreasedHeight(use);
@@ -1136,7 +1144,7 @@
             public void onInflate(ViewStub stub, View inflated) {
                 mChildrenContainer = (NotificationChildrenContainer) inflated;
                 mChildrenContainer.setIsLowPriority(mIsLowPriority);
-                mChildrenContainer.setNotificationParent(ExpandableNotificationRow.this);
+                mChildrenContainer.setContainingNotification(ExpandableNotificationRow.this);
                 mChildrenContainer.onNotificationUpdated();
                 mTranslateableViews.add(mChildrenContainer);
             }
@@ -1265,9 +1273,7 @@
         if (mChildrenContainer != null) {
             mChildrenContainer.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE
                     : INVISIBLE);
-            mChildrenContainer.updateHeaderVisibility(!mShowingPublic && mIsSummaryWithChildren
-                    ? VISIBLE
-                    : INVISIBLE);
+            mChildrenContainer.setHeaderVisible(!mShowingPublic && mIsSummaryWithChildren);
         }
         // The limits might have changed if the view suddenly became a group or vice versa
         updateLimits();
@@ -1335,7 +1341,6 @@
      */
     public void setUserExpanded(boolean userExpanded) {
         setUserExpanded(userExpanded, false /* allowChildExpansion */);
-        updateShelfIconColor();
     }
 
     /**
@@ -1346,22 +1351,28 @@
      */
     public void setUserExpanded(boolean userExpanded, boolean allowChildExpansion) {
         mFalsingManager.setNotificationExpanded();
-        if (mIsSummaryWithChildren && !mShowingPublic && allowChildExpansion) {
+        if (mIsSummaryWithChildren && !mShowingPublic && allowChildExpansion
+                && !mChildrenContainer.showingAsLowPriority()) {
             final boolean wasExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
             mGroupManager.setGroupExpanded(mStatusBarNotification, userExpanded);
-            logExpansionEvent(true /* userAction */, wasExpanded);
+            onExpansionChanged(true /* userAction */, wasExpanded);
             return;
         }
         if (userExpanded && !mExpandable) return;
         final boolean wasExpanded = isExpanded();
         mHasUserChangedExpansion = true;
         mUserExpanded = userExpanded;
-        logExpansionEvent(true, wasExpanded);
+        onExpansionChanged(true /* userAction */, wasExpanded);
     }
 
     public void resetUserExpansion() {
+        boolean changed = mUserExpanded;
         mHasUserChangedExpansion = false;
         mUserExpanded = false;
+        if (changed && mIsSummaryWithChildren) {
+            mChildrenContainer.onExpansionChanged();
+        }
+        updateShelfIconColor();
     }
 
     public boolean isUserLocked() {
@@ -1395,9 +1406,8 @@
         if (expand != mIsSystemExpanded) {
             final boolean wasExpanded = isExpanded();
             mIsSystemExpanded = expand;
-            updateShelfIconColor();
             notifyHeightChanged(false /* needsAnimation */);
-            logExpansionEvent(false, wasExpanded);
+            onExpansionChanged(false /* userAction */, wasExpanded);
             if (mIsSummaryWithChildren) {
                 mChildrenContainer.updateGroupOverflow();
             }
@@ -1411,7 +1421,7 @@
         if (onKeyguard != mOnKeyguard) {
             final boolean wasExpanded = isExpanded();
             mOnKeyguard = onKeyguard;
-            logExpansionEvent(false, wasExpanded);
+            onExpansionChanged(false /* userAction */, wasExpanded);
             if (wasExpanded != isExpanded()) {
                 if (mIsSummaryWithChildren) {
                     mChildrenContainer.updateGroupOverflow();
@@ -1482,8 +1492,8 @@
         mIsSummaryWithChildren = StatusBar.ENABLE_CHILD_NOTIFICATIONS
                 && mChildrenContainer != null && mChildrenContainer.getNotificationChildCount() > 0;
         if (mIsSummaryWithChildren && mChildrenContainer.getHeaderView() == null) {
-            mChildrenContainer.recreateNotificationHeader(mExpandClickListener,
-                    mEntry.notification);
+            mChildrenContainer.recreateNotificationHeader(mExpandClickListener
+            );
         }
         getShowingLayout().updateBackgroundColor(false /* animate */);
         mPrivateLayout.updateExpandButtons(isExpandable());
@@ -1538,7 +1548,7 @@
      * the top.
      */
     private void updateContentShiftHeight() {
-        NotificationHeaderView notificationHeader = getNotificationHeader();
+        NotificationHeaderView notificationHeader = getVisibleNotificationHeader();
         if (notificationHeader != null) {
             CachingIconView icon = notificationHeader.getIcon();
             mIconTransformContentShift = getRelativeTopPadding(icon) + icon.getHeight();
@@ -1932,7 +1942,7 @@
             if (isGroupExpanded()) {
                 return 1.0f;
             } else if (isUserLocked()) {
-                return mChildrenContainer.getGroupExpandFraction();
+                return mChildrenContainer.getIncreasedPaddingAmount();
             }
         } else if (isColorized() && (!mIsLowPriority || isExpanded())) {
             return -1.0f;
@@ -1955,13 +1965,19 @@
         return super.disallowSingleClick(event);
     }
 
-    private void logExpansionEvent(boolean userAction, boolean wasExpanded) {
+    private void onExpansionChanged(boolean userAction, boolean wasExpanded) {
         boolean nowExpanded = isExpanded();
-        if (mIsSummaryWithChildren) {
+        if (mIsSummaryWithChildren && (!mIsLowPriority || wasExpanded)) {
             nowExpanded = mGroupManager.isGroupExpanded(mStatusBarNotification);
         }
-        if (wasExpanded != nowExpanded && mLogger != null) {
-            mLogger.logNotificationExpansion(mLoggingKey, userAction, nowExpanded) ;
+        if (nowExpanded != wasExpanded) {
+            updateShelfIconColor();
+            if (mLogger != null) {
+                mLogger.logNotificationExpansion(mLoggingKey, userAction, nowExpanded);
+            }
+            if (mIsSummaryWithChildren) {
+                mChildrenContainer.onExpansionChanged();
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 2eb0817..74e65fb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -631,7 +631,7 @@
     }
 
     public int getMinHeight(boolean likeGroupExpanded) {
-        if (likeGroupExpanded || !mIsChildInGroup || isGroupExpanded() || mIsLowPriority) {
+        if (likeGroupExpanded || !mIsChildInGroup || isGroupExpanded()) {
             return mContractedChild.getHeight();
         } else {
             return mSingleLineView.getHeight();
@@ -905,7 +905,7 @@
                 height = mContentHeight;
             }
             int expandedVisualType = getVisualTypeForHeight(height);
-            int collapsedVisualType = mIsChildInGroup && !isGroupExpanded() && !mIsLowPriority
+            int collapsedVisualType = mIsChildInGroup && !isGroupExpanded()
                     ? VISIBLE_TYPE_SINGLELINE
                     : getVisualTypeForHeight(mContainingNotification.getCollapsedHeight());
             return mTransformationStartVisibleType == collapsedVisualType
@@ -926,7 +926,7 @@
         if (!noExpandedChild && viewHeight == mExpandedChild.getHeight()) {
             return VISIBLE_TYPE_EXPANDED;
         }
-        if (!mUserExpanding && mIsChildInGroup && !isGroupExpanded() && !mIsLowPriority) {
+        if (!mUserExpanding && mIsChildInGroup && !isGroupExpanded()) {
             return VISIBLE_TYPE_SINGLELINE;
         }
 
@@ -1005,6 +1005,18 @@
 
     public void setIsChildInGroup(boolean isChildInGroup) {
         mIsChildInGroup = isChildInGroup;
+        if (mContractedChild != null) {
+            mContractedWrapper.setIsChildInGroup(mIsChildInGroup);
+        }
+        if (mExpandedChild != null) {
+            mExpandedWrapper.setIsChildInGroup(mIsChildInGroup);
+        }
+        if (mHeadsUpChild != null) {
+            mHeadsUpWrapper.setIsChildInGroup(mIsChildInGroup);
+        }
+        if (mAmbientChild != null) {
+            mAmbientWrapper.setIsChildInGroup(mIsChildInGroup);
+        }
         updateSingleLineView();
     }
 
@@ -1013,16 +1025,16 @@
         mBeforeN = entry.targetSdk < Build.VERSION_CODES.N;
         updateSingleLineView();
         if (mContractedChild != null) {
-            mContractedWrapper.notifyContentUpdated(entry.notification, mIsLowPriority);
+            mContractedWrapper.notifyContentUpdated(entry.row);
         }
         if (mExpandedChild != null) {
-            mExpandedWrapper.notifyContentUpdated(entry.notification, mIsLowPriority);
+            mExpandedWrapper.notifyContentUpdated(entry.row);
         }
         if (mHeadsUpChild != null) {
-            mHeadsUpWrapper.notifyContentUpdated(entry.notification, mIsLowPriority);
+            mHeadsUpWrapper.notifyContentUpdated(entry.row);
         }
         if (mAmbientChild != null) {
-            mAmbientWrapper.notifyContentUpdated(entry.notification, mIsLowPriority);
+            mAmbientWrapper.notifyContentUpdated(entry.row);
         }
         applyRemoteInput(entry);
         updateLegacy();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 1cd909ea..36ed551 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -443,7 +443,8 @@
             }
             int shelfColor = icon.getStaticDrawableColor();
             if (!noIcon && shelfColor != StatusBarIconView.NO_COLOR) {
-                int notificationColor = row.getNotificationHeader().getOriginalNotificationColor();
+                int notificationColor
+                        = row.getVisibleNotificationHeader().getOriginalNotificationColor();
                 shelfColor = NotificationUtils.interpolateColors(notificationColor, shelfColor,
                         iconState.iconAppearAmount);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigPictureTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigPictureTemplateViewWrapper.java
index 78b967a..7a34b6e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigPictureTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigPictureTemplateViewWrapper.java
@@ -36,9 +36,9 @@
     }
 
     @Override
-    public void notifyContentUpdated(StatusBarNotification notification, boolean isLowPriority) {
-        super.notifyContentUpdated(notification, isLowPriority);
-        updateImageTag(notification);
+    public void notifyContentUpdated(ExpandableNotificationRow row) {
+        super.notifyContentUpdated(row);
+        updateImageTag(row.getStatusBarNotification());
     }
 
     private void updateImageTag(StatusBarNotification notification) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigTextTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigTextTemplateViewWrapper.java
index 39db243..9476eed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigTextTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigTextTemplateViewWrapper.java
@@ -41,11 +41,11 @@
     }
 
     @Override
-    public void notifyContentUpdated(StatusBarNotification notification, boolean isLowPriority) {
+    public void notifyContentUpdated(ExpandableNotificationRow row) {
         // Reinspect the notification. Before the super call, because the super call also updates
         // the transformation types and we need to have our values set by then.
-        resolveViews(notification);
-        super.notifyContentUpdated(notification, isLowPriority);
+        resolveViews(row.getStatusBarNotification());
+        super.notifyContentUpdated(row);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
index 8eab2e9..38e4ec1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
@@ -19,6 +19,7 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
+import android.app.Notification;
 import android.content.Context;
 import android.graphics.Color;
 import android.graphics.ColorFilter;
@@ -26,7 +27,6 @@
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.drawable.Drawable;
-import android.service.notification.StatusBarNotification;
 import android.util.ArraySet;
 import android.view.NotificationHeaderView;
 import android.view.View;
@@ -71,6 +71,7 @@
     private TextView mHeaderText;
     private ImageView mWorkProfileImage;
     private boolean mIsLowPriority;
+    private boolean mTransformLowPriorityTitle;
 
     protected NotificationHeaderViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
         super(view, row);
@@ -100,7 +101,7 @@
 
                     @Override
                     protected boolean hasCustomTransformation() {
-                        return mIsLowPriority;
+                        return mIsLowPriority && mTransformLowPriorityTitle;
                     }
                 }, TRANSFORMING_VIEW_TITLE);
         resolveHeaderViews();
@@ -128,9 +129,10 @@
     }
 
     @Override
-    public void notifyContentUpdated(StatusBarNotification notification, boolean isLowPriority) {
-        super.notifyContentUpdated(notification, isLowPriority);
-        mIsLowPriority = isLowPriority;
+    public void notifyContentUpdated(ExpandableNotificationRow row) {
+        super.notifyContentUpdated(row);
+        mIsLowPriority = row.isLowPriority();
+        mTransformLowPriorityTitle = !row.isChildInGroup() && !row.isSummaryWithChildren();
         ArraySet<View> previousViews = mTransformationHelper.getAllTransformingViews();
 
         // Reinspect the notification.
@@ -139,11 +141,11 @@
         updateTransformedTypes();
         addRemainingTransformTypes();
         updateCropToPaddingForImageViews();
-        mIcon.setTag(ImageTransformState.ICON_TAG, notification.getNotification().getSmallIcon());
+        Notification notification = row.getStatusBarNotification().getNotification();
+        mIcon.setTag(ImageTransformState.ICON_TAG, notification.getSmallIcon());
         // The work profile image is always the same lets just set the icon tag for it not to
         // animate
-        mWorkProfileImage.setTag(ImageTransformState.ICON_TAG,
-                notification.getNotification().getSmallIcon());
+        mWorkProfileImage.setTag(ImageTransformState.ICON_TAG, notification.getSmallIcon());
 
         // We need to reset all views that are no longer transforming in case a view was previously
         // transformed, but now we decided to transform its container instead.
@@ -361,6 +363,12 @@
     }
 
     @Override
+    public void setIsChildInGroup(boolean isChildInGroup) {
+        super.setIsChildInGroup(isChildInGroup);
+        mTransformLowPriorityTitle = !isChildInGroup;
+    }
+
+    @Override
     public void setVisible(boolean visible) {
         super.setVisible(visible);
         mTransformationHelper.setVisible(visible);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
index 04ee6aa..ef5a25c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
@@ -35,16 +35,16 @@
 
     View mActions;
 
-    private void resolveViews(StatusBarNotification notification) {
+    private void resolveViews() {
         mActions = mView.findViewById(com.android.internal.R.id.media_actions);
     }
 
     @Override
-    public void notifyContentUpdated(StatusBarNotification notification, boolean isLowPriority) {
+    public void notifyContentUpdated(ExpandableNotificationRow row) {
         // Reinspect the notification. Before the super call, because the super call also updates
         // the transformation types and we need to have our values set by then.
-        resolveViews(notification);
-        super.notifyContentUpdated(notification, isLowPriority);
+        resolveViews();
+        super.notifyContentUpdated(row);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java
index defeab2..9631556 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java
@@ -21,7 +21,6 @@
 import com.android.systemui.statusbar.TransformableView;
 
 import android.content.Context;
-import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
 import android.view.View;
 import android.widget.TextView;
@@ -71,11 +70,11 @@
     }
 
     @Override
-    public void notifyContentUpdated(StatusBarNotification notification, boolean isLowPriority) {
+    public void notifyContentUpdated(ExpandableNotificationRow row) {
         // Reinspect the notification. Before the super call, because the super call also updates
         // the transformation types and we need to have our values set by then.
         resolveViews();
-        super.notifyContentUpdated(notification, isLowPriority);
+        super.notifyContentUpdated(row);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
index e9956ff..846d03a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -133,11 +133,11 @@
     }
 
     @Override
-    public void notifyContentUpdated(StatusBarNotification notification, boolean isLowPriority) {
+    public void notifyContentUpdated(ExpandableNotificationRow row) {
         // Reinspect the notification. Before the super call, because the super call also updates
         // the transformation types and we need to have our values set by then.
-        resolveTemplateViews(notification);
-        super.notifyContentUpdated(notification, isLowPriority);
+        resolveTemplateViews(row.getStatusBarNotification());
+        super.notifyContentUpdated(row);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
index 8f0dcb0..c85e8d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -48,6 +48,7 @@
     private int mBackgroundColor = 0;
     protected boolean mShouldInvertDark;
     protected boolean mDarkInitialized = false;
+    private boolean mForcedInvisible;
 
     public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) {
         if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
@@ -87,10 +88,9 @@
 
     /**
      * Notifies this wrapper that the content of the view might have changed.
-     * @param notification the notification this is wrapped around
-     * @param isLowPriority is this notification low priority
+     * @param row the row this wrapper is attached to
      */
-    public void notifyContentUpdated(StatusBarNotification notification, boolean isLowPriority) {
+    public void notifyContentUpdated(ExpandableNotificationRow row) {
         mDarkInitialized = false;
         Drawable background = mView.getBackground();
         if (shouldClearBackgroundOnReapply()) {
@@ -193,4 +193,7 @@
 
     public void setRemoteInputVisible(boolean visible) {
     }
+
+    public void setIsChildInGroup(boolean isChildInGroup) {
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index f017eb1..3706dc8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -227,6 +227,7 @@
             ViewState iconState = mIconStates.get(view);
             iconState.initFrom(view);
             iconState.alpha = 1.0f;
+            iconState.hidden = false;
         }
     }
 
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 e6a3add..83cbd72 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -52,6 +52,14 @@
     private static final int NUMBER_OF_CHILDREN_WHEN_COLLAPSED = 2;
     private static final int NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED = 5;
     private static final int NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED = 8;
+    private static final AnimationProperties ALPHA_FADE_IN = new AnimationProperties() {
+        private AnimationFilter mAnimationFilter = new AnimationFilter().animateAlpha();
+
+        @Override
+        public AnimationFilter getAnimationFilter() {
+            return mAnimationFilter;
+        }
+    }.setDuration(200);
 
     private final List<View> mDividers = new ArrayList<>();
     private final List<ExpandableNotificationRow> mChildren = new ArrayList<>();
@@ -64,7 +72,7 @@
     private float mCollapsedBottompadding;
     private ViewInvertHelper mOverflowInvertHelper;
     private boolean mChildrenExpanded;
-    private ExpandableNotificationRow mNotificationParent;
+    private ExpandableNotificationRow mContainingNotification;
     private TextView mOverflowNumber;
     private ViewState mGroupOverFlowState;
     private int mRealHeight;
@@ -75,10 +83,15 @@
 
     private NotificationHeaderView mNotificationHeader;
     private NotificationViewWrapper mNotificationHeaderWrapper;
+    private NotificationHeaderView mNotificationHeaderLowPriority;
+    private NotificationViewWrapper mNotificationHeaderWrapperLowPriority;
     private NotificationHeaderUtil mHeaderUtil;
     private ViewState mHeaderViewState;
     private int mClipBottomAmount;
     private boolean mIsLowPriority;
+    private boolean mHeaderVisible = true;
+    private OnClickListener mHeaderClickListener;
+    private boolean mShowingNormalHeader;
 
     public NotificationChildrenContainer(Context context) {
         this(context, null);
@@ -135,6 +148,11 @@
             mNotificationHeader.layout(0, 0, mNotificationHeader.getMeasuredWidth(),
                     mNotificationHeader.getMeasuredHeight());
         }
+        if (mNotificationHeaderLowPriority != null) {
+            mNotificationHeaderLowPriority.layout(0, 0,
+                    mNotificationHeaderLowPriority.getMeasuredWidth(),
+                    mNotificationHeaderLowPriority.getMeasuredHeight());
+        }
     }
 
     @Override
@@ -178,10 +196,14 @@
             height = Math.min(height, size);
         }
 
+        int headerHeightSpec = MeasureSpec.makeMeasureSpec(mHeaderHeight, MeasureSpec.EXACTLY);
         if (mNotificationHeader != null) {
-            int headerHeightSpec = MeasureSpec.makeMeasureSpec(mHeaderHeight, MeasureSpec.EXACTLY);
             mNotificationHeader.measure(widthMeasureSpec, headerHeightSpec);
         }
+        if (mNotificationHeaderLowPriority != null) {
+            headerHeightSpec = MeasureSpec.makeMeasureSpec(mHeaderHeight, MeasureSpec.EXACTLY);
+            mNotificationHeaderLowPriority.measure(widthMeasureSpec, headerHeightSpec);
+        }
 
         setMeasuredDimension(width, height);
     }
@@ -247,30 +269,66 @@
         return mChildren.size();
     }
 
-    public void recreateNotificationHeader(OnClickListener listener,
-            StatusBarNotification notification) {
+    public void recreateNotificationHeader(OnClickListener listener) {
+        mHeaderClickListener = listener;
+        StatusBarNotification notification = mContainingNotification.getStatusBarNotification();
         final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(),
-                mNotificationParent.getStatusBarNotification().getNotification());
-        final RemoteViews header = mIsLowPriority
-                ? builder.makeLowPriorityContentView(true /* useRegularSubtext */)
-                : builder.makeNotificationHeader();
+                notification.getNotification());
+        RemoteViews header = builder.makeNotificationHeader();
         if (mNotificationHeader == null) {
             mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this);
             final View expandButton = mNotificationHeader.findViewById(
                     com.android.internal.R.id.expand_button);
             expandButton.setVisibility(VISIBLE);
-            mNotificationHeader.setOnClickListener(listener);
+            mNotificationHeader.setOnClickListener(mHeaderClickListener);
             mNotificationHeaderWrapper = NotificationViewWrapper.wrap(getContext(),
-                    mNotificationHeader, mNotificationParent);
+                    mNotificationHeader, mContainingNotification);
             addView(mNotificationHeader, 0);
             invalidate();
         } else {
             header.reapply(getContext(), mNotificationHeader);
-            mNotificationHeaderWrapper.notifyContentUpdated(notification, mIsLowPriority);
         }
+        mNotificationHeaderWrapper.notifyContentUpdated(mContainingNotification);
+        recreateLowPriorityHeader(builder);
+        updateHeaderVisibility(false /* animate */);
         updateChildrenHeaderAppearance();
     }
 
+    /**
+     * Recreate the low-priority header.
+     *
+     * @param builder a builder to reuse. Otherwise the builder will be recovered.
+     */
+    private void recreateLowPriorityHeader(Notification.Builder builder) {
+        RemoteViews header;
+        StatusBarNotification notification = mContainingNotification.getStatusBarNotification();
+        if (mIsLowPriority) {
+            if (builder == null) {
+                builder = Notification.Builder.recoverBuilder(getContext(),
+                        notification.getNotification());
+            }
+            header = builder.makeLowPriorityContentView(true /* useRegularSubtext */);
+            if (mNotificationHeaderLowPriority == null) {
+                mNotificationHeaderLowPriority = (NotificationHeaderView) header.apply(getContext(),
+                        this);
+                final View expandButton = mNotificationHeaderLowPriority.findViewById(
+                        com.android.internal.R.id.expand_button);
+                expandButton.setVisibility(VISIBLE);
+                mNotificationHeaderLowPriority.setOnClickListener(mHeaderClickListener);
+                mNotificationHeaderWrapperLowPriority = NotificationViewWrapper.wrap(getContext(),
+                        mNotificationHeaderLowPriority, mContainingNotification);
+                addView(mNotificationHeaderLowPriority, 0);
+                invalidate();
+            } else {
+                header.reapply(getContext(), mNotificationHeaderLowPriority);
+            }
+            mNotificationHeaderWrapperLowPriority.notifyContentUpdated(mContainingNotification);
+        } else {
+            mNotificationHeaderLowPriority = null;
+            mNotificationHeaderWrapperLowPriority = null;
+        }
+    }
+
     public void updateChildrenHeaderAppearance() {
         mHeaderUtil.updateChildrenHeaderAppearance();
     }
@@ -371,9 +429,6 @@
      * @return the intrinsic size of this children container, i.e the natural fully expanded state
      */
     public int getIntrinsicHeight() {
-        if (mIsLowPriority && !mChildrenExpanded) {
-            return mNotificationHeader.getHeight();
-        }
         int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren();
         return getIntrinsicHeight(maxAllowedVisibleChildren);
     }
@@ -383,6 +438,9 @@
      *         in @param maxAllowedVisibleChildren
      */
     private int getIntrinsicHeight(float maxAllowedVisibleChildren) {
+        if (showingAsLowPriority()) {
+            return mNotificationHeaderLowPriority.getHeight();
+        }
         int intrinsicHeight = mNotificationHeaderMargin;
         int visibleChildren = 0;
         int childCount = mChildren.size();
@@ -442,24 +500,25 @@
         int lastVisibleIndex = maxAllowedVisibleChildren - 1;
         int firstOverflowIndex = lastVisibleIndex + 1;
         float expandFactor = 0;
+        boolean expandingToExpandedGroup = mUserLocked && !showingAsLowPriority();
         if (mUserLocked) {
             expandFactor = getGroupExpandFraction();
             firstOverflowIndex = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
         }
 
-        boolean childrenExpanded = !mNotificationParent.isGroupExpansionChanging()
+        boolean childrenExpanded = !mContainingNotification.isGroupExpansionChanging()
                 && mChildrenExpanded;
         for (int i = 0; i < childCount; i++) {
             ExpandableNotificationRow child = mChildren.get(i);
             if (!firstChild) {
-                if (mUserLocked) {
+                if (expandingToExpandedGroup) {
                     yPosition += NotificationUtils.interpolate(mChildPadding, mDividerHeight,
                             expandFactor);
                 } else {
                     yPosition += mChildrenExpanded ? mDividerHeight : mChildPadding;
                 }
             } else {
-                if (mUserLocked) {
+                if (expandingToExpandedGroup) {
                     yPosition += NotificationUtils.interpolate(
                             0,
                             mNotificatonTopPadding + mDividerHeight,
@@ -478,7 +537,7 @@
             // When the group is expanded, the children cast the shadows rather than the parent
             // so use the parent's elevation here.
             childState.zTranslation = childrenExpanded
-                    ? mNotificationParent.getTranslationZ()
+                    ? mContainingNotification.getTranslationZ()
                     : 0;
             childState.dimmed = parentState.dimmed;
             childState.dark = parentState.dark;
@@ -487,7 +546,7 @@
             childState.clipTopAmount = 0;
             childState.alpha = 0;
             if (i < firstOverflowIndex) {
-                childState.alpha = mIsLowPriority && !mChildrenExpanded ? expandFactor : 1.0f;
+                childState.alpha = showingAsLowPriority() ? expandFactor : 1.0f;
             } else if (expandFactor == 1.0f && i <= lastVisibleIndex) {
                 childState.alpha = (mActualHeight - childState.yTranslation) / childState.height;
                 childState.alpha = Math.max(0.0f, Math.min(1.0f, childState.alpha));
@@ -526,7 +585,7 @@
             }
             mHeaderViewState.initFrom(mNotificationHeader);
             mHeaderViewState.zTranslation = childrenExpanded
-                    ? mNotificationParent.getTranslationZ()
+                    ? mContainingNotification.getTranslationZ()
                     : 0;
         }
     }
@@ -561,11 +620,11 @@
     }
 
     private int getMaxAllowedVisibleChildren(boolean likeCollapsed) {
-        if (!likeCollapsed && (mChildrenExpanded || mNotificationParent.isUserLocked())) {
+        if (!likeCollapsed && (mChildrenExpanded || mContainingNotification.isUserLocked())) {
             return NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED;
         }
-        if (!mNotificationParent.isOnKeyguard()
-                && (mNotificationParent.isExpanded() || mNotificationParent.isHeadsUp())) {
+        if (mIsLowPriority || !mContainingNotification.isOnKeyguard()
+                && (mContainingNotification.isExpanded() || mContainingNotification.isHeadsUp())) {
             return NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED;
         }
         return NUMBER_OF_CHILDREN_WHEN_COLLAPSED;
@@ -578,8 +637,8 @@
         if (mUserLocked) {
             expandFraction = getGroupExpandFraction();
         }
-        final boolean dividersVisible = mUserLocked
-                || mNotificationParent.isGroupExpansionChanging();
+        final boolean dividersVisible = mUserLocked && !showingAsLowPriority()
+                || mContainingNotification.isGroupExpansionChanging();
         for (int i = 0; i < childCount; i++) {
             ExpandableNotificationRow child = mChildren.get(i);
             ExpandableViewState viewState = state.getViewStateForView(child);
@@ -590,7 +649,7 @@
             tmpState.initFrom(divider);
             tmpState.yTranslation = viewState.yTranslation - mDividerHeight;
             float alpha = mChildrenExpanded && viewState.alpha != 0 ? 0.5f : 0;
-            if (mUserLocked && viewState.alpha != 0) {
+            if (mUserLocked && !showingAsLowPriority() && viewState.alpha != 0) {
                 alpha = NotificationUtils.interpolate(0, 0.5f,
                         Math.min(viewState.alpha, expandFraction));
             }
@@ -612,7 +671,7 @@
 
     private void updateChildrenClipping() {
         int childCount = mChildren.size();
-        int layoutEnd = mNotificationParent.getActualHeight() - mClipBottomAmount;
+        int layoutEnd = mContainingNotification.getActualHeight() - mClipBottomAmount;
         for (int i = 0; i < childCount; i++) {
             ExpandableNotificationRow child = mChildren.get(i);
             if (child.getVisibility() == GONE) {
@@ -652,8 +711,8 @@
         int childCount = mChildren.size();
         ViewState tmpState = new ViewState();
         float expandFraction = getGroupExpandFraction();
-        final boolean dividersVisible = mUserLocked
-                || mNotificationParent.isGroupExpansionChanging();
+        final boolean dividersVisible = mUserLocked && !showingAsLowPriority()
+                || mContainingNotification.isGroupExpansionChanging();
         for (int i = childCount - 1; i >= 0; i--) {
             ExpandableNotificationRow child = mChildren.get(i);
             ExpandableViewState viewState = state.getViewStateForView(child);
@@ -664,7 +723,7 @@
             tmpState.initFrom(divider);
             tmpState.yTranslation = viewState.yTranslation - mDividerHeight;
             float alpha = mChildrenExpanded && viewState.alpha != 0 ? 0.5f : 0;
-            if (mUserLocked && viewState.alpha != 0) {
+            if (mUserLocked && !showingAsLowPriority() && viewState.alpha != 0) {
                 alpha = NotificationUtils.interpolate(0, 0.5f,
                         Math.min(viewState.alpha, expandFraction));
             }
@@ -718,23 +777,100 @@
         }
     }
 
-    public void setNotificationParent(ExpandableNotificationRow parent) {
-        mNotificationParent = parent;
-        mHeaderUtil = new NotificationHeaderUtil(mNotificationParent);
+    public void setContainingNotification(ExpandableNotificationRow parent) {
+        mContainingNotification = parent;
+        mHeaderUtil = new NotificationHeaderUtil(mContainingNotification);
     }
 
-    public ExpandableNotificationRow getNotificationParent() {
-        return mNotificationParent;
+    public ExpandableNotificationRow getContainingNotification() {
+        return mContainingNotification;
     }
 
     public NotificationHeaderView getHeaderView() {
         return mNotificationHeader;
     }
 
-    public void updateHeaderVisibility(int visiblity) {
-        if (mNotificationHeader != null) {
-            mNotificationHeader.setVisibility(visiblity);
+    public NotificationHeaderView getLowPriorityHeaderView() {
+        return mNotificationHeaderLowPriority;
+    }
+
+    public void setHeaderVisible(boolean visible) {
+        mHeaderVisible = visible;
+        updateHeaderVisibility(false /* animate */);
+    }
+
+    private void updateHeaderVisibility(boolean animate) {
+        NotificationHeaderView visibleHeader = mNotificationHeader;
+        NotificationHeaderView hiddenHeader = mNotificationHeaderLowPriority;
+        boolean normalHeaderVisible = true;
+        if (showingAsLowPriority()) {
+            visibleHeader = mNotificationHeaderLowPriority;
+            hiddenHeader = mNotificationHeader;
+            normalHeaderVisible = false;
         }
+        if (animate) {
+            if (mHeaderVisible && visibleHeader != null && hiddenHeader != null
+                    && mShowingNormalHeader != normalHeaderVisible) {
+                hiddenHeader.setVisibility(VISIBLE);
+                visibleHeader.setVisibility(VISIBLE);
+                NotificationViewWrapper visibleWrapper = getWrapperForView(visibleHeader);
+                NotificationViewWrapper hiddenWrapper = getWrapperForView(hiddenHeader);
+                visibleWrapper.transformFrom(hiddenWrapper);
+                hiddenWrapper.transformTo(visibleWrapper, () -> updateHeaderVisibility(false));
+                startChildAlphaAnimations(normalHeaderVisible);
+            } else {
+                animate = false;
+            }
+        }
+        if (!animate) {
+            if (visibleHeader != null) {
+                getWrapperForView(visibleHeader).setVisible(true);
+                visibleHeader.setVisibility(mHeaderVisible ? VISIBLE : INVISIBLE);
+            }
+            if (hiddenHeader != null) {
+                getWrapperForView(hiddenHeader).setVisible(false);
+                hiddenHeader.setVisibility(INVISIBLE);
+            }
+        }
+        mShowingNormalHeader = normalHeaderVisible;
+    }
+
+    private void startChildAlphaAnimations(boolean toVisible) {
+        float target = toVisible ? 1.0f : 0.0f;
+        float start = 1.0f - target;
+        int childCount = mChildren.size();
+        for (int i = 0; i < childCount; i++) {
+            if (i >= NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED) {
+                break;
+            }
+            ExpandableNotificationRow child = mChildren.get(i);
+            child.setAlpha(start);
+            ViewState viewState = new ViewState();
+            viewState.initFrom(child);
+            viewState.alpha = target;
+            ALPHA_FADE_IN.setDelay(i * 50);
+            viewState.animateTo(child, ALPHA_FADE_IN);
+        }
+    }
+
+
+    private void updateHeaderTransformation() {
+        if (mUserLocked && mHeaderVisible && showingAsLowPriority()) {
+            float fraction = getGroupExpandFraction();
+            mNotificationHeaderWrapper.transformFrom(mNotificationHeaderWrapperLowPriority,
+                    fraction);
+            mNotificationHeader.setVisibility(VISIBLE);
+            mNotificationHeaderWrapperLowPriority.transformTo(mNotificationHeaderWrapper,
+                    fraction);
+        }
+
+    }
+
+    private NotificationViewWrapper getWrapperForView(NotificationHeaderView visibleHeader) {
+        if (visibleHeader == mNotificationHeader) {
+            return mNotificationHeaderWrapper;
+        }
+        return mNotificationHeaderWrapperLowPriority;
     }
 
     /**
@@ -746,7 +882,7 @@
         if (mNotificationHeader != null) {
             if (expanded) {
                 ColorDrawable cd = new ColorDrawable();
-                cd.setColor(mNotificationParent.calculateBgColor());
+                cd.setColor(mContainingNotification.calculateBgColor());
                 mNotificationHeader.setHeaderBackgroundDrawable(cd);
             } else {
                 mNotificationHeader.setHeaderBackgroundDrawable(null);
@@ -755,6 +891,10 @@
     }
 
     public int getMaxContentHeight() {
+        if (showingAsLowPriority()) {
+            return getMinHeight(NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED, true
+                    /* likeHighPriority */);
+        }
         int maxContentHeight = mNotificationHeaderMargin + mNotificatonTopPadding;
         int visibleChildren = 0;
         int childCount = mChildren.size();
@@ -781,13 +921,21 @@
         }
         mActualHeight = actualHeight;
         float fraction = getGroupExpandFraction();
+        boolean showingLowPriority = showingAsLowPriority();
+        updateHeaderTransformation();
         int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */);
         int childCount = mChildren.size();
         for (int i = 0; i < childCount; i++) {
             ExpandableNotificationRow child = mChildren.get(i);
-            float childHeight = child.isExpanded(true /* allowOnKeyguard */)
-                    ? child.getMaxExpandHeight()
-                    : child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */);
+            float childHeight;
+            if (showingLowPriority) {
+                childHeight = child.getShowingLayout().getMinHeight(false /* likeGroupExpanded */);
+            } else if (child.isExpanded(true /* allowOnKeyguard */)) {
+                childHeight = child.getMaxExpandHeight();
+            } else {
+                childHeight = child.getShowingLayout().getMinHeight(
+                        true /* likeGroupExpanded */);
+            }
             if (i < maxAllowedVisibleChildren) {
                 float singleLineHeight = child.getShowingLayout().getMinHeight(
                         false /* likeGroupExpanded */);
@@ -800,7 +948,8 @@
     }
 
     public float getGroupExpandFraction() {
-        int visibleChildrenExpandedHeight = getVisibleChildrenExpandHeight();
+        int visibleChildrenExpandedHeight = showingAsLowPriority() ? getMaxContentHeight()
+                : getVisibleChildrenExpandHeight();
         int minExpandHeight = getCollapsedHeight();
         float factor = (mActualHeight - minExpandHeight)
                 / (float) (visibleChildrenExpandedHeight - minExpandHeight);
@@ -827,16 +976,23 @@
     }
 
     public int getMinHeight() {
-        return getMinHeight(NUMBER_OF_CHILDREN_WHEN_COLLAPSED);
+        return getMinHeight(NUMBER_OF_CHILDREN_WHEN_COLLAPSED, false /* likeHighPriority */);
     }
 
     public int getCollapsedHeight() {
-        return getMinHeight(getMaxAllowedVisibleChildren(true /* forceCollapsed */));
+        return getMinHeight(getMaxAllowedVisibleChildren(true /* forceCollapsed */),
+                false /* likeHighPriority */);
     }
 
-    private int getMinHeight(int maxAllowedVisibleChildren) {
-        if (mIsLowPriority && !mChildrenExpanded) {
-            return mNotificationHeader.getHeight();
+    /**
+     * Get the minimum Height for this group.
+     *
+     * @param maxAllowedVisibleChildren the number of children that should be visible
+     * @param likeHighPriority if the height should be calculated as if it were not low priority
+     */
+    private int getMinHeight(int maxAllowedVisibleChildren, boolean likeHighPriority) {
+        if (!likeHighPriority && showingAsLowPriority()) {
+            return mNotificationHeaderLowPriority.getHeight();
         }
         int minExpandHeight = mNotificationHeaderMargin;
         int visibleChildren = 0;
@@ -859,6 +1015,10 @@
         return minExpandHeight;
     }
 
+    public boolean showingAsLowPriority() {
+        return mIsLowPriority && !mContainingNotification.isExpanded();
+    }
+
     public void setDark(boolean dark, boolean fade, long delay) {
         if (mOverflowNumber != null) {
             mOverflowInvertHelper.setInverted(dark, fade, delay);
@@ -867,9 +1027,15 @@
     }
 
     public void reInflateViews(OnClickListener listener, StatusBarNotification notification) {
-        removeView(mNotificationHeader);
-        mNotificationHeader = null;
-        recreateNotificationHeader(listener, notification);
+        if (mNotificationHeader != null) {
+            removeView(mNotificationHeader);
+            mNotificationHeader = null;
+        }
+        if (mNotificationHeaderLowPriority != null) {
+            removeView(mNotificationHeaderLowPriority);
+            mNotificationHeaderLowPriority = null;
+        }
+        recreateNotificationHeader(listener);
         initDimens();
         for (int i = 0; i < mDividers.size(); i++) {
             View prevDivider = mDividers.get(i);
@@ -888,16 +1054,19 @@
 
     public void setUserLocked(boolean userLocked) {
         mUserLocked = userLocked;
+        if (!mUserLocked) {
+            updateHeaderVisibility(false /* animate */);
+        }
         int childCount = mChildren.size();
         for (int i = 0; i < childCount; i++) {
             ExpandableNotificationRow child = mChildren.get(i);
-            child.setUserLocked(userLocked);
+            child.setUserLocked(userLocked && !showingAsLowPriority());
         }
     }
 
     public void onNotificationUpdated() {
         mHybridGroupManager.setOverflowNumberColor(mOverflowNumber,
-                mNotificationParent.getNotificationColor());
+                mContainingNotification.getNotificationColor());
     }
 
     public int getPositionInLinearLayout(View childInGroup) {
@@ -926,6 +1095,13 @@
                 header.getIcon().setForceHidden(!iconsVisible);
             }
         }
+        if (mNotificationHeaderWrapperLowPriority != null) {
+            NotificationHeaderView header
+                    = mNotificationHeaderWrapperLowPriority.getNotificationHeader();
+            if (header != null) {
+                header.getIcon().setForceHidden(!iconsVisible);
+            }
+        }
     }
 
     public void setClipBottomAmount(int clipBottomAmount) {
@@ -935,5 +1111,36 @@
 
     public void setIsLowPriority(boolean isLowPriority) {
         mIsLowPriority = isLowPriority;
+        if (mContainingNotification != null) { /* we're not yet set up yet otherwise */
+            recreateLowPriorityHeader(null /* existingBuilder */);
+            updateHeaderVisibility(false /* animate */);
+        }
+        if (mUserLocked) {
+            setUserLocked(mUserLocked);
+        }
+    }
+
+    public NotificationHeaderView getVisibleHeader() {
+        NotificationHeaderView header = mNotificationHeader;
+        if (showingAsLowPriority()) {
+            header = mNotificationHeaderLowPriority;
+        }
+        return header;
+    }
+
+    public void onExpansionChanged() {
+        if (mIsLowPriority) {
+            if (mUserLocked) {
+                setUserLocked(mUserLocked);
+            }
+            updateHeaderVisibility(true /* animate */);
+        }
+    }
+
+    public float getIncreasedPaddingAmount() {
+        if (showingAsLowPriority()) {
+            return 0.0f;
+        }
+        return getGroupExpandFraction();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
index e0a6159..624fd3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
@@ -136,7 +136,7 @@
         yTranslation = view.getTranslationY();
         zTranslation = view.getTranslationZ();
         gone = view.getVisibility() == View.GONE;
-        hidden = false;
+        hidden = view.getVisibility() == View.INVISIBLE;
         scaleX = view.getScaleX();
         scaleY = view.getScaleY();
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
index d07cea1..f016aa1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
@@ -52,11 +52,11 @@
         RemoteViews views = new RemoteViews(mContext.getPackageName(), R.layout.custom_view_dark);
         View v = views.apply(mContext, null);
         NotificationViewWrapper wrap = NotificationCustomViewWrapper.wrap(mContext, v, mRow);
-        wrap.notifyContentUpdated(null, false /* isLowPriority */);
+        wrap.notifyContentUpdated(mRow);
         Assert.assertTrue(wrap.getCustomBackgroundColor() != 0);
         views.reapply(mContext, v);
-        wrap.notifyContentUpdated(null, false /* isLowPriority */);
+        wrap.notifyContentUpdated(mRow);
         Assert.assertTrue(wrap.getCustomBackgroundColor() != 0);
     }
 
-}
\ No newline at end of file
+}