diff options
3 files changed, 104 insertions, 3 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt index ccf6feca6992..8f3eb4f7e223 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt @@ -440,6 +440,42 @@ class HeadsUpCoordinator @Inject constructor( override fun onEntryCleanUp(entry: NotificationEntry) { mHeadsUpViewBinder.abortBindCallback(entry) } + + /** + * Identify notifications whose heads-up state changes when the notification rankings are + * updated, and have those changed notifications alert if necessary. + * + * This method will occur after any operations in onEntryAdded or onEntryUpdated, so any + * handling of ranking changes needs to take into account that we may have just made a + * PostedEntry for some of these notifications. + */ + override fun onRankingApplied() { + // Because a ranking update may cause some notifications that are no longer (or were + // never) in mPostedEntries to need to alert, we need to check every notification + // known to the pipeline. + for (entry in mNotifPipeline.allNotifs) { + // The only entries we can consider alerting for here are entries that have never + // interrupted and that now say they should heads up; if they've alerted in the + // past, we don't want to incorrectly alert a second time if there wasn't an + // explicit notification update. + if (entry.hasInterrupted()) continue + + // The cases where we should consider this notification to be updated: + // - if this entry is not present in PostedEntries, and is now in a shouldHeadsUp + // state + // - if it is present in PostedEntries and the previous state of shouldHeadsUp + // differs from the updated one + val shouldHeadsUpEver = mNotificationInterruptStateProvider.checkHeadsUp(entry, + /* log= */ false) + val postedShouldHeadsUpEver = mPostedEntries[entry.key]?.shouldHeadsUpEver ?: false + val shouldUpdateEntry = postedShouldHeadsUpEver != shouldHeadsUpEver + + if (shouldUpdateEntry) { + mLogger.logEntryUpdatedByRanking(entry.key, shouldHeadsUpEver) + onEntryUpdated(entry) + } + } + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt index 204a494c32e8..8625cdbc89d5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt @@ -59,4 +59,13 @@ class HeadsUpCoordinatorLogger constructor( " numPostedEntries=$int1 logicalGroupSize=$int2" }) } + + fun logEntryUpdatedByRanking(key: String, shouldHun: Boolean) { + buffer.log(TAG, LogLevel.DEBUG, { + str1 = key + bool1 = shouldHun + }, { + "updating entry via ranking applied: $str1 updated shouldHeadsUp=$bool1" + }) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt index 2970807afb36..340bc96f80c2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt @@ -47,6 +47,8 @@ import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.withArgCaptor import com.android.systemui.util.time.FakeSystemClock +import java.util.ArrayList +import java.util.function.Consumer import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Before @@ -57,10 +59,8 @@ import org.mockito.BDDMockito.given import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify -import org.mockito.MockitoAnnotations -import java.util.ArrayList -import java.util.function.Consumer import org.mockito.Mockito.`when` as whenever +import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidTestingRunner::class) @@ -671,8 +671,64 @@ class HeadsUpCoordinatorTest : SysuiTestCase() { verify(mHeadsUpManager, never()).showNotification(mGroupChild2) } + @Test + fun testOnRankingApplied_newEntryShouldAlert() { + // GIVEN that mEntry has never interrupted in the past, and now should + assertFalse(mEntry.hasInterrupted()) + setShouldHeadsUp(mEntry) + whenever(mNotifPipeline.allNotifs).thenReturn(listOf(mEntry)) + + // WHEN a ranking applied update occurs + mCollectionListener.onRankingApplied() + mBeforeTransformGroupsListener.onBeforeTransformGroups(listOf(mEntry)) + mBeforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(mEntry)) + + // THEN the notification is shown + finishBind(mEntry) + verify(mHeadsUpManager).showNotification(mEntry) + } + + @Test + fun testOnRankingApplied_alreadyAlertedEntryShouldNotAlertAgain() { + // GIVEN that mEntry has alerted in the past + mEntry.setInterruption() + setShouldHeadsUp(mEntry) + whenever(mNotifPipeline.allNotifs).thenReturn(listOf(mEntry)) + + // WHEN a ranking applied update occurs + mCollectionListener.onRankingApplied() + mBeforeTransformGroupsListener.onBeforeTransformGroups(listOf(mEntry)) + mBeforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(mEntry)) + + // THEN the notification is never bound or shown + verify(mHeadsUpViewBinder, never()).bindHeadsUpView(any(), any()) + verify(mHeadsUpManager, never()).showNotification(any()) + } + + @Test + fun testOnRankingApplied_entryUpdatedToHun() { + // GIVEN that mEntry is added in a state where it should not HUN + setShouldHeadsUp(mEntry, false) + mCollectionListener.onEntryAdded(mEntry) + + // and it is then updated such that it should now HUN + setShouldHeadsUp(mEntry) + whenever(mNotifPipeline.allNotifs).thenReturn(listOf(mEntry)) + + // WHEN a ranking applied update occurs + mCollectionListener.onRankingApplied() + mBeforeTransformGroupsListener.onBeforeTransformGroups(listOf(mEntry)) + mBeforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(mEntry)) + + // THEN the notification is shown + finishBind(mEntry) + verify(mHeadsUpManager).showNotification(mEntry) + } + private fun setShouldHeadsUp(entry: NotificationEntry, should: Boolean = true) { whenever(mNotificationInterruptStateProvider.shouldHeadsUp(entry)).thenReturn(should) + whenever(mNotificationInterruptStateProvider.checkHeadsUp(eq(entry), any())) + .thenReturn(should) } private fun finishBind(entry: NotificationEntry) { |