• 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 package com.android.systemui.keyguard.data.repository
18 
19 import android.os.Build
20 import android.util.Log
21 import com.android.keyguard.ViewMediatorCallback
22 import com.android.systemui.dagger.SysUISingleton
23 import com.android.systemui.dagger.qualifiers.Application
24 import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
25 import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
26 import com.android.systemui.log.dagger.BouncerLog
27 import com.android.systemui.log.table.TableLogBuffer
28 import com.android.systemui.log.table.logDiffsForTable
29 import com.android.systemui.util.time.SystemClock
30 import javax.inject.Inject
31 import kotlinx.coroutines.CoroutineScope
32 import kotlinx.coroutines.flow.MutableStateFlow
33 import kotlinx.coroutines.flow.StateFlow
34 import kotlinx.coroutines.flow.asStateFlow
35 import kotlinx.coroutines.flow.filterNotNull
36 import kotlinx.coroutines.flow.launchIn
37 import kotlinx.coroutines.flow.map
38 import kotlinx.coroutines.flow.onEach
39 
40 /**
41  * Encapsulates app state for the lock screen primary and alternate bouncer.
42  *
43  * Make sure to add newly added flows to the logger.
44  */
45 interface KeyguardBouncerRepository {
46     /** Values associated with the PrimaryBouncer (pin/pattern/password) input. */
47     val primaryBouncerShow: StateFlow<Boolean>
48     val primaryBouncerShowingSoon: StateFlow<Boolean>
49     val primaryBouncerStartingToHide: StateFlow<Boolean>
50     val primaryBouncerStartingDisappearAnimation: StateFlow<Runnable?>
51     /** Determines if we want to instantaneously show the primary bouncer instead of translating. */
52     val primaryBouncerScrimmed: StateFlow<Boolean>
53     /**
54      * Set how much of the notification panel is showing on the screen.
55      *
56      * ```
57      *      0f = panel fully hidden = bouncer fully showing
58      *      1f = panel fully showing = bouncer fully hidden
59      * ```
60      */
61     val panelExpansionAmount: StateFlow<Float>
62     val keyguardPosition: StateFlow<Float>
63     val isBackButtonEnabled: StateFlow<Boolean?>
64     /** Determines if user is already unlocked */
65     val keyguardAuthenticated: StateFlow<Boolean?>
66     val showMessage: StateFlow<BouncerShowMessageModel?>
67     val resourceUpdateRequests: StateFlow<Boolean>
68     val bouncerPromptReason: Int
69     val bouncerErrorMessage: CharSequence?
70     val alternateBouncerVisible: StateFlow<Boolean>
71     val alternateBouncerUIAvailable: StateFlow<Boolean>
72     val sideFpsShowing: StateFlow<Boolean>
73 
74     var lastAlternateBouncerVisibleTime: Long
75 
setPrimaryScrimmednull76     fun setPrimaryScrimmed(isScrimmed: Boolean)
77 
78     fun setPrimaryShow(isShowing: Boolean)
79 
80     fun setPrimaryShowingSoon(showingSoon: Boolean)
81 
82     fun setPrimaryStartingToHide(startingToHide: Boolean)
83 
84     fun setPrimaryStartDisappearAnimation(runnable: Runnable?)
85 
86     fun setPanelExpansion(panelExpansion: Float)
87 
88     fun setKeyguardPosition(keyguardPosition: Float)
89 
90     fun setResourceUpdateRequests(willUpdateResources: Boolean)
91 
92     fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?)
93 
94     fun setKeyguardAuthenticated(keyguardAuthenticated: Boolean?)
95 
96     fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean)
97 
98     fun setAlternateVisible(isVisible: Boolean)
99 
100     fun setAlternateBouncerUIAvailable(isAvailable: Boolean)
101 
102     fun setSideFpsShowing(isShowing: Boolean)
103 }
104 
105 @SysUISingleton
106 class KeyguardBouncerRepositoryImpl
107 @Inject
108 constructor(
109     private val viewMediatorCallback: ViewMediatorCallback,
110     private val clock: SystemClock,
111     @Application private val applicationScope: CoroutineScope,
112     @BouncerLog private val buffer: TableLogBuffer,
113 ) : KeyguardBouncerRepository {
114     /** Values associated with the PrimaryBouncer (pin/pattern/password) input. */
115     private val _primaryBouncerShow = MutableStateFlow(false)
116     override val primaryBouncerShow = _primaryBouncerShow.asStateFlow()
117     private val _primaryBouncerShowingSoon = MutableStateFlow(false)
118     override val primaryBouncerShowingSoon = _primaryBouncerShowingSoon.asStateFlow()
119     private val _primaryBouncerStartingToHide = MutableStateFlow(false)
120     override val primaryBouncerStartingToHide = _primaryBouncerStartingToHide.asStateFlow()
121     private val _primaryBouncerDisappearAnimation = MutableStateFlow<Runnable?>(null)
122     override val primaryBouncerStartingDisappearAnimation =
123         _primaryBouncerDisappearAnimation.asStateFlow()
124     /** Determines if we want to instantaneously show the primary bouncer instead of translating. */
125     private val _primaryBouncerScrimmed = MutableStateFlow(false)
126     override val primaryBouncerScrimmed = _primaryBouncerScrimmed.asStateFlow()
127     /**
128      * Set how much of the notification panel is showing on the screen.
129      *
130      * ```
131      *      0f = panel fully hidden = bouncer fully showing
132      *      1f = panel fully showing = bouncer fully hidden
133      * ```
134      */
135     private val _panelExpansionAmount = MutableStateFlow(EXPANSION_HIDDEN)
136     override val panelExpansionAmount = _panelExpansionAmount.asStateFlow()
137     private val _keyguardPosition = MutableStateFlow(0f)
138     override val keyguardPosition = _keyguardPosition.asStateFlow()
139     private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null)
140     override val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow()
141     private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null)
142     /** Determines if user is already unlocked */
143     override val keyguardAuthenticated = _keyguardAuthenticated.asStateFlow()
144     private val _showMessage = MutableStateFlow<BouncerShowMessageModel?>(null)
145     override val showMessage = _showMessage.asStateFlow()
146     private val _resourceUpdateRequests = MutableStateFlow(false)
147     override val resourceUpdateRequests = _resourceUpdateRequests.asStateFlow()
148     override val bouncerPromptReason: Int
149         get() = viewMediatorCallback.bouncerPromptReason
150     override val bouncerErrorMessage: CharSequence?
151         get() = viewMediatorCallback.consumeCustomMessage()
152 
153     /** Values associated with the AlternateBouncer */
154     private val _alternateBouncerVisible = MutableStateFlow(false)
155     override val alternateBouncerVisible = _alternateBouncerVisible.asStateFlow()
156     override var lastAlternateBouncerVisibleTime: Long = NOT_VISIBLE
157     private val _alternateBouncerUIAvailable = MutableStateFlow(false)
158     override val alternateBouncerUIAvailable: StateFlow<Boolean> =
159         _alternateBouncerUIAvailable.asStateFlow()
160     private val _sideFpsShowing = MutableStateFlow(false)
161     override val sideFpsShowing: StateFlow<Boolean> = _sideFpsShowing.asStateFlow()
162 
163     init {
164         setUpLogging()
165     }
166 
167     override fun setPrimaryScrimmed(isScrimmed: Boolean) {
168         _primaryBouncerScrimmed.value = isScrimmed
169     }
170 
171     override fun setAlternateVisible(isVisible: Boolean) {
172         if (isVisible && !_alternateBouncerVisible.value) {
173             lastAlternateBouncerVisibleTime = clock.uptimeMillis()
174         } else if (!isVisible) {
175             lastAlternateBouncerVisibleTime = NOT_VISIBLE
176         }
177         _alternateBouncerVisible.value = isVisible
178     }
179 
180     override fun setAlternateBouncerUIAvailable(isAvailable: Boolean) {
181         _alternateBouncerUIAvailable.value = isAvailable
182     }
183 
184     override fun setPrimaryShow(isShowing: Boolean) {
185         _primaryBouncerShow.value = isShowing
186     }
187 
188     override fun setPrimaryShowingSoon(showingSoon: Boolean) {
189         _primaryBouncerShowingSoon.value = showingSoon
190     }
191 
192     override fun setPrimaryStartingToHide(startingToHide: Boolean) {
193         _primaryBouncerStartingToHide.value = startingToHide
194     }
195 
196     override fun setPrimaryStartDisappearAnimation(runnable: Runnable?) {
197         _primaryBouncerDisappearAnimation.value = runnable
198     }
199 
200     override fun setPanelExpansion(panelExpansion: Float) {
201         _panelExpansionAmount.value = panelExpansion
202     }
203 
204     override fun setKeyguardPosition(keyguardPosition: Float) {
205         _keyguardPosition.value = keyguardPosition
206     }
207 
208     override fun setResourceUpdateRequests(willUpdateResources: Boolean) {
209         _resourceUpdateRequests.value = willUpdateResources
210     }
211 
212     override fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?) {
213         _showMessage.value = bouncerShowMessageModel
214     }
215 
216     override fun setKeyguardAuthenticated(keyguardAuthenticated: Boolean?) {
217         _keyguardAuthenticated.value = keyguardAuthenticated
218     }
219 
220     override fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean) {
221         _isBackButtonEnabled.value = isBackButtonEnabled
222     }
223 
224     override fun setSideFpsShowing(isShowing: Boolean) {
225         _sideFpsShowing.value = isShowing
226     }
227 
228     /** Sets up logs for state flows. */
229     private fun setUpLogging() {
230         if (!Build.IS_DEBUGGABLE) {
231             return
232         }
233 
234         primaryBouncerShow
235             .logDiffsForTable(buffer, "", "PrimaryBouncerShow", false)
236             .onEach { Log.d(TAG, "Keyguard Bouncer is ${if (it) "showing" else "hiding."}") }
237             .launchIn(applicationScope)
238         primaryBouncerShowingSoon
239             .logDiffsForTable(buffer, "", "PrimaryBouncerShowingSoon", false)
240             .launchIn(applicationScope)
241         primaryBouncerStartingToHide
242             .logDiffsForTable(buffer, "", "PrimaryBouncerStartingToHide", false)
243             .launchIn(applicationScope)
244         primaryBouncerStartingDisappearAnimation
245             .map { it != null }
246             .logDiffsForTable(buffer, "", "PrimaryBouncerStartingDisappearAnimation", false)
247             .launchIn(applicationScope)
248         primaryBouncerScrimmed
249             .logDiffsForTable(buffer, "", "PrimaryBouncerScrimmed", false)
250             .launchIn(applicationScope)
251         panelExpansionAmount
252             .map { (it * 1000).toInt() }
253             .logDiffsForTable(buffer, "", "PanelExpansionAmountMillis", -1)
254             .launchIn(applicationScope)
255         keyguardPosition
256             .map { it.toInt() }
257             .logDiffsForTable(buffer, "", "KeyguardPosition", -1)
258             .launchIn(applicationScope)
259         isBackButtonEnabled
260             .filterNotNull()
261             .logDiffsForTable(buffer, "", "IsBackButtonEnabled", false)
262             .launchIn(applicationScope)
263         showMessage
264             .map { it?.message }
265             .logDiffsForTable(buffer, "", "ShowMessage", null)
266             .launchIn(applicationScope)
267         resourceUpdateRequests
268             .logDiffsForTable(buffer, "", "ResourceUpdateRequests", false)
269             .launchIn(applicationScope)
270         alternateBouncerUIAvailable
271             .logDiffsForTable(buffer, "", "IsAlternateBouncerUIAvailable", false)
272             .launchIn(applicationScope)
273         sideFpsShowing
274             .logDiffsForTable(buffer, "", "isSideFpsShowing", false)
275             .launchIn(applicationScope)
276     }
277 
278     companion object {
279         private const val NOT_VISIBLE = -1L
280         private const val TAG = "KeyguardBouncerRepositoryImpl"
281     }
282 }
283