Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/LockScreenMinimalismCoordinatorTest.kt +0 −15 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.app.Notification import android.app.NotificationManager.IMPORTANCE_DEFAULT import android.app.NotificationManager.IMPORTANCE_LOW import android.os.UserHandle import android.platform.test.annotations.EnableFlags import android.provider.Settings import androidx.test.ext.junit.runners.AndroidJUnit4 Loading Loading @@ -475,20 +474,6 @@ class LockScreenMinimalismCoordinatorTest : SysuiTestCase() { val collectionListener: NotifCollectionListener = argumentCaptor { verify(notifPipeline).addCollectionListener(capture()) }.lastValue var showOnlyUnseenNotifsOnKeyguardSetting: Boolean get() = fakeSettings.getIntForUser( Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, UserHandle.USER_CURRENT, ) == 1 set(value) { fakeSettings.putIntForUser( Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, if (value) 1 else 2, UserHandle.USER_CURRENT, ) } } companion object { Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinatorTest.kt +42 −50 Original line number Diff line number Diff line Loading @@ -18,21 +18,23 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.app.Notification import android.os.UserHandle import android.platform.test.flag.junit.FlagsParameterization import android.provider.Settings import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager import com.android.systemui.dump.dumpManager import com.android.systemui.flags.andSceneContainer import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.keyguardRepository import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.log.logcatLogBuffer import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.plugins.statusbar.statusBarStateController import com.android.systemui.scene.data.repository.Idle import com.android.systemui.scene.data.repository.setTransition import com.android.systemui.scene.domain.interactor.sceneInteractor Loading @@ -43,12 +45,15 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntryB import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository import com.android.systemui.statusbar.notification.domain.interactor.SeenNotificationsInteractor import com.android.systemui.statusbar.notification.domain.interactor.lockScreenShowOnlyUnseenNotificationsSetting import com.android.systemui.statusbar.notification.domain.interactor.seenNotificationsInteractor import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.policy.HeadsUpManager import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener import com.android.systemui.statusbar.policy.headsUpManager import com.android.systemui.testKosmos import com.android.systemui.util.settings.FakeSettings import com.android.systemui.util.settings.fakeSettings import com.google.common.truth.Truth.assertThat import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.CoroutineScope Loading @@ -73,13 +78,23 @@ import platform.test.runner.parameterized.Parameters @RunWith(ParameterizedAndroidJunit4::class) class OriginalUnseenKeyguardCoordinatorTest(flags: FlagsParameterization) : SysuiTestCase() { private val kosmos = Kosmos() private val kosmos = testKosmos().apply { testDispatcher = UnconfinedTestDispatcher() statusBarStateController = mock() fakeSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, 1) } private val keyguardRepository get() = kosmos.fakeKeyguardRepository private val keyguardTransitionRepository get() = kosmos.fakeKeyguardTransitionRepository private val statusBarStateController get() = kosmos.statusBarStateController private val headsUpManager: HeadsUpManager = mock() private val keyguardRepository = FakeKeyguardRepository() private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository private val notifPipeline: NotifPipeline = mock() private val statusBarStateController: StatusBarStateController = mock() init { mSetFlagsRule.setFlagsParameterization(flags) Loading Loading @@ -253,7 +268,7 @@ class OriginalUnseenKeyguardCoordinatorTest(flags: FlagsParameterization) : Sysu collectionListener.onEntryAdded(fakeEntry) // GIVEN: The setting for filtering unseen notifications is disabled showOnlyUnseenNotifsOnKeyguardSetting = false kosmos.lockScreenShowOnlyUnseenNotificationsSetting = false // GIVEN: The pipeline has registered the unseen filter for invalidation val invalidationListener: Pluggable.PluggableListener<NotifFilter> = mock() Loading @@ -267,7 +282,7 @@ class OriginalUnseenKeyguardCoordinatorTest(flags: FlagsParameterization) : Sysu assertThat(unseenFilter.shouldFilterOut(fakeEntry, 0L)).isFalse() // WHEN: The secure setting is changed showOnlyUnseenNotifsOnKeyguardSetting = true kosmos.lockScreenShowOnlyUnseenNotificationsSetting = true // THEN: The pipeline is invalidated verify(invalidationListener).onPluggableInvalidated(same(unseenFilter), any()) Loading Loading @@ -608,35 +623,25 @@ class OriginalUnseenKeyguardCoordinatorTest(flags: FlagsParameterization) : Sysu private fun runKeyguardCoordinatorTest( testBlock: suspend KeyguardCoordinatorTestScope.() -> Unit ) { val testDispatcher = UnconfinedTestDispatcher() val testScope = TestScope(testDispatcher) val fakeSettings = FakeSettings().apply { putInt(Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, 1) } val seenNotificationsInteractor = SeenNotificationsInteractor(ActiveNotificationListRepository()) val keyguardCoordinator = OriginalUnseenKeyguardCoordinator( testDispatcher, mock<DumpManager>(), headsUpManager, keyguardRepository, kosmos.keyguardTransitionInteractor, KeyguardCoordinatorLogger(logcatLogBuffer()), testScope.backgroundScope, fakeSettings, seenNotificationsInteractor, statusBarStateController, dumpManager = kosmos.dumpManager, headsUpManager = kosmos.headsUpManager, keyguardRepository = kosmos.keyguardRepository, keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor, logger = KeyguardCoordinatorLogger(logcatLogBuffer()), scope = kosmos.testScope.backgroundScope, seenNotificationsInteractor = kosmos.seenNotificationsInteractor, statusBarStateController = kosmos.statusBarStateController, sceneInteractor = kosmos.sceneInteractor, ) keyguardCoordinator.attach(notifPipeline) testScope.runTest { kosmos.testScope.runTest { KeyguardCoordinatorTestScope( keyguardCoordinator, testScope, seenNotificationsInteractor, fakeSettings, kosmos.testScope, kosmos.seenNotificationsInteractor, kosmos.fakeSettings, ) .testBlock() } Loading @@ -658,21 +663,8 @@ class OriginalUnseenKeyguardCoordinatorTest(flags: FlagsParameterization) : Sysu argumentCaptor { verify(notifPipeline).addCollectionListener(capture()) }.lastValue val onHeadsUpChangedListener: OnHeadsUpChangedListener get() = argumentCaptor { verify(headsUpManager).addListener(capture()) }.lastValue var showOnlyUnseenNotifsOnKeyguardSetting: Boolean get() = fakeSettings.getIntForUser( Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, UserHandle.USER_CURRENT, ) == 1 set(value) { fakeSettings.putIntForUser( Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, if (value) 1 else 2, UserHandle.USER_CURRENT, ) } argumentCaptor { verify(kosmos.headsUpManager).addListener(capture()) }.lastValue } companion object { Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/SeenNotificationsInteractorTest.kt→packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/SeenNotificationsInteractorTest.kt +94 −0 Original line number Diff line number Diff line Loading @@ -15,11 +15,14 @@ package com.android.systemui.statusbar.notification.domain.interactor import android.platform.test.annotations.EnableFlags import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder import com.android.systemui.statusbar.notification.shared.NotificationMinimalismPrototype import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest import org.junit.Test Loading @@ -29,8 +32,9 @@ import org.junit.runner.RunWith @SmallTest class SeenNotificationsInteractorTest : SysuiTestCase() { private val repository = ActiveNotificationListRepository() private val underTest = SeenNotificationsInteractor(repository) private val kosmos = testKosmos() private val underTest get() = kosmos.seenNotificationsInteractor @Test fun testNoFilteredOutSeenNotifications() = runTest { Loading @@ -51,4 +55,40 @@ class SeenNotificationsInteractorTest : SysuiTestCase() { assertThat(hasFilteredOutSeenNotifications).isTrue() } @Test @EnableFlags(NotificationMinimalismPrototype.FLAG_NAME) fun topOngoingAndUnseenNotification() = runTest { val entry1 = NotificationEntryBuilder().setTag("entry1").build() val entry2 = NotificationEntryBuilder().setTag("entry2").build() underTest.setTopOngoingNotification(null) underTest.setTopUnseenNotification(null) assertThat(underTest.isTopOngoingNotification(entry1)).isFalse() assertThat(underTest.isTopOngoingNotification(entry2)).isFalse() assertThat(underTest.isTopUnseenNotification(entry1)).isFalse() assertThat(underTest.isTopUnseenNotification(entry2)).isFalse() underTest.setTopOngoingNotification(entry1) underTest.setTopUnseenNotification(entry2) assertThat(underTest.isTopOngoingNotification(entry1)).isTrue() assertThat(underTest.isTopOngoingNotification(entry2)).isFalse() assertThat(underTest.isTopUnseenNotification(entry1)).isFalse() assertThat(underTest.isTopUnseenNotification(entry2)).isTrue() } fun testShowOnlyUnseenNotifsOnKeyguardSetting() = runTest { val settingEnabled by collectLastValue(underTest.isLockScreenShowOnlyUnseenNotificationsEnabled()) kosmos.lockScreenShowOnlyUnseenNotificationsSetting = false testScheduler.runCurrent() assertThat(settingEnabled).isFalse() kosmos.lockScreenShowOnlyUnseenNotificationsSetting = true testScheduler.runCurrent() assertThat(settingEnabled).isTrue() } } packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/LockScreenMinimalismCoordinator.kt +6 −38 Original line number Diff line number Diff line Loading @@ -18,12 +18,9 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.annotation.SuppressLint import android.app.NotificationManager import android.os.UserHandle import android.provider.Settings import androidx.annotation.VisibleForTesting import com.android.systemui.Dumpable import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.shade.domain.interactor.ShadeInteractor Loading @@ -43,23 +40,16 @@ import com.android.systemui.statusbar.notification.stack.BUCKET_TOP_ONGOING import com.android.systemui.statusbar.notification.stack.BUCKET_TOP_UNSEEN import com.android.systemui.util.asIndenting import com.android.systemui.util.printCollection import com.android.systemui.util.settings.SecureSettings import com.android.systemui.util.settings.SettingsProxyExt.observerFlow import java.io.PrintWriter import javax.inject.Inject import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.launch /** Loading @@ -73,12 +63,10 @@ import kotlinx.coroutines.launch class LockScreenMinimalismCoordinator @Inject constructor( @Background private val bgDispatcher: CoroutineDispatcher, private val dumpManager: DumpManager, private val headsUpInteractor: HeadsUpNotificationInteractor, private val logger: LockScreenMinimalismCoordinatorLogger, @Application private val scope: CoroutineScope, private val secureSettings: SecureSettings, private val seenNotificationsInteractor: SeenNotificationsInteractor, private val statusBarStateController: StatusBarStateController, private val shadeInteractor: ShadeInteractor, Loading Loading @@ -147,29 +135,7 @@ constructor( if (NotificationMinimalismPrototype.isEnabled) { return flowOf(true) } return secureSettings // emit whenever the setting has changed .observerFlow( UserHandle.USER_ALL, Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, ) // perform a query immediately .onStart { emit(Unit) } // for each change, lookup the new value .map { secureSettings.getIntForUser( name = Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, def = 0, userHandle = UserHandle.USER_CURRENT, ) == 1 } // don't emit anything if nothing has changed .distinctUntilChanged() // perform lookups on the bg thread pool .flowOn(bgDispatcher) // only track the most recent emission, if events are happening faster than they can be // consumed .conflate() return seenNotificationsInteractor.isLockScreenShowOnlyUnseenNotificationsEnabled() } private suspend fun trackUnseenFilterSettingChanges() { Loading @@ -177,6 +143,7 @@ constructor( // update local field and invalidate if necessary if (isSettingEnabled != unseenFilterEnabled) { unseenFilterEnabled = isSettingEnabled unseenNotifications.clear() unseenNotifPromoter.invalidateList("unseen setting changed") } // if the setting is enabled, then start tracking and filtering unseen notifications Loading @@ -190,21 +157,21 @@ constructor( private val collectionListener = object : NotifCollectionListener { override fun onEntryAdded(entry: NotificationEntry) { if (!isShadeVisible) { if (unseenFilterEnabled && !isShadeVisible) { logger.logUnseenAdded(entry.key) unseenNotifications.add(entry) } } override fun onEntryUpdated(entry: NotificationEntry) { if (!isShadeVisible) { if (unseenFilterEnabled && !isShadeVisible) { logger.logUnseenUpdated(entry.key) unseenNotifications.add(entry) } } override fun onEntryRemoved(entry: NotificationEntry, reason: Int) { if (unseenNotifications.remove(entry)) { if (unseenFilterEnabled && unseenNotifications.remove(entry)) { logger.logUnseenRemoved(entry.key) } } Loading @@ -212,6 +179,7 @@ constructor( private fun pickOutTopUnseenNotifs(list: List<ListEntry>) { if (NotificationMinimalismPrototype.isUnexpectedlyInLegacyMode()) return if (!unseenFilterEnabled) return // Only ever elevate a top unseen notification on keyguard, not even locked shade if (statusBarStateController.state != StatusBarState.KEYGUARD) { seenNotificationsInteractor.setTopOngoingNotification(null) Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinator.kt +1 −34 Original line number Diff line number Diff line Loading @@ -17,12 +17,9 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.annotation.SuppressLint import android.os.UserHandle import android.provider.Settings import androidx.annotation.VisibleForTesting import com.android.systemui.Dumpable import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dump.DumpManager import com.android.systemui.keyguard.data.repository.KeyguardRepository import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor Loading @@ -43,12 +40,9 @@ import com.android.systemui.statusbar.policy.HeadsUpManager import com.android.systemui.statusbar.policy.headsUpEvents import com.android.systemui.util.asIndenting import com.android.systemui.util.indentIfPossible import com.android.systemui.util.settings.SecureSettings import com.android.systemui.util.settings.SettingsProxyExt.observerFlow import java.io.PrintWriter import javax.inject.Inject import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.coroutineScope Loading @@ -56,13 +50,10 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.launch import kotlinx.coroutines.yield Loading @@ -79,14 +70,12 @@ import kotlinx.coroutines.yield class OriginalUnseenKeyguardCoordinator @Inject constructor( @Background private val bgDispatcher: CoroutineDispatcher, private val dumpManager: DumpManager, private val headsUpManager: HeadsUpManager, private val keyguardRepository: KeyguardRepository, private val keyguardTransitionInteractor: KeyguardTransitionInteractor, private val logger: KeyguardCoordinatorLogger, @Application private val scope: CoroutineScope, private val secureSettings: SecureSettings, private val seenNotificationsInteractor: SeenNotificationsInteractor, private val statusBarStateController: StatusBarStateController, private val sceneInteractor: SceneInteractor, Loading Loading @@ -268,29 +257,7 @@ constructor( // TODO(b/330387368): should this really just be turned off? If so, hide the setting. return flowOf(false) } return secureSettings // emit whenever the setting has changed .observerFlow( UserHandle.USER_ALL, Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, ) // perform a query immediately .onStart { emit(Unit) } // for each change, lookup the new value .map { secureSettings.getIntForUser( name = Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, def = 0, userHandle = UserHandle.USER_CURRENT, ) == 1 } // don't emit anything if nothing has changed .distinctUntilChanged() // perform lookups on the bg thread pool .flowOn(bgDispatcher) // only track the most recent emission, if events are happening faster than they can be // consumed .conflate() return seenNotificationsInteractor.isLockScreenShowOnlyUnseenNotificationsEnabled() } private suspend fun trackUnseenFilterSettingChanges() { Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/LockScreenMinimalismCoordinatorTest.kt +0 −15 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.app.Notification import android.app.NotificationManager.IMPORTANCE_DEFAULT import android.app.NotificationManager.IMPORTANCE_LOW import android.os.UserHandle import android.platform.test.annotations.EnableFlags import android.provider.Settings import androidx.test.ext.junit.runners.AndroidJUnit4 Loading Loading @@ -475,20 +474,6 @@ class LockScreenMinimalismCoordinatorTest : SysuiTestCase() { val collectionListener: NotifCollectionListener = argumentCaptor { verify(notifPipeline).addCollectionListener(capture()) }.lastValue var showOnlyUnseenNotifsOnKeyguardSetting: Boolean get() = fakeSettings.getIntForUser( Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, UserHandle.USER_CURRENT, ) == 1 set(value) { fakeSettings.putIntForUser( Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, if (value) 1 else 2, UserHandle.USER_CURRENT, ) } } companion object { Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinatorTest.kt +42 −50 Original line number Diff line number Diff line Loading @@ -18,21 +18,23 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.app.Notification import android.os.UserHandle import android.platform.test.flag.junit.FlagsParameterization import android.provider.Settings import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager import com.android.systemui.dump.dumpManager import com.android.systemui.flags.andSceneContainer import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.keyguardRepository import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.log.logcatLogBuffer import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.plugins.statusbar.statusBarStateController import com.android.systemui.scene.data.repository.Idle import com.android.systemui.scene.data.repository.setTransition import com.android.systemui.scene.domain.interactor.sceneInteractor Loading @@ -43,12 +45,15 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntryB import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository import com.android.systemui.statusbar.notification.domain.interactor.SeenNotificationsInteractor import com.android.systemui.statusbar.notification.domain.interactor.lockScreenShowOnlyUnseenNotificationsSetting import com.android.systemui.statusbar.notification.domain.interactor.seenNotificationsInteractor import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.policy.HeadsUpManager import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener import com.android.systemui.statusbar.policy.headsUpManager import com.android.systemui.testKosmos import com.android.systemui.util.settings.FakeSettings import com.android.systemui.util.settings.fakeSettings import com.google.common.truth.Truth.assertThat import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.CoroutineScope Loading @@ -73,13 +78,23 @@ import platform.test.runner.parameterized.Parameters @RunWith(ParameterizedAndroidJunit4::class) class OriginalUnseenKeyguardCoordinatorTest(flags: FlagsParameterization) : SysuiTestCase() { private val kosmos = Kosmos() private val kosmos = testKosmos().apply { testDispatcher = UnconfinedTestDispatcher() statusBarStateController = mock() fakeSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, 1) } private val keyguardRepository get() = kosmos.fakeKeyguardRepository private val keyguardTransitionRepository get() = kosmos.fakeKeyguardTransitionRepository private val statusBarStateController get() = kosmos.statusBarStateController private val headsUpManager: HeadsUpManager = mock() private val keyguardRepository = FakeKeyguardRepository() private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository private val notifPipeline: NotifPipeline = mock() private val statusBarStateController: StatusBarStateController = mock() init { mSetFlagsRule.setFlagsParameterization(flags) Loading Loading @@ -253,7 +268,7 @@ class OriginalUnseenKeyguardCoordinatorTest(flags: FlagsParameterization) : Sysu collectionListener.onEntryAdded(fakeEntry) // GIVEN: The setting for filtering unseen notifications is disabled showOnlyUnseenNotifsOnKeyguardSetting = false kosmos.lockScreenShowOnlyUnseenNotificationsSetting = false // GIVEN: The pipeline has registered the unseen filter for invalidation val invalidationListener: Pluggable.PluggableListener<NotifFilter> = mock() Loading @@ -267,7 +282,7 @@ class OriginalUnseenKeyguardCoordinatorTest(flags: FlagsParameterization) : Sysu assertThat(unseenFilter.shouldFilterOut(fakeEntry, 0L)).isFalse() // WHEN: The secure setting is changed showOnlyUnseenNotifsOnKeyguardSetting = true kosmos.lockScreenShowOnlyUnseenNotificationsSetting = true // THEN: The pipeline is invalidated verify(invalidationListener).onPluggableInvalidated(same(unseenFilter), any()) Loading Loading @@ -608,35 +623,25 @@ class OriginalUnseenKeyguardCoordinatorTest(flags: FlagsParameterization) : Sysu private fun runKeyguardCoordinatorTest( testBlock: suspend KeyguardCoordinatorTestScope.() -> Unit ) { val testDispatcher = UnconfinedTestDispatcher() val testScope = TestScope(testDispatcher) val fakeSettings = FakeSettings().apply { putInt(Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, 1) } val seenNotificationsInteractor = SeenNotificationsInteractor(ActiveNotificationListRepository()) val keyguardCoordinator = OriginalUnseenKeyguardCoordinator( testDispatcher, mock<DumpManager>(), headsUpManager, keyguardRepository, kosmos.keyguardTransitionInteractor, KeyguardCoordinatorLogger(logcatLogBuffer()), testScope.backgroundScope, fakeSettings, seenNotificationsInteractor, statusBarStateController, dumpManager = kosmos.dumpManager, headsUpManager = kosmos.headsUpManager, keyguardRepository = kosmos.keyguardRepository, keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor, logger = KeyguardCoordinatorLogger(logcatLogBuffer()), scope = kosmos.testScope.backgroundScope, seenNotificationsInteractor = kosmos.seenNotificationsInteractor, statusBarStateController = kosmos.statusBarStateController, sceneInteractor = kosmos.sceneInteractor, ) keyguardCoordinator.attach(notifPipeline) testScope.runTest { kosmos.testScope.runTest { KeyguardCoordinatorTestScope( keyguardCoordinator, testScope, seenNotificationsInteractor, fakeSettings, kosmos.testScope, kosmos.seenNotificationsInteractor, kosmos.fakeSettings, ) .testBlock() } Loading @@ -658,21 +663,8 @@ class OriginalUnseenKeyguardCoordinatorTest(flags: FlagsParameterization) : Sysu argumentCaptor { verify(notifPipeline).addCollectionListener(capture()) }.lastValue val onHeadsUpChangedListener: OnHeadsUpChangedListener get() = argumentCaptor { verify(headsUpManager).addListener(capture()) }.lastValue var showOnlyUnseenNotifsOnKeyguardSetting: Boolean get() = fakeSettings.getIntForUser( Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, UserHandle.USER_CURRENT, ) == 1 set(value) { fakeSettings.putIntForUser( Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, if (value) 1 else 2, UserHandle.USER_CURRENT, ) } argumentCaptor { verify(kosmos.headsUpManager).addListener(capture()) }.lastValue } companion object { Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/SeenNotificationsInteractorTest.kt→packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/domain/interactor/SeenNotificationsInteractorTest.kt +94 −0 Original line number Diff line number Diff line Loading @@ -15,11 +15,14 @@ package com.android.systemui.statusbar.notification.domain.interactor import android.platform.test.annotations.EnableFlags import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder import com.android.systemui.statusbar.notification.shared.NotificationMinimalismPrototype import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest import org.junit.Test Loading @@ -29,8 +32,9 @@ import org.junit.runner.RunWith @SmallTest class SeenNotificationsInteractorTest : SysuiTestCase() { private val repository = ActiveNotificationListRepository() private val underTest = SeenNotificationsInteractor(repository) private val kosmos = testKosmos() private val underTest get() = kosmos.seenNotificationsInteractor @Test fun testNoFilteredOutSeenNotifications() = runTest { Loading @@ -51,4 +55,40 @@ class SeenNotificationsInteractorTest : SysuiTestCase() { assertThat(hasFilteredOutSeenNotifications).isTrue() } @Test @EnableFlags(NotificationMinimalismPrototype.FLAG_NAME) fun topOngoingAndUnseenNotification() = runTest { val entry1 = NotificationEntryBuilder().setTag("entry1").build() val entry2 = NotificationEntryBuilder().setTag("entry2").build() underTest.setTopOngoingNotification(null) underTest.setTopUnseenNotification(null) assertThat(underTest.isTopOngoingNotification(entry1)).isFalse() assertThat(underTest.isTopOngoingNotification(entry2)).isFalse() assertThat(underTest.isTopUnseenNotification(entry1)).isFalse() assertThat(underTest.isTopUnseenNotification(entry2)).isFalse() underTest.setTopOngoingNotification(entry1) underTest.setTopUnseenNotification(entry2) assertThat(underTest.isTopOngoingNotification(entry1)).isTrue() assertThat(underTest.isTopOngoingNotification(entry2)).isFalse() assertThat(underTest.isTopUnseenNotification(entry1)).isFalse() assertThat(underTest.isTopUnseenNotification(entry2)).isTrue() } fun testShowOnlyUnseenNotifsOnKeyguardSetting() = runTest { val settingEnabled by collectLastValue(underTest.isLockScreenShowOnlyUnseenNotificationsEnabled()) kosmos.lockScreenShowOnlyUnseenNotificationsSetting = false testScheduler.runCurrent() assertThat(settingEnabled).isFalse() kosmos.lockScreenShowOnlyUnseenNotificationsSetting = true testScheduler.runCurrent() assertThat(settingEnabled).isTrue() } }
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/LockScreenMinimalismCoordinator.kt +6 −38 Original line number Diff line number Diff line Loading @@ -18,12 +18,9 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.annotation.SuppressLint import android.app.NotificationManager import android.os.UserHandle import android.provider.Settings import androidx.annotation.VisibleForTesting import com.android.systemui.Dumpable import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.shade.domain.interactor.ShadeInteractor Loading @@ -43,23 +40,16 @@ import com.android.systemui.statusbar.notification.stack.BUCKET_TOP_ONGOING import com.android.systemui.statusbar.notification.stack.BUCKET_TOP_UNSEEN import com.android.systemui.util.asIndenting import com.android.systemui.util.printCollection import com.android.systemui.util.settings.SecureSettings import com.android.systemui.util.settings.SettingsProxyExt.observerFlow import java.io.PrintWriter import javax.inject.Inject import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.launch /** Loading @@ -73,12 +63,10 @@ import kotlinx.coroutines.launch class LockScreenMinimalismCoordinator @Inject constructor( @Background private val bgDispatcher: CoroutineDispatcher, private val dumpManager: DumpManager, private val headsUpInteractor: HeadsUpNotificationInteractor, private val logger: LockScreenMinimalismCoordinatorLogger, @Application private val scope: CoroutineScope, private val secureSettings: SecureSettings, private val seenNotificationsInteractor: SeenNotificationsInteractor, private val statusBarStateController: StatusBarStateController, private val shadeInteractor: ShadeInteractor, Loading Loading @@ -147,29 +135,7 @@ constructor( if (NotificationMinimalismPrototype.isEnabled) { return flowOf(true) } return secureSettings // emit whenever the setting has changed .observerFlow( UserHandle.USER_ALL, Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, ) // perform a query immediately .onStart { emit(Unit) } // for each change, lookup the new value .map { secureSettings.getIntForUser( name = Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, def = 0, userHandle = UserHandle.USER_CURRENT, ) == 1 } // don't emit anything if nothing has changed .distinctUntilChanged() // perform lookups on the bg thread pool .flowOn(bgDispatcher) // only track the most recent emission, if events are happening faster than they can be // consumed .conflate() return seenNotificationsInteractor.isLockScreenShowOnlyUnseenNotificationsEnabled() } private suspend fun trackUnseenFilterSettingChanges() { Loading @@ -177,6 +143,7 @@ constructor( // update local field and invalidate if necessary if (isSettingEnabled != unseenFilterEnabled) { unseenFilterEnabled = isSettingEnabled unseenNotifications.clear() unseenNotifPromoter.invalidateList("unseen setting changed") } // if the setting is enabled, then start tracking and filtering unseen notifications Loading @@ -190,21 +157,21 @@ constructor( private val collectionListener = object : NotifCollectionListener { override fun onEntryAdded(entry: NotificationEntry) { if (!isShadeVisible) { if (unseenFilterEnabled && !isShadeVisible) { logger.logUnseenAdded(entry.key) unseenNotifications.add(entry) } } override fun onEntryUpdated(entry: NotificationEntry) { if (!isShadeVisible) { if (unseenFilterEnabled && !isShadeVisible) { logger.logUnseenUpdated(entry.key) unseenNotifications.add(entry) } } override fun onEntryRemoved(entry: NotificationEntry, reason: Int) { if (unseenNotifications.remove(entry)) { if (unseenFilterEnabled && unseenNotifications.remove(entry)) { logger.logUnseenRemoved(entry.key) } } Loading @@ -212,6 +179,7 @@ constructor( private fun pickOutTopUnseenNotifs(list: List<ListEntry>) { if (NotificationMinimalismPrototype.isUnexpectedlyInLegacyMode()) return if (!unseenFilterEnabled) return // Only ever elevate a top unseen notification on keyguard, not even locked shade if (statusBarStateController.state != StatusBarState.KEYGUARD) { seenNotificationsInteractor.setTopOngoingNotification(null) Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/OriginalUnseenKeyguardCoordinator.kt +1 −34 Original line number Diff line number Diff line Loading @@ -17,12 +17,9 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.annotation.SuppressLint import android.os.UserHandle import android.provider.Settings import androidx.annotation.VisibleForTesting import com.android.systemui.Dumpable import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dump.DumpManager import com.android.systemui.keyguard.data.repository.KeyguardRepository import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor Loading @@ -43,12 +40,9 @@ import com.android.systemui.statusbar.policy.HeadsUpManager import com.android.systemui.statusbar.policy.headsUpEvents import com.android.systemui.util.asIndenting import com.android.systemui.util.indentIfPossible import com.android.systemui.util.settings.SecureSettings import com.android.systemui.util.settings.SettingsProxyExt.observerFlow import java.io.PrintWriter import javax.inject.Inject import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.coroutineScope Loading @@ -56,13 +50,10 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.launch import kotlinx.coroutines.yield Loading @@ -79,14 +70,12 @@ import kotlinx.coroutines.yield class OriginalUnseenKeyguardCoordinator @Inject constructor( @Background private val bgDispatcher: CoroutineDispatcher, private val dumpManager: DumpManager, private val headsUpManager: HeadsUpManager, private val keyguardRepository: KeyguardRepository, private val keyguardTransitionInteractor: KeyguardTransitionInteractor, private val logger: KeyguardCoordinatorLogger, @Application private val scope: CoroutineScope, private val secureSettings: SecureSettings, private val seenNotificationsInteractor: SeenNotificationsInteractor, private val statusBarStateController: StatusBarStateController, private val sceneInteractor: SceneInteractor, Loading Loading @@ -268,29 +257,7 @@ constructor( // TODO(b/330387368): should this really just be turned off? If so, hide the setting. return flowOf(false) } return secureSettings // emit whenever the setting has changed .observerFlow( UserHandle.USER_ALL, Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, ) // perform a query immediately .onStart { emit(Unit) } // for each change, lookup the new value .map { secureSettings.getIntForUser( name = Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS, def = 0, userHandle = UserHandle.USER_CURRENT, ) == 1 } // don't emit anything if nothing has changed .distinctUntilChanged() // perform lookups on the bg thread pool .flowOn(bgDispatcher) // only track the most recent emission, if events are happening faster than they can be // consumed .conflate() return seenNotificationsInteractor.isLockScreenShowOnlyUnseenNotificationsEnabled() } private suspend fun trackUnseenFilterSettingChanges() { Loading