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