summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java95
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java44
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java99
3 files changed, 226 insertions, 12 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index 92ceb604d2e0..c376fad1503f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -70,6 +70,8 @@ import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.notification.ColorUpdateLogger;
import com.android.systemui.statusbar.notification.ConversationNotificationProcessor;
+import com.android.systemui.statusbar.notification.collection.GroupEntry;
+import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
@@ -106,6 +108,7 @@ import kotlinx.coroutines.test.TestScope;
import org.mockito.ArgumentCaptor;
+import java.util.List;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
@@ -338,6 +341,46 @@ public class NotificationTestHelper {
}
/**
+ * Returns an {@link GroupEntry} group with the given number of child
+ * notifications.
+ */
+ public GroupEntry createGroupEntry(int numChildren,
+ @Nullable List<NotificationEntry> additionalChildren) {
+ Notification summary = new Notification.Builder(mContext, "")
+ .setSmallIcon(R.drawable.ic_person)
+ .setGroupSummary(true)
+ .setGroup(GROUP_KEY)
+ .build();
+
+ NotificationEntry summaryEntry = new NotificationEntryBuilder()
+ .setPkg(PKG)
+ .setOpPkg(PKG)
+ .setId(mId++)
+ .setUid(UID)
+ .setInitialPid(2000)
+ .setNotification(summary)
+ .setParent(GroupEntry.ROOT_ENTRY)
+ .build();
+ GroupEntryBuilder groupEntry = new GroupEntryBuilder()
+ .setSummary(summaryEntry);
+
+ for (int i = 0; i < numChildren; i++) {
+ NotificationEntry child = new NotificationEntryBuilder()
+ .setParent(GroupEntry.ROOT_ENTRY)
+ .setNotification(new Notification.Builder(mContext, "")
+ .setSmallIcon(R.drawable.ic_person)
+ .setGroup(GROUP_KEY)
+ .build())
+ .build();
+ groupEntry.addChild(child);
+ }
+ for (NotificationEntry entry : additionalChildren) {
+ groupEntry.addChild(entry);
+ }
+ return groupEntry.build();
+ }
+
+ /**
* Returns an {@link ExpandableNotificationRow} group with the given number of child
* notifications.
*/
@@ -411,6 +454,23 @@ public class NotificationTestHelper {
}
/**
+ * Returns an {@link NotificationEntry} that should be shown as a bubble and is part
+ * of a group of notifications.
+ */
+ public NotificationEntry createBubbleEntryInGroup() throws Exception {
+ Notification n = createNotification(false /* isGroupSummary */,
+ GROUP_KEY /* groupKey */,
+ makeBubbleMetadata(null /* deleteIntent */, false /* autoExpand */));
+ n.flags |= FLAG_BUBBLE;
+ NotificationEntry entry = generateEntry(n, PKG, UID, USER_HANDLE,
+ mDefaultInflationFlags, IMPORTANCE_HIGH);
+ modifyRanking(entry)
+ .setCanBubble(true)
+ .build();
+ return entry;
+ }
+
+ /**
* Returns an {@link ExpandableNotificationRow} that should be shown as a bubble and is part
* of a group of notifications.
*/
@@ -573,6 +633,41 @@ public class NotificationTestHelper {
return mKeyguardBypassController;
}
+ private NotificationEntry generateEntry(
+ Notification notification,
+ String pkg,
+ int uid,
+ UserHandle userHandle,
+ @InflationFlag int extraInflationFlags,
+ int importance)
+ throws Exception {
+ final NotificationChannel channel =
+ new NotificationChannel(
+ notification.getChannelId(),
+ notification.getChannelId(),
+ importance);
+ channel.setBlockable(true);
+
+ NotificationEntry entry = new NotificationEntryBuilder()
+ .setPkg(pkg)
+ .setOpPkg(pkg)
+ .setId(mId++)
+ .setUid(uid)
+ .setInitialPid(2000)
+ .setNotification(notification)
+ .setUser(userHandle)
+ .setPostTime(System.currentTimeMillis())
+ .setChannel(channel)
+ .updateRanking(rankingBuilder -> rankingBuilder.setIsConversation(
+ notification.isStyle(Notification.MessagingStyle.class)
+ ))
+ .build();
+
+
+ return entry;
+ }
+
+
private ExpandableNotificationRow generateRow(
Notification notification,
String pkg,
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 fb2a66c94e09..c072ede250e1 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
@@ -589,25 +589,45 @@ public final class NotificationEntry extends ListEntry {
/**
* Get the children that are actually attached to this notification's row.
*
- * TODO: Seems like most callers here should probably be using
- * {@link GroupMembershipManager#getChildren(PipelineEntry)}
+ * TODO: Seems like most callers here should be asking a PipelineEntry, not a NotificationEntry
*/
public @Nullable List<NotificationEntry> getAttachedNotifChildren() {
- if (row == null) {
- return null;
- }
+ if (NotificationBundleUi.isEnabled()) {
+ if (isGroupSummary()) {
+ return ((GroupEntry) getParent()).getChildren();
+ }
+ } else {
+ if (row == null) {
+ return null;
+ }
- List<ExpandableNotificationRow> rowChildren = row.getAttachedChildren();
- if (rowChildren == null) {
- return null;
+ List<ExpandableNotificationRow> rowChildren = row.getAttachedChildren();
+ if (rowChildren == null) {
+ return null;
+ }
+
+ ArrayList<NotificationEntry> children = new ArrayList<>();
+ for (ExpandableNotificationRow child : rowChildren) {
+ children.add(child.getEntry());
+ }
+
+ return children;
}
+ return null;
+ }
- ArrayList<NotificationEntry> children = new ArrayList<>();
- for (ExpandableNotificationRow child : rowChildren) {
- children.add(child.getEntry());
+ private boolean isGroupSummary() {
+ if (getParent() == null) {
+ // The entry is not attached, so it doesn't count.
+ return false;
+ }
+ PipelineEntry pipelineEntry = getParent();
+ if (!(pipelineEntry instanceof GroupEntry groupEntry)) {
+ return false;
}
- return children;
+ // If entry is a summary, its parent is a GroupEntry with summary = entry.
+ return groupEntry.getSummary() == this;
}
public void notifyFullScreenIntentLaunched() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index 5e9582593422..8281132e7502 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -135,6 +135,8 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
+import com.android.systemui.statusbar.notification.collection.GroupEntry;
+import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -151,6 +153,7 @@ import com.android.systemui.statusbar.notification.interruption.VisualInterrupti
import com.android.systemui.statusbar.notification.interruption.VisualInterruptionDecisionProviderTestUtil;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.shared.NotificationBundleUi;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -1229,8 +1232,36 @@ public class BubblesTest extends SysuiTestCase {
}
@Test
+ @EnableFlags(NotificationBundleUi.FLAG_NAME)
public void testBubbleSummaryDismissal_suppressesSummaryAndBubbleFromShade() throws Exception {
// GIVEN a group summary with a bubble child
+ NotificationEntry groupedBubble = mNotificationTestHelper.createBubbleEntryInGroup();
+ GroupEntry groupSummary = mNotificationTestHelper.createGroupEntry(
+ 0, List.of(groupedBubble));
+ mEntryListener.onEntryAdded(groupedBubble);
+ when(mCommonNotifCollection.getEntry(groupedBubble.getKey()))
+ .thenReturn(groupedBubble);
+ assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getKey()));
+
+ // WHEN the summary is dismissed
+ mBubblesManager.handleDismissalInterception(groupSummary.getSummary());
+
+ // THEN the summary and bubbled child are suppressed from the shade
+ assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+ groupedBubble.getKey(),
+ groupedBubble.getSbn().getGroupKey()));
+ assertTrue(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
+ groupedBubble.getKey(),
+ groupedBubble.getSbn().getGroupKey()));
+ assertTrue(mBubbleData.isSummarySuppressed(
+ groupSummary.getSummary().getSbn().getGroupKey()));
+ }
+
+ @Test
+ @DisableFlags(NotificationBundleUi.FLAG_NAME)
+ public void testBubbleSummaryDismissal_suppressesSummaryAndBubbleFromShade_rows()
+ throws Exception {
+ // GIVEN a group summary with a bubble child
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
mEntryListener.onEntryAdded(groupedBubble.getEntry());
@@ -1253,8 +1284,33 @@ public class BubblesTest extends SysuiTestCase {
}
@Test
+ @EnableFlags(NotificationBundleUi.FLAG_NAME)
public void testAppRemovesSummary_removesAllBubbleChildren() throws Exception {
// GIVEN a group summary with a bubble child
+ NotificationEntry groupedBubble = mNotificationTestHelper.createBubbleEntryInGroup();
+ GroupEntry groupSummary = mNotificationTestHelper.createGroupEntry(
+ 0, List.of(groupedBubble));
+ mEntryListener.onEntryAdded(groupedBubble);
+ when(mCommonNotifCollection.getEntry(groupedBubble.getKey()))
+ .thenReturn(groupedBubble);
+ assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getKey()));
+
+ // GIVEN the summary is dismissed
+ mBubblesManager.handleDismissalInterception(groupSummary.getSummary());
+
+ // WHEN the summary is cancelled by the app
+ mEntryListener.onEntryRemoved(groupSummary.getSummary(), REASON_APP_CANCEL);
+
+ // THEN the summary and its children are removed from bubble data
+ assertFalse(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getKey()));
+ assertFalse(mBubbleData.isSummarySuppressed(
+ groupSummary.getSummary().getSbn().getGroupKey()));
+ }
+
+ @Test
+ @DisableFlags(NotificationBundleUi.FLAG_NAME)
+ public void testAppRemovesSummary_removesAllBubbleChildren_rows() throws Exception {
+ // GIVEN a group summary with a bubble child
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
mEntryListener.onEntryAdded(groupedBubble.getEntry());
@@ -1276,9 +1332,52 @@ public class BubblesTest extends SysuiTestCase {
}
@Test
+ @EnableFlags(NotificationBundleUi.FLAG_NAME)
public void testSummaryDismissalMarksBubblesHiddenFromShadeAndDismissesNonBubbledChildren()
throws Exception {
// GIVEN a group summary with two (non-bubble) children and one bubble child
+ NotificationEntry groupedBubble = mNotificationTestHelper.createBubbleEntryInGroup();
+ GroupEntry groupSummary = mNotificationTestHelper.createGroupEntry(
+ 2, List.of(groupedBubble));
+ mEntryListener.onEntryAdded(groupedBubble);
+ when(mCommonNotifCollection.getEntry(groupedBubble.getKey()))
+ .thenReturn(groupedBubble);
+
+ // WHEN the summary is dismissed
+ mBubblesManager.handleDismissalInterception(groupSummary.getSummary());
+
+ // THEN only the NON-bubble children are dismissed
+ List<NotificationEntry> children = groupSummary.getChildren();
+ verify(mNotifCallback, times(1)).removeNotification(
+ eq(children.get(0)), any(), eq(REASON_GROUP_SUMMARY_CANCELED));
+ verify(mNotifCallback, times(1)).removeNotification(
+ eq(children.get(1)), any(), eq(REASON_GROUP_SUMMARY_CANCELED));
+ verify(mNotifCallback, never()).removeNotification(eq(groupedBubble),
+ any(), anyInt());
+
+ // THEN the bubble child still exists as a bubble and is suppressed from the shade
+ assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getKey()));
+ assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+ groupedBubble.getKey(),
+ groupedBubble.getSbn().getGroupKey()));
+ assertTrue(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
+ groupedBubble.getKey(),
+ groupedBubble.getSbn().getGroupKey()));
+
+ // THEN the summary is also suppressed from the shade
+ assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+ groupSummary.getSummary().getKey(),
+ groupSummary.getSummary().getSbn().getGroupKey()));
+ assertTrue(mBubbleController.getImplCachedState().isBubbleNotificationSuppressedFromShade(
+ groupSummary.getSummary().getKey(),
+ groupSummary.getSummary().getSbn().getGroupKey()));
+ }
+
+ @Test
+ @DisableFlags(NotificationBundleUi.FLAG_NAME)
+ public void testSummaryDismissalMarksBubblesHiddenFromShadeAndDismissesNonBubbledChildren_row()
+ throws Exception {
+ // GIVEN a group summary with two (non-bubble) children and one bubble child
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(2);
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
mEntryListener.onEntryAdded(groupedBubble.getEntry());