• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * 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 package com.android.systemui.keyguard.domain.interactor
18 
19 import android.animation.ValueAnimator
20 import com.android.keyguard.KeyguardSecurityModel
21 import com.android.keyguard.KeyguardSecurityModel.SecurityMode.Password
22 import com.android.keyguard.KeyguardUpdateMonitor
23 import com.android.systemui.animation.Interpolators
24 import com.android.systemui.dagger.SysUISingleton
25 import com.android.systemui.dagger.qualifiers.Application
26 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
27 import com.android.systemui.keyguard.shared.model.KeyguardState
28 import com.android.systemui.keyguard.shared.model.TransitionInfo
29 import com.android.systemui.keyguard.shared.model.WakefulnessState
30 import com.android.systemui.util.kotlin.sample
31 import javax.inject.Inject
32 import kotlin.time.Duration
33 import kotlin.time.Duration.Companion.milliseconds
34 import kotlinx.coroutines.CoroutineScope
35 import kotlinx.coroutines.flow.combine
36 import kotlinx.coroutines.launch
37 
38 @SysUISingleton
39 class FromPrimaryBouncerTransitionInteractor
40 @Inject
41 constructor(
42     @Application private val scope: CoroutineScope,
43     private val keyguardInteractor: KeyguardInteractor,
44     private val keyguardTransitionRepository: KeyguardTransitionRepository,
45     private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
46     private val keyguardSecurityModel: KeyguardSecurityModel,
47 ) : TransitionInteractor(FromPrimaryBouncerTransitionInteractor::class.simpleName!!) {
48 
49     override fun start() {
50         listenForPrimaryBouncerToGone()
51         listenForPrimaryBouncerToLockscreenAodOrDozing()
52     }
53 
54     private fun listenForPrimaryBouncerToLockscreenAodOrDozing() {
55         scope.launch {
56             keyguardInteractor.primaryBouncerShowing
57                 .sample(
58                     combine(
59                         keyguardInteractor.wakefulnessModel,
60                         keyguardTransitionInteractor.startedKeyguardTransitionStep,
61                         keyguardInteractor.isAodAvailable,
62                         ::toTriple
63                     ),
64                     ::toQuad
65                 )
66                 .collect {
67                     (isBouncerShowing, wakefulnessState, lastStartedTransitionStep, isAodAvailable)
68                     ->
69                     if (
70                         !isBouncerShowing &&
71                             lastStartedTransitionStep.to == KeyguardState.PRIMARY_BOUNCER
72                     ) {
73                         val to =
74                             if (
75                                 wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP ||
76                                     wakefulnessState.state == WakefulnessState.ASLEEP
77                             ) {
78                                 if (isAodAvailable) {
79                                     KeyguardState.AOD
80                                 } else {
81                                     KeyguardState.DOZING
82                                 }
83                             } else {
84                                 KeyguardState.LOCKSCREEN
85                             }
86                         keyguardTransitionRepository.startTransition(
87                             TransitionInfo(
88                                 ownerName = name,
89                                 from = KeyguardState.PRIMARY_BOUNCER,
90                                 to = to,
91                                 animator = getAnimator(),
92                             )
93                         )
94                     }
95                 }
96         }
97     }
98 
99     private fun listenForPrimaryBouncerToGone() {
100         scope.launch {
101             keyguardInteractor.isKeyguardGoingAway
102                 .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
103                 .collect { (isKeyguardGoingAway, lastStartedTransitionStep) ->
104                     if (
105                         isKeyguardGoingAway &&
106                             lastStartedTransitionStep.to == KeyguardState.PRIMARY_BOUNCER
107                     ) {
108                         val securityMode =
109                             keyguardSecurityModel.getSecurityMode(
110                                 KeyguardUpdateMonitor.getCurrentUser()
111                             )
112                         // IME for password requires a slightly faster animation
113                         val duration =
114                             if (securityMode == Password) {
115                                 TO_GONE_SHORT_DURATION
116                             } else {
117                                 TO_GONE_DURATION
118                             }
119                         keyguardTransitionRepository.startTransition(
120                             TransitionInfo(
121                                 ownerName = name,
122                                 from = KeyguardState.PRIMARY_BOUNCER,
123                                 to = KeyguardState.GONE,
124                                 animator = getAnimator(duration),
125                             ),
126                             resetIfCanceled = true,
127                         )
128                     }
129                 }
130         }
131     }
132 
133     private fun getAnimator(duration: Duration = DEFAULT_DURATION): ValueAnimator {
134         return ValueAnimator().apply {
135             setInterpolator(Interpolators.LINEAR)
136             setDuration(duration.inWholeMilliseconds)
137         }
138     }
139 
140     companion object {
141         private val DEFAULT_DURATION = 300.milliseconds
142         val TO_GONE_DURATION = 250.milliseconds
143         val TO_GONE_SHORT_DURATION = 200.milliseconds
144     }
145 }
146