Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt +1 −4 Original line number Diff line number Diff line Loading @@ -39,10 +39,7 @@ class StackCoordinator @Inject internal constructor( override fun attach(pipeline: NotifPipeline) { pipeline.addOnAfterRenderListListener(::onAfterRenderList) // TODO(b/282865576): This has an issue where it makes changes to some groups without // notifying listeners. To be fixed in QPR, but for now let's comment it out to avoid the // group expansion bug. // groupExpansionManagerImpl.attach(pipeline) groupExpansionManagerImpl.attach(pipeline) } fun onAfterRenderList(entries: List<ListEntry>, controller: NotifStackController) = Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java +37 −3 Original line number Diff line number Diff line Loading @@ -67,19 +67,30 @@ public class GroupExpansionManagerImpl implements GroupExpansionManager, Dumpabl * Cleanup entries from mExpandedGroups that no longer exist in the pipeline. */ private final OnBeforeRenderListListener mNotifTracker = (entries) -> { if (mExpandedGroups.isEmpty()) { return; // nothing to do } final Set<NotificationEntry> renderingSummaries = new HashSet<>(); for (ListEntry entry : entries) { if (entry instanceof GroupEntry) { renderingSummaries.add(entry.getRepresentativeEntry()); } } mExpandedGroups.removeIf(expandedGroup -> !renderingSummaries.contains(expandedGroup)); // If a group is in mExpandedGroups but not in the pipeline entries, collapse it. final var groupsToRemove = setDifference(mExpandedGroups, renderingSummaries); for (NotificationEntry entry : groupsToRemove) { setGroupExpanded(entry, false); } }; public void attach(NotifPipeline pipeline) { if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE)) { mDumpManager.registerDumpable(this); pipeline.addOnBeforeRenderListListener(mNotifTracker); } } @Override public void registerGroupExpansionChangeListener(OnGroupExpansionChangeListener listener) { Loading Loading @@ -134,4 +145,27 @@ public class GroupExpansionManagerImpl implements GroupExpansionManager, Dumpabl listener.onGroupExpansionChange(entry.getRow(), expanded); } } /** * Utility method to compute the difference between two sets of NotificationEntry. Unfortunately * {@code Sets.difference} from Guava is not available in this codebase. */ @NonNull private Set<NotificationEntry> setDifference(Set<NotificationEntry> set1, Set<NotificationEntry> set2) { if (set1 == null || set1.isEmpty()) { return new HashSet<>(); } if (set2 == null || set2.isEmpty()) { return new HashSet<>(set1); } final Set<NotificationEntry> difference = new HashSet<>(); for (NotificationEntry e : set1) { if (!set2.contains(e)) { difference.add(e); } } return difference; } } packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java +9 −6 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.collection.render; import android.annotation.NonNull; import android.annotation.Nullable; import com.android.systemui.statusbar.notification.collection.ListEntry; Loading @@ -31,13 +32,14 @@ public interface GroupMembershipManager { * @return whether a given notification is a top level entry or is the summary in a group which * has children */ boolean isGroupSummary(NotificationEntry entry); boolean isGroupSummary(@NonNull NotificationEntry entry); /** * Get the summary of a specified status bar notification. For an isolated notification this * returns itself. */ NotificationEntry getGroupSummary(NotificationEntry entry); @Nullable NotificationEntry getGroupSummary(@NonNull NotificationEntry entry); /** * Similar to {@link #getGroupSummary(NotificationEntry)} but doesn't get the visual summary Loading @@ -46,19 +48,20 @@ public interface GroupMembershipManager { * TODO: remove this when migrating to the new pipeline, this is taken care of in the * dismissal logic built into NotifCollection */ default NotificationEntry getLogicalGroupSummary(NotificationEntry entry) { @Nullable default NotificationEntry getLogicalGroupSummary(@NonNull NotificationEntry entry) { return getGroupSummary(entry); } /** * @return whether a given notification is a child in a group */ boolean isChildInGroup(NotificationEntry entry); boolean isChildInGroup(@NonNull NotificationEntry entry); /** * Whether this is the only child in a group */ boolean isOnlyChildInGroup(NotificationEntry entry); boolean isOnlyChildInGroup(@NonNull NotificationEntry entry); /** * Get the children that are in the summary's group, not including those isolated. Loading @@ -67,5 +70,5 @@ public interface GroupMembershipManager { * @return list of the children */ @Nullable List<NotificationEntry> getChildren(ListEntry summary); List<NotificationEntry> getChildren(@NonNull ListEntry summary); } packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java +40 −11 Original line number Diff line number Diff line Loading @@ -18,40 +18,65 @@ package com.android.systemui.statusbar.notification.collection.render; import static com.android.systemui.statusbar.notification.collection.GroupEntry.ROOT_ENTRY; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; import com.android.systemui.statusbar.notification.collection.GroupEntry; import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import java.util.List; import javax.inject.Inject; /** * ShadeListBuilder groups notifications from system server. This manager translates * ShadeListBuilder's method of grouping to be used within SystemUI. */ @SysUISingleton public class GroupMembershipManagerImpl implements GroupMembershipManager { FeatureFlags mFeatureFlags; @Inject public GroupMembershipManagerImpl(FeatureFlags featureFlags) { mFeatureFlags = featureFlags; } @Override public boolean isGroupSummary(NotificationEntry entry) { public boolean isGroupSummary(@NonNull NotificationEntry entry) { return getGroupSummary(entry) == entry; } @Nullable @Override public NotificationEntry getGroupSummary(NotificationEntry entry) { public NotificationEntry getGroupSummary(@NonNull NotificationEntry entry) { if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE)) { if (!isChildInGroup(entry)) { return entry.getRepresentativeEntry(); } } else { if (isEntryTopLevel(entry) || entry.getParent() == null) { return null; } } return entry.getParent().getRepresentativeEntry(); } @Override public boolean isChildInGroup(NotificationEntry entry) { public boolean isChildInGroup(@NonNull NotificationEntry entry) { if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE)) { return !isEntryTopLevel(entry) && entry.getParent() != null; } else { return !isEntryTopLevel(entry); } } @Override public boolean isOnlyChildInGroup(NotificationEntry entry) { public boolean isOnlyChildInGroup(@NonNull NotificationEntry entry) { if (entry.getParent() == null) { return false; } Loading @@ -61,20 +86,24 @@ public class GroupMembershipManagerImpl implements GroupMembershipManager { @Nullable @Override public List<NotificationEntry> getChildren(ListEntry entry) { public List<NotificationEntry> getChildren(@NonNull ListEntry entry) { if (entry instanceof GroupEntry) { return ((GroupEntry) entry).getChildren(); } if (isGroupSummary(entry.getRepresentativeEntry())) { NotificationEntry representativeEntry = entry.getRepresentativeEntry(); if (representativeEntry != null && isGroupSummary(representativeEntry)) { // maybe we were actually passed the summary return entry.getRepresentativeEntry().getParent().getChildren(); GroupEntry parent = representativeEntry.getParent(); if (parent != null) { return parent.getChildren(); } } return null; } private boolean isEntryTopLevel(NotificationEntry entry) { private boolean isEntryTopLevel(@NonNull NotificationEntry entry) { return entry.getParent() == ROOT_ENTRY; } } packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java +2 −5 Original line number Diff line number Diff line Loading @@ -167,11 +167,8 @@ public interface NotificationsModule { } /** Provides an instance of {@link GroupMembershipManager} */ @SysUISingleton @Provides static GroupMembershipManager provideGroupMembershipManager() { return new GroupMembershipManagerImpl(); } @Binds GroupMembershipManager provideGroupMembershipManager(GroupMembershipManagerImpl impl); /** Provides an instance of {@link GroupExpansionManager} */ @Binds Loading Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt +1 −4 Original line number Diff line number Diff line Loading @@ -39,10 +39,7 @@ class StackCoordinator @Inject internal constructor( override fun attach(pipeline: NotifPipeline) { pipeline.addOnAfterRenderListListener(::onAfterRenderList) // TODO(b/282865576): This has an issue where it makes changes to some groups without // notifying listeners. To be fixed in QPR, but for now let's comment it out to avoid the // group expansion bug. // groupExpansionManagerImpl.attach(pipeline) groupExpansionManagerImpl.attach(pipeline) } fun onAfterRenderList(entries: List<ListEntry>, controller: NotifStackController) = Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java +37 −3 Original line number Diff line number Diff line Loading @@ -67,19 +67,30 @@ public class GroupExpansionManagerImpl implements GroupExpansionManager, Dumpabl * Cleanup entries from mExpandedGroups that no longer exist in the pipeline. */ private final OnBeforeRenderListListener mNotifTracker = (entries) -> { if (mExpandedGroups.isEmpty()) { return; // nothing to do } final Set<NotificationEntry> renderingSummaries = new HashSet<>(); for (ListEntry entry : entries) { if (entry instanceof GroupEntry) { renderingSummaries.add(entry.getRepresentativeEntry()); } } mExpandedGroups.removeIf(expandedGroup -> !renderingSummaries.contains(expandedGroup)); // If a group is in mExpandedGroups but not in the pipeline entries, collapse it. final var groupsToRemove = setDifference(mExpandedGroups, renderingSummaries); for (NotificationEntry entry : groupsToRemove) { setGroupExpanded(entry, false); } }; public void attach(NotifPipeline pipeline) { if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE)) { mDumpManager.registerDumpable(this); pipeline.addOnBeforeRenderListListener(mNotifTracker); } } @Override public void registerGroupExpansionChangeListener(OnGroupExpansionChangeListener listener) { Loading Loading @@ -134,4 +145,27 @@ public class GroupExpansionManagerImpl implements GroupExpansionManager, Dumpabl listener.onGroupExpansionChange(entry.getRow(), expanded); } } /** * Utility method to compute the difference between two sets of NotificationEntry. Unfortunately * {@code Sets.difference} from Guava is not available in this codebase. */ @NonNull private Set<NotificationEntry> setDifference(Set<NotificationEntry> set1, Set<NotificationEntry> set2) { if (set1 == null || set1.isEmpty()) { return new HashSet<>(); } if (set2 == null || set2.isEmpty()) { return new HashSet<>(set1); } final Set<NotificationEntry> difference = new HashSet<>(); for (NotificationEntry e : set1) { if (!set2.contains(e)) { difference.add(e); } } return difference; } }
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManager.java +9 −6 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.collection.render; import android.annotation.NonNull; import android.annotation.Nullable; import com.android.systemui.statusbar.notification.collection.ListEntry; Loading @@ -31,13 +32,14 @@ public interface GroupMembershipManager { * @return whether a given notification is a top level entry or is the summary in a group which * has children */ boolean isGroupSummary(NotificationEntry entry); boolean isGroupSummary(@NonNull NotificationEntry entry); /** * Get the summary of a specified status bar notification. For an isolated notification this * returns itself. */ NotificationEntry getGroupSummary(NotificationEntry entry); @Nullable NotificationEntry getGroupSummary(@NonNull NotificationEntry entry); /** * Similar to {@link #getGroupSummary(NotificationEntry)} but doesn't get the visual summary Loading @@ -46,19 +48,20 @@ public interface GroupMembershipManager { * TODO: remove this when migrating to the new pipeline, this is taken care of in the * dismissal logic built into NotifCollection */ default NotificationEntry getLogicalGroupSummary(NotificationEntry entry) { @Nullable default NotificationEntry getLogicalGroupSummary(@NonNull NotificationEntry entry) { return getGroupSummary(entry); } /** * @return whether a given notification is a child in a group */ boolean isChildInGroup(NotificationEntry entry); boolean isChildInGroup(@NonNull NotificationEntry entry); /** * Whether this is the only child in a group */ boolean isOnlyChildInGroup(NotificationEntry entry); boolean isOnlyChildInGroup(@NonNull NotificationEntry entry); /** * Get the children that are in the summary's group, not including those isolated. Loading @@ -67,5 +70,5 @@ public interface GroupMembershipManager { * @return list of the children */ @Nullable List<NotificationEntry> getChildren(ListEntry summary); List<NotificationEntry> getChildren(@NonNull ListEntry summary); }
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupMembershipManagerImpl.java +40 −11 Original line number Diff line number Diff line Loading @@ -18,40 +18,65 @@ package com.android.systemui.statusbar.notification.collection.render; import static com.android.systemui.statusbar.notification.collection.GroupEntry.ROOT_ENTRY; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; import com.android.systemui.statusbar.notification.collection.GroupEntry; import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import java.util.List; import javax.inject.Inject; /** * ShadeListBuilder groups notifications from system server. This manager translates * ShadeListBuilder's method of grouping to be used within SystemUI. */ @SysUISingleton public class GroupMembershipManagerImpl implements GroupMembershipManager { FeatureFlags mFeatureFlags; @Inject public GroupMembershipManagerImpl(FeatureFlags featureFlags) { mFeatureFlags = featureFlags; } @Override public boolean isGroupSummary(NotificationEntry entry) { public boolean isGroupSummary(@NonNull NotificationEntry entry) { return getGroupSummary(entry) == entry; } @Nullable @Override public NotificationEntry getGroupSummary(NotificationEntry entry) { public NotificationEntry getGroupSummary(@NonNull NotificationEntry entry) { if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE)) { if (!isChildInGroup(entry)) { return entry.getRepresentativeEntry(); } } else { if (isEntryTopLevel(entry) || entry.getParent() == null) { return null; } } return entry.getParent().getRepresentativeEntry(); } @Override public boolean isChildInGroup(NotificationEntry entry) { public boolean isChildInGroup(@NonNull NotificationEntry entry) { if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_GROUP_EXPANSION_CHANGE)) { return !isEntryTopLevel(entry) && entry.getParent() != null; } else { return !isEntryTopLevel(entry); } } @Override public boolean isOnlyChildInGroup(NotificationEntry entry) { public boolean isOnlyChildInGroup(@NonNull NotificationEntry entry) { if (entry.getParent() == null) { return false; } Loading @@ -61,20 +86,24 @@ public class GroupMembershipManagerImpl implements GroupMembershipManager { @Nullable @Override public List<NotificationEntry> getChildren(ListEntry entry) { public List<NotificationEntry> getChildren(@NonNull ListEntry entry) { if (entry instanceof GroupEntry) { return ((GroupEntry) entry).getChildren(); } if (isGroupSummary(entry.getRepresentativeEntry())) { NotificationEntry representativeEntry = entry.getRepresentativeEntry(); if (representativeEntry != null && isGroupSummary(representativeEntry)) { // maybe we were actually passed the summary return entry.getRepresentativeEntry().getParent().getChildren(); GroupEntry parent = representativeEntry.getParent(); if (parent != null) { return parent.getChildren(); } } return null; } private boolean isEntryTopLevel(NotificationEntry entry) { private boolean isEntryTopLevel(@NonNull NotificationEntry entry) { return entry.getParent() == ROOT_ENTRY; } }
packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java +2 −5 Original line number Diff line number Diff line Loading @@ -167,11 +167,8 @@ public interface NotificationsModule { } /** Provides an instance of {@link GroupMembershipManager} */ @SysUISingleton @Provides static GroupMembershipManager provideGroupMembershipManager() { return new GroupMembershipManagerImpl(); } @Binds GroupMembershipManager provideGroupMembershipManager(GroupMembershipManagerImpl impl); /** Provides an instance of {@link GroupExpansionManager} */ @Binds Loading