diff options
author | 2025-02-19 14:45:32 -0500 | |
---|---|---|
committer | 2025-02-20 08:27:46 -0500 | |
commit | fecfb9756dcebd824e74637a75bb623cc30846cc (patch) | |
tree | 7f72a49a06c79601a1e3fed1741cfea80f50a508 | |
parent | 1be4df1376b354024cb723de8b6bc9cb26568293 (diff) |
Fix swipe-to-bouncer on GH with face auth
When swiping up the bouncer on glanceable hub, if the user has a large
number of notifications, the notification limit is taking effect
mid-swipe and causing the bouncer to hide itself. This is because the
bouncer/alternate bouncer states are considered "lockscreen" states,
even if the bouncer is shown over the glanceable hub instead of over the
lockscreen.
This change does not consider the bouncer states as "lockscreen" if they
are being shown over the glanceable hub.
Fixes: 396689194
Test: atest SharedNotificationContainerViewModelTest
Flag: com.android.systemui.glanceable_hub_v2
Change-Id: I8cfa5ff3074d7d34f06b7db5a1051e367e290889
2 files changed, 74 insertions, 25 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt index 21297e3e64b7..c630a1c1e006 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt @@ -17,14 +17,15 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel +import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.FlagsParameterization import androidx.test.filters.SmallTest -import com.android.compose.animation.scene.ObservableTransitionState +import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2 import com.android.systemui.SysuiTestCase import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository import com.android.systemui.common.shared.model.NotificationContainerBounds import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository -import com.android.systemui.communal.data.repository.communalSceneRepository +import com.android.systemui.communal.domain.interactor.communalSceneInteractor import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectValues @@ -54,11 +55,14 @@ import com.android.systemui.keyguard.ui.viewmodel.AodBurnInViewModel import com.android.systemui.keyguard.ui.viewmodel.ViewStateAccessor import com.android.systemui.keyguard.ui.viewmodel.aodBurnInViewModel import com.android.systemui.keyguard.ui.viewmodel.keyguardRootViewModel +import com.android.systemui.kosmos.collectLastValue +import com.android.systemui.kosmos.runTest import com.android.systemui.kosmos.testScope import com.android.systemui.res.R import com.android.systemui.scene.data.repository.Idle import com.android.systemui.scene.data.repository.Transition import com.android.systemui.scene.data.repository.setTransition +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.domain.interactor.enableDualShade import com.android.systemui.shade.domain.interactor.enableSingleShade @@ -125,7 +129,6 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S kosmos.sharedNotificationContainerInteractor } private val largeScreenHeaderHelper by lazy { kosmos.mockLargeScreenHeaderHelper } - private val communalSceneRepository by lazy { kosmos.communalSceneRepository } lateinit var underTest: SharedNotificationContainerViewModel @@ -591,6 +594,25 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S } @Test + @DisableSceneContainer + @EnableFlags(FLAG_GLANCEABLE_HUB_V2) + fun isOnLockscreenFalseWhenCommunalShowing() = + kosmos.runTest { + val isOnLockscreen by collectLastValue(underTest.isOnLockscreen) + + setTransition( + sceneTransition = Idle(Scenes.Bouncer), + stateTransition = TransitionStep(from = LOCKSCREEN, to = PRIMARY_BOUNCER), + ) + assertThat(isOnLockscreen).isTrue() + + testScope.showCommunalScene() + + // If bouncer is showing over the hub, it should not be considered on lockscreen + assertThat(isOnLockscreen).isFalse() + } + + @Test fun isOnLockscreenWithoutShade() = testScope.runTest { val isOnLockscreenWithoutShade by collectLastValue(underTest.isOnLockscreenWithoutShade) @@ -1472,20 +1494,24 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S } private fun TestScope.showCommunalScene() { - val transitionState = - MutableStateFlow<ObservableTransitionState>( - ObservableTransitionState.Idle(CommunalScenes.Communal) - ) - communalSceneRepository.setTransitionState(transitionState) + val targetScene = + if (SceneContainerFlag.isEnabled) { + Scenes.Communal + } else { + CommunalScenes.Communal + } + kosmos.communalSceneInteractor.changeScene(targetScene, "test") runCurrent() } private fun TestScope.hideCommunalScene() { - val transitionState = - MutableStateFlow<ObservableTransitionState>( - ObservableTransitionState.Idle(CommunalScenes.Blank) - ) - communalSceneRepository.setTransitionState(transitionState) + val targetScene = + if (SceneContainerFlag.isEnabled) { + Scenes.Lockscreen + } else { + CommunalScenes.Blank + } + kosmos.communalSceneInteractor.changeScene(targetScene, "test") runCurrent() } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt index 5c81c8e22bfc..34b65603542c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt @@ -20,6 +20,7 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel import android.content.Context import androidx.annotation.VisibleForTesting import com.android.app.tracing.coroutines.flow.flowName +import com.android.systemui.Flags.glanceableHubV2 import com.android.systemui.common.shared.model.NotificationContainerBounds import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor @@ -87,7 +88,9 @@ import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNoti import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor +import com.android.systemui.util.kotlin.BooleanFlowOperators.allOf import com.android.systemui.util.kotlin.BooleanFlowOperators.anyOf +import com.android.systemui.util.kotlin.BooleanFlowOperators.not import com.android.systemui.util.kotlin.FlowDumperImpl import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleCombine import com.android.systemui.util.kotlin.sample @@ -299,20 +302,40 @@ constructor( .distinctUntilChanged() .dumpWhileCollecting("configurationBasedDimensions") + private val isOnAnyBouncer: Flow<Boolean> = + anyOf( + keyguardTransitionInteractor.transitionValue(ALTERNATE_BOUNCER).map { it > 0f }, + keyguardTransitionInteractor + .transitionValue( + scene = Scenes.Bouncer, + stateWithoutSceneContainer = PRIMARY_BOUNCER, + ) + .map { it > 0f }, + ) + /** If the user is visually on one of the unoccluded lockscreen states. */ val isOnLockscreen: Flow<Boolean> = - anyOf( - keyguardTransitionInteractor.transitionValue(AOD).map { it > 0f }, - keyguardTransitionInteractor.transitionValue(DOZING).map { it > 0f }, - keyguardTransitionInteractor.transitionValue(ALTERNATE_BOUNCER).map { it > 0f }, - keyguardTransitionInteractor - .transitionValue( - scene = Scenes.Bouncer, - stateWithoutSceneContainer = PRIMARY_BOUNCER, - ) - .map { it > 0f }, - keyguardTransitionInteractor.transitionValue(LOCKSCREEN).map { it > 0f }, - ) + if (glanceableHubV2()) { + anyOf( + keyguardTransitionInteractor.transitionValue(AOD).map { it > 0f }, + keyguardTransitionInteractor.transitionValue(DOZING).map { it > 0f }, + keyguardTransitionInteractor.transitionValue(LOCKSCREEN).map { it > 0f }, + allOf( + // Exclude bouncer showing over communal hub, as this should not be + // considered + // "lockscreen" + not(communalSceneInteractor.isCommunalVisible), + isOnAnyBouncer, + ), + ) + } else { + anyOf( + keyguardTransitionInteractor.transitionValue(AOD).map { it > 0f }, + keyguardTransitionInteractor.transitionValue(DOZING).map { it > 0f }, + keyguardTransitionInteractor.transitionValue(LOCKSCREEN).map { it > 0f }, + isOnAnyBouncer, + ) + } .flowName("isOnLockscreen") .stateIn( scope = applicationScope, |