• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 
18 package com.android.systemui.keyguard.domain.interactor
19 
20 import androidx.test.ext.junit.runners.AndroidJUnit4
21 import androidx.test.filters.SmallTest
22 import com.android.systemui.SysuiTestCase
23 import com.android.systemui.coroutines.collectValues
24 import com.android.systemui.flags.DisableSceneContainer
25 import com.android.systemui.flags.EnableSceneContainer
26 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
27 import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
28 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
29 import com.android.systemui.keyguard.shared.model.Edge
30 import com.android.systemui.keyguard.shared.model.KeyguardState
31 import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
32 import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING
33 import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
34 import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
35 import com.android.systemui.keyguard.shared.model.KeyguardState.OFF
36 import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
37 import com.android.systemui.keyguard.shared.model.KeyguardState.UNDEFINED
38 import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
39 import com.android.systemui.keyguard.shared.model.TransitionState.CANCELED
40 import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED
41 import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
42 import com.android.systemui.keyguard.shared.model.TransitionState.STARTED
43 import com.android.systemui.keyguard.shared.model.TransitionStep
44 import com.android.systemui.kosmos.testScope
45 import com.android.systemui.scene.data.repository.HideOverlay
46 import com.android.systemui.scene.data.repository.Idle
47 import com.android.systemui.scene.data.repository.ShowOverlay
48 import com.android.systemui.scene.data.repository.Transition
49 import com.android.systemui.scene.data.repository.setSceneTransition
50 import com.android.systemui.scene.domain.interactor.sceneInteractor
51 import com.android.systemui.scene.shared.model.Overlays
52 import com.android.systemui.scene.shared.model.Scenes
53 import com.android.systemui.testKosmos
54 import com.google.common.truth.Truth.assertThat
55 import junit.framework.Assert.assertEquals
56 import kotlinx.coroutines.ExperimentalCoroutinesApi
57 import kotlinx.coroutines.flow.MutableSharedFlow
58 import kotlinx.coroutines.test.runCurrent
59 import kotlinx.coroutines.test.runTest
60 import org.junit.Assert.assertThrows
61 import org.junit.Before
62 import org.junit.Test
63 import org.junit.runner.RunWith
64 
65 @OptIn(ExperimentalCoroutinesApi::class)
66 @SmallTest
67 @RunWith(AndroidJUnit4::class)
68 class KeyguardTransitionInteractorTest : SysuiTestCase() {
69 
70     private val kosmos = testKosmos()
71     private val testScope = kosmos.testScope
72 
73     private lateinit var repository: FakeKeyguardTransitionRepository
74     private lateinit var underTest: KeyguardTransitionInteractor
75 
76     @Before
setupnull77     fun setup() {
78         repository = kosmos.fakeKeyguardTransitionRepository
79         underTest = kosmos.keyguardTransitionInteractor
80     }
81 
82     @Test
transitionCollectorsReceivesOnlyAppropriateEventsnull83     fun transitionCollectorsReceivesOnlyAppropriateEvents() =
84         testScope.runTest {
85             val lockscreenToAodSteps by
86                 collectValues(underTest.transition(Edge.create(LOCKSCREEN, AOD)))
87             val aodToLockscreenSteps by
88                 collectValues(underTest.transition(Edge.create(AOD, LOCKSCREEN)))
89 
90             val steps = mutableListOf<TransitionStep>()
91             steps.add(TransitionStep(AOD, GONE, 0f, STARTED))
92             steps.add(TransitionStep(AOD, GONE, 1f, FINISHED))
93             steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED))
94             steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING))
95             steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED))
96             steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED))
97             steps.add(TransitionStep(LOCKSCREEN, AOD, 0.1f, RUNNING))
98             steps.add(TransitionStep(LOCKSCREEN, AOD, 0.2f, RUNNING))
99 
100             steps.forEach {
101                 repository.sendTransitionStep(it)
102                 runCurrent()
103             }
104 
105             assertThat(aodToLockscreenSteps).isEqualTo(steps.subList(2, 5))
106             assertThat(lockscreenToAodSteps).isEqualTo(steps.subList(5, 8))
107         }
108 
109     @Test
startedKeyguardTransitionStepTestsnull110     fun startedKeyguardTransitionStepTests() =
111         testScope.runTest {
112             val startedSteps by collectValues(underTest.startedKeyguardTransitionStep)
113 
114             val steps = mutableListOf<TransitionStep>()
115 
116             steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED))
117             steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING))
118             steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED))
119             steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED))
120             steps.add(TransitionStep(LOCKSCREEN, AOD, 0.9f, RUNNING))
121             steps.add(TransitionStep(LOCKSCREEN, AOD, 1f, FINISHED))
122             steps.add(TransitionStep(AOD, GONE, 1f, STARTED))
123 
124             steps.forEach {
125                 repository.sendTransitionStep(it)
126                 runCurrent()
127             }
128 
129             assertThat(startedSteps)
130                 .isEqualTo(
131                     listOf(
132                         // The initial transition will also get sent when collect started
133                         TransitionStep(
134                             OFF,
135                             LOCKSCREEN,
136                             0f,
137                             STARTED,
138                             ownerName = "KeyguardTransitionRepository(boot)",
139                         ),
140                         steps[0],
141                         steps[3],
142                         steps[6],
143                     )
144                 )
145         }
146 
147     @Test
transitionValuenull148     fun transitionValue() =
149         testScope.runTest {
150             resetTransitionValueReplayCache(setOf(AOD, DOZING, LOCKSCREEN))
151             val transitionValues by collectValues(underTest.transitionValue(state = DOZING))
152 
153             val toSteps =
154                 listOf(
155                     TransitionStep(AOD, DOZING, 0f, STARTED),
156                     TransitionStep(AOD, DOZING, 0.5f, RUNNING),
157                     TransitionStep(AOD, DOZING, 1f, FINISHED),
158                 )
159             toSteps.forEach {
160                 repository.sendTransitionStep(it)
161                 runCurrent()
162             }
163 
164             val fromSteps =
165                 listOf(
166                     TransitionStep(DOZING, LOCKSCREEN, 0f, STARTED),
167                     TransitionStep(DOZING, LOCKSCREEN, 0.5f, RUNNING),
168                     TransitionStep(DOZING, LOCKSCREEN, 1f, FINISHED),
169                 )
170             fromSteps.forEach {
171                 repository.sendTransitionStep(it)
172                 runCurrent()
173             }
174 
175             assertThat(transitionValues).isEqualTo(listOf(0f, 0.5f, 1f, 1f, 0.5f, 0f))
176         }
177 
178     @Test
transitionValue_badTransitionResetsTransitionValuenull179     fun transitionValue_badTransitionResetsTransitionValue() =
180         testScope.runTest {
181             resetTransitionValueReplayCache(setOf(AOD, DOZING, LOCKSCREEN))
182             val transitionValues by collectValues(underTest.transitionValue(state = DOZING))
183 
184             val toSteps =
185                 listOf(
186                     TransitionStep(AOD, DOZING, 0f, STARTED),
187                     TransitionStep(AOD, DOZING, 0.5f, RUNNING),
188                 )
189             toSteps.forEach {
190                 repository.sendTransitionStep(it)
191                 runCurrent()
192             }
193 
194             // This is an intentionally bad sequence that will leave the transitionValue for
195             // DOZING in a bad place, since no CANCELED will be issued for DOZING
196             val fromSteps =
197                 listOf(
198                     TransitionStep(AOD, LOCKSCREEN, 0f, STARTED),
199                     TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING),
200                     TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED),
201                 )
202             fromSteps.forEach {
203                 repository.sendTransitionStep(it)
204                 runCurrent()
205             }
206 
207             assertThat(transitionValues).isEqualTo(listOf(0f, 0.5f, 0f))
208         }
209 
210     @Test
transitionValue_canceled_toAnotherStatenull211     fun transitionValue_canceled_toAnotherState() =
212         testScope.runTest {
213             resetTransitionValueReplayCache(setOf(AOD, GONE, LOCKSCREEN))
214 
215             val transitionValuesGone by collectValues(underTest.transitionValue(state = GONE))
216             val transitionValuesAod by collectValues(underTest.transitionValue(state = AOD))
217             val transitionValuesLs by collectValues(underTest.transitionValue(state = LOCKSCREEN))
218 
219             listOf(
220                     TransitionStep(GONE, AOD, 0f, STARTED),
221                     TransitionStep(GONE, AOD, 0.5f, RUNNING),
222                     TransitionStep(GONE, AOD, 0.5f, CANCELED),
223                     TransitionStep(AOD, LOCKSCREEN, 0.5f, STARTED),
224                     TransitionStep(AOD, LOCKSCREEN, 0.7f, RUNNING),
225                     TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED),
226                 )
227                 .forEach {
228                     repository.sendTransitionStep(it)
229                     runCurrent()
230                 }
231 
232             assertThat(transitionValuesGone).isEqualTo(listOf(1f, 0.5f, 0f))
233             assertThat(transitionValuesAod).isEqualTo(listOf(0f, 0.5f, 0.5f, 0.3f, 0f))
234             assertThat(transitionValuesLs).isEqualTo(listOf(0.5f, 0.7f, 1f))
235         }
236 
237     @Test
transitionValue_canceled_backToOriginalStatenull238     fun transitionValue_canceled_backToOriginalState() =
239         testScope.runTest {
240             resetTransitionValueReplayCache(setOf(AOD, GONE))
241 
242             val transitionValuesGone by collectValues(underTest.transitionValue(state = GONE))
243             val transitionValuesAod by collectValues(underTest.transitionValue(state = AOD))
244 
245             listOf(
246                     TransitionStep(GONE, AOD, 0f, STARTED),
247                     TransitionStep(GONE, AOD, 0.5f, RUNNING),
248                     TransitionStep(GONE, AOD, 1f, CANCELED),
249                     TransitionStep(AOD, GONE, 0.5f, STARTED),
250                     TransitionStep(AOD, GONE, 0.7f, RUNNING),
251                     TransitionStep(AOD, GONE, 1f, FINISHED),
252                 )
253                 .forEach {
254                     repository.sendTransitionStep(it)
255                     runCurrent()
256                 }
257 
258             assertThat(transitionValuesGone).isEqualTo(listOf(1f, 0.5f, 0.5f, 0.7f, 1f))
259             assertThat(transitionValuesAod).isEqualTo(listOf(0f, 0.5f, 0.5f, 0.3f, 0f))
260         }
261 
262     @Test
isInTransitionToAnyStatenull263     fun isInTransitionToAnyState() =
264         testScope.runTest {
265             val inTransition by collectValues(underTest.isInTransition)
266 
267             assertEquals(
268                 listOf(
269                     false,
270                     true, // The repo is seeded with a transition from OFF to LOCKSCREEN.
271                     false,
272                 ),
273                 inTransition,
274             )
275 
276             sendSteps(TransitionStep(LOCKSCREEN, GONE, 0f, STARTED))
277 
278             assertEquals(listOf(false, true, false, true), inTransition)
279 
280             sendSteps(TransitionStep(LOCKSCREEN, GONE, 0.5f, RUNNING))
281 
282             assertEquals(listOf(false, true, false, true), inTransition)
283 
284             sendSteps(TransitionStep(LOCKSCREEN, GONE, 1f, FINISHED))
285 
286             assertEquals(listOf(false, true, false, true, false), inTransition)
287         }
288 
289     @Test
290     @EnableSceneContainer
isInTransition_withScenenull291     fun isInTransition_withScene() =
292         testScope.runTest {
293             val inTransition by collectValues(underTest.isInTransition)
294 
295             assertEquals(
296                 listOf(
297                     false,
298                     true, // The repo is seeded with a transition from OFF to LOCKSCREEN.
299                     false,
300                 ),
301                 inTransition,
302             )
303 
304             kosmos.setSceneTransition(
305                 ShowOverlay(overlay = Overlays.Bouncer, fromScene = Scenes.Gone)
306             )
307 
308             assertEquals(listOf(false, true, false, true), inTransition)
309 
310             kosmos.setSceneTransition(Idle(Scenes.Lockscreen, setOf(Overlays.Bouncer)))
311 
312             assertEquals(listOf(false, true, false, true, false), inTransition)
313         }
314 
315     @Test
isInTransitionToAnyState_finishedStateIsStartedStateAfterCancelsnull316     fun isInTransitionToAnyState_finishedStateIsStartedStateAfterCancels() =
317         testScope.runTest {
318             val inTransition by collectValues(underTest.isInTransition)
319 
320             assertEquals(listOf(false, true, false), inTransition)
321 
322             // Start FINISHED in GONE.
323             sendSteps(
324                 TransitionStep(LOCKSCREEN, GONE, 0f, STARTED),
325                 TransitionStep(LOCKSCREEN, GONE, 0.5f, RUNNING),
326                 TransitionStep(LOCKSCREEN, GONE, 1f, FINISHED),
327             )
328 
329             assertEquals(listOf(false, true, false, true, false), inTransition)
330 
331             sendSteps(TransitionStep(GONE, DOZING, 0f, STARTED))
332 
333             assertEquals(listOf(false, true, false, true, false, true), inTransition)
334 
335             sendSteps(
336                 TransitionStep(GONE, DOZING, 0.5f, RUNNING),
337                 TransitionStep(GONE, DOZING, 0.6f, CANCELED),
338                 TransitionStep(DOZING, LOCKSCREEN, 0f, STARTED),
339                 TransitionStep(DOZING, LOCKSCREEN, 0.5f, RUNNING),
340                 TransitionStep(DOZING, LOCKSCREEN, 0.6f, CANCELED),
341                 TransitionStep(LOCKSCREEN, GONE, 0f, STARTED),
342             )
343 
344             assertEquals(
345                 listOf(
346                     false,
347                     true,
348                     false,
349                     true,
350                     false,
351                     // We should have been in transition throughout the entire transition, including
352                     // both cancellations, and we should still be in transition despite now
353                     // transitioning to GONE, the state we're also FINISHED in.
354                     true,
355                 ),
356                 inTransition,
357             )
358 
359             sendSteps(
360                 TransitionStep(LOCKSCREEN, GONE, 0.5f, RUNNING),
361                 TransitionStep(LOCKSCREEN, GONE, 1f, FINISHED),
362             )
363 
364             assertEquals(listOf(false, true, false, true, false, true, false), inTransition)
365         }
366 
367     @Test
368     @DisableSceneContainer
isInTransitionToStatenull369     fun isInTransitionToState() =
370         testScope.runTest {
371             val results by
372                 collectValues(
373                     underTest.isInTransition(
374                         edge = Edge.create(OFF, OFF),
375                         edgeWithoutSceneContainer = Edge.create(to = LOCKSCREEN),
376                     )
377                 )
378 
379             sendSteps(
380                 TransitionStep(AOD, DOZING, 0f, STARTED),
381                 TransitionStep(AOD, DOZING, 0.5f, RUNNING),
382                 TransitionStep(AOD, DOZING, 1f, FINISHED),
383             )
384 
385             assertThat(results).isEqualTo(listOf(false))
386 
387             sendSteps(TransitionStep(DOZING, LOCKSCREEN, 0f, STARTED))
388 
389             assertThat(results).isEqualTo(listOf(false, true))
390 
391             sendSteps(TransitionStep(DOZING, LOCKSCREEN, 0f, RUNNING))
392 
393             assertThat(results).isEqualTo(listOf(false, true))
394 
395             sendSteps(TransitionStep(DOZING, LOCKSCREEN, 0f, FINISHED))
396 
397             assertThat(results).isEqualTo(listOf(false, true, false))
398 
399             sendSteps(
400                 TransitionStep(LOCKSCREEN, DOZING, 0f, STARTED),
401                 TransitionStep(LOCKSCREEN, DOZING, 0f, RUNNING),
402                 TransitionStep(LOCKSCREEN, DOZING, 1f, FINISHED),
403             )
404 
405             assertThat(results).isEqualTo(listOf(false, true, false))
406 
407             sendSteps(
408                 TransitionStep(DOZING, LOCKSCREEN, 0f, STARTED),
409                 TransitionStep(DOZING, LOCKSCREEN, 0f, RUNNING),
410             )
411 
412             assertThat(results).isEqualTo(listOf(false, true, false, true))
413         }
414 
415     @Test
416     @EnableSceneContainer
isInTransitionFromScenenull417     fun isInTransitionFromScene() =
418         testScope.runTest {
419             val results by
420                 collectValues(underTest.isInTransition(edge = Edge.create(Scenes.Lockscreen, null)))
421 
422             kosmos.setSceneTransition(Transition(from = Scenes.Gone, to = Scenes.Lockscreen))
423             kosmos.setSceneTransition(Idle(Scenes.Lockscreen))
424 
425             assertThat(results).isEqualTo(listOf(false))
426 
427             kosmos.setSceneTransition(Transition(from = Scenes.Lockscreen, to = Scenes.Shade))
428 
429             assertThat(results).isEqualTo(listOf(false, true))
430 
431             kosmos.setSceneTransition(Idle(Scenes.Shade))
432 
433             assertThat(results).isEqualTo(listOf(false, true, false))
434         }
435 
436     @Test
437     @EnableSceneContainer
isInTransitionToScenenull438     fun isInTransitionToScene() =
439         testScope.runTest {
440             val results by
441                 collectValues(underTest.isInTransition(edge = Edge.create(null, Scenes.Lockscreen)))
442 
443             kosmos.setSceneTransition(Transition(from = Scenes.Gone, to = Scenes.Lockscreen))
444             kosmos.setSceneTransition(Idle(Scenes.Lockscreen))
445             kosmos.setSceneTransition(Transition(from = Scenes.Lockscreen, to = Scenes.Gone))
446 
447             assertThat(results).isEqualTo(listOf(false, true, false))
448         }
449 
450     @Test
451     @EnableSceneContainer
isInTransitionStateToScenenull452     fun isInTransitionStateToScene() =
453         testScope.runTest {
454             val results by
455                 collectValues(underTest.isInTransition(edge = Edge.create(AOD, Scenes.Gone)))
456 
457             kosmos.setSceneTransition(Transition(from = Scenes.Lockscreen, to = Scenes.Gone))
458 
459             sendSteps(
460                 TransitionStep(AOD, UNDEFINED, 0f, STARTED),
461                 TransitionStep(AOD, UNDEFINED, 0.5f, RUNNING),
462                 TransitionStep(AOD, UNDEFINED, 1f, FINISHED),
463             )
464 
465             kosmos.setSceneTransition(Idle(Scenes.Gone))
466 
467             assertThat(results).isEqualTo(listOf(false, true, false))
468         }
469 
470     @Test
isInTransitionFromStatenull471     fun isInTransitionFromState() =
472         testScope.runTest {
473             val results by collectValues(underTest.isInTransition(Edge.create(from = DOZING)))
474 
475             sendSteps(
476                 TransitionStep(AOD, DOZING, 0f, STARTED),
477                 TransitionStep(AOD, DOZING, 0.5f, RUNNING),
478                 TransitionStep(AOD, DOZING, 1f, FINISHED),
479             )
480 
481             assertThat(results).isEqualTo(listOf(false))
482 
483             sendSteps(TransitionStep(DOZING, LOCKSCREEN, 0f, STARTED))
484 
485             assertThat(results).isEqualTo(listOf(false, true))
486 
487             sendSteps(TransitionStep(DOZING, LOCKSCREEN, 0f, RUNNING))
488 
489             assertThat(results).isEqualTo(listOf(false, true))
490 
491             sendSteps(TransitionStep(DOZING, LOCKSCREEN, 0f, FINISHED))
492 
493             assertThat(results).isEqualTo(listOf(false, true, false))
494 
495             sendSteps(
496                 TransitionStep(LOCKSCREEN, DOZING, 0f, STARTED),
497                 TransitionStep(LOCKSCREEN, DOZING, 0f, RUNNING),
498                 TransitionStep(LOCKSCREEN, DOZING, 1f, FINISHED),
499             )
500 
501             assertThat(results).isEqualTo(listOf(false, true, false))
502 
503             sendSteps(
504                 TransitionStep(DOZING, LOCKSCREEN, 0f, STARTED),
505                 TransitionStep(DOZING, LOCKSCREEN, 0f, RUNNING),
506             )
507 
508             assertThat(results).isEqualTo(listOf(false, true, false, true))
509         }
510 
511     @Test
isInTransitionWherenull512     fun isInTransitionWhere() =
513         testScope.runTest {
514             val results by
515                 collectValues(
516                     underTest.isInTransitionWhere(
517                         fromStatePredicate = { it == DOZING },
518                         toStatePredicate = { it == GONE },
519                     )
520                 )
521 
522             sendSteps(
523                 TransitionStep(AOD, DOZING, 0f, STARTED),
524                 TransitionStep(AOD, DOZING, 0.5f, RUNNING),
525                 TransitionStep(AOD, DOZING, 1f, FINISHED),
526             )
527 
528             assertThat(results).isEqualTo(listOf(false))
529 
530             sendSteps(TransitionStep(DOZING, GONE, 0f, STARTED))
531 
532             assertThat(results).isEqualTo(listOf(false, true))
533 
534             sendSteps(TransitionStep(DOZING, GONE, 0f, RUNNING))
535 
536             assertThat(results).isEqualTo(listOf(false, true))
537 
538             sendSteps(TransitionStep(DOZING, GONE, 0f, FINISHED))
539 
540             assertThat(results).isEqualTo(listOf(false, true, false))
541 
542             sendSteps(
543                 TransitionStep(GONE, DOZING, 0f, STARTED),
544                 TransitionStep(GONE, DOZING, 0f, RUNNING),
545                 TransitionStep(GONE, DOZING, 1f, FINISHED),
546             )
547 
548             assertThat(results).isEqualTo(listOf(false, true, false))
549 
550             sendSteps(
551                 TransitionStep(DOZING, GONE, 0f, STARTED),
552                 TransitionStep(DOZING, GONE, 0f, RUNNING),
553             )
554 
555             assertThat(results).isEqualTo(listOf(false, true, false, true))
556         }
557 
558     @Test
isInTransitionWhere_withCanceledStepnull559     fun isInTransitionWhere_withCanceledStep() =
560         testScope.runTest {
561             val results by
562                 collectValues(
563                     underTest.isInTransitionWhere(
564                         fromStatePredicate = { it == DOZING },
565                         toStatePredicate = { it == GONE },
566                     )
567                 )
568 
569             sendSteps(
570                 TransitionStep(AOD, DOZING, 0f, STARTED),
571                 TransitionStep(AOD, DOZING, 0.5f, RUNNING),
572                 TransitionStep(AOD, DOZING, 1f, FINISHED),
573             )
574 
575             assertThat(results).isEqualTo(listOf(false))
576 
577             sendSteps(TransitionStep(DOZING, GONE, 0f, STARTED))
578 
579             assertThat(results).isEqualTo(listOf(false, true))
580 
581             sendSteps(TransitionStep(DOZING, GONE, 0f, RUNNING))
582 
583             assertThat(results).isEqualTo(listOf(false, true))
584 
585             sendSteps(TransitionStep(DOZING, GONE, 0f, CANCELED))
586 
587             assertThat(results).isEqualTo(listOf(false, true))
588 
589             sendSteps(
590                 TransitionStep(GONE, DOZING, 0f, STARTED),
591                 TransitionStep(GONE, DOZING, 0f, RUNNING),
592                 TransitionStep(GONE, DOZING, 1f, FINISHED),
593             )
594 
595             assertThat(results).isEqualTo(listOf(false, true, false))
596 
597             sendSteps(
598                 TransitionStep(DOZING, GONE, 0f, STARTED),
599                 TransitionStep(DOZING, GONE, 0f, RUNNING),
600             )
601 
602             assertThat(results).isEqualTo(listOf(false, true, false, true))
603         }
604 
605     @Test
isFinishedInStateWherenull606     fun isFinishedInStateWhere() =
607         testScope.runTest {
608             val results by collectValues(underTest.isFinishedInStateWhere { it == GONE })
609 
610             sendSteps(
611                 TransitionStep(AOD, DOZING, 0f, STARTED),
612                 TransitionStep(AOD, DOZING, 0.5f, RUNNING),
613                 TransitionStep(AOD, DOZING, 1f, FINISHED),
614             )
615 
616             assertThat(results)
617                 .isEqualTo(
618                     listOf(
619                         false // Finished in DOZING, not GONE.
620                     )
621                 )
622 
623             sendSteps(TransitionStep(DOZING, GONE, 0f, STARTED))
624 
625             assertThat(results).isEqualTo(listOf(false))
626 
627             sendSteps(TransitionStep(DOZING, GONE, 0f, RUNNING))
628 
629             assertThat(results).isEqualTo(listOf(false))
630 
631             sendSteps(TransitionStep(DOZING, GONE, 1f, FINISHED))
632 
633             assertThat(results).isEqualTo(listOf(false, true))
634 
635             sendSteps(
636                 TransitionStep(GONE, DOZING, 0f, STARTED),
637                 TransitionStep(GONE, DOZING, 0f, RUNNING),
638             )
639 
640             assertThat(results).isEqualTo(listOf(false, true))
641 
642             sendSteps(TransitionStep(GONE, DOZING, 1f, FINISHED))
643 
644             assertThat(results).isEqualTo(listOf(false, true, false))
645 
646             sendSteps(
647                 TransitionStep(DOZING, GONE, 0f, STARTED),
648                 TransitionStep(DOZING, GONE, 0f, RUNNING),
649             )
650 
651             assertThat(results).isEqualTo(listOf(false, true, false))
652 
653             sendSteps(TransitionStep(DOZING, GONE, 1f, FINISHED))
654 
655             assertThat(results).isEqualTo(listOf(false, true, false, true))
656         }
657 
658     @Test
659     @DisableSceneContainer
isFinishedInStatenull660     fun isFinishedInState() =
661         testScope.runTest {
662             val results by collectValues(underTest.isFinishedIn(Scenes.Gone, GONE))
663 
664             sendSteps(
665                 TransitionStep(AOD, DOZING, 0f, STARTED),
666                 TransitionStep(AOD, DOZING, 0.5f, RUNNING),
667                 TransitionStep(AOD, DOZING, 1f, FINISHED),
668             )
669 
670             assertThat(results)
671                 .isEqualTo(
672                     listOf(
673                         false // Finished in DOZING, not GONE.
674                     )
675                 )
676 
677             sendSteps(TransitionStep(DOZING, GONE, 0f, STARTED))
678 
679             assertThat(results).isEqualTo(listOf(false))
680 
681             sendSteps(TransitionStep(DOZING, GONE, 0f, RUNNING))
682 
683             assertThat(results).isEqualTo(listOf(false))
684 
685             sendSteps(TransitionStep(DOZING, GONE, 1f, FINISHED))
686 
687             assertThat(results).isEqualTo(listOf(false, true))
688 
689             sendSteps(
690                 TransitionStep(GONE, DOZING, 0f, STARTED),
691                 TransitionStep(GONE, DOZING, 0f, RUNNING),
692             )
693 
694             assertThat(results).isEqualTo(listOf(false, true))
695 
696             sendSteps(TransitionStep(GONE, DOZING, 1f, FINISHED))
697 
698             assertThat(results).isEqualTo(listOf(false, true, false))
699 
700             sendSteps(
701                 TransitionStep(DOZING, GONE, 0f, STARTED),
702                 TransitionStep(DOZING, GONE, 0f, RUNNING),
703             )
704 
705             assertThat(results).isEqualTo(listOf(false, true, false))
706 
707             sendSteps(TransitionStep(DOZING, GONE, 1f, FINISHED))
708 
709             assertThat(results).isEqualTo(listOf(false, true, false, true))
710         }
711 
712     @Test
713     @EnableSceneContainer
isFinishedInnull714     fun isFinishedIn() =
715         testScope.runTest {
716             val results by collectValues(underTest.isFinishedIn(Scenes.Gone, GONE))
717 
718             sendSteps(
719                 TransitionStep(AOD, DOZING, 0f, STARTED),
720                 TransitionStep(AOD, DOZING, 0.5f, RUNNING),
721                 TransitionStep(AOD, DOZING, 1f, FINISHED),
722             )
723 
724             kosmos.sceneInteractor.snapToScene(Scenes.Lockscreen, "reason")
725             kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
726                 SuccessFingerprintAuthenticationStatus(0, true)
727             )
728 
729             assertThat(results)
730                 .isEqualTo(
731                     listOf(
732                         false // Finished in DOZING, not GONE.
733                     )
734                 )
735 
736             kosmos.setSceneTransition(Transition(from = Scenes.Lockscreen, to = Scenes.Gone))
737 
738             assertThat(results).isEqualTo(listOf(false))
739 
740             kosmos.sceneInteractor.changeScene(Scenes.Gone, "reason")
741             kosmos.setSceneTransition(Idle(Scenes.Gone))
742 
743             assertThat(results).isEqualTo(listOf(false, true))
744 
745             kosmos.setSceneTransition(Transition(from = Scenes.Gone, to = Scenes.Lockscreen))
746 
747             assertThat(results).isEqualTo(listOf(false, true))
748 
749             kosmos.sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
750             kosmos.setSceneTransition(Idle(Scenes.Lockscreen))
751 
752             assertThat(results).isEqualTo(listOf(false, true, false))
753 
754             kosmos.setSceneTransition(Transition(from = Scenes.Lockscreen, to = Scenes.Gone))
755 
756             assertThat(results).isEqualTo(listOf(false, true, false))
757 
758             kosmos.sceneInteractor.changeScene(Scenes.Gone, "reason")
759             kosmos.setSceneTransition(Idle(Scenes.Gone))
760 
761             assertThat(results).isEqualTo(listOf(false, true, false, true))
762         }
763 
764     @Test
testCurrentStatenull765     fun testCurrentState() =
766         testScope.runTest {
767             val currentStates by collectValues(underTest.currentKeyguardState)
768 
769             // We init the repo with a transition from OFF -> LOCKSCREEN.
770             assertEquals(listOf(OFF, LOCKSCREEN), currentStates)
771 
772             sendSteps(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED))
773 
774             // The current state should continue to be LOCKSCREEN as we transition to AOD.
775             assertEquals(listOf(OFF, LOCKSCREEN), currentStates)
776 
777             sendSteps(TransitionStep(LOCKSCREEN, AOD, 0.5f, RUNNING))
778 
779             // The current state should continue to be LOCKSCREEN as we transition to AOD.
780             assertEquals(listOf(OFF, LOCKSCREEN), currentStates)
781 
782             sendSteps(TransitionStep(LOCKSCREEN, AOD, 0.6f, CANCELED))
783 
784             // Once CANCELED, we're still currently in LOCKSCREEN...
785             assertEquals(listOf(OFF, LOCKSCREEN), currentStates)
786 
787             sendSteps(TransitionStep(AOD, LOCKSCREEN, 0.6f, STARTED))
788 
789             // ...until STARTING back to LOCKSCREEN, at which point the "current" state should be
790             // the
791             // one we're transitioning from, despite never FINISHING in that state.
792             assertEquals(listOf(OFF, LOCKSCREEN, AOD), currentStates)
793 
794             sendSteps(
795                 TransitionStep(AOD, LOCKSCREEN, 0.8f, RUNNING),
796                 TransitionStep(AOD, LOCKSCREEN, 0.8f, FINISHED),
797             )
798 
799             // FINSHING in LOCKSCREEN should update the current state to LOCKSCREEN.
800             assertEquals(listOf(OFF, LOCKSCREEN, AOD, LOCKSCREEN), currentStates)
801         }
802 
803     @Test
testCurrentState_multipleCancellations_backToLastFinishedStatenull804     fun testCurrentState_multipleCancellations_backToLastFinishedState() =
805         testScope.runTest {
806             val currentStates by collectValues(underTest.currentKeyguardState)
807 
808             // We init the repo with a transition from OFF -> LOCKSCREEN.
809             assertEquals(listOf(OFF, LOCKSCREEN), currentStates)
810 
811             sendSteps(
812                 TransitionStep(LOCKSCREEN, GONE, 0f, STARTED),
813                 TransitionStep(LOCKSCREEN, GONE, 0.5f, RUNNING),
814                 TransitionStep(LOCKSCREEN, GONE, 1f, FINISHED),
815             )
816 
817             assertEquals(
818                 listOf(
819                     // Default transition from OFF -> LOCKSCREEN
820                     OFF,
821                     LOCKSCREEN,
822                     // Transitioned to GONE
823                     GONE,
824                 ),
825                 currentStates,
826             )
827 
828             sendSteps(
829                 TransitionStep(GONE, DOZING, 0f, STARTED),
830                 TransitionStep(GONE, DOZING, 0.5f, RUNNING),
831                 TransitionStep(GONE, DOZING, 0.6f, CANCELED),
832             )
833 
834             assertEquals(
835                 listOf(
836                     OFF,
837                     LOCKSCREEN,
838                     GONE,
839                     // Current state should not be DOZING until the post-cancelation transition is
840                     // STARTED
841                 ),
842                 currentStates,
843             )
844 
845             sendSteps(TransitionStep(DOZING, LOCKSCREEN, 0f, STARTED))
846 
847             assertEquals(
848                 listOf(
849                     OFF,
850                     LOCKSCREEN,
851                     GONE,
852                     // DOZING -> LS STARTED, DOZING is now the current state.
853                     DOZING,
854                 ),
855                 currentStates,
856             )
857 
858             sendSteps(
859                 TransitionStep(DOZING, LOCKSCREEN, 0.5f, RUNNING),
860                 TransitionStep(DOZING, LOCKSCREEN, 0.6f, CANCELED),
861             )
862 
863             assertEquals(listOf(OFF, LOCKSCREEN, GONE, DOZING), currentStates)
864 
865             sendSteps(TransitionStep(LOCKSCREEN, GONE, 0f, STARTED))
866 
867             assertEquals(
868                 listOf(
869                     OFF,
870                     LOCKSCREEN,
871                     GONE,
872                     DOZING,
873                     // LS -> GONE STARTED, LS is now the current state.
874                     LOCKSCREEN,
875                 ),
876                 currentStates,
877             )
878 
879             sendSteps(
880                 TransitionStep(LOCKSCREEN, GONE, 0.5f, RUNNING),
881                 TransitionStep(LOCKSCREEN, GONE, 1f, FINISHED),
882             )
883 
884             assertEquals(
885                 listOf(
886                     OFF,
887                     LOCKSCREEN,
888                     GONE,
889                     DOZING,
890                     LOCKSCREEN,
891                     // FINISHED in GONE, GONE is now the current state.
892                     GONE,
893                 ),
894                 currentStates,
895             )
896         }
897 
898     @Test
899     @DisableSceneContainer
transition_no_conversion_with_flag_offnull900     fun transition_no_conversion_with_flag_off() =
901         testScope.runTest {
902             val currentStates by
903                 collectValues(underTest.transition(Edge.create(PRIMARY_BOUNCER, GONE)))
904 
905             val sendStep1 = TransitionStep(PRIMARY_BOUNCER, GONE, 0f, STARTED)
906             sendSteps(sendStep1)
907 
908             assertEquals(listOf(sendStep1), currentStates)
909         }
910 
911     @Test
912     @EnableSceneContainer
transition_conversion_with_flag_onnull913     fun transition_conversion_with_flag_on() =
914         testScope.runTest {
915             val currentStates by
916                 collectValues(underTest.transition(Edge.create(PRIMARY_BOUNCER, GONE)))
917 
918             val sendStep1 = TransitionStep(PRIMARY_BOUNCER, GONE, 0f, STARTED)
919             sendSteps(sendStep1)
920 
921             assertEquals(listOf<TransitionStep>(), currentStates)
922         }
923 
924     @Test
925     @EnableSceneContainer
transition_conversion_emits_values_with_sceneContainer_in_correct_statenull926     fun transition_conversion_emits_values_with_sceneContainer_in_correct_state() =
927         testScope.runTest {
928             val currentStates by collectValues(underTest.transition(Edge.create(LOCKSCREEN, GONE)))
929             val currentStatesConverted by
930                 collectValues(underTest.transition(Edge.create(LOCKSCREEN, UNDEFINED)))
931 
932             kosmos.setSceneTransition(Transition(Scenes.Lockscreen, Scenes.Gone))
933             val sendStep1 = TransitionStep(LOCKSCREEN, UNDEFINED, 0f, STARTED)
934             sendSteps(sendStep1)
935             kosmos.setSceneTransition(Idle(Scenes.Gone))
936             val sendStep2 = TransitionStep(LOCKSCREEN, UNDEFINED, 1f, FINISHED)
937             val sendStep3 = TransitionStep(LOCKSCREEN, AOD, 0f, STARTED)
938             sendSteps(sendStep2, sendStep3)
939 
940             assertEquals(listOf(sendStep1, sendStep2), currentStates)
941             assertEquals(listOf(sendStep1, sendStep2), currentStatesConverted)
942         }
943 
944     @Test
945     @EnableSceneContainer
transition_conversion_emits_nothing_with_sceneContainer_in_wrong_statenull946     fun transition_conversion_emits_nothing_with_sceneContainer_in_wrong_state() =
947         testScope.runTest {
948             val currentStates by collectValues(underTest.transition(Edge.create(LOCKSCREEN, GONE)))
949 
950             kosmos.setSceneTransition(Transition(Scenes.Gone, Scenes.Lockscreen))
951             val sendStep1 = TransitionStep(LOCKSCREEN, UNDEFINED, 0f, STARTED)
952             kosmos.setSceneTransition(Idle(Scenes.Lockscreen))
953             val sendStep2 = TransitionStep(LOCKSCREEN, UNDEFINED, 1f, FINISHED)
954             val sendStep3 = TransitionStep(LOCKSCREEN, AOD, 0f, STARTED)
955             sendSteps(sendStep1, sendStep2, sendStep3)
956 
957             assertEquals(listOf<TransitionStep>(), currentStates)
958         }
959 
960     @Test
961     @EnableSceneContainer
transition_conversion_emits_values_when_edge_within_lockscreen_scenenull962     fun transition_conversion_emits_values_when_edge_within_lockscreen_scene() =
963         testScope.runTest {
964             val currentStates by
965                 collectValues(underTest.transition(Edge.create(LOCKSCREEN, DOZING)))
966 
967             kosmos.setSceneTransition(Transition(Scenes.Gone, Scenes.Lockscreen))
968             val sendStep1 = TransitionStep(LOCKSCREEN, DOZING, 0f, STARTED)
969             kosmos.setSceneTransition(Idle(Scenes.Lockscreen))
970             val sendStep2 = TransitionStep(LOCKSCREEN, DOZING, 1f, FINISHED)
971             val sendStep3 = TransitionStep(LOCKSCREEN, AOD, 0f, STARTED)
972             sendSteps(sendStep1, sendStep2, sendStep3)
973 
974             assertEquals(listOf(sendStep1, sendStep2), currentStates)
975         }
976 
977     @Test
978     @EnableSceneContainer
transition_conversion_emits_values_with_null_edge_within_lockscreen_scenenull979     fun transition_conversion_emits_values_with_null_edge_within_lockscreen_scene() =
980         testScope.runTest {
981             val currentStates by collectValues(underTest.transition(Edge.create(LOCKSCREEN, null)))
982             val currentStatesReversed by
983                 collectValues(underTest.transition(Edge.create(null, LOCKSCREEN)))
984 
985             kosmos.setSceneTransition(Transition(Scenes.Gone, Scenes.Lockscreen))
986             val sendStep1 = TransitionStep(LOCKSCREEN, DOZING, 0f, STARTED)
987             kosmos.setSceneTransition(Idle(Scenes.Lockscreen))
988             val sendStep2 = TransitionStep(LOCKSCREEN, DOZING, 1f, FINISHED)
989             val sendStep3 = TransitionStep(LOCKSCREEN, AOD, 0f, STARTED)
990             val sendStep4 = TransitionStep(AOD, LOCKSCREEN, 0f, STARTED)
991             sendSteps(sendStep1, sendStep2, sendStep3, sendStep4)
992 
993             assertEquals(listOf(sendStep1, sendStep2, sendStep3), currentStates)
994             assertEquals(listOf(sendStep4), currentStatesReversed)
995         }
996 
997     @Test
998     @EnableSceneContainer
transition_conversion_emits_values_with_null_edge_out_of_lockscreen_scenenull999     fun transition_conversion_emits_values_with_null_edge_out_of_lockscreen_scene() =
1000         testScope.runTest {
1001             val currentStates by collectValues(underTest.transition(Edge.create(null, UNDEFINED)))
1002             val currentStatesMapped by collectValues(underTest.transition(Edge.create(null, GONE)))
1003 
1004             kosmos.setSceneTransition(Transition(Scenes.Lockscreen, Scenes.Gone))
1005             val sendStep1 = TransitionStep(LOCKSCREEN, UNDEFINED, 0f, STARTED)
1006             sendSteps(sendStep1)
1007             kosmos.setSceneTransition(Idle(Scenes.Gone))
1008             val sendStep2 = TransitionStep(LOCKSCREEN, UNDEFINED, 1f, FINISHED)
1009             val sendStep3 = TransitionStep(UNDEFINED, AOD, 0f, STARTED)
1010             val sendStep4 = TransitionStep(AOD, LOCKSCREEN, 0f, STARTED)
1011             sendSteps(sendStep2, sendStep3, sendStep4)
1012 
1013             assertEquals(listOf(sendStep1, sendStep2), currentStates)
1014             assertEquals(listOf(sendStep1, sendStep2), currentStatesMapped)
1015         }
1016 
1017     @Test
1018     @EnableSceneContainer
transition_conversion_does_not_emit_with_null_edge_with_wrong_stl_statenull1019     fun transition_conversion_does_not_emit_with_null_edge_with_wrong_stl_state() =
1020         testScope.runTest {
1021             val currentStatesMapped by collectValues(underTest.transition(Edge.create(null, GONE)))
1022 
1023             kosmos.setSceneTransition(Transition(Scenes.Gone, Scenes.Lockscreen))
1024             val sendStep1 = TransitionStep(LOCKSCREEN, UNDEFINED, 0f, STARTED)
1025             val sendStep2 = TransitionStep(LOCKSCREEN, UNDEFINED, 1f, FINISHED)
1026             sendSteps(sendStep1, sendStep2)
1027             kosmos.setSceneTransition(Idle(Scenes.Gone))
1028             val sendStep3 = TransitionStep(UNDEFINED, AOD, 0f, STARTED)
1029             val sendStep4 = TransitionStep(AOD, LOCKSCREEN, 0f, STARTED)
1030             sendSteps(sendStep3, sendStep4)
1031 
1032             assertEquals(listOf<TransitionStep>(), currentStatesMapped)
1033         }
1034 
1035     @Test
1036     @EnableSceneContainer
transition_null_edges_thrownull1037     fun transition_null_edges_throw() =
1038         testScope.runTest {
1039             assertThrows(IllegalStateException::class.java) {
1040                 underTest.transition(Edge.create(null, null))
1041             }
1042         }
1043 
1044     @Test
1045     @EnableSceneContainer
simulateTransitionStepsForSceneTransitions_emits_correct_values_for_wildcard_from_edgenull1046     fun simulateTransitionStepsForSceneTransitions_emits_correct_values_for_wildcard_from_edge() =
1047         testScope.runTest {
1048             val sceneToSceneSteps by
1049                 collectValues(underTest.transition(Edge.create(from = Scenes.Gone)))
1050             val progress = MutableSharedFlow<Float>()
1051 
1052             kosmos.setSceneTransition(
1053                 Transition(Scenes.Gone, Scenes.Lockscreen, progress = progress)
1054             )
1055 
1056             progress.emit(0.2f)
1057             runCurrent()
1058             progress.emit(0.6f)
1059             runCurrent()
1060 
1061             kosmos.setSceneTransition(
1062                 ShowOverlay(
1063                     overlay = Overlays.Bouncer,
1064                     fromScene = Scenes.Gone,
1065                     progress = progress,
1066                 )
1067             )
1068 
1069             progress.emit(0.1f)
1070             runCurrent()
1071 
1072             kosmos.setSceneTransition(
1073                 HideOverlay(
1074                     overlay = Overlays.Bouncer,
1075                     toScene = Scenes.Lockscreen,
1076                     progress = progress,
1077                 )
1078             )
1079 
1080             progress.emit(0.3f)
1081             runCurrent()
1082 
1083             kosmos.setSceneTransition(Idle(Scenes.Gone))
1084 
1085             assertEquals(
1086                 listOf(
1087                     TransitionStep(UNDEFINED, UNDEFINED, 0f, STARTED),
1088                     TransitionStep(UNDEFINED, UNDEFINED, 0.2f, RUNNING),
1089                     TransitionStep(UNDEFINED, UNDEFINED, 0.6f, RUNNING),
1090                     TransitionStep(UNDEFINED, UNDEFINED, 1f, FINISHED),
1091                     TransitionStep(UNDEFINED, UNDEFINED, 0f, STARTED),
1092                     TransitionStep(UNDEFINED, UNDEFINED, 0.1f, RUNNING),
1093                     TransitionStep(UNDEFINED, UNDEFINED, 1f, FINISHED),
1094                 ),
1095                 sceneToSceneSteps,
1096             )
1097         }
1098 
1099     @Test
1100     @EnableSceneContainer
simulateTransitionStepsForSceneTransitions_emits_correct_values_for_wildcard_to_edgenull1101     fun simulateTransitionStepsForSceneTransitions_emits_correct_values_for_wildcard_to_edge() =
1102         testScope.runTest {
1103             val sceneToSceneSteps by
1104                 collectValues(underTest.transition(Edge.create(to = Scenes.Gone)))
1105             val progress = MutableSharedFlow<Float>()
1106 
1107             kosmos.setSceneTransition(
1108                 Transition(Scenes.Gone, Scenes.Lockscreen, progress = progress)
1109             )
1110 
1111             progress.emit(0.2f)
1112             runCurrent()
1113 
1114             kosmos.setSceneTransition(Idle(Scenes.Gone))
1115 
1116             kosmos.setSceneTransition(
1117                 ShowOverlay(
1118                     overlay = Overlays.Bouncer,
1119                     fromScene = Scenes.Gone,
1120                     progress = progress,
1121                 )
1122             )
1123 
1124             progress.emit(0.1f)
1125             runCurrent()
1126 
1127             kosmos.setSceneTransition(
1128                 HideOverlay(overlay = Overlays.Bouncer, toScene = Scenes.Gone, progress = progress)
1129             )
1130 
1131             progress.emit(0.3f)
1132             runCurrent()
1133 
1134             kosmos.setSceneTransition(Idle(Scenes.Gone))
1135 
1136             assertEquals(
1137                 listOf(
1138                     TransitionStep(UNDEFINED, UNDEFINED, 0f, STARTED),
1139                     TransitionStep(UNDEFINED, UNDEFINED, 0.3f, RUNNING),
1140                     TransitionStep(UNDEFINED, UNDEFINED, 1f, FINISHED),
1141                 ),
1142                 sceneToSceneSteps,
1143             )
1144         }
1145 
1146     @Test
1147     @EnableSceneContainer
flatMapLatestWithFinished_emission_of_previous_progress_flow_is_not_interleavingnull1148     fun flatMapLatestWithFinished_emission_of_previous_progress_flow_is_not_interleaving() =
1149         testScope.runTest {
1150             val sceneToSceneSteps by
1151                 collectValues(underTest.transition(Edge.create(from = Scenes.Gone)))
1152             val progress1 = MutableSharedFlow<Float>()
1153             val progress2 = MutableSharedFlow<Float>()
1154 
1155             kosmos.setSceneTransition(
1156                 Transition(Scenes.Gone, Scenes.Lockscreen, progress = progress1)
1157             )
1158 
1159             progress1.emit(0.1f)
1160             runCurrent()
1161 
1162             kosmos.setSceneTransition(
1163                 ShowOverlay(
1164                     overlay = Overlays.Bouncer,
1165                     fromScene = Scenes.Gone,
1166                     progress = progress2,
1167                 )
1168             )
1169 
1170             progress2.emit(0.3f)
1171             runCurrent()
1172 
1173             progress1.emit(0.2f)
1174             runCurrent()
1175 
1176             assertEquals(
1177                 listOf(
1178                     TransitionStep(UNDEFINED, UNDEFINED, 0f, STARTED),
1179                     TransitionStep(UNDEFINED, UNDEFINED, 0.1f, RUNNING),
1180                     TransitionStep(UNDEFINED, UNDEFINED, 1f, FINISHED),
1181                     TransitionStep(UNDEFINED, UNDEFINED, 0f, STARTED),
1182                     TransitionStep(UNDEFINED, UNDEFINED, 0.3f, RUNNING),
1183                 ),
1184                 sceneToSceneSteps,
1185             )
1186         }
1187 
1188     @Test
1189     @EnableSceneContainer
transition_filter_on_belongsToInstantReversedTransition_out_of_lockscreen_scenenull1190     fun transition_filter_on_belongsToInstantReversedTransition_out_of_lockscreen_scene() =
1191         testScope.runTest {
1192             val currentStatesMapped by
1193                 collectValues(underTest.transition(Edge.create(LOCKSCREEN, Scenes.Gone)))
1194 
1195             kosmos.sceneInteractor.snapToScene(Scenes.Lockscreen, "reason")
1196             kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
1197                 SuccessFingerprintAuthenticationStatus(0, true)
1198             )
1199 
1200             kosmos.setSceneTransition(Transition(Scenes.Gone, Scenes.Lockscreen))
1201             val sendStep1 = TransitionStep(UNDEFINED, LOCKSCREEN, 0f, STARTED)
1202             kosmos.sceneInteractor.changeScene(Scenes.Gone, "reason")
1203             kosmos.setSceneTransition(Idle(Scenes.Gone))
1204             val sendStep2 = TransitionStep(UNDEFINED, LOCKSCREEN, 0.6f, CANCELED)
1205             sendSteps(sendStep1, sendStep2)
1206             val sendStep3 = TransitionStep(LOCKSCREEN, UNDEFINED, 0f, STARTED)
1207             val sendStep4 = TransitionStep(LOCKSCREEN, UNDEFINED, 1f, FINISHED)
1208             sendSteps(sendStep3, sendStep4)
1209 
1210             assertEquals(listOf(sendStep3, sendStep4), currentStatesMapped)
1211         }
1212 
1213     @Test
1214     @EnableSceneContainer
transition_filter_on_belongsToInstantReversedTransition_into_lockscreen_scenenull1215     fun transition_filter_on_belongsToInstantReversedTransition_into_lockscreen_scene() =
1216         testScope.runTest {
1217             val currentStatesMapped by
1218                 collectValues(underTest.transition(Edge.create(Scenes.Gone, LOCKSCREEN)))
1219 
1220             kosmos.setSceneTransition(Transition(Scenes.Lockscreen, Scenes.Gone))
1221             val sendStep1 = TransitionStep(LOCKSCREEN, UNDEFINED, 0f, STARTED)
1222             kosmos.setSceneTransition(Idle(Scenes.Lockscreen))
1223             val sendStep2 = TransitionStep(LOCKSCREEN, UNDEFINED, 0.6f, CANCELED)
1224             sendSteps(sendStep1, sendStep2)
1225             val sendStep3 = TransitionStep(UNDEFINED, LOCKSCREEN, 0f, STARTED)
1226             val sendStep4 = TransitionStep(UNDEFINED, LOCKSCREEN, 1f, FINISHED)
1227             sendSteps(sendStep3, sendStep4)
1228 
1229             assertEquals(listOf(sendStep3, sendStep4), currentStatesMapped)
1230         }
1231 
1232     @Test
1233     @EnableSceneContainer
transition_filter_on_belongsToInstantReversedTransition_out_of_ls_with_wildcardnull1234     fun transition_filter_on_belongsToInstantReversedTransition_out_of_ls_with_wildcard() =
1235         testScope.runTest {
1236             val currentStatesMapped by
1237                 collectValues(underTest.transition(Edge.create(to = LOCKSCREEN)))
1238 
1239             kosmos.setSceneTransition(Transition(Scenes.Lockscreen, Scenes.Gone))
1240             val sendStep1 = TransitionStep(LOCKSCREEN, UNDEFINED, 0f, STARTED)
1241             kosmos.setSceneTransition(Idle(Scenes.Lockscreen))
1242             val sendStep2 = TransitionStep(LOCKSCREEN, UNDEFINED, 0.6f, CANCELED)
1243             sendSteps(sendStep1, sendStep2)
1244             val sendStep3 = TransitionStep(UNDEFINED, LOCKSCREEN, 0f, STARTED)
1245             val sendStep4 = TransitionStep(UNDEFINED, LOCKSCREEN, 1f, FINISHED)
1246             sendSteps(sendStep3, sendStep4)
1247 
1248             assertEquals(listOf(sendStep3, sendStep4), currentStatesMapped)
1249         }
1250 
sendStepsnull1251     private suspend fun sendSteps(vararg steps: TransitionStep) {
1252         steps.forEach {
1253             repository.sendTransitionStep(it)
1254             testScope.runCurrent()
1255         }
1256     }
1257 
resetTransitionValueReplayCachenull1258     private fun resetTransitionValueReplayCache(states: Set<KeyguardState>) {
1259         states.forEach { (underTest.transitionValue(it) as MutableSharedFlow).resetReplayCache() }
1260     }
1261 }
1262