Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22bba40d authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Move duplicated code to SeenNotificationsInteractor" into main

parents 1ec9bcc4 e7031ec1
Loading
Loading
Loading
Loading
+0 −15
Original line number Diff line number Diff line
@@ -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
@@ -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 {
+42 −50
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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)
@@ -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()
@@ -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())
@@ -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()
        }
@@ -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 {
+94 −0
Original line number Diff line number Diff line
@@ -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
@@ -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 {
@@ -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()
    }
}
+6 −38
Original line number Diff line number Diff line
@@ -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
@@ -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

/**
@@ -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,
@@ -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() {
@@ -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
@@ -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)
                }
            }
@@ -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)
+1 −34
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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

@@ -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,
@@ -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