Prune summaries if only group children filtered

Fixes: 222146955
Test: manual
  1. Post a group consisting of a summary and ongoing media
     notification
  2. Observe no summary shown in the shade.
Change-Id: I4e3fee1dd91706ec60ec8ae7ede3990319297202
This commit is contained in:
Steve Elliott
2022-03-28 16:18:39 -04:00
parent dc622e8d91
commit be918ae7ee
2 changed files with 50 additions and 18 deletions

View File

@@ -35,6 +35,7 @@ import static java.util.Objects.requireNonNull;
import android.annotation.MainThread; import android.annotation.MainThread;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.os.Trace; import android.os.Trace;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.ArraySet; import android.util.ArraySet;
@@ -704,13 +705,17 @@ public class ShadeListBuilder implements Dumpable {
// having its summary promoted, regardless of how many children it has // having its summary promoted, regardless of how many children it has
Set<String> groupsWithChildrenLostToStability = Set<String> groupsWithChildrenLostToStability =
getGroupsWithChildrenLostToStability(shadeList); getGroupsWithChildrenLostToStability(shadeList);
// Like groups which lost a child to stability, any group which lost a child to promotion // Groups with children lost to stability are exempt from summary promotion.
// is exempt from having its summary promoted when it has no attached children. ArraySet<String> groupsExemptFromSummaryPromotion =
Set<String> groupsWithChildrenLostToPromotionOrStability = new ArraySet<>(groupsWithChildrenLostToStability);
getGroupsWithChildrenLostToPromotion(shadeList); // Any group which lost a child to filtering or promotion is exempt from having its summary
groupsWithChildrenLostToPromotionOrStability.addAll(groupsWithChildrenLostToStability); // promoted when it has no attached children.
getGroupsWithChildrenLostToFiltering(groupsExemptFromSummaryPromotion);
getGroupsWithChildrenLostToPromotion(shadeList, groupsExemptFromSummaryPromotion);
for (int i = 0; i < shadeList.size(); i++) { // Iterate backwards, so that we can remove elements without affecting indices of
// yet-to-be-accessed entries.
for (int i = shadeList.size() - 1; i >= 0; i--) {
final ListEntry tle = shadeList.get(i); final ListEntry tle = shadeList.get(i);
if (tle instanceof GroupEntry) { if (tle instanceof GroupEntry) {
@@ -719,7 +724,7 @@ public class ShadeListBuilder implements Dumpable {
final boolean hasSummary = group.getSummary() != null; final boolean hasSummary = group.getSummary() != null;
if (hasSummary && children.size() == 0) { if (hasSummary && children.size() == 0) {
if (groupsWithChildrenLostToPromotionOrStability.contains(group.getKey())) { if (groupsExemptFromSummaryPromotion.contains(group.getKey())) {
// This group lost a child on this run to promotion or stability, so it is // This group lost a child on this run to promotion or stability, so it is
// exempt from having its summary promoted to the top level, so prune it. // exempt from having its summary promoted to the top level, so prune it.
// It has no children, so it will just vanish. // It has no children, so it will just vanish.
@@ -728,14 +733,10 @@ public class ShadeListBuilder implements Dumpable {
// For any other summary with no children, promote the summary. // For any other summary with no children, promote the summary.
pruneGroupAtIndexAndPromoteSummary(shadeList, group, i); pruneGroupAtIndexAndPromoteSummary(shadeList, group, i);
} }
i--; // The node we visited is gone, so be sure to visit this index again.
} else if (!hasSummary) { } else if (!hasSummary) {
// If the group doesn't provide a summary, ignore it and add // If the group doesn't provide a summary, ignore it and add
// any children it may have directly to top-level. // any children it may have directly to top-level.
pruneGroupAtIndexAndPromoteAnyChildren(shadeList, group, i); pruneGroupAtIndexAndPromoteAnyChildren(shadeList, group, i);
i--; // The node we visited is gone, so be sure to visit this index again.
} else if (children.size() < MIN_CHILDREN_FOR_GROUP) { } else if (children.size() < MIN_CHILDREN_FOR_GROUP) {
// This group has a summary and insufficient, but nonzero children. // This group has a summary and insufficient, but nonzero children.
checkState(hasSummary, "group must have summary at this point"); checkState(hasSummary, "group must have summary at this point");
@@ -760,8 +761,6 @@ public class ShadeListBuilder implements Dumpable {
// The group is too small, ignore it and add // The group is too small, ignore it and add
// its children (if any) directly to top-level. // its children (if any) directly to top-level.
pruneGroupAtIndexAndPromoteAnyChildren(shadeList, group, i); pruneGroupAtIndexAndPromoteAnyChildren(shadeList, group, i);
i--; // The node we visited is gone, so be sure to visit this index again.
} }
} }
} }
@@ -867,18 +866,32 @@ public class ShadeListBuilder implements Dumpable {
* *
* These groups will be exempt from appearing without any children. * These groups will be exempt from appearing without any children.
*/ */
@NonNull private void getGroupsWithChildrenLostToPromotion(List<ListEntry> shadeList, Set<String> out) {
private Set<String> getGroupsWithChildrenLostToPromotion(List<ListEntry> shadeList) {
ArraySet<String> groupsWithChildrenLostToPromotion = new ArraySet<>();
for (int i = 0; i < shadeList.size(); i++) { for (int i = 0; i < shadeList.size(); i++) {
final ListEntry tle = shadeList.get(i); final ListEntry tle = shadeList.get(i);
if (tle.getAttachState().getPromoter() != null) { if (tle.getAttachState().getPromoter() != null) {
// This top-level-entry was part of a group, but was promoted out of it. // This top-level-entry was part of a group, but was promoted out of it.
final String groupKey = tle.getRepresentativeEntry().getSbn().getGroupKey(); final String groupKey = tle.getRepresentativeEntry().getSbn().getGroupKey();
groupsWithChildrenLostToPromotion.add(groupKey); out.add(groupKey);
}
}
}
/**
* Collect the keys of any groups which have already lost a child to a {@link NotifFilter}
* this run.
*
* These groups will be exempt from appearing without any children.
*/
private void getGroupsWithChildrenLostToFiltering(Set<String> out) {
for (ListEntry tle : mAllEntries) {
StatusBarNotification sbn = tle.getRepresentativeEntry().getSbn();
if (sbn.isGroup()
&& !sbn.getNotification().isGroupSummary()
&& tle.getAttachState().getExcludingFilter() != null) {
out.add(sbn.getGroup());
} }
} }
return groupsWithChildrenLostToPromotion;
} }
/** /**

View File

@@ -1450,6 +1450,25 @@ public class ShadeListBuilderTest extends SysuiTestCase {
); );
} }
@Test
public void testGroupWithChildRemovedByFilterIsPrunedWhenOtherwiseEmpty() {
// GIVEN a group with only one child
addGroupSummary(0, PACKAGE_1, GROUP_1);
addGroupChild(1, PACKAGE_1, GROUP_1);
dispatchBuild();
// NOTICE that the group is pruned and the child is moved to the top level
verifyBuiltList(
notif(1) // group with only one child is promoted
);
// WHEN the only child is filtered
mFinalizeFilter.mIndicesToFilter.add(1);
dispatchBuild();
// THEN the new list should be empty (the group summary should not be promoted)
verifyBuiltList();
}
@Test @Test
public void testFinalizeFilteredSummaryPromotesChildren() { public void testFinalizeFilteredSummaryPromotesChildren() {
// GIVEN a group with only one child was already drawn // GIVEN a group with only one child was already drawn