Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt +8 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,11 @@ data class ListAttachState private constructor( */ var parent: GroupEntry?, /** * Identifies the notification order in the entire notification list */ var stableIndex: Int = -1, /** * The section that this ListEntry was sorted into. If the child of the group, this will be the * parent's section. Null if not attached to the list. Loading Loading @@ -58,6 +63,7 @@ data class ListAttachState private constructor( /** Copies the state of another instance. */ fun clone(other: ListAttachState) { parent = other.parent stableIndex = other.stableIndex section = other.section excludingFilter = other.excludingFilter promoter = other.promoter Loading @@ -70,6 +76,7 @@ data class ListAttachState private constructor( section = null excludingFilter = null promoter = null stableIndex = -1 suppressedChanges.reset() } Loading @@ -78,6 +85,7 @@ data class ListAttachState private constructor( fun create(): ListAttachState { return ListAttachState( null, -1, null, null, null, Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java +59 −28 Original line number Diff line number Diff line Loading @@ -775,18 +775,44 @@ public class ShadeListBuilder implements Dumpable { for (NotificationEntry child : parent.getChildren()) { setEntrySection(child, section); } parent.sortChildren(sChildComparator); parent.sortChildren(mGroupChildrenComparator); } } // Finally, sort all top-level elements mNotifList.sort(mTopLevelComparator); assignIndexes(mNotifList); // notify sections since the list is sorted now notifySectionEntriesUpdated(); Trace.endSection(); } /** * Assign the index of each notification relative to the total order * @param notifList */ private void assignIndexes(List<ListEntry> notifList) { if (notifList.size() == 0) return; NotifSection currentSection = notifList.get(0).getSection(); int sectionMemberIndex = 0; for (int i = 0; i < notifList.size(); i++) { ListEntry entry = notifList.get(i); NotifSection section = entry.getSection(); if (section.getIndex() != currentSection.getIndex()) { sectionMemberIndex = 0; currentSection = section; } entry.getAttachState().setStableIndex(sectionMemberIndex); if (entry instanceof GroupEntry) { GroupEntry parent = (GroupEntry) entry; for (int j = 0; j < parent.getChildren().size(); j++) { entry = parent.getChildren().get(j); entry.getAttachState().setStableIndex(sectionMemberIndex); sectionMemberIndex++; } } sectionMemberIndex++; } } private void freeEmptyGroups() { mGroups.values().removeIf(ge -> ge.getSummary() == null && ge.getChildren().isEmpty()); } Loading Loading @@ -891,48 +917,53 @@ public class ShadeListBuilder implements Dumpable { } private final Comparator<ListEntry> mTopLevelComparator = (o1, o2) -> { int cmp = Integer.compare( o1.getSectionIndex(), o2.getSectionIndex()); if (cmp != 0) return cmp; int index1 = canReorder(o1) ? -1 : o1.getPreviousAttachState().getStableIndex(); int index2 = canReorder(o2) ? -1 : o2.getPreviousAttachState().getStableIndex(); cmp = Integer.compare(index1, index2); if (cmp != 0) return cmp; if (cmp == 0) { for (int i = 0; i < mNotifComparators.size(); i++) { cmp = mNotifComparators.get(i).compare(o1, o2); if (cmp != 0) { break; } } if (cmp != 0) return cmp; } final NotificationEntry rep1 = o1.getRepresentativeEntry(); final NotificationEntry rep2 = o2.getRepresentativeEntry(); if (cmp == 0) { cmp = rep1.getRanking().getRank() - rep2.getRanking().getRank(); } if (cmp != 0) return cmp; if (cmp == 0) { cmp = Long.compare( rep2.getSbn().getNotification().when, rep1.getSbn().getNotification().when); } return cmp; }; private static final Comparator<NotificationEntry> sChildComparator = (o1, o2) -> { int cmp = o1.getRanking().getRank() - o2.getRanking().getRank(); if (cmp == 0) { cmp = Long.compare( o2.getSbn().getNotification().when, o1.getSbn().getNotification().when); } private final Comparator<ListEntry> mGroupChildrenComparator = (o1, o2) -> { int index1 = canReorder(o1) ? -1 : o1.getPreviousAttachState().getStableIndex(); int index2 = canReorder(o2) ? -1 : o2.getPreviousAttachState().getStableIndex(); int cmp = Integer.compare(index1, index2); if (cmp != 0) return cmp; cmp = o1.getRepresentativeEntry().getRanking().getRank() - o2.getRepresentativeEntry().getRanking().getRank(); if (cmp != 0) return cmp; cmp = Long.compare( o2.getRepresentativeEntry().getSbn().getNotification().when, o1.getRepresentativeEntry().getSbn().getNotification().when); return cmp; }; private boolean canReorder(ListEntry entry) { return mNotifStabilityManager.isEntryReorderingAllowed(entry); } private boolean applyFilters(NotificationEntry entry, long now, List<NotifFilter> filters) { final NotifFilter filter = findRejectingFilter(entry, now, filters); entry.getAttachState().setExcludingFilter(filter); Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt +1 −0 Original line number Diff line number Diff line Loading @@ -98,6 +98,7 @@ class NotifCoordinatorsImpl @Inject constructor( mOrderedSections.add(conversationCoordinator.sectioner) // People mOrderedSections.add(rankingCoordinator.alertingSectioner) // Alerting mOrderedSections.add(rankingCoordinator.silentSectioner) // Silent mOrderedSections.add(rankingCoordinator.minimizedSectioner) // Minimized } /** Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java +48 −4 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator; import android.annotation.NonNull; import android.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; Loading Loading @@ -52,6 +53,8 @@ public class RankingCoordinator implements Coordinator { private final NodeController mSilentNodeController; private final SectionHeaderController mSilentHeaderController; private final NodeController mAlertingHeaderController; private boolean mHasSilentEntries; private boolean mHasMinimizedEntries; @Inject public RankingCoordinator( Loading @@ -73,6 +76,7 @@ public class RankingCoordinator implements Coordinator { pipeline.addPreGroupFilter(mSuspendedFilter); pipeline.addPreGroupFilter(mDndVisualEffectsFilter); pipeline.addOnBeforeSortListener(entries -> resetClearAllFlags()); } public NotifSectioner getAlertingSectioner() { Loading @@ -83,6 +87,10 @@ public class RankingCoordinator implements Coordinator { return mSilentNotifSectioner; } public NotifSectioner getMinimizedSectioner() { return mMinimizedNotifSectioner; } private final NotifSectioner mAlertingNotifSectioner = new NotifSectioner("Alerting", NotificationPriorityBucketKt.BUCKET_ALERTING) { @Override Loading @@ -105,7 +113,8 @@ public class RankingCoordinator implements Coordinator { NotificationPriorityBucketKt.BUCKET_SILENT) { @Override public boolean isInSection(ListEntry entry) { return !mHighPriorityProvider.isHighPriority(entry); return !mHighPriorityProvider.isHighPriority(entry) && !entry.getRepresentativeEntry().isAmbient(); } @Nullable Loading @@ -119,11 +128,40 @@ public class RankingCoordinator implements Coordinator { public void onEntriesUpdated(@NonNull List<ListEntry> entries) { for (int i = 0; i < entries.size(); i++) { if (entries.get(i).getRepresentativeEntry().getSbn().isClearable()) { mSilentHeaderController.setClearSectionEnabled(true); return; mHasSilentEntries = true; break; } } mSilentHeaderController.setClearSectionEnabled(false); mSilentHeaderController.setClearSectionEnabled( mHasSilentEntries | mHasMinimizedEntries); } }; private final NotifSectioner mMinimizedNotifSectioner = new NotifSectioner("Minimized", NotificationPriorityBucketKt.BUCKET_SILENT) { @Override public boolean isInSection(ListEntry entry) { return !mHighPriorityProvider.isHighPriority(entry) && entry.getRepresentativeEntry().isAmbient(); } @Nullable @Override public NodeController getHeaderNodeController() { return mSilentNodeController; } @Nullable @Override public void onEntriesUpdated(@NonNull List<ListEntry> entries) { for (int i = 0; i < entries.size(); i++) { if (entries.get(i).getRepresentativeEntry().getSbn().isClearable()) { mHasMinimizedEntries = true; break; } } mSilentHeaderController.setClearSectionEnabled( mHasSilentEntries | mHasMinimizedEntries); } }; Loading Loading @@ -151,6 +189,12 @@ public class RankingCoordinator implements Coordinator { } }; @VisibleForTesting protected void resetClearAllFlags() { mHasSilentEntries = false; mHasMinimizedEntries = false; } private final StatusBarStateController.StateListener mStatusBarStateCallback = new StatusBarStateController.StateListener() { @Override Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java +9 −1 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationViewHierarchyManager; import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager; Loading Loading @@ -98,7 +99,9 @@ public class VisualStabilityCoordinator implements Coordinator { pipeline.setVisualStabilityManager(mNotifStabilityManager); } // TODO(b/203828145): Ensure stability manager handles minimized state changes // TODO(b/203826051): Ensure stability manager can allow reordering off-screen // HUNs to the top of the shade private final NotifStabilityManager mNotifStabilityManager = new NotifStabilityManager("VisualStabilityCoordinator") { @Override Loading Loading @@ -126,6 +129,11 @@ public class VisualStabilityCoordinator implements Coordinator { } return isSectionChangeAllowedForEntry; } @Override public boolean isEntryReorderingAllowed(ListEntry section) { return mReorderingAllowed; } }; private void updateAllowedStates() { Loading Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt +8 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,11 @@ data class ListAttachState private constructor( */ var parent: GroupEntry?, /** * Identifies the notification order in the entire notification list */ var stableIndex: Int = -1, /** * The section that this ListEntry was sorted into. If the child of the group, this will be the * parent's section. Null if not attached to the list. Loading Loading @@ -58,6 +63,7 @@ data class ListAttachState private constructor( /** Copies the state of another instance. */ fun clone(other: ListAttachState) { parent = other.parent stableIndex = other.stableIndex section = other.section excludingFilter = other.excludingFilter promoter = other.promoter Loading @@ -70,6 +76,7 @@ data class ListAttachState private constructor( section = null excludingFilter = null promoter = null stableIndex = -1 suppressedChanges.reset() } Loading @@ -78,6 +85,7 @@ data class ListAttachState private constructor( fun create(): ListAttachState { return ListAttachState( null, -1, null, null, null, Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java +59 −28 Original line number Diff line number Diff line Loading @@ -775,18 +775,44 @@ public class ShadeListBuilder implements Dumpable { for (NotificationEntry child : parent.getChildren()) { setEntrySection(child, section); } parent.sortChildren(sChildComparator); parent.sortChildren(mGroupChildrenComparator); } } // Finally, sort all top-level elements mNotifList.sort(mTopLevelComparator); assignIndexes(mNotifList); // notify sections since the list is sorted now notifySectionEntriesUpdated(); Trace.endSection(); } /** * Assign the index of each notification relative to the total order * @param notifList */ private void assignIndexes(List<ListEntry> notifList) { if (notifList.size() == 0) return; NotifSection currentSection = notifList.get(0).getSection(); int sectionMemberIndex = 0; for (int i = 0; i < notifList.size(); i++) { ListEntry entry = notifList.get(i); NotifSection section = entry.getSection(); if (section.getIndex() != currentSection.getIndex()) { sectionMemberIndex = 0; currentSection = section; } entry.getAttachState().setStableIndex(sectionMemberIndex); if (entry instanceof GroupEntry) { GroupEntry parent = (GroupEntry) entry; for (int j = 0; j < parent.getChildren().size(); j++) { entry = parent.getChildren().get(j); entry.getAttachState().setStableIndex(sectionMemberIndex); sectionMemberIndex++; } } sectionMemberIndex++; } } private void freeEmptyGroups() { mGroups.values().removeIf(ge -> ge.getSummary() == null && ge.getChildren().isEmpty()); } Loading Loading @@ -891,48 +917,53 @@ public class ShadeListBuilder implements Dumpable { } private final Comparator<ListEntry> mTopLevelComparator = (o1, o2) -> { int cmp = Integer.compare( o1.getSectionIndex(), o2.getSectionIndex()); if (cmp != 0) return cmp; int index1 = canReorder(o1) ? -1 : o1.getPreviousAttachState().getStableIndex(); int index2 = canReorder(o2) ? -1 : o2.getPreviousAttachState().getStableIndex(); cmp = Integer.compare(index1, index2); if (cmp != 0) return cmp; if (cmp == 0) { for (int i = 0; i < mNotifComparators.size(); i++) { cmp = mNotifComparators.get(i).compare(o1, o2); if (cmp != 0) { break; } } if (cmp != 0) return cmp; } final NotificationEntry rep1 = o1.getRepresentativeEntry(); final NotificationEntry rep2 = o2.getRepresentativeEntry(); if (cmp == 0) { cmp = rep1.getRanking().getRank() - rep2.getRanking().getRank(); } if (cmp != 0) return cmp; if (cmp == 0) { cmp = Long.compare( rep2.getSbn().getNotification().when, rep1.getSbn().getNotification().when); } return cmp; }; private static final Comparator<NotificationEntry> sChildComparator = (o1, o2) -> { int cmp = o1.getRanking().getRank() - o2.getRanking().getRank(); if (cmp == 0) { cmp = Long.compare( o2.getSbn().getNotification().when, o1.getSbn().getNotification().when); } private final Comparator<ListEntry> mGroupChildrenComparator = (o1, o2) -> { int index1 = canReorder(o1) ? -1 : o1.getPreviousAttachState().getStableIndex(); int index2 = canReorder(o2) ? -1 : o2.getPreviousAttachState().getStableIndex(); int cmp = Integer.compare(index1, index2); if (cmp != 0) return cmp; cmp = o1.getRepresentativeEntry().getRanking().getRank() - o2.getRepresentativeEntry().getRanking().getRank(); if (cmp != 0) return cmp; cmp = Long.compare( o2.getRepresentativeEntry().getSbn().getNotification().when, o1.getRepresentativeEntry().getSbn().getNotification().when); return cmp; }; private boolean canReorder(ListEntry entry) { return mNotifStabilityManager.isEntryReorderingAllowed(entry); } private boolean applyFilters(NotificationEntry entry, long now, List<NotifFilter> filters) { final NotifFilter filter = findRejectingFilter(entry, now, filters); entry.getAttachState().setExcludingFilter(filter); Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt +1 −0 Original line number Diff line number Diff line Loading @@ -98,6 +98,7 @@ class NotifCoordinatorsImpl @Inject constructor( mOrderedSections.add(conversationCoordinator.sectioner) // People mOrderedSections.add(rankingCoordinator.alertingSectioner) // Alerting mOrderedSections.add(rankingCoordinator.silentSectioner) // Silent mOrderedSections.add(rankingCoordinator.minimizedSectioner) // Minimized } /** Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java +48 −4 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator; import android.annotation.NonNull; import android.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; Loading Loading @@ -52,6 +53,8 @@ public class RankingCoordinator implements Coordinator { private final NodeController mSilentNodeController; private final SectionHeaderController mSilentHeaderController; private final NodeController mAlertingHeaderController; private boolean mHasSilentEntries; private boolean mHasMinimizedEntries; @Inject public RankingCoordinator( Loading @@ -73,6 +76,7 @@ public class RankingCoordinator implements Coordinator { pipeline.addPreGroupFilter(mSuspendedFilter); pipeline.addPreGroupFilter(mDndVisualEffectsFilter); pipeline.addOnBeforeSortListener(entries -> resetClearAllFlags()); } public NotifSectioner getAlertingSectioner() { Loading @@ -83,6 +87,10 @@ public class RankingCoordinator implements Coordinator { return mSilentNotifSectioner; } public NotifSectioner getMinimizedSectioner() { return mMinimizedNotifSectioner; } private final NotifSectioner mAlertingNotifSectioner = new NotifSectioner("Alerting", NotificationPriorityBucketKt.BUCKET_ALERTING) { @Override Loading @@ -105,7 +113,8 @@ public class RankingCoordinator implements Coordinator { NotificationPriorityBucketKt.BUCKET_SILENT) { @Override public boolean isInSection(ListEntry entry) { return !mHighPriorityProvider.isHighPriority(entry); return !mHighPriorityProvider.isHighPriority(entry) && !entry.getRepresentativeEntry().isAmbient(); } @Nullable Loading @@ -119,11 +128,40 @@ public class RankingCoordinator implements Coordinator { public void onEntriesUpdated(@NonNull List<ListEntry> entries) { for (int i = 0; i < entries.size(); i++) { if (entries.get(i).getRepresentativeEntry().getSbn().isClearable()) { mSilentHeaderController.setClearSectionEnabled(true); return; mHasSilentEntries = true; break; } } mSilentHeaderController.setClearSectionEnabled(false); mSilentHeaderController.setClearSectionEnabled( mHasSilentEntries | mHasMinimizedEntries); } }; private final NotifSectioner mMinimizedNotifSectioner = new NotifSectioner("Minimized", NotificationPriorityBucketKt.BUCKET_SILENT) { @Override public boolean isInSection(ListEntry entry) { return !mHighPriorityProvider.isHighPriority(entry) && entry.getRepresentativeEntry().isAmbient(); } @Nullable @Override public NodeController getHeaderNodeController() { return mSilentNodeController; } @Nullable @Override public void onEntriesUpdated(@NonNull List<ListEntry> entries) { for (int i = 0; i < entries.size(); i++) { if (entries.get(i).getRepresentativeEntry().getSbn().isClearable()) { mHasMinimizedEntries = true; break; } } mSilentHeaderController.setClearSectionEnabled( mHasSilentEntries | mHasMinimizedEntries); } }; Loading Loading @@ -151,6 +189,12 @@ public class RankingCoordinator implements Coordinator { } }; @VisibleForTesting protected void resetClearAllFlags() { mHasSilentEntries = false; mHasMinimizedEntries = false; } private final StatusBarStateController.StateListener mStatusBarStateCallback = new StatusBarStateController.StateListener() { @Override Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java +9 −1 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationViewHierarchyManager; import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager; Loading Loading @@ -98,7 +99,9 @@ public class VisualStabilityCoordinator implements Coordinator { pipeline.setVisualStabilityManager(mNotifStabilityManager); } // TODO(b/203828145): Ensure stability manager handles minimized state changes // TODO(b/203826051): Ensure stability manager can allow reordering off-screen // HUNs to the top of the shade private final NotifStabilityManager mNotifStabilityManager = new NotifStabilityManager("VisualStabilityCoordinator") { @Override Loading Loading @@ -126,6 +129,11 @@ public class VisualStabilityCoordinator implements Coordinator { } return isSectionChangeAllowedForEntry; } @Override public boolean isEntryReorderingAllowed(ListEntry section) { return mReorderingAllowed; } }; private void updateAllowedStates() { Loading