• 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.ui.binder
18 
19 import android.view.KeyEvent
20 import android.view.View
21 import android.view.ViewGroup
22 import android.window.OnBackAnimationCallback
23 import androidx.lifecycle.Lifecycle
24 import androidx.lifecycle.repeatOnLifecycle
25 import com.android.keyguard.KeyguardSecurityContainerController
26 import com.android.keyguard.KeyguardSecurityModel
27 import com.android.keyguard.KeyguardSecurityView
28 import com.android.keyguard.KeyguardUpdateMonitor
29 import com.android.keyguard.dagger.KeyguardBouncerComponent
30 import com.android.systemui.keyguard.data.BouncerViewDelegate
31 import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
32 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
33 import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
34 import com.android.systemui.lifecycle.repeatWhenAttached
35 import com.android.systemui.plugins.ActivityStarter
36 import kotlinx.coroutines.awaitCancellation
37 import kotlinx.coroutines.flow.filter
38 import kotlinx.coroutines.launch
39 
40 /** Binds the bouncer container to its view model. */
41 object KeyguardBouncerViewBinder {
42     @JvmStatic
43     fun bind(
44         view: ViewGroup,
45         viewModel: KeyguardBouncerViewModel,
46         primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel,
47         componentFactory: KeyguardBouncerComponent.Factory
48     ) {
49         // Builds the KeyguardSecurityContainerController from bouncer view group.
50         val securityContainerController: KeyguardSecurityContainerController =
51             componentFactory.create(view).securityContainerController
52         securityContainerController.init()
53         val delegate =
54             object : BouncerViewDelegate {
55                 override fun isFullScreenBouncer(): Boolean {
56                     val mode = securityContainerController.currentSecurityMode
57                     return mode == KeyguardSecurityModel.SecurityMode.SimPin ||
58                         mode == KeyguardSecurityModel.SecurityMode.SimPuk
59                 }
60 
61                 override fun getBackCallback(): OnBackAnimationCallback {
62                     return securityContainerController.backCallback
63                 }
64 
65                 override fun shouldDismissOnMenuPressed(): Boolean {
66                     return securityContainerController.shouldEnableMenuKey()
67                 }
68 
69                 override fun interceptMediaKey(event: KeyEvent?): Boolean {
70                     return securityContainerController.interceptMediaKey(event)
71                 }
72 
73                 override fun dispatchBackKeyEventPreIme(): Boolean {
74                     return securityContainerController.dispatchBackKeyEventPreIme()
75                 }
76 
77                 override fun showNextSecurityScreenOrFinish(): Boolean {
78                     return securityContainerController.dismiss(
79                         KeyguardUpdateMonitor.getCurrentUser()
80                     )
81                 }
82 
83                 override fun resume() {
84                     securityContainerController.showPrimarySecurityScreen(/* isTurningOff= */ false)
85                     securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON)
86                 }
87 
88                 override fun setDismissAction(
89                     onDismissAction: ActivityStarter.OnDismissAction?,
90                     cancelAction: Runnable?
91                 ) {
92                     securityContainerController.setOnDismissAction(onDismissAction, cancelAction)
93                 }
94 
95                 override fun willDismissWithActions(): Boolean {
96                     return securityContainerController.hasDismissActions()
97                 }
98 
99                 override fun willRunDismissFromKeyguard(): Boolean {
100                     return securityContainerController.willRunDismissFromKeyguard()
101                 }
102 
103                 override fun showPromptReason(reason: Int) {
104                     securityContainerController.showPromptReason(reason)
105                 }
106             }
107         view.repeatWhenAttached {
108             repeatOnLifecycle(Lifecycle.State.CREATED) {
109                 try {
110                     viewModel.setBouncerViewDelegate(delegate)
111                     launch {
112                         viewModel.isShowing.collect { isShowing ->
113                             view.visibility = if (isShowing) View.VISIBLE else View.INVISIBLE
114                             if (isShowing) {
115                                 // Reset Security Container entirely.
116                                 securityContainerController.reinflateViewFlipper {
117                                     // Reset Security Container entirely.
118                                     securityContainerController.onBouncerVisibilityChanged(
119                                         /* isVisible= */ true
120                                     )
121                                     securityContainerController.showPrimarySecurityScreen(
122                                         /* turningOff= */ false
123                                     )
124                                     securityContainerController.appear()
125                                     securityContainerController.onResume(
126                                         KeyguardSecurityView.SCREEN_ON
127                                     )
128                                 }
129                             } else {
130                                 securityContainerController.onBouncerVisibilityChanged(
131                                     /* isVisible= */ false
132                                 )
133                                 securityContainerController.cancelDismissAction()
134                                 securityContainerController.reset()
135                                 securityContainerController.onPause()
136                             }
137                         }
138                     }
139 
140                     launch {
141                         viewModel.startingToHide.collect {
142                             securityContainerController.onStartingToHide()
143                         }
144                     }
145 
146                     launch {
147                         viewModel.startDisappearAnimation.collect {
148                             securityContainerController.startDisappearAnimation(it)
149                         }
150                     }
151 
152                     launch {
153                         viewModel.bouncerExpansionAmount.collect { expansion ->
154                             securityContainerController.setExpansion(expansion)
155                         }
156                     }
157 
158                     launch {
159                         primaryBouncerToGoneTransitionViewModel.bouncerAlpha.collect { alpha ->
160                             securityContainerController.setAlpha(alpha)
161                         }
162                     }
163 
164                     launch {
165                         viewModel.bouncerExpansionAmount
166                             .filter { it == EXPANSION_VISIBLE }
167                             .collect {
168                                 securityContainerController.onResume(KeyguardSecurityView.SCREEN_ON)
169                                 view.announceForAccessibility(securityContainerController.title)
170                             }
171                     }
172 
173                     launch {
174                         viewModel.isInteractable.collect { isInteractable ->
175                             securityContainerController.setInteractable(isInteractable)
176                         }
177                     }
178 
179                     launch {
180                         viewModel.keyguardPosition.collect { position ->
181                             securityContainerController.updateKeyguardPosition(position)
182                         }
183                     }
184 
185                     launch {
186                         viewModel.updateResources.collect {
187                             securityContainerController.updateResources()
188                             viewModel.notifyUpdateResources()
189                         }
190                     }
191 
192                     launch {
193                         viewModel.bouncerShowMessage.collect {
194                             securityContainerController.showMessage(it.message, it.colorStateList)
195                             viewModel.onMessageShown()
196                         }
197                     }
198 
199                     launch {
200                         viewModel.keyguardAuthenticated.collect {
201                             securityContainerController.finish(
202                                 it,
203                                 KeyguardUpdateMonitor.getCurrentUser()
204                             )
205                             viewModel.notifyKeyguardAuthenticated()
206                         }
207                     }
208 
209                     launch {
210                         viewModel
211                             .observeOnIsBackButtonEnabled { view.systemUiVisibility }
212                             .collect { view.systemUiVisibility = it }
213                     }
214 
215                     launch {
216                         viewModel.shouldUpdateSideFps.collect {
217                             viewModel.updateSideFpsVisibility()
218                         }
219                     }
220 
221                     launch {
222                         viewModel.sideFpsShowing.collect {
223                             securityContainerController.updateSideFpsVisibility(it)
224                         }
225                     }
226                     awaitCancellation()
227                 } finally {
228                     viewModel.setBouncerViewDelegate(null)
229                 }
230             }
231         }
232     }
233 }
234