Lazy async group notification views inflation

Use the result of the notification pipeline grouping to inflate the single-line and group summary views instead of the grouping status of status bar notification. This change can reduce the views to inflate to optimize memory usage.

Bug: 217799515
Test: atest NotifUiAdjustmentProviderTest
Flag: ACONFIG notification_async_hybrid_view_inflation STAGING
ACONFIG notification_async_group_header_inflation DEVELOPMENT

Change-Id: If33f4862b540754dc67651b06f5fa354fb23aa8c
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index d821074..264b53c 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -174,23 +174,6 @@
         return sbnKey;
     }
 
-    /**
-     * @return Whether the Entry is a group child by the app or system
-     * @hide
-     */
-    public boolean isAppOrSystemGroupChild() {
-        return isGroup() && !getNotification().isGroupSummary();
-    }
-
-
-    /**
-     * @return Whether the Entry is a group summary by the app or system
-     * @hide
-     */
-    public boolean isAppOrSystemGroupSummary() {
-        return isGroup() && getNotification().isGroupSummary();
-    }
-
     private String groupKey() {
         if (overrideGroupKey != null) {
             return user.getIdentifier() + "|" + pkg + "|" + "g:" + overrideGroupKey;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 8cdf60b..c1dd992 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -171,6 +171,9 @@
     private boolean mIsMarkedForUserTriggeredMovement;
     private boolean mIsHeadsUpEntry;
 
+    private boolean mHasEverBeenGroupSummary;
+    private boolean mHasEverBeenGroupChild;
+
     public boolean mRemoteEditImeAnimatingAway;
     public boolean mRemoteEditImeVisible;
     private boolean mExpandAnimationRunning;
@@ -217,6 +220,26 @@
         mIsDemoted = true;
     }
 
+    /** called when entry is currently a summary of a group */
+    public void markAsGroupSummary() {
+        mHasEverBeenGroupSummary = true;
+    }
+
+    /** whether this entry has ever been marked as a summary */
+    public boolean hasEverBeenGroupSummary() {
+        return mHasEverBeenGroupSummary;
+    }
+
+    /** called when entry is currently a child in a group */
+    public void markAsGroupChild() {
+        mHasEverBeenGroupChild = true;
+    }
+
+    /** whether this entry has ever been marked as a child */
+    public boolean hasEverBeenGroupChild() {
+        return mHasEverBeenGroupChild;
+    }
+
     /**
      * @param sbn the StatusBarNotification from system server
      * @param ranking also from system server
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
index 7a7b184..9b075a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
@@ -49,6 +49,8 @@
 import com.android.systemui.statusbar.notification.collection.render.NotifViewController;
 import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager;
 import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager.NotifInflationErrorListener;
+import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation;
+import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -273,10 +275,14 @@
 
     private void inflateRequiredGroupViews(GroupEntry groupEntry) {
         NotificationEntry summary = groupEntry.getSummary();
+        if (summary != null && AsyncGroupHeaderViewInflation.isEnabled()) {
+            summary.markAsGroupSummary();
+        }
         List<NotificationEntry> children = groupEntry.getChildren();
         inflateRequiredNotifViews(summary);
         for (int j = 0; j < children.size(); j++) {
             NotificationEntry child = children.get(j);
+            if (AsyncHybridViewInflation.isEnabled()) child.markAsGroupChild();
             boolean childShouldBeBound = j < mChildBindCutoff;
             if (childShouldBeBound) {
                 inflateRequiredNotifViews(child);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustment.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustment.kt
index bab94b5..e70fb6b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustment.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustment.kt
@@ -52,11 +52,8 @@
             oldAdjustment.needsRedaction != newAdjustment.needsRedaction -> true
             areDifferent(oldAdjustment.smartActions, newAdjustment.smartActions) -> true
             newAdjustment.smartReplies != oldAdjustment.smartReplies -> true
-            // TODO(b/217799515): Here we decide whether to re-inflate the row on every group-status
-            //  change if we want to keep the single-line view, the following line should be:
-            //  !oldAdjustment.isChildInGroup && newAdjustment.isChildInGroup -> true
             AsyncHybridViewInflation.isEnabled &&
-                    oldAdjustment.isChildInGroup != newAdjustment.isChildInGroup -> true
+                    !oldAdjustment.isChildInGroup && newAdjustment.isChildInGroup -> true
             AsyncGroupHeaderViewInflation.isEnabled &&
                 !oldAdjustment.isGroupSummary && newAdjustment.isGroupSummary -> true
             else -> false
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
index e0e5a35..4c2ef83 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
@@ -141,7 +141,7 @@
             lockscreenUserManager.needsRedaction(entry) ||
                 (screenshareNotificationHiding() &&
                     sensitiveNotifProtectionController.shouldProtectNotification(entry)),
-        isChildInGroup = entry.sbn.isAppOrSystemGroupChild,
-        isGroupSummary = entry.sbn.isAppOrSystemGroupSummary,
+        isChildInGroup = entry.hasEverBeenGroupChild(),
+        isGroupSummary = entry.hasEverBeenGroupSummary(),
     )
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt
index 34eeba0..8e6cecc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt
@@ -49,7 +49,6 @@
 import org.junit.runner.RunWith
 import org.mockito.Mockito.clearInvocations
 import org.mockito.Mockito.inOrder
-import org.mockito.Mockito.spy
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.verifyNoMoreInteractions
 import org.mockito.Mockito.`when` as whenever
@@ -158,17 +157,14 @@
 
     @Test
     @EnableFlags(AsyncHybridViewInflation.FLAG_NAME)
-    fun changeIsChildInGroup_asyncHybirdFlagEnabled_needReInflation() {
+    fun becomeChildInGroup_asyncHybirdFlagEnabled_needReInflation() {
         // Given: an Entry that is not child in group
         // AsyncHybridViewInflation flag is enabled
-        val spySbn = spy(entry.sbn)
-        entry.sbn = spySbn
-        whenever(spySbn.isAppOrSystemGroupChild).thenReturn(false)
         val oldAdjustment = adjustmentProvider.calculateAdjustment(entry)
         assertThat(oldAdjustment.isChildInGroup).isFalse()
 
         // When: the Entry becomes a group child
-        whenever(spySbn.isAppOrSystemGroupChild).thenReturn(true)
+        entry.markAsGroupChild()
         val newAdjustment = adjustmentProvider.calculateAdjustment(entry)
         assertThat(newAdjustment.isChildInGroup).isTrue()
         assertThat(newAdjustment).isNotEqualTo(oldAdjustment)
@@ -179,17 +175,14 @@
 
     @Test
     @DisableFlags(AsyncHybridViewInflation.FLAG_NAME)
-    fun changeIsChildInGroup_asyncHybirdFlagDisabled_noNeedForReInflation() {
+    fun becomeChildInGroup_asyncHybirdFlagDisabled_noNeedForReInflation() {
         // Given: an Entry that is not child in group
         // AsyncHybridViewInflation flag is disabled
-        val spySbn = spy(entry.sbn)
-        entry.sbn = spySbn
-        whenever(spySbn.isAppOrSystemGroupChild).thenReturn(false)
         val oldAdjustment = adjustmentProvider.calculateAdjustment(entry)
         assertThat(oldAdjustment.isChildInGroup).isFalse()
 
         // When: the Entry becomes a group child
-        whenever(spySbn.isAppOrSystemGroupChild).thenReturn(true)
+        entry.markAsGroupChild()
         val newAdjustment = adjustmentProvider.calculateAdjustment(entry)
         assertThat(newAdjustment.isChildInGroup).isTrue()
         assertThat(newAdjustment).isNotEqualTo(oldAdjustment)
@@ -202,14 +195,11 @@
     @EnableFlags(AsyncGroupHeaderViewInflation.FLAG_NAME)
     fun changeIsGroupSummary_needReInflation() {
         // Given: an Entry that is not a group summary
-        val spySbn = spy(entry.sbn)
-        entry.sbn = spySbn
-        whenever(spySbn.isAppOrSystemGroupSummary).thenReturn(false)
         val oldAdjustment = adjustmentProvider.calculateAdjustment(entry)
         assertThat(oldAdjustment.isGroupSummary).isFalse()
 
         // When: the Entry becomes a group summary
-        whenever(spySbn.isAppOrSystemGroupSummary).thenReturn(true)
+        entry.markAsGroupSummary()
         val newAdjustment = adjustmentProvider.calculateAdjustment(entry)
         assertThat(newAdjustment.isGroupSummary).isTrue()
         assertThat(newAdjustment).isNotEqualTo(oldAdjustment)