Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt +40 −1 Original line number Diff line number Diff line Loading @@ -41,6 +41,8 @@ import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepos import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.keyguard.shared.model.BurnInModel import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.KeyguardState.AOD import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionStep Loading @@ -53,6 +55,7 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.res.R import com.android.systemui.shade.mockLargeScreenHeaderHelper import com.android.systemui.shade.shadeTestUtil import com.android.systemui.statusbar.notification.NotificationUtils.interpolate import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor import com.android.systemui.testKosmos import com.android.systemui.util.mockito.any Loading Loading @@ -794,11 +797,47 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S @DisableSceneContainer fun updateBounds_fromKeyguardRoot() = testScope.runTest { val bounds by collectLastValue(underTest.bounds) val startProgress = 0f val startStep = TransitionStep(LOCKSCREEN, AOD, startProgress, TransitionState.STARTED) val boundsChangingProgress = 0.2f val boundsChangingStep = TransitionStep(LOCKSCREEN, AOD, boundsChangingProgress, TransitionState.RUNNING) val boundsInterpolatingProgress = 0.6f val boundsInterpolatingStep = TransitionStep( LOCKSCREEN, AOD, boundsInterpolatingProgress, TransitionState.RUNNING ) val finishProgress = 1.0f val finishStep = TransitionStep(LOCKSCREEN, AOD, finishProgress, TransitionState.FINISHED) val bounds by collectLastValue(underTest.bounds) val top = 123f val bottom = 456f kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(startStep) runCurrent() kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(boundsChangingStep) runCurrent() keyguardRootViewModel.onNotificationContainerBoundsChanged(top, bottom) kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(boundsInterpolatingStep) runCurrent() val adjustedProgress = (boundsInterpolatingProgress - boundsChangingProgress) / (1 - boundsChangingProgress) val interpolatedTop = interpolate(0f, top, adjustedProgress) val interpolatedBottom = interpolate(0f, bottom, adjustedProgress) assertThat(bounds) .isEqualTo( NotificationContainerBounds(top = interpolatedTop, bottom = interpolatedBottom) ) kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(finishStep) runCurrent() assertThat(bounds).isEqualTo(NotificationContainerBounds(top = top, bottom = bottom)) } Loading packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt +45 −3 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel import com.android.systemui.keyguard.shared.model.DozeStateModel import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDozeOff import com.android.systemui.keyguard.shared.model.DozeTransitionModel import com.android.systemui.keyguard.shared.model.KeyguardState.AOD import com.android.systemui.keyguard.shared.model.KeyguardState.GONE import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN import com.android.systemui.keyguard.shared.model.StatusBarState Loading @@ -47,8 +48,10 @@ import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.data.repository.ShadeRepository import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.notification.NotificationUtils.interpolate import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleCombine import com.android.systemui.util.kotlin.pairwise import com.android.systemui.util.kotlin.sample import javax.inject.Inject import javax.inject.Provider Loading @@ -66,7 +69,9 @@ import kotlinx.coroutines.flow.combineTransform import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.merge Loading Loading @@ -96,17 +101,54 @@ constructor( // TODO(b/296118689): move to a repository private val _notificationPlaceholderBounds = MutableStateFlow(NotificationContainerBounds()) // When going to AOD, we interpolate bounds when receiving the new bounds // When going back to LS, we'll apply new bounds directly private val _nonSplitShadeNotifciationPlaceholderBounds = _notificationPlaceholderBounds.pairwise().flatMapLatest { (oldBounds, newBounds) -> val lastChangeStep = keyguardTransitionInteractor.transitionState.first() if (lastChangeStep.to == AOD) { keyguardTransitionInteractor.transitionState.map { step -> val startingProgress = lastChangeStep.value val progress = step.value if (step.to == AOD && progress >= startingProgress) { val adjustedProgress = ((progress - startingProgress) / (1F - startingProgress)).coerceIn( 0F, 1F ) val top = interpolate(oldBounds.top, newBounds.top, adjustedProgress) val bottom = interpolate( oldBounds.bottom, newBounds.bottom, adjustedProgress.coerceIn(0F, 1F) ) NotificationContainerBounds(top = top, bottom = bottom) } else { newBounds } } } else { flow { emit(newBounds) } } } /** Bounds of the notification container. */ val notificationContainerBounds: StateFlow<NotificationContainerBounds> by lazy { SceneContainerFlag.assertInLegacyMode() combine( _notificationPlaceholderBounds, _nonSplitShadeNotifciationPlaceholderBounds, sharedNotificationContainerInteractor.get().configurationBasedDimensions, ) { bounds, cfg -> ) { bounds, nonSplitShadeBounds: NotificationContainerBounds, cfg -> // We offset the placeholder bounds by the configured top margin to account for // legacy placement behavior within notifications for splitshade. if (MigrateClocksToBlueprint.isEnabled && cfg.useSplitShade) { if (MigrateClocksToBlueprint.isEnabled) { if (cfg.useSplitShade) { bounds.copy(bottom = bounds.bottom - cfg.keyguardSplitShadeTopMargin) } else { nonSplitShadeBounds } } else bounds } .stateIn( Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt +40 −1 Original line number Diff line number Diff line Loading @@ -41,6 +41,8 @@ import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepos import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.keyguard.shared.model.BurnInModel import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.KeyguardState.AOD import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionStep Loading @@ -53,6 +55,7 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.res.R import com.android.systemui.shade.mockLargeScreenHeaderHelper import com.android.systemui.shade.shadeTestUtil import com.android.systemui.statusbar.notification.NotificationUtils.interpolate import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor import com.android.systemui.testKosmos import com.android.systemui.util.mockito.any Loading Loading @@ -794,11 +797,47 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S @DisableSceneContainer fun updateBounds_fromKeyguardRoot() = testScope.runTest { val bounds by collectLastValue(underTest.bounds) val startProgress = 0f val startStep = TransitionStep(LOCKSCREEN, AOD, startProgress, TransitionState.STARTED) val boundsChangingProgress = 0.2f val boundsChangingStep = TransitionStep(LOCKSCREEN, AOD, boundsChangingProgress, TransitionState.RUNNING) val boundsInterpolatingProgress = 0.6f val boundsInterpolatingStep = TransitionStep( LOCKSCREEN, AOD, boundsInterpolatingProgress, TransitionState.RUNNING ) val finishProgress = 1.0f val finishStep = TransitionStep(LOCKSCREEN, AOD, finishProgress, TransitionState.FINISHED) val bounds by collectLastValue(underTest.bounds) val top = 123f val bottom = 456f kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(startStep) runCurrent() kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(boundsChangingStep) runCurrent() keyguardRootViewModel.onNotificationContainerBoundsChanged(top, bottom) kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(boundsInterpolatingStep) runCurrent() val adjustedProgress = (boundsInterpolatingProgress - boundsChangingProgress) / (1 - boundsChangingProgress) val interpolatedTop = interpolate(0f, top, adjustedProgress) val interpolatedBottom = interpolate(0f, bottom, adjustedProgress) assertThat(bounds) .isEqualTo( NotificationContainerBounds(top = interpolatedTop, bottom = interpolatedBottom) ) kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(finishStep) runCurrent() assertThat(bounds).isEqualTo(NotificationContainerBounds(top = top, bottom = bottom)) } Loading
packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt +45 −3 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel import com.android.systemui.keyguard.shared.model.DozeStateModel import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDozeOff import com.android.systemui.keyguard.shared.model.DozeTransitionModel import com.android.systemui.keyguard.shared.model.KeyguardState.AOD import com.android.systemui.keyguard.shared.model.KeyguardState.GONE import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN import com.android.systemui.keyguard.shared.model.StatusBarState Loading @@ -47,8 +48,10 @@ import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.shade.data.repository.ShadeRepository import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.notification.NotificationUtils.interpolate import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleCombine import com.android.systemui.util.kotlin.pairwise import com.android.systemui.util.kotlin.sample import javax.inject.Inject import javax.inject.Provider Loading @@ -66,7 +69,9 @@ import kotlinx.coroutines.flow.combineTransform import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.merge Loading Loading @@ -96,17 +101,54 @@ constructor( // TODO(b/296118689): move to a repository private val _notificationPlaceholderBounds = MutableStateFlow(NotificationContainerBounds()) // When going to AOD, we interpolate bounds when receiving the new bounds // When going back to LS, we'll apply new bounds directly private val _nonSplitShadeNotifciationPlaceholderBounds = _notificationPlaceholderBounds.pairwise().flatMapLatest { (oldBounds, newBounds) -> val lastChangeStep = keyguardTransitionInteractor.transitionState.first() if (lastChangeStep.to == AOD) { keyguardTransitionInteractor.transitionState.map { step -> val startingProgress = lastChangeStep.value val progress = step.value if (step.to == AOD && progress >= startingProgress) { val adjustedProgress = ((progress - startingProgress) / (1F - startingProgress)).coerceIn( 0F, 1F ) val top = interpolate(oldBounds.top, newBounds.top, adjustedProgress) val bottom = interpolate( oldBounds.bottom, newBounds.bottom, adjustedProgress.coerceIn(0F, 1F) ) NotificationContainerBounds(top = top, bottom = bottom) } else { newBounds } } } else { flow { emit(newBounds) } } } /** Bounds of the notification container. */ val notificationContainerBounds: StateFlow<NotificationContainerBounds> by lazy { SceneContainerFlag.assertInLegacyMode() combine( _notificationPlaceholderBounds, _nonSplitShadeNotifciationPlaceholderBounds, sharedNotificationContainerInteractor.get().configurationBasedDimensions, ) { bounds, cfg -> ) { bounds, nonSplitShadeBounds: NotificationContainerBounds, cfg -> // We offset the placeholder bounds by the configured top margin to account for // legacy placement behavior within notifications for splitshade. if (MigrateClocksToBlueprint.isEnabled && cfg.useSplitShade) { if (MigrateClocksToBlueprint.isEnabled) { if (cfg.useSplitShade) { bounds.copy(bottom = bounds.bottom - cfg.keyguardSplitShadeTopMargin) } else { nonSplitShadeBounds } } else bounds } .stateIn( Loading