Merge "Base "seen" logic on shade expansion and heads up" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
156fdcab1b
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.statusbar
|
||||||
|
|
||||||
|
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
||||||
|
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
||||||
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
/** Returns a [Flow] that emits whenever [StatusBarStateController.isExpanded] changes value. */
|
||||||
|
val StatusBarStateController.expansionChanges: Flow<Boolean>
|
||||||
|
get() = conflatedCallbackFlow {
|
||||||
|
val listener =
|
||||||
|
object : StatusBarStateController.StateListener {
|
||||||
|
override fun onExpandedChanged(isExpanded: Boolean) {
|
||||||
|
trySend(isExpanded)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trySend(isExpanded)
|
||||||
|
addCallback(listener)
|
||||||
|
awaitClose { removeCallback(listener) }
|
||||||
|
}
|
||||||
@@ -16,16 +16,15 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.notification.collection.coordinator
|
package com.android.systemui.statusbar.notification.collection.coordinator
|
||||||
|
|
||||||
import android.database.ContentObserver
|
|
||||||
import android.os.UserHandle
|
import android.os.UserHandle
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
|
||||||
import com.android.systemui.dagger.qualifiers.Application
|
import com.android.systemui.dagger.qualifiers.Application
|
||||||
import com.android.systemui.dagger.qualifiers.Background
|
import com.android.systemui.dagger.qualifiers.Background
|
||||||
import com.android.systemui.keyguard.data.repository.KeyguardRepository
|
import com.android.systemui.keyguard.data.repository.KeyguardRepository
|
||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
||||||
import com.android.systemui.statusbar.StatusBarState
|
import com.android.systemui.statusbar.StatusBarState
|
||||||
|
import com.android.systemui.statusbar.expansionChanges
|
||||||
import com.android.systemui.statusbar.notification.NotifPipelineFlags
|
import com.android.systemui.statusbar.notification.NotifPipelineFlags
|
||||||
import com.android.systemui.statusbar.notification.collection.NotifPipeline
|
import com.android.systemui.statusbar.notification.collection.NotifPipeline
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
||||||
@@ -35,15 +34,14 @@ import com.android.systemui.statusbar.notification.collection.notifcollection.No
|
|||||||
import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider
|
import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider
|
||||||
import com.android.systemui.statusbar.notification.collection.provider.SeenNotificationsProviderImpl
|
import com.android.systemui.statusbar.notification.collection.provider.SeenNotificationsProviderImpl
|
||||||
import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider
|
import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider
|
||||||
|
import com.android.systemui.statusbar.policy.HeadsUpManager
|
||||||
|
import com.android.systemui.statusbar.policy.headsUpEvents
|
||||||
import com.android.systemui.util.settings.SecureSettings
|
import com.android.systemui.util.settings.SecureSettings
|
||||||
import com.android.systemui.util.settings.SettingsProxy
|
import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.time.Duration.Companion.seconds
|
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.channels.awaitClose
|
import kotlinx.coroutines.coroutineScope
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.flow.conflate
|
import kotlinx.coroutines.flow.conflate
|
||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
@@ -60,6 +58,7 @@ class KeyguardCoordinator
|
|||||||
@Inject
|
@Inject
|
||||||
constructor(
|
constructor(
|
||||||
@Background private val bgDispatcher: CoroutineDispatcher,
|
@Background private val bgDispatcher: CoroutineDispatcher,
|
||||||
|
private val headsUpManager: HeadsUpManager,
|
||||||
private val keyguardNotificationVisibilityProvider: KeyguardNotificationVisibilityProvider,
|
private val keyguardNotificationVisibilityProvider: KeyguardNotificationVisibilityProvider,
|
||||||
private val keyguardRepository: KeyguardRepository,
|
private val keyguardRepository: KeyguardRepository,
|
||||||
private val notifPipelineFlags: NotifPipelineFlags,
|
private val notifPipelineFlags: NotifPipelineFlags,
|
||||||
@@ -87,28 +86,53 @@ constructor(
|
|||||||
private fun attachUnseenFilter(pipeline: NotifPipeline) {
|
private fun attachUnseenFilter(pipeline: NotifPipeline) {
|
||||||
pipeline.addFinalizeFilter(unseenNotifFilter)
|
pipeline.addFinalizeFilter(unseenNotifFilter)
|
||||||
pipeline.addCollectionListener(collectionListener)
|
pipeline.addCollectionListener(collectionListener)
|
||||||
scope.launch { clearUnseenWhenKeyguardIsDismissed() }
|
scope.launch { trackUnseenNotificationsWhileUnlocked() }
|
||||||
scope.launch { invalidateWhenUnseenSettingChanges() }
|
scope.launch { invalidateWhenUnseenSettingChanges() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun clearUnseenWhenKeyguardIsDismissed() {
|
private suspend fun trackUnseenNotificationsWhileUnlocked() {
|
||||||
// Use collectLatest so that the suspending block is cancelled if isKeyguardShowing changes
|
// Use collectLatest so that trackUnseenNotifications() is cancelled when the keyguard is
|
||||||
// during the timeout period
|
// showing again
|
||||||
keyguardRepository.isKeyguardShowing.collectLatest { isKeyguardShowing ->
|
keyguardRepository.isKeyguardShowing.collectLatest { isKeyguardShowing ->
|
||||||
if (!isKeyguardShowing) {
|
if (!isKeyguardShowing) {
|
||||||
unseenNotifFilter.invalidateList("keyguard no longer showing")
|
unseenNotifFilter.invalidateList("keyguard no longer showing")
|
||||||
delay(SEEN_TIMEOUT)
|
trackUnseenNotifications()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun trackUnseenNotifications() {
|
||||||
|
coroutineScope {
|
||||||
|
launch { clearUnseenNotificationsWhenShadeIsExpanded() }
|
||||||
|
launch { markHeadsUpNotificationsAsSeen() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun clearUnseenNotificationsWhenShadeIsExpanded() {
|
||||||
|
statusBarStateController.expansionChanges.collect { isExpanded ->
|
||||||
|
if (isExpanded) {
|
||||||
unseenNotifications.clear()
|
unseenNotifications.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun markHeadsUpNotificationsAsSeen() {
|
||||||
|
headsUpManager.allEntries
|
||||||
|
.filter { it.isRowPinned }
|
||||||
|
.forEach { unseenNotifications.remove(it) }
|
||||||
|
headsUpManager.headsUpEvents.collect { (entry, isHun) ->
|
||||||
|
if (isHun) {
|
||||||
|
unseenNotifications.remove(entry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun invalidateWhenUnseenSettingChanges() {
|
private suspend fun invalidateWhenUnseenSettingChanges() {
|
||||||
secureSettings
|
secureSettings
|
||||||
// emit whenever the setting has changed
|
// emit whenever the setting has changed
|
||||||
.settingChangesForUser(
|
.observerFlow(
|
||||||
Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS,
|
|
||||||
UserHandle.USER_ALL,
|
UserHandle.USER_ALL,
|
||||||
|
Settings.Secure.LOCK_SCREEN_SHOW_ONLY_UNSEEN_NOTIFICATIONS,
|
||||||
)
|
)
|
||||||
// perform a query immediately
|
// perform a query immediately
|
||||||
.onStart { emit(Unit) }
|
.onStart { emit(Unit) }
|
||||||
@@ -136,13 +160,17 @@ constructor(
|
|||||||
private val collectionListener =
|
private val collectionListener =
|
||||||
object : NotifCollectionListener {
|
object : NotifCollectionListener {
|
||||||
override fun onEntryAdded(entry: NotificationEntry) {
|
override fun onEntryAdded(entry: NotificationEntry) {
|
||||||
if (keyguardRepository.isKeyguardShowing()) {
|
if (
|
||||||
|
keyguardRepository.isKeyguardShowing() || !statusBarStateController.isExpanded
|
||||||
|
) {
|
||||||
unseenNotifications.add(entry)
|
unseenNotifications.add(entry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onEntryUpdated(entry: NotificationEntry) {
|
override fun onEntryUpdated(entry: NotificationEntry) {
|
||||||
if (keyguardRepository.isKeyguardShowing()) {
|
if (
|
||||||
|
keyguardRepository.isKeyguardShowing() || !statusBarStateController.isExpanded
|
||||||
|
) {
|
||||||
unseenNotifications.add(entry)
|
unseenNotifications.add(entry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,18 +240,5 @@ constructor(
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "KeyguardCoordinator"
|
private const val TAG = "KeyguardCoordinator"
|
||||||
private val SEEN_TIMEOUT = 5.seconds
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun SettingsProxy.settingChangesForUser(name: String, userHandle: Int): Flow<Unit> =
|
|
||||||
conflatedCallbackFlow {
|
|
||||||
val observer =
|
|
||||||
object : ContentObserver(null) {
|
|
||||||
override fun onChange(selfChange: Boolean) {
|
|
||||||
trySend(Unit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
registerContentObserverForUser(name, observer, userHandle)
|
|
||||||
awaitClose { unregisterContentObserver(observer) }
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.statusbar.policy
|
||||||
|
|
||||||
|
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
||||||
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
||||||
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a [Flow] that emits events whenever a [NotificationEntry] enters or exists the "heads up"
|
||||||
|
* state.
|
||||||
|
*/
|
||||||
|
val HeadsUpManager.headsUpEvents: Flow<Pair<NotificationEntry, Boolean>>
|
||||||
|
get() = conflatedCallbackFlow {
|
||||||
|
val listener =
|
||||||
|
object : OnHeadsUpChangedListener {
|
||||||
|
override fun onHeadsUpStateChanged(entry: NotificationEntry, isHeadsUp: Boolean) {
|
||||||
|
trySend(entry to isHeadsUp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addListener(listener)
|
||||||
|
awaitClose { removeListener(listener) }
|
||||||
|
}
|
||||||
@@ -38,6 +38,8 @@ import com.android.systemui.statusbar.notification.collection.provider.SeenNotif
|
|||||||
import com.android.systemui.statusbar.notification.collection.provider.SeenNotificationsProviderImpl
|
import com.android.systemui.statusbar.notification.collection.provider.SeenNotificationsProviderImpl
|
||||||
import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider
|
import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider
|
||||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
|
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.util.mockito.eq
|
import com.android.systemui.util.mockito.eq
|
||||||
import com.android.systemui.util.mockito.mock
|
import com.android.systemui.util.mockito.mock
|
||||||
import com.android.systemui.util.mockito.withArgCaptor
|
import com.android.systemui.util.mockito.withArgCaptor
|
||||||
@@ -63,6 +65,7 @@ import org.mockito.Mockito.`when` as whenever
|
|||||||
@RunWith(AndroidTestingRunner::class)
|
@RunWith(AndroidTestingRunner::class)
|
||||||
class KeyguardCoordinatorTest : SysuiTestCase() {
|
class KeyguardCoordinatorTest : SysuiTestCase() {
|
||||||
|
|
||||||
|
private val headsUpManager: HeadsUpManager = mock()
|
||||||
private val keyguardNotifVisibilityProvider: KeyguardNotificationVisibilityProvider = mock()
|
private val keyguardNotifVisibilityProvider: KeyguardNotificationVisibilityProvider = mock()
|
||||||
private val keyguardRepository = FakeKeyguardRepository()
|
private val keyguardRepository = FakeKeyguardRepository()
|
||||||
private val notifPipelineFlags: NotifPipelineFlags = mock()
|
private val notifPipelineFlags: NotifPipelineFlags = mock()
|
||||||
@@ -90,8 +93,9 @@ class KeyguardCoordinatorTest : SysuiTestCase() {
|
|||||||
fun unseenFilterSuppressesSeenNotifWhileKeyguardShowing() {
|
fun unseenFilterSuppressesSeenNotifWhileKeyguardShowing() {
|
||||||
whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
|
whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
|
||||||
|
|
||||||
// GIVEN: Keyguard is not showing, and a notification is present
|
// GIVEN: Keyguard is not showing, shade is expanded, and a notification is present
|
||||||
keyguardRepository.setKeyguardShowing(false)
|
keyguardRepository.setKeyguardShowing(false)
|
||||||
|
whenever(statusBarStateController.isExpanded).thenReturn(true)
|
||||||
runKeyguardCoordinatorTest {
|
runKeyguardCoordinatorTest {
|
||||||
val fakeEntry = NotificationEntryBuilder().build()
|
val fakeEntry = NotificationEntryBuilder().build()
|
||||||
collectionListener.onEntryAdded(fakeEntry)
|
collectionListener.onEntryAdded(fakeEntry)
|
||||||
@@ -112,12 +116,45 @@ class KeyguardCoordinatorTest : SysuiTestCase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun unseenFilter_headsUpMarkedAsSeen() {
|
||||||
|
whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
|
||||||
|
|
||||||
|
// GIVEN: Keyguard is not showing, shade is not expanded
|
||||||
|
keyguardRepository.setKeyguardShowing(false)
|
||||||
|
whenever(statusBarStateController.isExpanded).thenReturn(false)
|
||||||
|
runKeyguardCoordinatorTest {
|
||||||
|
// WHEN: A notification is posted
|
||||||
|
val fakeEntry = NotificationEntryBuilder().build()
|
||||||
|
collectionListener.onEntryAdded(fakeEntry)
|
||||||
|
|
||||||
|
// WHEN: That notification is heads up
|
||||||
|
onHeadsUpChangedListener.onHeadsUpStateChanged(fakeEntry, /* isHeadsUp= */ true)
|
||||||
|
testScheduler.runCurrent()
|
||||||
|
|
||||||
|
// WHEN: The keyguard is now showing
|
||||||
|
keyguardRepository.setKeyguardShowing(true)
|
||||||
|
testScheduler.runCurrent()
|
||||||
|
|
||||||
|
// THEN: The notification is recognized as "seen" and is filtered out.
|
||||||
|
assertThat(unseenFilter.shouldFilterOut(fakeEntry, 0L)).isTrue()
|
||||||
|
|
||||||
|
// WHEN: The keyguard goes away
|
||||||
|
keyguardRepository.setKeyguardShowing(false)
|
||||||
|
testScheduler.runCurrent()
|
||||||
|
|
||||||
|
// THEN: The notification is shown regardless
|
||||||
|
assertThat(unseenFilter.shouldFilterOut(fakeEntry, 0L)).isFalse()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun unseenFilterDoesNotSuppressSeenOngoingNotifWhileKeyguardShowing() {
|
fun unseenFilterDoesNotSuppressSeenOngoingNotifWhileKeyguardShowing() {
|
||||||
whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
|
whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
|
||||||
|
|
||||||
// GIVEN: Keyguard is not showing, and an ongoing notification is present
|
// GIVEN: Keyguard is not showing, shade is expanded, and an ongoing notification is present
|
||||||
keyguardRepository.setKeyguardShowing(false)
|
keyguardRepository.setKeyguardShowing(false)
|
||||||
|
whenever(statusBarStateController.isExpanded).thenReturn(true)
|
||||||
runKeyguardCoordinatorTest {
|
runKeyguardCoordinatorTest {
|
||||||
val fakeEntry = NotificationEntryBuilder()
|
val fakeEntry = NotificationEntryBuilder()
|
||||||
.setNotification(Notification.Builder(mContext).setOngoing(true).build())
|
.setNotification(Notification.Builder(mContext).setOngoing(true).build())
|
||||||
@@ -137,8 +174,9 @@ class KeyguardCoordinatorTest : SysuiTestCase() {
|
|||||||
fun unseenFilterDoesNotSuppressSeenMediaNotifWhileKeyguardShowing() {
|
fun unseenFilterDoesNotSuppressSeenMediaNotifWhileKeyguardShowing() {
|
||||||
whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
|
whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
|
||||||
|
|
||||||
// GIVEN: Keyguard is not showing, and a media notification is present
|
// GIVEN: Keyguard is not showing, shade is expanded, and a media notification is present
|
||||||
keyguardRepository.setKeyguardShowing(false)
|
keyguardRepository.setKeyguardShowing(false)
|
||||||
|
whenever(statusBarStateController.isExpanded).thenReturn(true)
|
||||||
runKeyguardCoordinatorTest {
|
runKeyguardCoordinatorTest {
|
||||||
val fakeEntry = NotificationEntryBuilder().build().apply {
|
val fakeEntry = NotificationEntryBuilder().build().apply {
|
||||||
row = mock<ExpandableNotificationRow>().apply {
|
row = mock<ExpandableNotificationRow>().apply {
|
||||||
@@ -160,8 +198,9 @@ class KeyguardCoordinatorTest : SysuiTestCase() {
|
|||||||
fun unseenFilterUpdatesSeenProviderWhenSuppressing() {
|
fun unseenFilterUpdatesSeenProviderWhenSuppressing() {
|
||||||
whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
|
whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
|
||||||
|
|
||||||
// GIVEN: Keyguard is not showing, and a notification is present
|
// GIVEN: Keyguard is not showing, shade is expanded, and a notification is present
|
||||||
keyguardRepository.setKeyguardShowing(false)
|
keyguardRepository.setKeyguardShowing(false)
|
||||||
|
whenever(statusBarStateController.isExpanded).thenReturn(true)
|
||||||
runKeyguardCoordinatorTest {
|
runKeyguardCoordinatorTest {
|
||||||
val fakeEntry = NotificationEntryBuilder().build()
|
val fakeEntry = NotificationEntryBuilder().build()
|
||||||
collectionListener.onEntryAdded(fakeEntry)
|
collectionListener.onEntryAdded(fakeEntry)
|
||||||
@@ -185,8 +224,9 @@ class KeyguardCoordinatorTest : SysuiTestCase() {
|
|||||||
fun unseenFilterInvalidatesWhenSettingChanges() {
|
fun unseenFilterInvalidatesWhenSettingChanges() {
|
||||||
whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
|
whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
|
||||||
|
|
||||||
// GIVEN: Keyguard is not showing
|
// GIVEN: Keyguard is not showing, and shade is expanded
|
||||||
keyguardRepository.setKeyguardShowing(false)
|
keyguardRepository.setKeyguardShowing(false)
|
||||||
|
whenever(statusBarStateController.isExpanded).thenReturn(true)
|
||||||
runKeyguardCoordinatorTest {
|
runKeyguardCoordinatorTest {
|
||||||
// GIVEN: A notification is present
|
// GIVEN: A notification is present
|
||||||
val fakeEntry = NotificationEntryBuilder().build()
|
val fakeEntry = NotificationEntryBuilder().build()
|
||||||
@@ -237,8 +277,9 @@ class KeyguardCoordinatorTest : SysuiTestCase() {
|
|||||||
fun unseenFilterSeenGroupSummaryWithUnseenChild() {
|
fun unseenFilterSeenGroupSummaryWithUnseenChild() {
|
||||||
whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
|
whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
|
||||||
|
|
||||||
// GIVEN: Keyguard is not showing, and a notification is present
|
// GIVEN: Keyguard is not showing, shade is expanded, and a notification is present
|
||||||
keyguardRepository.setKeyguardShowing(false)
|
keyguardRepository.setKeyguardShowing(false)
|
||||||
|
whenever(statusBarStateController.isExpanded).thenReturn(true)
|
||||||
runKeyguardCoordinatorTest {
|
runKeyguardCoordinatorTest {
|
||||||
// WHEN: A new notification is posted
|
// WHEN: A new notification is posted
|
||||||
val fakeSummary = NotificationEntryBuilder().build()
|
val fakeSummary = NotificationEntryBuilder().build()
|
||||||
@@ -276,11 +317,11 @@ class KeyguardCoordinatorTest : SysuiTestCase() {
|
|||||||
val fakeEntry = NotificationEntryBuilder().build()
|
val fakeEntry = NotificationEntryBuilder().build()
|
||||||
collectionListener.onEntryAdded(fakeEntry)
|
collectionListener.onEntryAdded(fakeEntry)
|
||||||
|
|
||||||
// WHEN: Keyguard is no longer showing for 5 seconds
|
// WHEN: Keyguard is no longer showing
|
||||||
keyguardRepository.setKeyguardShowing(false)
|
keyguardRepository.setKeyguardShowing(false)
|
||||||
testScheduler.runCurrent()
|
|
||||||
testScheduler.advanceTimeBy(5.seconds.inWholeMilliseconds)
|
// When: Shade is expanded
|
||||||
testScheduler.runCurrent()
|
statusBarStateListener.onExpandedChanged(true)
|
||||||
|
|
||||||
// WHEN: Keyguard is shown again
|
// WHEN: Keyguard is shown again
|
||||||
keyguardRepository.setKeyguardShowing(true)
|
keyguardRepository.setKeyguardShowing(true)
|
||||||
@@ -292,7 +333,7 @@ class KeyguardCoordinatorTest : SysuiTestCase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun unseenNotificationIsNotMarkedAsSeenIfTimeThresholdNotMet() {
|
fun unseenNotificationIsNotMarkedAsSeenIfShadeNotExpanded() {
|
||||||
whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
|
whenever(notifPipelineFlags.shouldFilterUnseenNotifsOnKeyguard).thenReturn(true)
|
||||||
|
|
||||||
// GIVEN: Keyguard is showing, unseen notification is present
|
// GIVEN: Keyguard is showing, unseen notification is present
|
||||||
@@ -301,10 +342,8 @@ class KeyguardCoordinatorTest : SysuiTestCase() {
|
|||||||
val fakeEntry = NotificationEntryBuilder().build()
|
val fakeEntry = NotificationEntryBuilder().build()
|
||||||
collectionListener.onEntryAdded(fakeEntry)
|
collectionListener.onEntryAdded(fakeEntry)
|
||||||
|
|
||||||
// WHEN: Keyguard is no longer showing for <5 seconds
|
// WHEN: Keyguard is no longer showing
|
||||||
keyguardRepository.setKeyguardShowing(false)
|
keyguardRepository.setKeyguardShowing(false)
|
||||||
testScheduler.runCurrent()
|
|
||||||
testScheduler.advanceTimeBy(1.seconds.inWholeMilliseconds)
|
|
||||||
|
|
||||||
// WHEN: Keyguard is shown again
|
// WHEN: Keyguard is shown again
|
||||||
keyguardRepository.setKeyguardShowing(true)
|
keyguardRepository.setKeyguardShowing(true)
|
||||||
@@ -327,6 +366,7 @@ class KeyguardCoordinatorTest : SysuiTestCase() {
|
|||||||
val keyguardCoordinator =
|
val keyguardCoordinator =
|
||||||
KeyguardCoordinator(
|
KeyguardCoordinator(
|
||||||
testDispatcher,
|
testDispatcher,
|
||||||
|
headsUpManager,
|
||||||
keyguardNotifVisibilityProvider,
|
keyguardNotifVisibilityProvider,
|
||||||
keyguardRepository,
|
keyguardRepository,
|
||||||
notifPipelineFlags,
|
notifPipelineFlags,
|
||||||
@@ -364,12 +404,21 @@ class KeyguardCoordinatorTest : SysuiTestCase() {
|
|||||||
val unseenFilter: NotifFilter
|
val unseenFilter: NotifFilter
|
||||||
get() = keyguardCoordinator.unseenNotifFilter
|
get() = keyguardCoordinator.unseenNotifFilter
|
||||||
|
|
||||||
// TODO(254647461): Remove lazy once Flags.FILTER_UNSEEN_NOTIFS_ON_KEYGUARD is enabled and
|
// TODO(254647461): Remove lazy from these properties once
|
||||||
// removed
|
// Flags.FILTER_UNSEEN_NOTIFS_ON_KEYGUARD is enabled and removed
|
||||||
|
|
||||||
val collectionListener: NotifCollectionListener by lazy {
|
val collectionListener: NotifCollectionListener by lazy {
|
||||||
withArgCaptor { verify(notifPipeline).addCollectionListener(capture()) }
|
withArgCaptor { verify(notifPipeline).addCollectionListener(capture()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val onHeadsUpChangedListener: OnHeadsUpChangedListener by lazy {
|
||||||
|
withArgCaptor { verify(headsUpManager).addListener(capture()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val statusBarStateListener: StatusBarStateController.StateListener by lazy {
|
||||||
|
withArgCaptor { verify(statusBarStateController).addCallback(capture()) }
|
||||||
|
}
|
||||||
|
|
||||||
var showOnlyUnseenNotifsOnKeyguardSetting: Boolean
|
var showOnlyUnseenNotifsOnKeyguardSetting: Boolean
|
||||||
get() =
|
get() =
|
||||||
fakeSettings.getIntForUser(
|
fakeSettings.getIntForUser(
|
||||||
|
|||||||
Reference in New Issue
Block a user