Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt +36 −0 Original line number Diff line number Diff line Loading @@ -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) } } } } /** Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt +9 −0 Original line number Diff line number Diff line Loading @@ -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" }) } } packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt +59 −3 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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) Loading Loading @@ -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) { Loading Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt +36 −0 Original line number Diff line number Diff line Loading @@ -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) } } } } /** Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt +9 −0 Original line number Diff line number Diff line Loading @@ -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" }) } }
packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt +59 −3 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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) Loading Loading @@ -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) { Loading