Improved the transitions and layout of the app name in conversations

The transition was using getTop instead of absolute positions which
didn't work well for the conversation layout.
Also, we were fading in views that were GONE and making them VISIBLE
which lead to bugs during the transitions.
Additionally, the header text would become visible when a notification
was removed from a group and reset.

Bug: 150905003
Test: visual, add conversations in groups and non-groups
Change-Id: I3c31006a1fc79f7d58cc1dd3d5af44129c9f02bb
diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java
index 49cf3e0..4e7ae8a 100644
--- a/core/java/com/android/internal/widget/ConversationLayout.java
+++ b/core/java/com/android/internal/widget/ConversationLayout.java
@@ -469,6 +469,10 @@
         mAppName.setVisibility(mIsCollapsed ? GONE : VISIBLE);
     }
 
+    public boolean shouldHideAppName() {
+        return mIsCollapsed;
+    }
+
     /**
      * update the icon position and sizing
      */
diff --git a/core/res/res/layout/notification_template_material_conversation.xml b/core/res/res/layout/notification_template_material_conversation.xml
index 0c4be1a..0f895d6 100644
--- a/core/res/res/layout/notification_template_material_conversation.xml
+++ b/core/res/res/layout/notification_template_material_conversation.xml
@@ -122,6 +122,7 @@
                     android:layout_height="wrap_content"
                     android:orientation="horizontal"
                     android:paddingTop="16dp"
+                    android:layout_marginBottom="2dp"
                     android:paddingStart="@dimen/conversation_content_start"
                 >
                     <TextView
@@ -180,8 +181,8 @@
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_marginStart="@dimen/conversation_content_start"
-                    android:paddingBottom="16dp"
                     android:textSize="12sp"
+                    android:layout_marginBottom="16dp"
                     android:textAppearance="@style/TextAppearance.DeviceDefault.Notification"
                 />
 
@@ -190,7 +191,6 @@
                     android:id="@+id/notification_messaging"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
-                    android:layout_marginTop="2dp"
                     android:spacing="@dimen/notification_messaging_spacing"
                     android:clipToPadding="false"
                     android:clipChildren="false"
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index abc9692..f2e2599 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -695,9 +695,9 @@
     <!-- size of the notification badge when applied to the conversation icon -->
     <dimen name="conversation_icon_size_badged">20dp</dimen>
     <!-- size of the notification badge when centered in a conversation -->
-    <dimen name="conversation_icon_size_centered">25dp</dimen>
+    <dimen name="conversation_icon_size_centered">26dp</dimen>
     <!-- margin on the top when the icon is centered for group conversations -->
-    <dimen name="conversation_icon_margin_top_centered">5dp</dimen>
+    <dimen name="conversation_icon_margin_top_centered">12dp</dimen>
 
     <!-- The padding of the conversation header when expanded. This is calculated from the expand button size + notification_content_margin_end -->
     <dimen name="conversation_header_expanded_padding_end">38dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java
index 164215b..b57b22f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java
@@ -50,7 +50,9 @@
                         if (endRunnable != null) {
                             endRunnable.run();
                         }
-                        view.setVisibility(View.INVISIBLE);
+                        if (view.getVisibility() != View.GONE) {
+                            view.setVisibility(View.INVISIBLE);
+                        }
                     }
                 });
         if (view.hasOverlappingRendering()) {
@@ -75,7 +77,7 @@
      */
     public static void fadeOut(View view, float fadeOutAmount, boolean remap) {
         view.animate().cancel();
-        if (fadeOutAmount == 1.0f) {
+        if (fadeOutAmount == 1.0f && view.getVisibility() != View.GONE) {
             view.setVisibility(View.INVISIBLE);
         } else if (view.getVisibility() == View.INVISIBLE) {
             view.setVisibility(View.VISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
index 4759d56..ba3db09 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
@@ -28,6 +28,7 @@
 import android.widget.TextView;
 
 import com.android.internal.util.ContrastColorUtil;
+import com.android.internal.widget.ConversationLayout;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.NotificationContentView;
 
@@ -42,6 +43,7 @@
 
     private static final TextViewComparator sTextViewComparator = new TextViewComparator();
     private static final VisibilityApplicator sVisibilityApplicator = new VisibilityApplicator();
+    private static final VisibilityApplicator sAppNameApplicator = new AppNameApplicator();
     private static  final DataExtractor sIconExtractor = new DataExtractor() {
         @Override
         public Object extractData(ExpandableNotificationRow row) {
@@ -64,7 +66,7 @@
     };
     private final static ResultApplicator mGreyApplicator = new ResultApplicator() {
         @Override
-        public void apply(View view, boolean apply) {
+        public void apply(View parent, View view, boolean apply, boolean reset) {
             NotificationHeaderView header = (NotificationHeaderView) view;
             ImageView icon = (ImageView) view.findViewById(
                     com.android.internal.R.id.icon);
@@ -132,8 +134,12 @@
                     }
                 },
                 sVisibilityApplicator));
-        mComparators.add(HeaderProcessor.forTextView(mRow,
-                com.android.internal.R.id.app_name_text));
+        mComparators.add(new HeaderProcessor(
+                mRow,
+                com.android.internal.R.id.app_name_text,
+                null,
+                sTextViewComparator,
+                sAppNameApplicator));
         mComparators.add(HeaderProcessor.forTextView(mRow,
                 com.android.internal.R.id.header_text));
         mDividers.add(com.android.internal.R.id.header_text_divider);
@@ -299,19 +305,19 @@
         public void apply(ExpandableNotificationRow row, boolean reset) {
             boolean apply = mApply && !reset;
             if (row.isSummaryWithChildren()) {
-                applyToView(apply, row.getNotificationHeader());
+                applyToView(apply, reset, row.getNotificationHeader());
                 return;
             }
-            applyToView(apply, row.getPrivateLayout().getContractedChild());
-            applyToView(apply, row.getPrivateLayout().getHeadsUpChild());
-            applyToView(apply, row.getPrivateLayout().getExpandedChild());
+            applyToView(apply, reset, row.getPrivateLayout().getContractedChild());
+            applyToView(apply, reset, row.getPrivateLayout().getHeadsUpChild());
+            applyToView(apply, reset, row.getPrivateLayout().getExpandedChild());
         }
 
-        private void applyToView(boolean apply, View parent) {
+        private void applyToView(boolean apply, boolean reset, View parent) {
             if (parent != null) {
                 View view = parent.findViewById(mId);
                 if (view != null && !mComparator.isEmpty(view)) {
-                    mApplicator.apply(view, apply);
+                    mApplicator.apply(parent, view, apply, reset);
                 }
             }
         }
@@ -375,14 +381,26 @@
     }
 
     private interface ResultApplicator {
-        void apply(View view, boolean apply);
+        void apply(View parent, View view, boolean apply, boolean reset);
     }
 
     private static class VisibilityApplicator implements ResultApplicator {
 
         @Override
-        public void apply(View view, boolean apply) {
+        public void apply(View parent, View view, boolean apply, boolean reset) {
             view.setVisibility(apply ? View.GONE : View.VISIBLE);
         }
     }
+
+    private static class AppNameApplicator extends VisibilityApplicator {
+
+        @Override
+        public void apply(View parent, View view, boolean apply, boolean reset) {
+            if (reset && parent instanceof ConversationLayout) {
+                ConversationLayout layout = (ConversationLayout) parent;
+                apply = layout.shouldHideAppName();
+            }
+            super.apply(parent, view, apply, reset);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
index 6f27ff3..5ee4693 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
@@ -102,11 +102,11 @@
             MessagingGroup matchingGroup = pairs.get(ownGroup);
             if (!isGone(ownGroup)) {
                 if (matchingGroup != null) {
-                    transformGroups(ownGroup, matchingGroup, transformationAmount, to);
+                    int totalTranslation = transformGroups(ownGroup, matchingGroup,
+                            transformationAmount, to);
                     if (lastPairedGroup == null) {
                         lastPairedGroup = ownGroup;
                         if (to){
-                            float totalTranslation = ownGroup.getTop() - matchingGroup.getTop();
                             currentTranslation = matchingGroup.getAvatar().getTranslationY()
                                     - totalTranslation;
                         } else {
@@ -229,14 +229,19 @@
         return result;
     }
 
-    private void transformGroups(MessagingGroup ownGroup, MessagingGroup otherGroup,
+    /**
+     * Transform two groups towards each other.
+     *
+     * @return the total transformation distance that the group goes through
+     */
+    private int transformGroups(MessagingGroup ownGroup, MessagingGroup otherGroup,
             float transformationAmount, boolean to) {
         boolean useLinearTransformation =
                 otherGroup.getIsolatedMessage() == null && !mTransformInfo.isAnimating();
         transformView(transformationAmount, to, ownGroup.getSenderView(), otherGroup.getSenderView(),
                 true /* sameAsAny */, useLinearTransformation);
-        transformView(transformationAmount, to, ownGroup.getAvatar(), otherGroup.getAvatar(),
-                true /* sameAsAny */, useLinearTransformation);
+        int totalAvatarTranslation = transformView(transformationAmount, to, ownGroup.getAvatar(),
+                otherGroup.getAvatar(), true /* sameAsAny */, useLinearTransformation);
         List<MessagingMessage> ownMessages = ownGroup.getMessages();
         List<MessagingMessage> otherMessages = otherGroup.getMessages();
         float previousTranslation = 0;
@@ -284,6 +289,7 @@
             }
         }
         ownGroup.updateClipRect();
+        return totalAvatarTranslation;
     }
 
     /**