Loading packages/SystemUI/src/com/android/systemui/flags/Flags.java +3 −0 Original line number Diff line number Diff line Loading @@ -60,6 +60,9 @@ public class Flags { public static final ResourceBooleanFlag NOTIFICATION_DRAG_TO_CONTENTS = new ResourceBooleanFlag(108, R.bool.config_notificationToContents); public static final BooleanFlag REMOVE_UNRANKED_NOTIFICATIONS = new BooleanFlag(109, false); /***************************************/ // 200 - keyguard/lockscreen Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt +4 −1 Original line number Diff line number Diff line Loading @@ -56,4 +56,7 @@ class NotifPipelineFlags @Inject constructor( fun isSmartspaceDedupingEnabled(): Boolean = featureFlags.isEnabled(Flags.SMARTSPACE) && featureFlags.isEnabled(Flags.SMARTSPACE_DEDUPING) fun removeUnrankedNotifs(): Boolean = featureFlags.isEnabled(Flags.REMOVE_UNRANKED_NOTIFICATIONS) } packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java +6 −0 Original line number Diff line number Diff line Loading @@ -601,6 +601,12 @@ public class NotifCollection implements Dumpable, PipelineDumpable { ); mNotificationsWithoutRankings = currentEntriesWithoutRankings == null ? Collections.emptySet() : currentEntriesWithoutRankings.keySet(); if (currentEntriesWithoutRankings != null && mNotifPipelineFlags.removeUnrankedNotifs()) { for (NotificationEntry entry : currentEntriesWithoutRankings.values()) { entry.mCancellationReason = REASON_UNKNOWN; tryRemoveNotification(entry); } } mEventQueue.add(new RankingAppliedEvent()); } Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NoManSimulator.java +5 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,11 @@ public class NoManSimulator { mRankings.put(key, ranking); } /** This is for testing error cases: b/216384850 */ public Ranking removeRankingWithoutEvent(String key) { return mRankings.remove(key); } private RankingMap buildRankingMap() { return new RankingMap(mRankings.values().toArray(new Ranking[0])); } Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java +74 −0 Original line number Diff line number Diff line Loading @@ -1491,6 +1491,80 @@ public class NotifCollectionTest extends SysuiTestCase { verify(mCollectionListener, never()).onEntryUpdated(any(), anyBoolean()); } @Test public void testMissingRankingWhenRemovalFeatureIsDisabled() { // GIVEN a pipeline with one two notifications when(mNotifPipelineFlags.removeUnrankedNotifs()).thenReturn(false); String key1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 1, "myTag")).key; String key2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 2, "myTag")).key; NotificationEntry entry1 = mCollectionListener.getEntry(key1); NotificationEntry entry2 = mCollectionListener.getEntry(key2); clearInvocations(mCollectionListener); // GIVEN the message for removing key1 gets does not reach NotifCollection Ranking ranking1 = mNoMan.removeRankingWithoutEvent(key1); // WHEN the message for removing key2 arrives mNoMan.retractNotif(entry2.getSbn(), REASON_APP_CANCEL); // THEN only entry2 gets removed verify(mCollectionListener).onEntryRemoved(eq(entry2), eq(REASON_APP_CANCEL)); verify(mCollectionListener).onEntryCleanUp(eq(entry2)); verify(mCollectionListener).onRankingApplied(); verifyNoMoreInteractions(mCollectionListener); verify(mLogger).logMissingRankings(eq(List.of(entry1)), eq(1), any()); verify(mLogger, never()).logRecoveredRankings(any()); clearInvocations(mCollectionListener, mLogger); // WHEN a ranking update includes key1 again mNoMan.setRanking(key1, ranking1); mNoMan.issueRankingUpdate(); // VERIFY that we do nothing but log the 'recovery' verify(mCollectionListener).onRankingUpdate(any()); verify(mCollectionListener).onRankingApplied(); verifyNoMoreInteractions(mCollectionListener); verify(mLogger, never()).logMissingRankings(any(), anyInt(), any()); verify(mLogger).logRecoveredRankings(eq(List.of(key1))); } @Test public void testMissingRankingWhenRemovalFeatureIsEnabled() { // GIVEN a pipeline with one two notifications when(mNotifPipelineFlags.removeUnrankedNotifs()).thenReturn(true); String key1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 1, "myTag")).key; String key2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 2, "myTag")).key; NotificationEntry entry1 = mCollectionListener.getEntry(key1); NotificationEntry entry2 = mCollectionListener.getEntry(key2); clearInvocations(mCollectionListener); // GIVEN the message for removing key1 gets does not reach NotifCollection Ranking ranking1 = mNoMan.removeRankingWithoutEvent(key1); // WHEN the message for removing key2 arrives mNoMan.retractNotif(entry2.getSbn(), REASON_APP_CANCEL); // THEN both entry1 and entry2 get removed verify(mCollectionListener).onEntryRemoved(eq(entry2), eq(REASON_APP_CANCEL)); verify(mCollectionListener).onEntryRemoved(eq(entry1), eq(REASON_UNKNOWN)); verify(mCollectionListener).onEntryCleanUp(eq(entry2)); verify(mCollectionListener).onEntryCleanUp(eq(entry1)); verify(mCollectionListener).onRankingApplied(); verifyNoMoreInteractions(mCollectionListener); verify(mLogger).logMissingRankings(eq(List.of(entry1)), eq(1), any()); verify(mLogger, never()).logRecoveredRankings(any()); clearInvocations(mCollectionListener, mLogger); // WHEN a ranking update includes key1 again mNoMan.setRanking(key1, ranking1); mNoMan.issueRankingUpdate(); // VERIFY that we do nothing but log the 'recovery' verify(mCollectionListener).onRankingUpdate(any()); verify(mCollectionListener).onRankingApplied(); verifyNoMoreInteractions(mCollectionListener); verify(mLogger, never()).logMissingRankings(any(), anyInt(), any()); verify(mLogger).logRecoveredRankings(eq(List.of(key1))); } @Test public void testRegisterFutureDismissal() throws RemoteException { // GIVEN a pipeline with one notification Loading Loading
packages/SystemUI/src/com/android/systemui/flags/Flags.java +3 −0 Original line number Diff line number Diff line Loading @@ -60,6 +60,9 @@ public class Flags { public static final ResourceBooleanFlag NOTIFICATION_DRAG_TO_CONTENTS = new ResourceBooleanFlag(108, R.bool.config_notificationToContents); public static final BooleanFlag REMOVE_UNRANKED_NOTIFICATIONS = new BooleanFlag(109, false); /***************************************/ // 200 - keyguard/lockscreen Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt +4 −1 Original line number Diff line number Diff line Loading @@ -56,4 +56,7 @@ class NotifPipelineFlags @Inject constructor( fun isSmartspaceDedupingEnabled(): Boolean = featureFlags.isEnabled(Flags.SMARTSPACE) && featureFlags.isEnabled(Flags.SMARTSPACE_DEDUPING) fun removeUnrankedNotifs(): Boolean = featureFlags.isEnabled(Flags.REMOVE_UNRANKED_NOTIFICATIONS) }
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java +6 −0 Original line number Diff line number Diff line Loading @@ -601,6 +601,12 @@ public class NotifCollection implements Dumpable, PipelineDumpable { ); mNotificationsWithoutRankings = currentEntriesWithoutRankings == null ? Collections.emptySet() : currentEntriesWithoutRankings.keySet(); if (currentEntriesWithoutRankings != null && mNotifPipelineFlags.removeUnrankedNotifs()) { for (NotificationEntry entry : currentEntriesWithoutRankings.values()) { entry.mCancellationReason = REASON_UNKNOWN; tryRemoveNotification(entry); } } mEventQueue.add(new RankingAppliedEvent()); } Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NoManSimulator.java +5 −0 Original line number Diff line number Diff line Loading @@ -85,6 +85,11 @@ public class NoManSimulator { mRankings.put(key, ranking); } /** This is for testing error cases: b/216384850 */ public Ranking removeRankingWithoutEvent(String key) { return mRankings.remove(key); } private RankingMap buildRankingMap() { return new RankingMap(mRankings.values().toArray(new Ranking[0])); } Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java +74 −0 Original line number Diff line number Diff line Loading @@ -1491,6 +1491,80 @@ public class NotifCollectionTest extends SysuiTestCase { verify(mCollectionListener, never()).onEntryUpdated(any(), anyBoolean()); } @Test public void testMissingRankingWhenRemovalFeatureIsDisabled() { // GIVEN a pipeline with one two notifications when(mNotifPipelineFlags.removeUnrankedNotifs()).thenReturn(false); String key1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 1, "myTag")).key; String key2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 2, "myTag")).key; NotificationEntry entry1 = mCollectionListener.getEntry(key1); NotificationEntry entry2 = mCollectionListener.getEntry(key2); clearInvocations(mCollectionListener); // GIVEN the message for removing key1 gets does not reach NotifCollection Ranking ranking1 = mNoMan.removeRankingWithoutEvent(key1); // WHEN the message for removing key2 arrives mNoMan.retractNotif(entry2.getSbn(), REASON_APP_CANCEL); // THEN only entry2 gets removed verify(mCollectionListener).onEntryRemoved(eq(entry2), eq(REASON_APP_CANCEL)); verify(mCollectionListener).onEntryCleanUp(eq(entry2)); verify(mCollectionListener).onRankingApplied(); verifyNoMoreInteractions(mCollectionListener); verify(mLogger).logMissingRankings(eq(List.of(entry1)), eq(1), any()); verify(mLogger, never()).logRecoveredRankings(any()); clearInvocations(mCollectionListener, mLogger); // WHEN a ranking update includes key1 again mNoMan.setRanking(key1, ranking1); mNoMan.issueRankingUpdate(); // VERIFY that we do nothing but log the 'recovery' verify(mCollectionListener).onRankingUpdate(any()); verify(mCollectionListener).onRankingApplied(); verifyNoMoreInteractions(mCollectionListener); verify(mLogger, never()).logMissingRankings(any(), anyInt(), any()); verify(mLogger).logRecoveredRankings(eq(List.of(key1))); } @Test public void testMissingRankingWhenRemovalFeatureIsEnabled() { // GIVEN a pipeline with one two notifications when(mNotifPipelineFlags.removeUnrankedNotifs()).thenReturn(true); String key1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 1, "myTag")).key; String key2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 2, "myTag")).key; NotificationEntry entry1 = mCollectionListener.getEntry(key1); NotificationEntry entry2 = mCollectionListener.getEntry(key2); clearInvocations(mCollectionListener); // GIVEN the message for removing key1 gets does not reach NotifCollection Ranking ranking1 = mNoMan.removeRankingWithoutEvent(key1); // WHEN the message for removing key2 arrives mNoMan.retractNotif(entry2.getSbn(), REASON_APP_CANCEL); // THEN both entry1 and entry2 get removed verify(mCollectionListener).onEntryRemoved(eq(entry2), eq(REASON_APP_CANCEL)); verify(mCollectionListener).onEntryRemoved(eq(entry1), eq(REASON_UNKNOWN)); verify(mCollectionListener).onEntryCleanUp(eq(entry2)); verify(mCollectionListener).onEntryCleanUp(eq(entry1)); verify(mCollectionListener).onRankingApplied(); verifyNoMoreInteractions(mCollectionListener); verify(mLogger).logMissingRankings(eq(List.of(entry1)), eq(1), any()); verify(mLogger, never()).logRecoveredRankings(any()); clearInvocations(mCollectionListener, mLogger); // WHEN a ranking update includes key1 again mNoMan.setRanking(key1, ranking1); mNoMan.issueRankingUpdate(); // VERIFY that we do nothing but log the 'recovery' verify(mCollectionListener).onRankingUpdate(any()); verify(mCollectionListener).onRankingApplied(); verifyNoMoreInteractions(mCollectionListener); verify(mLogger, never()).logMissingRankings(any(), anyInt(), any()); verify(mLogger).logRecoveredRankings(eq(List.of(key1))); } @Test public void testRegisterFutureDismissal() throws RemoteException { // GIVEN a pipeline with one notification Loading