• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.shared.model
18 
19 import com.android.compose.animation.scene.OverlayKey
20 import com.android.compose.animation.scene.SceneKey
21 import com.android.compose.animation.scene.TransitionKey
22 import com.android.systemui.kosmos.currentValue
23 import kotlinx.coroutines.flow.MutableStateFlow
24 import kotlinx.coroutines.flow.StateFlow
25 import kotlinx.coroutines.flow.asStateFlow
26 import kotlinx.coroutines.test.TestScope
27 
28 class FakeSceneDataSource(initialSceneKey: SceneKey, val testScope: TestScope) : SceneDataSource {
29 
30     private val _currentScene = MutableStateFlow(initialSceneKey)
31     override val currentScene: StateFlow<SceneKey> = _currentScene.asStateFlow()
32 
33     private val _currentOverlays = MutableStateFlow<Set<OverlayKey>>(emptySet())
34     override val currentOverlays: StateFlow<Set<OverlayKey>> = _currentOverlays.asStateFlow()
35 
36     private var _isPaused = false
37     val isPaused
<lambda>null38         get() = testScope.currentValue { _isPaused }
39 
40     private var _pendingScene: SceneKey? = null
41     val pendingScene
<lambda>null42         get() = testScope.currentValue { _pendingScene }
43 
44     var pendingOverlays: Set<OverlayKey>? = null
45         private set
46 
47     var freezeAndAnimateToCurrentStateCallCount = 0
48 
changeScenenull49     override fun changeScene(toScene: SceneKey, transitionKey: TransitionKey?) {
50         if (_isPaused) {
51             _pendingScene = toScene
52         } else {
53             _currentScene.value = toScene
54         }
55     }
56 
snapToScenenull57     override fun snapToScene(toScene: SceneKey) {
58         changeScene(toScene)
59     }
60 
showOverlaynull61     override fun showOverlay(overlay: OverlayKey, transitionKey: TransitionKey?) {
62         if (_isPaused) {
63             pendingOverlays = (pendingOverlays ?: currentOverlays.value) + overlay
64         } else {
65             _currentOverlays.value += overlay
66         }
67     }
68 
hideOverlaynull69     override fun hideOverlay(overlay: OverlayKey, transitionKey: TransitionKey?) {
70         if (_isPaused) {
71             pendingOverlays = (pendingOverlays ?: currentOverlays.value) - overlay
72         } else {
73             _currentOverlays.value -= overlay
74         }
75     }
76 
replaceOverlaynull77     override fun replaceOverlay(from: OverlayKey, to: OverlayKey, transitionKey: TransitionKey?) {
78         hideOverlay(from, transitionKey)
79         showOverlay(to, transitionKey)
80     }
81 
instantlyShowOverlaynull82     override fun instantlyShowOverlay(overlay: OverlayKey) {
83         showOverlay(overlay)
84     }
85 
instantlyHideOverlaynull86     override fun instantlyHideOverlay(overlay: OverlayKey) {
87         hideOverlay(overlay)
88     }
89 
freezeAndAnimateToCurrentStatenull90     override fun freezeAndAnimateToCurrentState() {
91         freezeAndAnimateToCurrentStateCallCount++
92     }
93 
94     /**
95      * Pauses scene and overlay changes.
96      *
97      * Any following calls to [changeScene] or overlay changing functions will be conflated and the
98      * last one will be remembered.
99      */
pausenull100     fun pause() {
101         check(!_isPaused) { "Can't pause what's already paused!" }
102 
103         _isPaused = true
104     }
105 
106     /**
107      * Unpauses scene and overlay changes.
108      *
109      * If there were any calls to [changeScene] since [pause] was called, the latest of the bunch
110      * will be replayed.
111      *
112      * If there were any calls to show, hide or replace overlays since [pause] was called, they will
113      * all be applied at once.
114      *
115      * If [force] is `true`, there will be no check that [isPaused] is true.
116      *
117      * If [expectedScene] is provided, will assert that it's indeed the latest called.
118      *
119      * If [expectedOverlays] is provided, will assert they are indeed present.
120      */
unpausenull121     fun unpause(
122         force: Boolean = false,
123         expectedScene: SceneKey? = null,
124         expectedOverlays: Set<OverlayKey>? = null,
125     ) {
126         check(force || _isPaused) { "Can't unpause what's already not paused!" }
127 
128         _isPaused = false
129         _pendingScene?.let { _currentScene.value = it }
130         _pendingScene = null
131         pendingOverlays?.let { _currentOverlays.value = it }
132         pendingOverlays = null
133 
134         check(expectedScene == null || currentScene.value == expectedScene) {
135             """
136                 Unexpected scene while unpausing.
137                 Expected $expectedScene but was ${currentScene.value}.
138             """
139                 .trimIndent()
140         }
141         check(expectedOverlays == null || expectedOverlays == currentOverlays.value) {
142             "Expected $expectedOverlays, but instead found overlays ${currentOverlays.value}."
143         }
144     }
145 }
146