Merge "Debounce HeadsUpNotificationInteractor.isHeadsUpOrAnimatingAway" into main
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index fd1b213..b5e47d1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -85,6 +85,7 @@
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -181,6 +182,7 @@
kosmos.headsUpNotificationRepository.activeHeadsUpRows.value =
buildNotificationRows(isPinned = false)
+ advanceTimeBy(50L) // account for HeadsUpNotificationInteractor debounce
assertThat(isVisible).isFalse()
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractorTest.kt
index 8b4265f..5ef3485 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractorTest.kt
@@ -23,6 +23,7 @@
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.coroutines.collectValues
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
@@ -279,6 +280,64 @@
}
@Test
+ fun isHeadsUpOrAnimatingAway_falseOnStart() =
+ testScope.runTest {
+ val isHeadsUpOrAnimatingAway by collectLastValue(underTest.isHeadsUpOrAnimatingAway)
+
+ runCurrent()
+
+ assertThat(isHeadsUpOrAnimatingAway).isFalse()
+ }
+
+ @Test
+ fun isHeadsUpOrAnimatingAway_hasPinnedRows() =
+ testScope.runTest {
+ val isHeadsUpOrAnimatingAway by collectLastValue(underTest.isHeadsUpOrAnimatingAway)
+
+ // WHEN a row is pinned
+ headsUpRepository.setNotifications(fakeHeadsUpRowRepository("key 0", isPinned = true))
+ runCurrent()
+
+ assertThat(isHeadsUpOrAnimatingAway).isTrue()
+ }
+
+ @Test
+ fun isHeadsUpOrAnimatingAway_headsUpAnimatingAway() =
+ testScope.runTest {
+ val isHeadsUpOrAnimatingAway by collectLastValue(underTest.isHeadsUpOrAnimatingAway)
+
+ // WHEN the last row is animating away
+ headsUpRepository.setHeadsUpAnimatingAway(true)
+ runCurrent()
+
+ assertThat(isHeadsUpOrAnimatingAway).isTrue()
+ }
+
+ @Test
+ fun isHeadsUpOrAnimatingAway_headsUpAnimatingAwayDebounced() =
+ testScope.runTest {
+ val values by collectValues(underTest.isHeadsUpOrAnimatingAway)
+
+ // GIVEN a row is pinned
+ headsUpRepository.setNotifications(fakeHeadsUpRowRepository("key 0", isPinned = true))
+ runCurrent()
+ assertThat(values.size).isEqualTo(2)
+ assertThat(values.first()).isFalse() // initial value
+ assertThat(values.last()).isTrue()
+
+ // WHEN the last row is removed
+ headsUpRepository.setNotifications(emptyList())
+ runCurrent()
+ // AND starts to animate away
+ headsUpRepository.setHeadsUpAnimatingAway(true)
+ runCurrent()
+
+ // THEN isHeadsUpOrAnimatingAway remained true
+ assertThat(values.size).isEqualTo(2)
+ assertThat(values.last()).isTrue()
+ }
+
+ @Test
fun showHeadsUpStatusBar_true() =
testScope.runTest {
val showHeadsUpStatusBar by collectLastValue(underTest.showHeadsUpStatusBar)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt
index cdab108..eebbb13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
+@file:OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)
package com.android.systemui.statusbar.notification.domain.interactor
@@ -27,11 +27,15 @@
import com.android.systemui.statusbar.notification.shared.HeadsUpRowKey
import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.debounce
+import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onStart
class HeadsUpNotificationInteractor
@Inject
@@ -73,10 +77,21 @@
val isHeadsUpOrAnimatingAway: Flow<Boolean> =
combine(hasPinnedRows, headsUpRepository.isHeadsUpAnimatingAway) {
- hasPinnedRows,
- animatingAway ->
- hasPinnedRows || animatingAway
- }
+ hasPinnedRows,
+ animatingAway ->
+ hasPinnedRows || animatingAway
+ }
+ .debounce { isHeadsUpOrAnimatingAway ->
+ if (isHeadsUpOrAnimatingAway) {
+ 0
+ } else {
+ // When the last pinned entry is removed from the [HeadsUpRepository],
+ // there might be a delay before the View starts animating.
+ 50L
+ }
+ }
+ .onStart { emit(false) } // emit false, so we don't wait for the initial update
+ .distinctUntilChanged()
private val canShowHeadsUp: Flow<Boolean> =
combine(