Loading packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt +2 −2 Original line number Original line Diff line number Diff line Loading @@ -8,7 +8,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase import com.android.systemui.complication.ComplicationHostViewController import com.android.systemui.complication.ComplicationHostViewController import com.android.systemui.dreams.ui.viewmodel.DreamOverlayViewModel import com.android.systemui.dreams.ui.viewmodel.DreamViewModel import com.android.systemui.log.core.FakeLogBuffer import com.android.systemui.log.core.FakeLogBuffer import com.android.systemui.statusbar.BlurUtils import com.android.systemui.statusbar.BlurUtils import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.argumentCaptor Loading Loading @@ -45,7 +45,7 @@ class DreamOverlayAnimationsControllerTest : SysuiTestCase() { @Mock private lateinit var hostViewController: ComplicationHostViewController @Mock private lateinit var hostViewController: ComplicationHostViewController @Mock private lateinit var statusBarViewController: DreamOverlayStatusBarViewController @Mock private lateinit var statusBarViewController: DreamOverlayStatusBarViewController @Mock private lateinit var stateController: DreamOverlayStateController @Mock private lateinit var stateController: DreamOverlayStateController @Mock private lateinit var transitionViewModel: DreamOverlayViewModel @Mock private lateinit var transitionViewModel: DreamViewModel private val logBuffer = FakeLogBuffer.Factory.create() private val logBuffer = FakeLogBuffer.Factory.create() private lateinit var controller: DreamOverlayAnimationsController private lateinit var controller: DreamOverlayAnimationsController Loading packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt +0 −36 Original line number Original line Diff line number Diff line Loading @@ -26,14 +26,9 @@ import com.android.systemui.biometrics.shared.model.SensorStrength import com.android.systemui.coroutines.collectValues import com.android.systemui.coroutines.collectValues import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState.AOD import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING 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.KeyguardState.LOCKSCREEN import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionState.CANCELED import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING import com.android.systemui.keyguard.shared.model.TransitionState.STARTED import com.android.systemui.keyguard.shared.model.TransitionState.STARTED import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.keyguard.shared.model.TransitionStep Loading Loading @@ -219,37 +214,6 @@ class DreamingToLockscreenTransitionViewModelTest : SysuiTestCase() { values.forEach { assertThat(it).isIn(Range.closed(-100f, 0f)) } values.forEach { assertThat(it).isIn(Range.closed(-100f, 0f)) } } } @Test fun transitionEnded() = testScope.runTest { val values by collectValues(underTest.transitionEnded) keyguardTransitionRepository.sendTransitionSteps( listOf( TransitionStep(DOZING, DREAMING, 0.0f, STARTED), TransitionStep(DOZING, DREAMING, 1.0f, FINISHED), TransitionStep(DREAMING, LOCKSCREEN, 0.0f, STARTED), TransitionStep(DREAMING, LOCKSCREEN, 0.1f, RUNNING), TransitionStep(DREAMING, LOCKSCREEN, 1.0f, FINISHED), TransitionStep(LOCKSCREEN, DREAMING, 0.0f, STARTED), TransitionStep(LOCKSCREEN, DREAMING, 0.5f, RUNNING), TransitionStep(LOCKSCREEN, DREAMING, 1.0f, FINISHED), TransitionStep(DREAMING, GONE, 0.0f, STARTED), TransitionStep(DREAMING, GONE, 0.5f, RUNNING), TransitionStep(DREAMING, GONE, 1.0f, CANCELED), TransitionStep(DREAMING, AOD, 0.0f, STARTED), TransitionStep(DREAMING, AOD, 1.0f, FINISHED), ), testScope, ) assertThat(values.size).isEqualTo(3) values.forEach { assertThat(it.transitionState == FINISHED || it.transitionState == CANCELED) .isTrue() } } private fun step(value: Float, state: TransitionState = RUNNING): TransitionStep { private fun step(value: Float, state: TransitionState = RUNNING): TransitionStep { return TransitionStep( return TransitionStep( from = DREAMING, from = DREAMING, Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt +64 −17 Original line number Original line Diff line number Diff line Loading @@ -21,13 +21,10 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState import com.android.systemui.Flags.FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX import com.android.systemui.Flags.FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.NotificationContainerBounds import com.android.systemui.common.shared.model.NotificationContainerBounds import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.Flags import com.android.systemui.flags.Flags import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.flags.fakeFeatureFlagsClassic Loading Loading @@ -80,13 +77,13 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { init { init { kosmos.aodBurnInViewModel = aodBurnInViewModel kosmos.aodBurnInViewModel = aodBurnInViewModel } } val testScope = kosmos.testScope val testScope = kosmos.testScope val configurationRepository = kosmos.fakeConfigurationRepository val configurationRepository = kosmos.fakeConfigurationRepository val keyguardRepository = kosmos.fakeKeyguardRepository val keyguardRepository = kosmos.fakeKeyguardRepository val keyguardInteractor = kosmos.keyguardInteractor val keyguardInteractor = kosmos.keyguardInteractor val keyguardRootViewModel = kosmos.keyguardRootViewModel val keyguardRootViewModel = kosmos.keyguardRootViewModel val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository val communalInteractor = kosmos.communalInteractor val shadeRepository = kosmos.shadeRepository val shadeRepository = kosmos.shadeRepository val sharedNotificationContainerInteractor = kosmos.sharedNotificationContainerInteractor val sharedNotificationContainerInteractor = kosmos.sharedNotificationContainerInteractor val largeScreenHeaderHelper = kosmos.mockLargeScreenHeaderHelper val largeScreenHeaderHelper = kosmos.mockLargeScreenHeaderHelper Loading Loading @@ -239,7 +236,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } } @Test @Test fun glanceableHubAlpha() = fun glanceableHubAlpha_lockscreenToHub() = testScope.runTest { testScope.runTest { val alpha by collectLastValue(underTest.glanceableHubAlpha) val alpha by collectLastValue(underTest.glanceableHubAlpha) Loading Loading @@ -278,12 +275,6 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { value = 1f, value = 1f, ) ) ) ) val idleTransitionState = MutableStateFlow<ObservableTransitionState>( ObservableTransitionState.Idle(CommunalScenes.Communal) ) communalInteractor.setTransitionState(idleTransitionState) runCurrent() assertThat(alpha).isEqualTo(0f) assertThat(alpha).isEqualTo(0f) // While state is GLANCEABLE_HUB, verify alpha is restored to full if glanceable hub is // While state is GLANCEABLE_HUB, verify alpha is restored to full if glanceable hub is Loading @@ -292,6 +283,50 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { assertThat(alpha).isEqualTo(1f) assertThat(alpha).isEqualTo(1f) } } @Test fun glanceableHubAlpha_dreamToHub() = testScope.runTest { val alpha by collectLastValue(underTest.glanceableHubAlpha) // Start on dream showDream() assertThat(alpha).isEqualTo(1f) // Start transitioning to glanceable hub val progress = 0.6f keyguardTransitionRepository.sendTransitionStep( TransitionStep( transitionState = TransitionState.STARTED, from = KeyguardState.DREAMING, to = KeyguardState.GLANCEABLE_HUB, value = 0f, ) ) runCurrent() keyguardTransitionRepository.sendTransitionStep( TransitionStep( transitionState = TransitionState.RUNNING, from = KeyguardState.DREAMING, to = KeyguardState.GLANCEABLE_HUB, value = progress, ) ) runCurrent() // Keep notifications hidden during the transition from dream to hub assertThat(alpha).isEqualTo(0) // Finish transition to glanceable hub keyguardTransitionRepository.sendTransitionStep( TransitionStep( transitionState = TransitionState.FINISHED, from = KeyguardState.DREAMING, to = KeyguardState.GLANCEABLE_HUB, value = 1f, ) ) assertThat(alpha).isEqualTo(0f) } @Test @Test fun validateMarginTop() = fun validateMarginTop() = testScope.runTest { testScope.runTest { Loading Loading @@ -391,12 +426,11 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { assertThat(isOnGlanceableHubWithoutShade).isFalse() assertThat(isOnGlanceableHubWithoutShade).isFalse() // Move to glanceable hub // Move to glanceable hub val idleTransitionState = keyguardTransitionRepository.sendTransitionSteps( MutableStateFlow<ObservableTransitionState>( from = KeyguardState.LOCKSCREEN, ObservableTransitionState.Idle(CommunalScenes.Communal) to = KeyguardState.GLANCEABLE_HUB, testScope = this ) ) communalInteractor.setTransitionState(idleTransitionState) runCurrent() assertThat(isOnGlanceableHubWithoutShade).isTrue() assertThat(isOnGlanceableHubWithoutShade).isTrue() // While state is GLANCEABLE_HUB, validate variations of both shade and qs expansion // While state is GLANCEABLE_HUB, validate variations of both shade and qs expansion Loading Loading @@ -726,6 +760,19 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { ) ) } } private suspend fun TestScope.showDream() { shadeRepository.setLockscreenShadeExpansion(0f) shadeRepository.setQsExpansion(0f) runCurrent() keyguardRepository.setDreaming(true) runCurrent() keyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.LOCKSCREEN, to = KeyguardState.DREAMING, testScope, ) } private suspend fun TestScope.showLockscreenWithShadeExpanded() { private suspend fun TestScope.showLockscreenWithShadeExpanded() { shadeRepository.setLockscreenShadeExpansion(1f) shadeRepository.setLockscreenShadeExpansion(1f) shadeRepository.setQsExpansion(0f) shadeRepository.setQsExpansion(0f) Loading packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt +6 −6 Original line number Original line Diff line number Diff line Loading @@ -33,7 +33,7 @@ import com.android.systemui.complication.ComplicationLayoutParams.POSITION_BOTTO import com.android.systemui.complication.ComplicationLayoutParams.POSITION_TOP import com.android.systemui.complication.ComplicationLayoutParams.POSITION_TOP import com.android.systemui.complication.ComplicationLayoutParams.Position import com.android.systemui.complication.ComplicationLayoutParams.Position import com.android.systemui.dreams.dagger.DreamOverlayModule import com.android.systemui.dreams.dagger.DreamOverlayModule import com.android.systemui.dreams.ui.viewmodel.DreamOverlayViewModel import com.android.systemui.dreams.ui.viewmodel.DreamViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.Logger import com.android.systemui.log.core.Logger Loading @@ -53,7 +53,7 @@ constructor( private val mStatusBarViewController: DreamOverlayStatusBarViewController, private val mStatusBarViewController: DreamOverlayStatusBarViewController, private val mOverlayStateController: DreamOverlayStateController, private val mOverlayStateController: DreamOverlayStateController, @Named(DreamOverlayModule.DREAM_BLUR_RADIUS) private val mDreamBlurRadius: Int, @Named(DreamOverlayModule.DREAM_BLUR_RADIUS) private val mDreamBlurRadius: Int, private val dreamOverlayViewModel: DreamOverlayViewModel, private val dreamViewModel: DreamViewModel, @Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DURATION) @Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DURATION) private val mDreamInBlurAnimDurationMs: Long, private val mDreamInBlurAnimDurationMs: Long, @Named(DreamOverlayModule.DREAM_IN_COMPLICATIONS_ANIMATION_DURATION) @Named(DreamOverlayModule.DREAM_IN_COMPLICATIONS_ANIMATION_DURATION) Loading Loading @@ -87,7 +87,7 @@ constructor( view.repeatWhenAttached { view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { repeatOnLifecycle(Lifecycle.State.CREATED) { launch { launch { dreamOverlayViewModel.dreamOverlayTranslationY.collect { px -> dreamViewModel.dreamOverlayTranslationY.collect { px -> ComplicationLayoutParams.iteratePositions( ComplicationLayoutParams.iteratePositions( { position: Int -> setElementsTranslationYAtPosition(px, position) }, { position: Int -> setElementsTranslationYAtPosition(px, position) }, POSITION_TOP or POSITION_BOTTOM POSITION_TOP or POSITION_BOTTOM Loading @@ -96,7 +96,7 @@ constructor( } } launch { launch { dreamOverlayViewModel.dreamOverlayTranslationX.collect { px -> dreamViewModel.dreamOverlayTranslationX.collect { px -> ComplicationLayoutParams.iteratePositions( ComplicationLayoutParams.iteratePositions( { position: Int -> setElementsTranslationXAtPosition(px, position) }, { position: Int -> setElementsTranslationXAtPosition(px, position) }, POSITION_TOP or POSITION_BOTTOM POSITION_TOP or POSITION_BOTTOM Loading @@ -105,7 +105,7 @@ constructor( } } launch { launch { dreamOverlayViewModel.dreamOverlayAlpha.collect { alpha -> dreamViewModel.dreamOverlayAlpha.collect { alpha -> ComplicationLayoutParams.iteratePositions( ComplicationLayoutParams.iteratePositions( { position: Int -> { position: Int -> setElementsAlphaAtPosition( setElementsAlphaAtPosition( Loading @@ -120,7 +120,7 @@ constructor( } } launch { launch { dreamOverlayViewModel.transitionEnded.collect { _ -> dreamViewModel.transitionEnded.collect { _ -> mOverlayStateController.setExitAnimationsRunning(false) mOverlayStateController.setExitAnimationsRunning(false) } } } } Loading packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamOverlayViewModel.kt→packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt +103 −0 Original line number Original line Diff line number Diff line Loading @@ -16,34 +16,62 @@ package com.android.systemui.dreams.ui.viewmodel package com.android.systemui.dreams.ui.viewmodel import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dock.DockManager import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.ui.viewmodel.DreamingToGlanceableHubTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.DreamingToGlanceableHubTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToDreamingTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToDreamingTransitionViewModel import com.android.systemui.res.R import com.android.systemui.res.R import com.android.systemui.settings.UserTracker import javax.inject.Inject import javax.inject.Inject import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.merge @OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class) @SysUISingleton @SysUISingleton class DreamOverlayViewModel class DreamViewModel @Inject @Inject constructor( constructor( configurationInteractor: ConfigurationInteractor, configurationInteractor: ConfigurationInteractor, toGlanceableHubTransitionViewModel: DreamingToGlanceableHubTransitionViewModel, keyguardTransitionInteractor: KeyguardTransitionInteractor, fromGlanceableHubTransitionInteractor: GlanceableHubToDreamingTransitionViewModel, fromGlanceableHubTransitionInteractor: GlanceableHubToDreamingTransitionViewModel, private val toGlanceableHubTransitionViewModel: DreamingToGlanceableHubTransitionViewModel, private val toLockscreenTransitionViewModel: DreamingToLockscreenTransitionViewModel, private val toLockscreenTransitionViewModel: DreamingToLockscreenTransitionViewModel, private val dockManager: DockManager, private val communalInteractor: CommunalInteractor, private val keyguardUpdateMonitor: KeyguardUpdateMonitor, private val userTracker: UserTracker, ) { ) { fun startTransitionFromDream() { val showGlanceableHub = dockManager.isDocked && communalInteractor.isCommunalEnabled.value && !keyguardUpdateMonitor.isEncryptedOrLockdown(userTracker.userId) if (showGlanceableHub) { toGlanceableHubTransitionViewModel.startTransition() communalInteractor.onSceneChanged(CommunalScenes.Communal) } else { toLockscreenTransitionViewModel.startTransition() } } val dreamOverlayTranslationX: Flow<Float> = val dreamOverlayTranslationX: Flow<Float> = merge( merge( toGlanceableHubTransitionViewModel.dreamOverlayTranslationX, toGlanceableHubTransitionViewModel.dreamOverlayTranslationX, fromGlanceableHubTransitionInteractor.dreamOverlayTranslationX, fromGlanceableHubTransitionInteractor.dreamOverlayTranslationX, ) ) .distinctUntilChanged() val dreamOverlayTranslationY: Flow<Float> = val dreamOverlayTranslationY: Flow<Float> = configurationInteractor configurationInteractor Loading @@ -52,12 +80,24 @@ constructor( toLockscreenTransitionViewModel.dreamOverlayTranslationY(px) toLockscreenTransitionViewModel.dreamOverlayTranslationY(px) } } val dreamAlpha: Flow<Float> = merge( toLockscreenTransitionViewModel.dreamOverlayAlpha, toGlanceableHubTransitionViewModel.dreamAlpha, ) .distinctUntilChanged() val dreamOverlayAlpha: Flow<Float> = val dreamOverlayAlpha: Flow<Float> = merge( merge( toLockscreenTransitionViewModel.dreamOverlayAlpha, toLockscreenTransitionViewModel.dreamOverlayAlpha, toGlanceableHubTransitionViewModel.dreamOverlayAlpha, toGlanceableHubTransitionViewModel.dreamOverlayAlpha, fromGlanceableHubTransitionInteractor.dreamOverlayAlpha, fromGlanceableHubTransitionInteractor.dreamOverlayAlpha, ) ) .distinctUntilChanged() val transitionEnded = toLockscreenTransitionViewModel.transitionEnded val transitionEnded = keyguardTransitionInteractor.fromDreamingTransition.filter { step -> step.transitionState == TransitionState.FINISHED || step.transitionState == TransitionState.CANCELED } } } Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt +2 −2 Original line number Original line Diff line number Diff line Loading @@ -8,7 +8,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase import com.android.systemui.complication.ComplicationHostViewController import com.android.systemui.complication.ComplicationHostViewController import com.android.systemui.dreams.ui.viewmodel.DreamOverlayViewModel import com.android.systemui.dreams.ui.viewmodel.DreamViewModel import com.android.systemui.log.core.FakeLogBuffer import com.android.systemui.log.core.FakeLogBuffer import com.android.systemui.statusbar.BlurUtils import com.android.systemui.statusbar.BlurUtils import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.argumentCaptor Loading Loading @@ -45,7 +45,7 @@ class DreamOverlayAnimationsControllerTest : SysuiTestCase() { @Mock private lateinit var hostViewController: ComplicationHostViewController @Mock private lateinit var hostViewController: ComplicationHostViewController @Mock private lateinit var statusBarViewController: DreamOverlayStatusBarViewController @Mock private lateinit var statusBarViewController: DreamOverlayStatusBarViewController @Mock private lateinit var stateController: DreamOverlayStateController @Mock private lateinit var stateController: DreamOverlayStateController @Mock private lateinit var transitionViewModel: DreamOverlayViewModel @Mock private lateinit var transitionViewModel: DreamViewModel private val logBuffer = FakeLogBuffer.Factory.create() private val logBuffer = FakeLogBuffer.Factory.create() private lateinit var controller: DreamOverlayAnimationsController private lateinit var controller: DreamOverlayAnimationsController Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt +0 −36 Original line number Original line Diff line number Diff line Loading @@ -26,14 +26,9 @@ import com.android.systemui.biometrics.shared.model.SensorStrength import com.android.systemui.coroutines.collectValues import com.android.systemui.coroutines.collectValues import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState.AOD import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING 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.KeyguardState.LOCKSCREEN import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionState.CANCELED import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING import com.android.systemui.keyguard.shared.model.TransitionState.STARTED import com.android.systemui.keyguard.shared.model.TransitionState.STARTED import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.keyguard.shared.model.TransitionStep Loading Loading @@ -219,37 +214,6 @@ class DreamingToLockscreenTransitionViewModelTest : SysuiTestCase() { values.forEach { assertThat(it).isIn(Range.closed(-100f, 0f)) } values.forEach { assertThat(it).isIn(Range.closed(-100f, 0f)) } } } @Test fun transitionEnded() = testScope.runTest { val values by collectValues(underTest.transitionEnded) keyguardTransitionRepository.sendTransitionSteps( listOf( TransitionStep(DOZING, DREAMING, 0.0f, STARTED), TransitionStep(DOZING, DREAMING, 1.0f, FINISHED), TransitionStep(DREAMING, LOCKSCREEN, 0.0f, STARTED), TransitionStep(DREAMING, LOCKSCREEN, 0.1f, RUNNING), TransitionStep(DREAMING, LOCKSCREEN, 1.0f, FINISHED), TransitionStep(LOCKSCREEN, DREAMING, 0.0f, STARTED), TransitionStep(LOCKSCREEN, DREAMING, 0.5f, RUNNING), TransitionStep(LOCKSCREEN, DREAMING, 1.0f, FINISHED), TransitionStep(DREAMING, GONE, 0.0f, STARTED), TransitionStep(DREAMING, GONE, 0.5f, RUNNING), TransitionStep(DREAMING, GONE, 1.0f, CANCELED), TransitionStep(DREAMING, AOD, 0.0f, STARTED), TransitionStep(DREAMING, AOD, 1.0f, FINISHED), ), testScope, ) assertThat(values.size).isEqualTo(3) values.forEach { assertThat(it.transitionState == FINISHED || it.transitionState == CANCELED) .isTrue() } } private fun step(value: Float, state: TransitionState = RUNNING): TransitionStep { private fun step(value: Float, state: TransitionState = RUNNING): TransitionStep { return TransitionStep( return TransitionStep( from = DREAMING, from = DREAMING, Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt +64 −17 Original line number Original line Diff line number Diff line Loading @@ -21,13 +21,10 @@ package com.android.systemui.statusbar.notification.stack.ui.viewmodel import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState import com.android.systemui.Flags.FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX import com.android.systemui.Flags.FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.NotificationContainerBounds import com.android.systemui.common.shared.model.NotificationContainerBounds import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.Flags import com.android.systemui.flags.Flags import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.flags.fakeFeatureFlagsClassic Loading Loading @@ -80,13 +77,13 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { init { init { kosmos.aodBurnInViewModel = aodBurnInViewModel kosmos.aodBurnInViewModel = aodBurnInViewModel } } val testScope = kosmos.testScope val testScope = kosmos.testScope val configurationRepository = kosmos.fakeConfigurationRepository val configurationRepository = kosmos.fakeConfigurationRepository val keyguardRepository = kosmos.fakeKeyguardRepository val keyguardRepository = kosmos.fakeKeyguardRepository val keyguardInteractor = kosmos.keyguardInteractor val keyguardInteractor = kosmos.keyguardInteractor val keyguardRootViewModel = kosmos.keyguardRootViewModel val keyguardRootViewModel = kosmos.keyguardRootViewModel val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository val communalInteractor = kosmos.communalInteractor val shadeRepository = kosmos.shadeRepository val shadeRepository = kosmos.shadeRepository val sharedNotificationContainerInteractor = kosmos.sharedNotificationContainerInteractor val sharedNotificationContainerInteractor = kosmos.sharedNotificationContainerInteractor val largeScreenHeaderHelper = kosmos.mockLargeScreenHeaderHelper val largeScreenHeaderHelper = kosmos.mockLargeScreenHeaderHelper Loading Loading @@ -239,7 +236,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { } } @Test @Test fun glanceableHubAlpha() = fun glanceableHubAlpha_lockscreenToHub() = testScope.runTest { testScope.runTest { val alpha by collectLastValue(underTest.glanceableHubAlpha) val alpha by collectLastValue(underTest.glanceableHubAlpha) Loading Loading @@ -278,12 +275,6 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { value = 1f, value = 1f, ) ) ) ) val idleTransitionState = MutableStateFlow<ObservableTransitionState>( ObservableTransitionState.Idle(CommunalScenes.Communal) ) communalInteractor.setTransitionState(idleTransitionState) runCurrent() assertThat(alpha).isEqualTo(0f) assertThat(alpha).isEqualTo(0f) // While state is GLANCEABLE_HUB, verify alpha is restored to full if glanceable hub is // While state is GLANCEABLE_HUB, verify alpha is restored to full if glanceable hub is Loading @@ -292,6 +283,50 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { assertThat(alpha).isEqualTo(1f) assertThat(alpha).isEqualTo(1f) } } @Test fun glanceableHubAlpha_dreamToHub() = testScope.runTest { val alpha by collectLastValue(underTest.glanceableHubAlpha) // Start on dream showDream() assertThat(alpha).isEqualTo(1f) // Start transitioning to glanceable hub val progress = 0.6f keyguardTransitionRepository.sendTransitionStep( TransitionStep( transitionState = TransitionState.STARTED, from = KeyguardState.DREAMING, to = KeyguardState.GLANCEABLE_HUB, value = 0f, ) ) runCurrent() keyguardTransitionRepository.sendTransitionStep( TransitionStep( transitionState = TransitionState.RUNNING, from = KeyguardState.DREAMING, to = KeyguardState.GLANCEABLE_HUB, value = progress, ) ) runCurrent() // Keep notifications hidden during the transition from dream to hub assertThat(alpha).isEqualTo(0) // Finish transition to glanceable hub keyguardTransitionRepository.sendTransitionStep( TransitionStep( transitionState = TransitionState.FINISHED, from = KeyguardState.DREAMING, to = KeyguardState.GLANCEABLE_HUB, value = 1f, ) ) assertThat(alpha).isEqualTo(0f) } @Test @Test fun validateMarginTop() = fun validateMarginTop() = testScope.runTest { testScope.runTest { Loading Loading @@ -391,12 +426,11 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { assertThat(isOnGlanceableHubWithoutShade).isFalse() assertThat(isOnGlanceableHubWithoutShade).isFalse() // Move to glanceable hub // Move to glanceable hub val idleTransitionState = keyguardTransitionRepository.sendTransitionSteps( MutableStateFlow<ObservableTransitionState>( from = KeyguardState.LOCKSCREEN, ObservableTransitionState.Idle(CommunalScenes.Communal) to = KeyguardState.GLANCEABLE_HUB, testScope = this ) ) communalInteractor.setTransitionState(idleTransitionState) runCurrent() assertThat(isOnGlanceableHubWithoutShade).isTrue() assertThat(isOnGlanceableHubWithoutShade).isTrue() // While state is GLANCEABLE_HUB, validate variations of both shade and qs expansion // While state is GLANCEABLE_HUB, validate variations of both shade and qs expansion Loading Loading @@ -726,6 +760,19 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() { ) ) } } private suspend fun TestScope.showDream() { shadeRepository.setLockscreenShadeExpansion(0f) shadeRepository.setQsExpansion(0f) runCurrent() keyguardRepository.setDreaming(true) runCurrent() keyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.LOCKSCREEN, to = KeyguardState.DREAMING, testScope, ) } private suspend fun TestScope.showLockscreenWithShadeExpanded() { private suspend fun TestScope.showLockscreenWithShadeExpanded() { shadeRepository.setLockscreenShadeExpansion(1f) shadeRepository.setLockscreenShadeExpansion(1f) shadeRepository.setQsExpansion(0f) shadeRepository.setQsExpansion(0f) Loading
packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt +6 −6 Original line number Original line Diff line number Diff line Loading @@ -33,7 +33,7 @@ import com.android.systemui.complication.ComplicationLayoutParams.POSITION_BOTTO import com.android.systemui.complication.ComplicationLayoutParams.POSITION_TOP import com.android.systemui.complication.ComplicationLayoutParams.POSITION_TOP import com.android.systemui.complication.ComplicationLayoutParams.Position import com.android.systemui.complication.ComplicationLayoutParams.Position import com.android.systemui.dreams.dagger.DreamOverlayModule import com.android.systemui.dreams.dagger.DreamOverlayModule import com.android.systemui.dreams.ui.viewmodel.DreamOverlayViewModel import com.android.systemui.dreams.ui.viewmodel.DreamViewModel import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.Logger import com.android.systemui.log.core.Logger Loading @@ -53,7 +53,7 @@ constructor( private val mStatusBarViewController: DreamOverlayStatusBarViewController, private val mStatusBarViewController: DreamOverlayStatusBarViewController, private val mOverlayStateController: DreamOverlayStateController, private val mOverlayStateController: DreamOverlayStateController, @Named(DreamOverlayModule.DREAM_BLUR_RADIUS) private val mDreamBlurRadius: Int, @Named(DreamOverlayModule.DREAM_BLUR_RADIUS) private val mDreamBlurRadius: Int, private val dreamOverlayViewModel: DreamOverlayViewModel, private val dreamViewModel: DreamViewModel, @Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DURATION) @Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DURATION) private val mDreamInBlurAnimDurationMs: Long, private val mDreamInBlurAnimDurationMs: Long, @Named(DreamOverlayModule.DREAM_IN_COMPLICATIONS_ANIMATION_DURATION) @Named(DreamOverlayModule.DREAM_IN_COMPLICATIONS_ANIMATION_DURATION) Loading Loading @@ -87,7 +87,7 @@ constructor( view.repeatWhenAttached { view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.CREATED) { repeatOnLifecycle(Lifecycle.State.CREATED) { launch { launch { dreamOverlayViewModel.dreamOverlayTranslationY.collect { px -> dreamViewModel.dreamOverlayTranslationY.collect { px -> ComplicationLayoutParams.iteratePositions( ComplicationLayoutParams.iteratePositions( { position: Int -> setElementsTranslationYAtPosition(px, position) }, { position: Int -> setElementsTranslationYAtPosition(px, position) }, POSITION_TOP or POSITION_BOTTOM POSITION_TOP or POSITION_BOTTOM Loading @@ -96,7 +96,7 @@ constructor( } } launch { launch { dreamOverlayViewModel.dreamOverlayTranslationX.collect { px -> dreamViewModel.dreamOverlayTranslationX.collect { px -> ComplicationLayoutParams.iteratePositions( ComplicationLayoutParams.iteratePositions( { position: Int -> setElementsTranslationXAtPosition(px, position) }, { position: Int -> setElementsTranslationXAtPosition(px, position) }, POSITION_TOP or POSITION_BOTTOM POSITION_TOP or POSITION_BOTTOM Loading @@ -105,7 +105,7 @@ constructor( } } launch { launch { dreamOverlayViewModel.dreamOverlayAlpha.collect { alpha -> dreamViewModel.dreamOverlayAlpha.collect { alpha -> ComplicationLayoutParams.iteratePositions( ComplicationLayoutParams.iteratePositions( { position: Int -> { position: Int -> setElementsAlphaAtPosition( setElementsAlphaAtPosition( Loading @@ -120,7 +120,7 @@ constructor( } } launch { launch { dreamOverlayViewModel.transitionEnded.collect { _ -> dreamViewModel.transitionEnded.collect { _ -> mOverlayStateController.setExitAnimationsRunning(false) mOverlayStateController.setExitAnimationsRunning(false) } } } } Loading
packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamOverlayViewModel.kt→packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt +103 −0 Original line number Original line Diff line number Diff line Loading @@ -16,34 +16,62 @@ package com.android.systemui.dreams.ui.viewmodel package com.android.systemui.dreams.ui.viewmodel import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dock.DockManager import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.ui.viewmodel.DreamingToGlanceableHubTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.DreamingToGlanceableHubTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToDreamingTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToDreamingTransitionViewModel import com.android.systemui.res.R import com.android.systemui.res.R import com.android.systemui.settings.UserTracker import javax.inject.Inject import javax.inject.Inject import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.merge @OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class) @SysUISingleton @SysUISingleton class DreamOverlayViewModel class DreamViewModel @Inject @Inject constructor( constructor( configurationInteractor: ConfigurationInteractor, configurationInteractor: ConfigurationInteractor, toGlanceableHubTransitionViewModel: DreamingToGlanceableHubTransitionViewModel, keyguardTransitionInteractor: KeyguardTransitionInteractor, fromGlanceableHubTransitionInteractor: GlanceableHubToDreamingTransitionViewModel, fromGlanceableHubTransitionInteractor: GlanceableHubToDreamingTransitionViewModel, private val toGlanceableHubTransitionViewModel: DreamingToGlanceableHubTransitionViewModel, private val toLockscreenTransitionViewModel: DreamingToLockscreenTransitionViewModel, private val toLockscreenTransitionViewModel: DreamingToLockscreenTransitionViewModel, private val dockManager: DockManager, private val communalInteractor: CommunalInteractor, private val keyguardUpdateMonitor: KeyguardUpdateMonitor, private val userTracker: UserTracker, ) { ) { fun startTransitionFromDream() { val showGlanceableHub = dockManager.isDocked && communalInteractor.isCommunalEnabled.value && !keyguardUpdateMonitor.isEncryptedOrLockdown(userTracker.userId) if (showGlanceableHub) { toGlanceableHubTransitionViewModel.startTransition() communalInteractor.onSceneChanged(CommunalScenes.Communal) } else { toLockscreenTransitionViewModel.startTransition() } } val dreamOverlayTranslationX: Flow<Float> = val dreamOverlayTranslationX: Flow<Float> = merge( merge( toGlanceableHubTransitionViewModel.dreamOverlayTranslationX, toGlanceableHubTransitionViewModel.dreamOverlayTranslationX, fromGlanceableHubTransitionInteractor.dreamOverlayTranslationX, fromGlanceableHubTransitionInteractor.dreamOverlayTranslationX, ) ) .distinctUntilChanged() val dreamOverlayTranslationY: Flow<Float> = val dreamOverlayTranslationY: Flow<Float> = configurationInteractor configurationInteractor Loading @@ -52,12 +80,24 @@ constructor( toLockscreenTransitionViewModel.dreamOverlayTranslationY(px) toLockscreenTransitionViewModel.dreamOverlayTranslationY(px) } } val dreamAlpha: Flow<Float> = merge( toLockscreenTransitionViewModel.dreamOverlayAlpha, toGlanceableHubTransitionViewModel.dreamAlpha, ) .distinctUntilChanged() val dreamOverlayAlpha: Flow<Float> = val dreamOverlayAlpha: Flow<Float> = merge( merge( toLockscreenTransitionViewModel.dreamOverlayAlpha, toLockscreenTransitionViewModel.dreamOverlayAlpha, toGlanceableHubTransitionViewModel.dreamOverlayAlpha, toGlanceableHubTransitionViewModel.dreamOverlayAlpha, fromGlanceableHubTransitionInteractor.dreamOverlayAlpha, fromGlanceableHubTransitionInteractor.dreamOverlayAlpha, ) ) .distinctUntilChanged() val transitionEnded = toLockscreenTransitionViewModel.transitionEnded val transitionEnded = keyguardTransitionInteractor.fromDreamingTransition.filter { step -> step.transitionState == TransitionState.FINISHED || step.transitionState == TransitionState.CANCELED } } }