1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.scene.data.repository
18 
19 import com.android.compose.animation.scene.ObservableTransitionState
20 import com.android.compose.animation.scene.SceneKey
21 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
22 import com.android.systemui.keyguard.shared.model.KeyguardState
23 import com.android.systemui.keyguard.shared.model.TransitionStep
24 import com.android.systemui.kosmos.Kosmos
25 import com.android.systemui.kosmos.testScope
26 import com.android.systemui.scene.shared.flag.SceneContainerFlag
27 import com.android.systemui.scene.shared.model.Scenes
28 import kotlinx.coroutines.flow.Flow
29 import kotlinx.coroutines.flow.MutableStateFlow
30 import kotlinx.coroutines.flow.flowOf
31 import kotlinx.coroutines.test.TestScope
32 
33 private val mutableTransitionState =
34     MutableStateFlow<ObservableTransitionState>(ObservableTransitionState.Idle(Scenes.Lockscreen))
35 
setTransitionnull36 suspend fun Kosmos.setTransition(
37     sceneTransition: ObservableTransitionState,
38     stateTransition: TransitionStep? = null,
39     fillInStateSteps: Boolean = true,
40     scope: TestScope = testScope,
41     repository: SceneContainerRepository = sceneContainerRepository
42 ) {
43     var state: TransitionStep? = stateTransition
44     if (SceneContainerFlag.isEnabled) {
45         setSceneTransition(sceneTransition, scope, repository)
46 
47         if (state != null) {
48             state = getStateWithUndefined(sceneTransition, state)
49         }
50     }
51 
52     if (state == null) return
53     fakeKeyguardTransitionRepository.sendTransitionSteps(
54         step = state,
55         testScope = scope,
56         fillInSteps = fillInStateSteps,
57     )
58     scope.testScheduler.runCurrent()
59 }
60 
setSceneTransitionnull61 fun Kosmos.setSceneTransition(
62     transition: ObservableTransitionState,
63     scope: TestScope = testScope,
64     repository: SceneContainerRepository = sceneContainerRepository
65 ) {
66     repository.setTransitionState(mutableTransitionState)
67     mutableTransitionState.value = transition
68     scope.testScheduler.runCurrent()
69 }
70 
Transitionnull71 fun Transition(
72     from: SceneKey,
73     to: SceneKey,
74     currentScene: Flow<SceneKey> = flowOf(to),
75     progress: Flow<Float> = flowOf(0f),
76     isInitiatedByUserInput: Boolean = false,
77     isUserInputOngoing: Flow<Boolean> = flowOf(false),
78     previewProgress: Flow<Float> = flowOf(0f),
79     isInPreviewStage: Flow<Boolean> = flowOf(false)
80 ): ObservableTransitionState.Transition {
81     return ObservableTransitionState.Transition(
82         fromScene = from,
83         toScene = to,
84         currentScene = currentScene,
85         progress = progress,
86         isInitiatedByUserInput = isInitiatedByUserInput,
87         isUserInputOngoing = isUserInputOngoing,
88         previewProgress = previewProgress,
89         isInPreviewStage = isInPreviewStage
90     )
91 }
92 
Idlenull93 fun Idle(currentScene: SceneKey): ObservableTransitionState.Idle {
94     return ObservableTransitionState.Idle(currentScene)
95 }
96 
getStateWithUndefinednull97 private fun getStateWithUndefined(
98     sceneTransition: ObservableTransitionState,
99     state: TransitionStep
100 ): TransitionStep {
101     return when (sceneTransition) {
102         is ObservableTransitionState.Idle -> {
103             TransitionStep(
104                 from = state.from,
105                 to =
106                     if (sceneTransition.currentScene != Scenes.Lockscreen) {
107                         KeyguardState.UNDEFINED
108                     } else {
109                         state.to
110                     },
111                 value = state.value,
112                 transitionState = state.transitionState
113             )
114         }
115         is ObservableTransitionState.Transition -> {
116             TransitionStep(
117                 from =
118                     if (sceneTransition.fromContent != Scenes.Lockscreen) {
119                         KeyguardState.UNDEFINED
120                     } else {
121                         state.from
122                     },
123                 to =
124                     if (sceneTransition.toContent != Scenes.Lockscreen) {
125                         KeyguardState.UNDEFINED
126                     } else {
127                         state.from
128                     },
129                 value = state.value,
130                 transitionState = state.transitionState
131             )
132         }
133         else -> state
134     }
135 }
136