• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2023 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.keyguard.domain.interactor
18 
19 import android.animation.ValueAnimator
20 import com.android.systemui.animation.Interpolators
21 import com.android.systemui.dagger.SysUISingleton
22 import com.android.systemui.dagger.qualifiers.Application
23 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
24 import com.android.systemui.keyguard.shared.model.KeyguardState
25 import com.android.systemui.keyguard.shared.model.TransitionInfo
26 import com.android.systemui.keyguard.shared.model.WakefulnessState
27 import com.android.systemui.util.kotlin.sample
28 import javax.inject.Inject
29 import kotlinx.coroutines.CoroutineScope
30 import kotlinx.coroutines.delay
31 import kotlinx.coroutines.flow.combine
32 import kotlinx.coroutines.flow.onEach
33 import kotlinx.coroutines.launch
34 
35 @SysUISingleton
36 class FromAlternateBouncerTransitionInteractor
37 @Inject
38 constructor(
39     @Application private val scope: CoroutineScope,
40     private val keyguardInteractor: KeyguardInteractor,
41     private val keyguardTransitionRepository: KeyguardTransitionRepository,
42     private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
43 ) : TransitionInteractor(FromAlternateBouncerTransitionInteractor::class.simpleName!!) {
44 
45     override fun start() {
46         listenForAlternateBouncerToGone()
47         listenForAlternateBouncerToLockscreenAodOrDozing()
48         listenForAlternateBouncerToPrimaryBouncer()
49     }
50 
51     private fun listenForAlternateBouncerToLockscreenAodOrDozing() {
52         scope.launch {
53             keyguardInteractor.alternateBouncerShowing
54                 // Add a slight delay, as alternateBouncer and primaryBouncer showing event changes
55                 // will arrive with a small gap in time. This prevents a transition to LOCKSCREEN
56                 // happening prematurely.
57                 .onEach { delay(50) }
58                 .sample(
59                     combine(
60                         keyguardInteractor.primaryBouncerShowing,
61                         keyguardTransitionInteractor.startedKeyguardTransitionStep,
62                         keyguardInteractor.wakefulnessModel,
63                         keyguardInteractor.isAodAvailable,
64                         ::toQuad
65                     ),
66                     ::toQuint
67                 )
68                 .collect {
69                     (
70                         isAlternateBouncerShowing,
71                         isPrimaryBouncerShowing,
72                         lastStartedTransitionStep,
73                         wakefulnessState,
74                         isAodAvailable) ->
75                     if (
76                         !isAlternateBouncerShowing &&
77                             !isPrimaryBouncerShowing &&
78                             lastStartedTransitionStep.to == KeyguardState.ALTERNATE_BOUNCER
79                     ) {
80                         val to =
81                             if (
82                                 wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP ||
83                                     wakefulnessState.state == WakefulnessState.ASLEEP
84                             ) {
85                                 if (isAodAvailable) {
86                                     KeyguardState.AOD
87                                 } else {
88                                     KeyguardState.DOZING
89                                 }
90                             } else {
91                                 KeyguardState.LOCKSCREEN
92                             }
93                         keyguardTransitionRepository.startTransition(
94                             TransitionInfo(
95                                 ownerName = name,
96                                 from = KeyguardState.ALTERNATE_BOUNCER,
97                                 to = to,
98                                 animator = getAnimator(),
99                             )
100                         )
101                     }
102                 }
103         }
104     }
105 
106     private fun listenForAlternateBouncerToGone() {
107         scope.launch {
108             keyguardInteractor.isKeyguardGoingAway
109                 .sample(keyguardTransitionInteractor.finishedKeyguardState, ::Pair)
110                 .collect { (isKeyguardGoingAway, keyguardState) ->
111                     if (isKeyguardGoingAway && keyguardState == KeyguardState.ALTERNATE_BOUNCER) {
112                         keyguardTransitionRepository.startTransition(
113                             TransitionInfo(
114                                 ownerName = name,
115                                 from = KeyguardState.ALTERNATE_BOUNCER,
116                                 to = KeyguardState.GONE,
117                                 animator = getAnimator(),
118                             )
119                         )
120                     }
121                 }
122         }
123     }
124 
125     private fun listenForAlternateBouncerToPrimaryBouncer() {
126         scope.launch {
127             keyguardInteractor.primaryBouncerShowing
128                 .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
129                 .collect { (isPrimaryBouncerShowing, startedKeyguardState) ->
130                     if (
131                         isPrimaryBouncerShowing &&
132                             startedKeyguardState.to == KeyguardState.ALTERNATE_BOUNCER
133                     ) {
134                         keyguardTransitionRepository.startTransition(
135                             TransitionInfo(
136                                 ownerName = name,
137                                 from = KeyguardState.ALTERNATE_BOUNCER,
138                                 to = KeyguardState.PRIMARY_BOUNCER,
139                                 animator = getAnimator(),
140                             )
141                         )
142                     }
143                 }
144         }
145     }
146 
147     private fun getAnimator(): ValueAnimator {
148         return ValueAnimator().apply {
149             interpolator = Interpolators.LINEAR
150             duration = TRANSITION_DURATION_MS
151         }
152     }
153 
154     companion object {
155         private const val TRANSITION_DURATION_MS = 300L
156     }
157 }
158