Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java +0 −1 Original line number Diff line number Diff line Loading @@ -1311,7 +1311,6 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { // Sort children of groups within bundles for (ListEntry le : bundleEntry.getChildren()) { if (le instanceof GroupEntry ge) { // TODO(b/399736937) Add tests. allSorted &= sortGroupChildren(ge.getRawChildren()); } } Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java +201 −45 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import static org.mockito.Mockito.verify; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import android.app.NotificationChannel; import android.os.SystemClock; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; Loading Loading @@ -71,6 +72,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.OnBefo import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener; import com.android.systemui.statusbar.notification.collection.listbuilder.ShadeListBuilderLogger; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifBundler; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter; Loading Loading @@ -277,6 +279,35 @@ public class ShadeListBuilderTest extends SysuiTestCase { ); } @Test @EnableFlags(NotificationBundleUi.FLAG_NAME) public void testBundleGroupChildrenAreSorted() { mListBuilder.setBundler(TestBundler.INSTANCE); // GIVEN a simple pipeline // WHEN we add two groups addGroupChild(0, PACKAGE_1, GROUP_1, BUNDLE_1).setRank(3); addGroupChild(1, PACKAGE_1, GROUP_1, BUNDLE_1).setRank(2); addGroupChild(2, PACKAGE_1, GROUP_1, BUNDLE_1).setRank(1); addGroupSummary(3, PACKAGE_1, GROUP_1, BUNDLE_1); dispatchBuild(); // THEN bundle group children are sorted by rank verifyBuiltList( bundle( BUNDLE_1, group( summary(3), child(2), child(1), child(0) ) ) ); } @Test public void testDuplicateGroupSummariesAreDiscarded() { // GIVEN a simple pipeline Loading Loading @@ -555,7 +586,7 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.addFinalizeFilter(filter1); // WHEN the pipeline is kicked off on a list of notifs addGroupChildWithTag(0, PACKAGE_2, GROUP_1, filterTag); addGroupChildWithTag(0, PACKAGE_2, GROUP_1, filterTag, "test_channel"); addGroupChild(1, PACKAGE_2, GROUP_1); addGroupSummary(2, PACKAGE_2, GROUP_1); dispatchBuild(); Loading Loading @@ -2347,10 +2378,13 @@ public class ShadeListBuilderTest extends SysuiTestCase { return builder; } /** Same behavior as {@link #addNotif(int, String)}. */ private NotificationEntryBuilder addGroupSummary(int index, String packageId, String groupId) { private NotificationEntryBuilder addGroupSummary(int index, String packageId, String groupId, String channelId) { NotificationChannel channel = new NotificationChannel(channelId, "channelName", 3); final NotificationEntryBuilder builder = new NotificationEntryBuilder() .setPkg(packageId) .setChannel(channel) .setId(nextId(packageId)) .setRank(nextRank()); Loading @@ -2365,16 +2399,22 @@ public class ShadeListBuilderTest extends SysuiTestCase { return builder; } /** Same behavior as {@link #addNotif(int, String)}. */ private NotificationEntryBuilder addGroupSummary(int index, String packageId, String groupId) { return addGroupSummary(index, packageId, groupId, "test_channel"); } private NotificationEntryBuilder addGroupChildWithTag(int index, String packageId, String groupId, String tag) { String groupId, String tag, String channelId) { final NotificationEntryBuilder builder = new NotificationEntryBuilder() .setTag(tag) .setPkg(packageId) .setId(nextId(packageId)) .setRank(nextRank()); .setRank(nextRank()) .setChannel(new NotificationChannel(channelId, "channelName", 3)); builder.modifyNotification(mContext) .setChannelId("test_channel") .setContentTitle("Group child") .setGroup(groupId); Loading @@ -2385,7 +2425,12 @@ public class ShadeListBuilderTest extends SysuiTestCase { /** Same behavior as {@link #addNotif(int, String)}. */ private NotificationEntryBuilder addGroupChild(int index, String packageId, String groupId) { return addGroupChildWithTag(index, packageId, groupId, null); return addGroupChildWithTag(index, packageId, groupId, null, "test_channel"); } private NotificationEntryBuilder addGroupChild(int index, String packageId, String groupId, String channelId) { return addGroupChildWithTag(index, packageId, groupId, null, channelId); } private void assertOrder(String visible, String active, String expected, Loading Loading @@ -2473,59 +2518,94 @@ public class ShadeListBuilderTest extends SysuiTestCase { } } private void verifyBuiltList(ExpectedEntry ...expectedEntries) { try { assertEquals( "List is the wrong length", expectedEntries.length, mBuiltList.size()); for (int i = 0; i < expectedEntries.length; i++) { PipelineEntry outEntry = mBuiltList.get(i); ExpectedEntry expectedEntry = expectedEntries[i]; if (expectedEntry instanceof ExpectedNotif) { private void verifyNotifEntry(ExpectedNotif expectedEntry, PipelineEntry actualPipelineEntry, int i) { assertEquals( "Entry " + i + " isn't a NotifEntry", NotificationEntry.class, outEntry.getClass()); actualPipelineEntry.getClass()); assertEquals( "Entry " + i + " doesn't match expected value.", ((ExpectedNotif) expectedEntry).entry, outEntry); } else { ExpectedGroup cmpGroup = (ExpectedGroup) expectedEntry; ((ExpectedNotif) expectedEntry).entry, actualPipelineEntry); } private void verifyGroupEntry(ExpectedGroup expectedGroup, PipelineEntry actualPipelineEntry, int i) { assertEquals( "Entry " + i + " isn't a GroupEntry", GroupEntry.class, outEntry.getClass()); actualPipelineEntry.getClass()); GroupEntry outGroup = (GroupEntry) outEntry; GroupEntry actualGroupEntry = (GroupEntry) actualPipelineEntry; assertEquals( "Summary notif for entry " + i + " doesn't match expected value", cmpGroup.summary, outGroup.getSummary()); expectedGroup.summary, actualGroupEntry.getSummary()); assertEquals( "Summary notif for entry " + i + " doesn't have proper parent", outGroup, outGroup.getSummary().getParent()); actualGroupEntry, actualGroupEntry.getSummary().getParent()); assertEquals("Children for entry " + i, cmpGroup.children, outGroup.getChildren()); expectedGroup.children, actualGroupEntry.getChildren()); for (int j = 0; j < outGroup.getChildren().size(); j++) { NotificationEntry child = outGroup.getChildren().get(j); for (int j = 0; j < actualGroupEntry.getChildren().size(); j++) { NotificationEntry child = actualGroupEntry.getChildren().get(j); assertEquals( "Child " + j + " for entry " + i + " doesn't have proper parent", outGroup, actualGroupEntry, child.getParent()); } } private void verifyBuiltList(ExpectedEntry ...expectedEntries) { try { assertEquals( "List is the wrong length", expectedEntries.length, mBuiltList.size()); for (int i = 0; i < expectedEntries.length; i++) { PipelineEntry actualPipelineEntry = mBuiltList.get(i); ExpectedEntry expectedEntry = expectedEntries[i]; if (expectedEntry instanceof ExpectedNotif expectedNotif) { verifyNotifEntry(expectedNotif, actualPipelineEntry, i); } else if (expectedEntry instanceof ExpectedGroup cmpGroup) { verifyGroupEntry(cmpGroup, actualPipelineEntry, i); } else { ExpectedBundle expectedBundle = (ExpectedBundle) expectedEntry; assertEquals( "Entry " + i + " isn't a BundleEntry", BundleEntry.class, actualPipelineEntry.getClass()); BundleEntry actualBundle = (BundleEntry) actualPipelineEntry; int expectedBundleSize = expectedBundle.children.size(); int actualBundleSize = actualBundle.getChildren().size(); assertEquals("Expected bundle size: " + expectedBundleSize + " Actual children count: " + actualBundleSize, expectedBundleSize, actualBundleSize); for (int j = 0; j < actualBundle.getChildren().size(); j++) { ListEntry actualChild = actualBundle.getChildren().get(j); ExpectedEntry expectedChild = expectedBundle.children.get(j); if (actualChild instanceof NotificationEntry actualNotif) { verifyNotifEntry((ExpectedNotif) expectedChild, actualChild, j); } else { verifyGroupEntry((ExpectedGroup) expectedChild, actualChild, j); } } } } } catch (AssertionError err) { throw new AssertionError( Loading @@ -2546,6 +2626,13 @@ public class ShadeListBuilderTest extends SysuiTestCase { .collect(Collectors.toList())); } private ExpectedBundle bundle(String bundleId, ExpectedEntry...children) { return new ExpectedBundle( bundleId, Arrays.stream(children).collect(Collectors.toList())); } private ExpectedSummary summary(int index) { return new ExpectedSummary(mEntrySet.get(index)); } Loading Loading @@ -2577,6 +2664,15 @@ public class ShadeListBuilderTest extends SysuiTestCase { } } private static class ExpectedBundle extends ExpectedEntry { public final String bundleId; public final List<ExpectedEntry> children; private ExpectedBundle(String bundleId, List<ExpectedEntry> children) { this.bundleId = bundleId; this.children = children; } } private static class ExpectedSummary { public final NotificationEntry entry; Loading Loading @@ -2832,4 +2928,64 @@ public class ShadeListBuilderTest extends SysuiTestCase { private static final String GROUP_1 = "group_1"; private static final String GROUP_2 = "group_2"; private static final String BUNDLE_1 = "bundle_1"; } class TestBundler extends NotifBundler { public static final TestBundler INSTANCE = new TestBundler(); List<BundleSpec> mBundleSpecs = List.of(new BundleSpec("bundle_1",0)); List<String> mBundleIds = this.mBundleSpecs.stream() .map(BundleSpec::getKey) .collect(Collectors.toList()); private TestBundler() { super("TestBundler"); } @Override public List<BundleSpec> getBundleSpecs() { return mBundleSpecs; } @Nullable public String getBundleIdOrNull(ListEntry entry) { if (entry instanceof GroupEntry) { GroupEntry groupEntry = (GroupEntry) entry; if (groupEntry.getChildren() == null || groupEntry.getChildren().isEmpty()) { return null; } NotificationEntry summary = groupEntry.getSummary(); if (summary == null) { return null; } return getBundleIdForNotifEntry(summary); } if (entry instanceof NotificationEntry) { return getBundleIdForNotifEntry((NotificationEntry) entry); } else { return null; } } @Nullable private String getBundleIdForNotifEntry(NotificationEntry notifEntry) { if (notifEntry == null) { return null; } NotificationEntry representativeEntry = notifEntry.getRepresentativeEntry(); if (representativeEntry == null) { return null; } if (representativeEntry.getChannel() == null) { return null; } String id = representativeEntry.getChannel().getId(); if (id != null && this.mBundleIds != null && this.mBundleIds.contains(id)) { return id; } return null; } } No newline at end of file Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java +0 −1 Original line number Diff line number Diff line Loading @@ -1311,7 +1311,6 @@ public class ShadeListBuilder implements Dumpable, PipelineDumpable { // Sort children of groups within bundles for (ListEntry le : bundleEntry.getChildren()) { if (le instanceof GroupEntry ge) { // TODO(b/399736937) Add tests. allSorted &= sortGroupChildren(ge.getRawChildren()); } } Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java +201 −45 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import static org.mockito.Mockito.verify; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import android.app.NotificationChannel; import android.os.SystemClock; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; Loading Loading @@ -71,6 +72,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.OnBefo import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener; import com.android.systemui.statusbar.notification.collection.listbuilder.ShadeListBuilderLogger; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifBundler; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter; Loading Loading @@ -277,6 +279,35 @@ public class ShadeListBuilderTest extends SysuiTestCase { ); } @Test @EnableFlags(NotificationBundleUi.FLAG_NAME) public void testBundleGroupChildrenAreSorted() { mListBuilder.setBundler(TestBundler.INSTANCE); // GIVEN a simple pipeline // WHEN we add two groups addGroupChild(0, PACKAGE_1, GROUP_1, BUNDLE_1).setRank(3); addGroupChild(1, PACKAGE_1, GROUP_1, BUNDLE_1).setRank(2); addGroupChild(2, PACKAGE_1, GROUP_1, BUNDLE_1).setRank(1); addGroupSummary(3, PACKAGE_1, GROUP_1, BUNDLE_1); dispatchBuild(); // THEN bundle group children are sorted by rank verifyBuiltList( bundle( BUNDLE_1, group( summary(3), child(2), child(1), child(0) ) ) ); } @Test public void testDuplicateGroupSummariesAreDiscarded() { // GIVEN a simple pipeline Loading Loading @@ -555,7 +586,7 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.addFinalizeFilter(filter1); // WHEN the pipeline is kicked off on a list of notifs addGroupChildWithTag(0, PACKAGE_2, GROUP_1, filterTag); addGroupChildWithTag(0, PACKAGE_2, GROUP_1, filterTag, "test_channel"); addGroupChild(1, PACKAGE_2, GROUP_1); addGroupSummary(2, PACKAGE_2, GROUP_1); dispatchBuild(); Loading Loading @@ -2347,10 +2378,13 @@ public class ShadeListBuilderTest extends SysuiTestCase { return builder; } /** Same behavior as {@link #addNotif(int, String)}. */ private NotificationEntryBuilder addGroupSummary(int index, String packageId, String groupId) { private NotificationEntryBuilder addGroupSummary(int index, String packageId, String groupId, String channelId) { NotificationChannel channel = new NotificationChannel(channelId, "channelName", 3); final NotificationEntryBuilder builder = new NotificationEntryBuilder() .setPkg(packageId) .setChannel(channel) .setId(nextId(packageId)) .setRank(nextRank()); Loading @@ -2365,16 +2399,22 @@ public class ShadeListBuilderTest extends SysuiTestCase { return builder; } /** Same behavior as {@link #addNotif(int, String)}. */ private NotificationEntryBuilder addGroupSummary(int index, String packageId, String groupId) { return addGroupSummary(index, packageId, groupId, "test_channel"); } private NotificationEntryBuilder addGroupChildWithTag(int index, String packageId, String groupId, String tag) { String groupId, String tag, String channelId) { final NotificationEntryBuilder builder = new NotificationEntryBuilder() .setTag(tag) .setPkg(packageId) .setId(nextId(packageId)) .setRank(nextRank()); .setRank(nextRank()) .setChannel(new NotificationChannel(channelId, "channelName", 3)); builder.modifyNotification(mContext) .setChannelId("test_channel") .setContentTitle("Group child") .setGroup(groupId); Loading @@ -2385,7 +2425,12 @@ public class ShadeListBuilderTest extends SysuiTestCase { /** Same behavior as {@link #addNotif(int, String)}. */ private NotificationEntryBuilder addGroupChild(int index, String packageId, String groupId) { return addGroupChildWithTag(index, packageId, groupId, null); return addGroupChildWithTag(index, packageId, groupId, null, "test_channel"); } private NotificationEntryBuilder addGroupChild(int index, String packageId, String groupId, String channelId) { return addGroupChildWithTag(index, packageId, groupId, null, channelId); } private void assertOrder(String visible, String active, String expected, Loading Loading @@ -2473,59 +2518,94 @@ public class ShadeListBuilderTest extends SysuiTestCase { } } private void verifyBuiltList(ExpectedEntry ...expectedEntries) { try { assertEquals( "List is the wrong length", expectedEntries.length, mBuiltList.size()); for (int i = 0; i < expectedEntries.length; i++) { PipelineEntry outEntry = mBuiltList.get(i); ExpectedEntry expectedEntry = expectedEntries[i]; if (expectedEntry instanceof ExpectedNotif) { private void verifyNotifEntry(ExpectedNotif expectedEntry, PipelineEntry actualPipelineEntry, int i) { assertEquals( "Entry " + i + " isn't a NotifEntry", NotificationEntry.class, outEntry.getClass()); actualPipelineEntry.getClass()); assertEquals( "Entry " + i + " doesn't match expected value.", ((ExpectedNotif) expectedEntry).entry, outEntry); } else { ExpectedGroup cmpGroup = (ExpectedGroup) expectedEntry; ((ExpectedNotif) expectedEntry).entry, actualPipelineEntry); } private void verifyGroupEntry(ExpectedGroup expectedGroup, PipelineEntry actualPipelineEntry, int i) { assertEquals( "Entry " + i + " isn't a GroupEntry", GroupEntry.class, outEntry.getClass()); actualPipelineEntry.getClass()); GroupEntry outGroup = (GroupEntry) outEntry; GroupEntry actualGroupEntry = (GroupEntry) actualPipelineEntry; assertEquals( "Summary notif for entry " + i + " doesn't match expected value", cmpGroup.summary, outGroup.getSummary()); expectedGroup.summary, actualGroupEntry.getSummary()); assertEquals( "Summary notif for entry " + i + " doesn't have proper parent", outGroup, outGroup.getSummary().getParent()); actualGroupEntry, actualGroupEntry.getSummary().getParent()); assertEquals("Children for entry " + i, cmpGroup.children, outGroup.getChildren()); expectedGroup.children, actualGroupEntry.getChildren()); for (int j = 0; j < outGroup.getChildren().size(); j++) { NotificationEntry child = outGroup.getChildren().get(j); for (int j = 0; j < actualGroupEntry.getChildren().size(); j++) { NotificationEntry child = actualGroupEntry.getChildren().get(j); assertEquals( "Child " + j + " for entry " + i + " doesn't have proper parent", outGroup, actualGroupEntry, child.getParent()); } } private void verifyBuiltList(ExpectedEntry ...expectedEntries) { try { assertEquals( "List is the wrong length", expectedEntries.length, mBuiltList.size()); for (int i = 0; i < expectedEntries.length; i++) { PipelineEntry actualPipelineEntry = mBuiltList.get(i); ExpectedEntry expectedEntry = expectedEntries[i]; if (expectedEntry instanceof ExpectedNotif expectedNotif) { verifyNotifEntry(expectedNotif, actualPipelineEntry, i); } else if (expectedEntry instanceof ExpectedGroup cmpGroup) { verifyGroupEntry(cmpGroup, actualPipelineEntry, i); } else { ExpectedBundle expectedBundle = (ExpectedBundle) expectedEntry; assertEquals( "Entry " + i + " isn't a BundleEntry", BundleEntry.class, actualPipelineEntry.getClass()); BundleEntry actualBundle = (BundleEntry) actualPipelineEntry; int expectedBundleSize = expectedBundle.children.size(); int actualBundleSize = actualBundle.getChildren().size(); assertEquals("Expected bundle size: " + expectedBundleSize + " Actual children count: " + actualBundleSize, expectedBundleSize, actualBundleSize); for (int j = 0; j < actualBundle.getChildren().size(); j++) { ListEntry actualChild = actualBundle.getChildren().get(j); ExpectedEntry expectedChild = expectedBundle.children.get(j); if (actualChild instanceof NotificationEntry actualNotif) { verifyNotifEntry((ExpectedNotif) expectedChild, actualChild, j); } else { verifyGroupEntry((ExpectedGroup) expectedChild, actualChild, j); } } } } } catch (AssertionError err) { throw new AssertionError( Loading @@ -2546,6 +2626,13 @@ public class ShadeListBuilderTest extends SysuiTestCase { .collect(Collectors.toList())); } private ExpectedBundle bundle(String bundleId, ExpectedEntry...children) { return new ExpectedBundle( bundleId, Arrays.stream(children).collect(Collectors.toList())); } private ExpectedSummary summary(int index) { return new ExpectedSummary(mEntrySet.get(index)); } Loading Loading @@ -2577,6 +2664,15 @@ public class ShadeListBuilderTest extends SysuiTestCase { } } private static class ExpectedBundle extends ExpectedEntry { public final String bundleId; public final List<ExpectedEntry> children; private ExpectedBundle(String bundleId, List<ExpectedEntry> children) { this.bundleId = bundleId; this.children = children; } } private static class ExpectedSummary { public final NotificationEntry entry; Loading Loading @@ -2832,4 +2928,64 @@ public class ShadeListBuilderTest extends SysuiTestCase { private static final String GROUP_1 = "group_1"; private static final String GROUP_2 = "group_2"; private static final String BUNDLE_1 = "bundle_1"; } class TestBundler extends NotifBundler { public static final TestBundler INSTANCE = new TestBundler(); List<BundleSpec> mBundleSpecs = List.of(new BundleSpec("bundle_1",0)); List<String> mBundleIds = this.mBundleSpecs.stream() .map(BundleSpec::getKey) .collect(Collectors.toList()); private TestBundler() { super("TestBundler"); } @Override public List<BundleSpec> getBundleSpecs() { return mBundleSpecs; } @Nullable public String getBundleIdOrNull(ListEntry entry) { if (entry instanceof GroupEntry) { GroupEntry groupEntry = (GroupEntry) entry; if (groupEntry.getChildren() == null || groupEntry.getChildren().isEmpty()) { return null; } NotificationEntry summary = groupEntry.getSummary(); if (summary == null) { return null; } return getBundleIdForNotifEntry(summary); } if (entry instanceof NotificationEntry) { return getBundleIdForNotifEntry((NotificationEntry) entry); } else { return null; } } @Nullable private String getBundleIdForNotifEntry(NotificationEntry notifEntry) { if (notifEntry == null) { return null; } NotificationEntry representativeEntry = notifEntry.getRepresentativeEntry(); if (representativeEntry == null) { return null; } if (representativeEntry.getChannel() == null) { return null; } String id = representativeEntry.getChannel().getId(); if (id != null && this.mBundleIds != null && this.mBundleIds.contains(id)) { return id; } return null; } } No newline at end of file