Add tests for autogrouping
Bug: 64158706
Test: this
Change-Id: I2a5a401579809ce805272450f33f21bc9f14d4af
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
index 3200409..a0cf0fd 100644
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -32,6 +32,7 @@
import android.test.AndroidTestCase;
import android.util.Log;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -278,6 +279,10 @@
continue;
}
assertFalse(channel3.getId().equals(nc.getId()));
+ if (!channelMap.containsKey(nc.getId())) {
+ // failed cleanup from prior test run; ignore
+ continue;
+ }
compareChannels(channelMap.get(nc.getId()), nc);
}
}
@@ -375,7 +380,161 @@
checkNotificationExistence(id, false);
}
+ public void testAutogrouping() throws Exception {
+ sendNotification(1, R.drawable.black);
+ sendNotification(2, R.drawable.blue);
+ sendNotification(3, R.drawable.yellow);
+ sendNotification(4, R.drawable.yellow);
+
+ assertNotificationCount(5);
+ assertAllPostedNotificationsAutogrouped();
+ }
+
+ public void testAutogrouping_autogroupStaysUntilAllNotificationsCanceled() throws Exception {
+ sendNotification(1, R.drawable.black);
+ sendNotification(2, R.drawable.blue);
+ sendNotification(3, R.drawable.yellow);
+ sendNotification(4, R.drawable.yellow);
+
+ assertNotificationCount(5);
+ assertAllPostedNotificationsAutogrouped();
+
+ // Assert all notis stay in the same autogroup until all children are canceled
+ for (int i = 4; i > 1; i--) {
+ cancelAndPoll(i);
+ assertNotificationCount(i);
+ assertAllPostedNotificationsAutogrouped();
+ }
+ cancelAndPoll(1);
+ assertNotificationCount(0);
+ }
+
+ public void testAutogrouping_autogroupStaysUntilAllNotificationsAddedToGroup()
+ throws Exception {
+ String newGroup = "new!";
+ sendNotification(1, R.drawable.black);
+ sendNotification(2, R.drawable.blue);
+ sendNotification(3, R.drawable.yellow);
+ sendNotification(4, R.drawable.yellow);
+
+ List<Integer> postedIds = new ArrayList<>();
+ postedIds.add(1);
+ postedIds.add(2);
+ postedIds.add(3);
+ postedIds.add(4);
+
+ assertNotificationCount(5);
+ assertAllPostedNotificationsAutogrouped();
+
+ // Assert all notis stay in the same autogroup until all children are canceled
+ for (int i = 4; i > 1; i--) {
+ sendNotification(i, newGroup, R.drawable.blue);
+ postedIds.remove(postedIds.size() - 1);
+ assertNotificationCount(5);
+ assertOnlySomeNotificationsAutogrouped(postedIds);
+ }
+ sendNotification(1, newGroup, R.drawable.blue);
+ assertNotificationCount(4); // no more autogroup summary
+ postedIds.remove(0);
+ assertOnlySomeNotificationsAutogrouped(postedIds);
+ }
+
+ public void testNewNotificationsAddedToAutogroup_ifOriginalNotificationsCanceled()
+ throws Exception {
+ String newGroup = "new!";
+ sendNotification(10, R.drawable.black);
+ sendNotification(20, R.drawable.blue);
+ sendNotification(30, R.drawable.yellow);
+ sendNotification(40, R.drawable.yellow);
+
+ List<Integer> postedIds = new ArrayList<>();
+ postedIds.add(10);
+ postedIds.add(20);
+ postedIds.add(30);
+ postedIds.add(40);
+
+ assertNotificationCount(5);
+ assertAllPostedNotificationsAutogrouped();
+
+ // regroup all but one of the children
+ for (int i = 40; i > 10; ) {
+ sendNotification(i, newGroup, R.drawable.blue);
+ postedIds.remove(postedIds.size() - 1);
+ assertNotificationCount(5);
+ try {
+ Thread.sleep(200);
+ } catch (InterruptedException ex) {
+ // pass
+ }
+ assertOnlySomeNotificationsAutogrouped(postedIds);
+ i = i - 10;
+ }
+
+ // send a new non-grouped notification. since the autogroup summary still exists,
+ // the notification should be added to it
+ sendNotification(50, R.drawable.blue);
+ postedIds.add(50);
+ try {
+ Thread.sleep(200);
+ } catch (InterruptedException ex) {
+ // pass
+ }
+ assertOnlySomeNotificationsAutogrouped(postedIds);
+ }
+
+ private boolean isGroupSummary(Notification n) {
+ return n.getGroup() != null && (n.flags & Notification.FLAG_GROUP_SUMMARY) != 0;
+ }
+
+ private void assertOnlySomeNotificationsAutogrouped(List<Integer> autoGroupedIds) {
+ String expectedGroupKey = null;
+ StatusBarNotification[] sbns = mNotificationManager.getActiveNotifications();
+ for (StatusBarNotification sbn : sbns) {
+ if (isGroupSummary(sbn.getNotification())
+ || autoGroupedIds.contains(sbn.getId())) {
+ assertTrue(sbn.getKey() + " is unexpectedly not autogrouped",
+ sbn.getOverrideGroupKey() != null);
+ if (expectedGroupKey == null) {
+ expectedGroupKey = sbn.getGroupKey();
+ }
+ assertEquals(expectedGroupKey, sbn.getGroupKey());
+ } else {
+ assertTrue(sbn.isGroup());
+ assertTrue(sbn.getKey() + " is unexpectedly autogrouped",
+ sbn.getOverrideGroupKey() == null);
+ assertTrue(sbn.getKey() + " has an unusual group key",
+ sbn.getGroupKey() != expectedGroupKey);
+ }
+ }
+ }
+
+ private void assertAllPostedNotificationsAutogrouped() {
+ String expectedGroupKey = null;
+ StatusBarNotification[] sbns = mNotificationManager.getActiveNotifications();
+ for (StatusBarNotification sbn : sbns) {
+ // all notis should be in a group determined by autogrouping
+ assertTrue(sbn.getOverrideGroupKey() != null);
+ if (expectedGroupKey == null) {
+ expectedGroupKey = sbn.getGroupKey();
+ }
+ // all notis should be in the same group
+ assertEquals(expectedGroupKey, sbn.getGroupKey());
+ }
+ }
+
+ private void cancelAndPoll(int id) {
+ mNotificationManager.cancel(id);
+
+ if (!checkNotificationExistence(id, /*shouldExist=*/ false)) {
+ fail("canceled notification was still alive, id=" + 1);
+ }
+ }
+
private void sendNotification(final int id, final int icon) throws Exception {
+ sendNotification(id, null, icon);
+ }
+
+ private void sendNotification(final int id, String groupKey, final int icon) throws Exception {
final Intent intent = new Intent(Intent.ACTION_MAIN, Threads.CONTENT_URI);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP
@@ -385,12 +544,13 @@
final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
final Notification notification =
new Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
- .setSmallIcon(icon)
- .setWhen(System.currentTimeMillis())
- .setContentTitle("notify#" + id)
- .setContentText("This is #" + id + "notification ")
- .setContentIntent(pendingIntent)
- .build();
+ .setSmallIcon(icon)
+ .setWhen(System.currentTimeMillis())
+ .setContentTitle("notify#" + id)
+ .setContentText("This is #" + id + "notification ")
+ .setContentIntent(pendingIntent)
+ .setGroup(groupKey)
+ .build();
mNotificationManager.notify(id, notification);
if (!checkNotificationExistence(id, /*shouldExist=*/ true)) {
@@ -401,9 +561,9 @@
private boolean checkNotificationExistence(int id, boolean shouldExist) {
// notification is a bit asynchronous so it may take a few ms to appear in
// getActiveNotifications()
- // we will check for it for up to 200ms before giving up
+ // we will check for it for up to 300ms before giving up
boolean found = false;
- for (int tries=3; tries-->0;) {
+ for (int tries = 3; tries--> 0;) {
// Need reset flag.
found = false;
final StatusBarNotification[] sbns = mNotificationManager.getActiveNotifications();
@@ -423,6 +583,24 @@
return found == shouldExist;
}
+ private void assertNotificationCount(int expectedCount) {
+ // notification is a bit asynchronous so it may take a few ms to appear in
+ // getActiveNotifications()
+ // we will check for it for up to 400ms before giving up
+ int lastCount = 0;
+ for (int tries = 4; tries-- > 0;) {
+ final StatusBarNotification[] sbns = mNotificationManager.getActiveNotifications();
+ lastCount = sbns.length;
+ if (expectedCount == lastCount) return;
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException ex) {
+ // pass
+ }
+ }
+ fail("Expected " + expectedCount + " posted notifications, were " + lastCount);
+ }
+
private void compareChannels(NotificationChannel expected, NotificationChannel actual) {
if (actual == null) {
fail("actual channel is null");