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.bouncer.data.repository 18 19 import android.os.Build 20 import android.util.Log 21 import com.android.keyguard.KeyguardSecurityModel 22 import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN 23 import com.android.systemui.bouncer.shared.model.BouncerDismissActionModel 24 import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel 25 import com.android.systemui.dagger.SysUISingleton 26 import com.android.systemui.dagger.qualifiers.Application 27 import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor 28 import com.android.systemui.log.dagger.BouncerTableLog 29 import com.android.systemui.log.table.TableLogBuffer 30 import com.android.systemui.log.table.logDiffsForTable 31 import com.android.systemui.util.time.SystemClock 32 import javax.inject.Inject 33 import kotlinx.coroutines.CoroutineScope 34 import kotlinx.coroutines.flow.Flow 35 import kotlinx.coroutines.flow.MutableSharedFlow 36 import kotlinx.coroutines.flow.MutableStateFlow 37 import kotlinx.coroutines.flow.StateFlow 38 import kotlinx.coroutines.flow.asSharedFlow 39 import kotlinx.coroutines.flow.asStateFlow 40 import kotlinx.coroutines.flow.filterNotNull 41 import kotlinx.coroutines.flow.launchIn 42 import kotlinx.coroutines.flow.map 43 import kotlinx.coroutines.flow.onEach 44 45 /** 46 * Encapsulates app state for the lock screen primary and alternate bouncer. 47 * 48 * Make sure to add newly added flows to the logger. 49 */ 50 interface KeyguardBouncerRepository { 51 /** Values associated with the PrimaryBouncer (pin/pattern/password) input. */ 52 val primaryBouncerShow: StateFlow<Boolean> 53 val primaryBouncerShowingSoon: StateFlow<Boolean> 54 val primaryBouncerStartingToHide: StateFlow<Boolean> 55 val primaryBouncerStartingDisappearAnimation: StateFlow<Runnable?> 56 57 /** Determines if we want to instantaneously show the primary bouncer instead of translating. */ 58 val primaryBouncerScrimmed: StateFlow<Boolean> 59 60 /** 61 * Set how much of the notification panel is showing on the screen. 62 * 63 * ``` 64 * 0f = panel fully hidden = bouncer fully showing 65 * 1f = panel fully showing = bouncer fully hidden 66 * ``` 67 */ 68 val panelExpansionAmount: StateFlow<Float> 69 val keyguardPosition: StateFlow<Float?> 70 val isBackButtonEnabled: StateFlow<Boolean?> 71 72 /** 73 * Triggers when the user has successfully used biometrics to authenticate. True = biometrics 74 * used to authenticate is Class 3, else false. When null, biometrics haven't authenticated the 75 * device. 76 */ 77 val keyguardAuthenticatedBiometrics: StateFlow<Boolean?> 78 79 /** 80 * Triggers when the given userId (Int) has successfully used primary authentication to 81 * authenticate 82 */ 83 val keyguardAuthenticatedPrimaryAuth: Flow<Int> 84 85 /** Triggers when the given userId (Int) has requested the bouncer when already authenticated */ 86 val userRequestedBouncerWhenAlreadyAuthenticated: Flow<Int> 87 88 val showMessage: StateFlow<BouncerShowMessageModel?> 89 val resourceUpdateRequests: StateFlow<Boolean> 90 val alternateBouncerVisible: StateFlow<Boolean> 91 val alternateBouncerUIAvailable: StateFlow<Boolean> 92 93 /** Last shown security mode of the primary bouncer (ie: pin/pattern/password/SIM) */ 94 val lastShownSecurityMode: StateFlow<KeyguardSecurityModel.SecurityMode> 95 96 /** Action that should be run right after the bouncer is dismissed. */ 97 var bouncerDismissActionModel: BouncerDismissActionModel? 98 99 var lastAlternateBouncerVisibleTime: Long 100 setPrimaryScrimmednull101 fun setPrimaryScrimmed(isScrimmed: Boolean) 102 103 fun setPrimaryShow(isShowing: Boolean) 104 105 fun setPrimaryShowingSoon(showingSoon: Boolean) 106 107 fun setPrimaryStartingToHide(startingToHide: Boolean) 108 109 fun setPrimaryStartDisappearAnimation(runnable: Runnable?) 110 111 fun setPanelExpansion(panelExpansion: Float) 112 113 fun setKeyguardPosition(keyguardPosition: Float) 114 115 fun setResourceUpdateRequests(willUpdateResources: Boolean) 116 117 fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?) 118 119 fun setKeyguardAuthenticatedBiometrics(keyguardAuthenticatedBiometrics: Boolean?) 120 121 suspend fun setKeyguardAuthenticatedPrimaryAuth(userId: Int) 122 123 suspend fun setUserRequestedBouncerWhenAlreadyAuthenticated(userId: Int) 124 125 fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean) 126 127 fun setAlternateVisible(isVisible: Boolean) 128 129 fun setAlternateBouncerUIAvailable(isAvailable: Boolean) 130 131 fun setLastShownSecurityMode(securityMode: KeyguardSecurityModel.SecurityMode) 132 } 133 134 @SysUISingleton 135 class KeyguardBouncerRepositoryImpl 136 @Inject 137 constructor( 138 private val clock: SystemClock, 139 @Application private val applicationScope: CoroutineScope, 140 @BouncerTableLog private val buffer: TableLogBuffer, 141 ) : KeyguardBouncerRepository { 142 override var bouncerDismissActionModel: BouncerDismissActionModel? = null 143 144 /** Values associated with the PrimaryBouncer (pin/pattern/password) input. */ 145 private val _primaryBouncerShow = MutableStateFlow(false) 146 override val primaryBouncerShow = _primaryBouncerShow.asStateFlow() 147 private val _primaryBouncerShowingSoon = MutableStateFlow(false) 148 override val primaryBouncerShowingSoon = _primaryBouncerShowingSoon.asStateFlow() 149 private val _primaryBouncerStartingToHide = MutableStateFlow(false) 150 override val primaryBouncerStartingToHide = _primaryBouncerStartingToHide.asStateFlow() 151 private val _primaryBouncerDisappearAnimation = MutableStateFlow<Runnable?>(null) 152 override val primaryBouncerStartingDisappearAnimation = 153 _primaryBouncerDisappearAnimation.asStateFlow() 154 155 /** Determines if we want to instantaneously show the primary bouncer instead of translating. */ 156 private val _primaryBouncerScrimmed = MutableStateFlow(false) 157 override val primaryBouncerScrimmed = _primaryBouncerScrimmed.asStateFlow() 158 159 /** 160 * Set how much of the notification panel is showing on the screen. 161 * 162 * ``` 163 * 0f = panel fully hidden = bouncer fully showing 164 * 1f = panel fully showing = bouncer fully hidden 165 * ``` 166 */ 167 private val _panelExpansionAmount = MutableStateFlow(EXPANSION_HIDDEN) 168 override val panelExpansionAmount = _panelExpansionAmount.asStateFlow() 169 private val _keyguardPosition = MutableStateFlow<Float?>(null) 170 override val keyguardPosition = _keyguardPosition.asStateFlow() 171 private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null) 172 override val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow() 173 174 /** Whether the user is already unlocked by biometrics */ 175 private val _keyguardAuthenticatedBiometrics = MutableStateFlow<Boolean?>(null) 176 override val keyguardAuthenticatedBiometrics = _keyguardAuthenticatedBiometrics.asStateFlow() 177 178 /** Whether the user is unlocked via a primary authentication method (pin/pattern/password). */ 179 private val _keyguardAuthenticatedPrimaryAuth = MutableSharedFlow<Int>() 180 override val keyguardAuthenticatedPrimaryAuth: Flow<Int> = 181 _keyguardAuthenticatedPrimaryAuth.asSharedFlow() 182 183 /** Whether the user requested to show the bouncer when device is already authenticated */ 184 private val _userRequestedBouncerWhenAlreadyAuthenticated = MutableSharedFlow<Int>() 185 override val userRequestedBouncerWhenAlreadyAuthenticated: Flow<Int> = 186 _userRequestedBouncerWhenAlreadyAuthenticated.asSharedFlow() 187 188 private val _showMessage = MutableStateFlow<BouncerShowMessageModel?>(null) 189 override val showMessage = _showMessage.asStateFlow() 190 private val _lastShownSecurityMode = 191 MutableStateFlow(KeyguardSecurityModel.SecurityMode.Invalid) 192 override val lastShownSecurityMode: StateFlow<KeyguardSecurityModel.SecurityMode> = 193 _lastShownSecurityMode.asStateFlow() 194 195 private val _resourceUpdateRequests = MutableStateFlow(false) 196 override val resourceUpdateRequests = _resourceUpdateRequests.asStateFlow() 197 198 /** Values associated with the AlternateBouncer */ 199 private val _alternateBouncerVisible = MutableStateFlow(false) 200 override val alternateBouncerVisible = _alternateBouncerVisible.asStateFlow() 201 override var lastAlternateBouncerVisibleTime: Long = NOT_VISIBLE 202 private val _alternateBouncerUIAvailable = MutableStateFlow(false) 203 override val alternateBouncerUIAvailable: StateFlow<Boolean> = 204 _alternateBouncerUIAvailable.asStateFlow() 205 206 init { 207 setUpLogging() 208 } 209 210 override fun setPrimaryScrimmed(isScrimmed: Boolean) { 211 _primaryBouncerScrimmed.value = isScrimmed 212 } 213 214 override fun setAlternateVisible(isVisible: Boolean) { 215 if (isVisible && !_alternateBouncerVisible.value) { 216 lastAlternateBouncerVisibleTime = clock.uptimeMillis() 217 } else if (!isVisible) { 218 lastAlternateBouncerVisibleTime = NOT_VISIBLE 219 } 220 _alternateBouncerVisible.value = isVisible 221 } 222 223 override fun setAlternateBouncerUIAvailable(isAvailable: Boolean) { 224 DeviceEntryUdfpsRefactor.assertInLegacyMode() 225 _alternateBouncerUIAvailable.value = isAvailable 226 } 227 228 override fun setPrimaryShow(isShowing: Boolean) { 229 _primaryBouncerShow.value = isShowing 230 } 231 232 override fun setPrimaryShowingSoon(showingSoon: Boolean) { 233 _primaryBouncerShowingSoon.value = showingSoon 234 } 235 236 override fun setPrimaryStartingToHide(startingToHide: Boolean) { 237 _primaryBouncerStartingToHide.value = startingToHide 238 } 239 240 override fun setPrimaryStartDisappearAnimation(runnable: Runnable?) { 241 _primaryBouncerDisappearAnimation.value = runnable 242 } 243 244 override fun setPanelExpansion(panelExpansion: Float) { 245 _panelExpansionAmount.value = panelExpansion 246 } 247 248 override fun setKeyguardPosition(keyguardPosition: Float) { 249 _keyguardPosition.value = keyguardPosition 250 } 251 252 override fun setResourceUpdateRequests(willUpdateResources: Boolean) { 253 _resourceUpdateRequests.value = willUpdateResources 254 } 255 256 override fun setShowMessage(bouncerShowMessageModel: BouncerShowMessageModel?) { 257 _showMessage.value = bouncerShowMessageModel 258 } 259 260 override fun setKeyguardAuthenticatedBiometrics(keyguardAuthenticatedBiometrics: Boolean?) { 261 _keyguardAuthenticatedBiometrics.value = keyguardAuthenticatedBiometrics 262 } 263 264 override suspend fun setKeyguardAuthenticatedPrimaryAuth(userId: Int) { 265 _keyguardAuthenticatedPrimaryAuth.emit(userId) 266 } 267 268 override suspend fun setUserRequestedBouncerWhenAlreadyAuthenticated(userId: Int) { 269 _userRequestedBouncerWhenAlreadyAuthenticated.emit(userId) 270 } 271 272 override fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean) { 273 _isBackButtonEnabled.value = isBackButtonEnabled 274 } 275 276 override fun setLastShownSecurityMode(securityMode: KeyguardSecurityModel.SecurityMode) { 277 _lastShownSecurityMode.value = securityMode 278 } 279 280 /** Sets up logs for state flows. */ 281 private fun setUpLogging() { 282 if (!Build.IS_DEBUGGABLE) { 283 return 284 } 285 286 primaryBouncerShow 287 .logDiffsForTable(buffer, "", "PrimaryBouncerShow", false) 288 .onEach { Log.d(TAG, "Keyguard Bouncer is ${if (it) "showing" else "hiding."}") } 289 .launchIn(applicationScope) 290 primaryBouncerShowingSoon 291 .logDiffsForTable(buffer, "", "PrimaryBouncerShowingSoon", false) 292 .launchIn(applicationScope) 293 primaryBouncerStartingToHide 294 .logDiffsForTable(buffer, "", "PrimaryBouncerStartingToHide", false) 295 .launchIn(applicationScope) 296 primaryBouncerStartingDisappearAnimation 297 .map { it != null } 298 .logDiffsForTable(buffer, "", "PrimaryBouncerStartingDisappearAnimation", false) 299 .launchIn(applicationScope) 300 primaryBouncerScrimmed 301 .logDiffsForTable(buffer, "", "PrimaryBouncerScrimmed", false) 302 .launchIn(applicationScope) 303 panelExpansionAmount 304 .map { (it * 1000).toInt() } 305 .logDiffsForTable(buffer, "", "PanelExpansionAmountMillis", -1) 306 .launchIn(applicationScope) 307 keyguardPosition 308 .filterNotNull() 309 .map { it.toInt() } 310 .logDiffsForTable(buffer, "", "KeyguardPosition", -1) 311 .launchIn(applicationScope) 312 isBackButtonEnabled 313 .filterNotNull() 314 .logDiffsForTable(buffer, "", "IsBackButtonEnabled", false) 315 .launchIn(applicationScope) 316 showMessage 317 .map { it?.message } 318 .logDiffsForTable(buffer, "", "ShowMessage", null) 319 .launchIn(applicationScope) 320 resourceUpdateRequests 321 .logDiffsForTable(buffer, "", "ResourceUpdateRequests", false) 322 .launchIn(applicationScope) 323 alternateBouncerUIAvailable 324 .logDiffsForTable(buffer, "", "IsAlternateBouncerUIAvailable", false) 325 .launchIn(applicationScope) 326 alternateBouncerVisible 327 .logDiffsForTable(buffer, "", "AlternateBouncerVisible", false) 328 .launchIn(applicationScope) 329 lastShownSecurityMode 330 .map { it.name } 331 .logDiffsForTable(buffer, "", "lastShownSecurityMode", null) 332 .launchIn(applicationScope) 333 } 334 335 companion object { 336 private const val NOT_VISIBLE = -1L 337 private const val TAG = "KeyguardBouncerRepositoryImpl" 338 } 339 } 340