diff --git a/packages/SystemUI/src/com/android/systemui/authentication/AuthenticationModule.kt b/packages/SystemUI/src/com/android/systemui/authentication/AuthenticationModule.kt index 7c394a62a5f42..6128d9195d198 100644 --- a/packages/SystemUI/src/com/android/systemui/authentication/AuthenticationModule.kt +++ b/packages/SystemUI/src/com/android/systemui/authentication/AuthenticationModule.kt @@ -16,8 +16,11 @@ package com.android.systemui.authentication +import com.android.keyguard.KeyguardSecurityModel import com.android.systemui.authentication.data.repository.AuthenticationRepositoryModule import dagger.Module +import dagger.Provides +import java.util.function.Function @Module( includes = @@ -25,4 +28,12 @@ import dagger.Module AuthenticationRepositoryModule::class, ], ) -object AuthenticationModule +object AuthenticationModule { + + @Provides + fun getSecurityMode( + model: KeyguardSecurityModel, + ): Function { + return Function { userId -> model.getSecurityMode(userId) } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt index 0530aed912bc8..35830dad80137 100644 --- a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt @@ -16,13 +16,20 @@ package com.android.systemui.authentication.data.repository +import com.android.internal.widget.LockPatternUtils +import com.android.keyguard.KeyguardSecurityModel import com.android.systemui.authentication.shared.model.AuthenticationMethodModel +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.user.data.repository.UserRepository import dagger.Binds import dagger.Module -import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.withContext +import java.util.function.Function +import javax.inject.Inject /** Defines interface for classes that can access authentication-related application state. */ interface AuthenticationRepository { @@ -37,12 +44,6 @@ interface AuthenticationRepository { */ val isUnlocked: StateFlow - /** - * The currently-configured authentication method. This determines how the authentication - * challenge is completed in order to unlock an otherwise locked device. - */ - val authenticationMethod: StateFlow - /** * Whether lock screen bypass is enabled. When enabled, the lock screen will be automatically * dismisses once the authentication challenge is completed. For example, completing a biometric @@ -57,12 +58,15 @@ interface AuthenticationRepository { */ val failedAuthenticationAttempts: StateFlow + /** + * Returns the currently-configured authentication method. This determines how the + * authentication challenge is completed in order to unlock an otherwise locked device. + */ + suspend fun getAuthenticationMethod(): AuthenticationMethodModel + /** See [isUnlocked]. */ fun setUnlocked(isUnlocked: Boolean) - /** See [authenticationMethod]. */ - fun setAuthenticationMethod(authenticationMethod: AuthenticationMethodModel) - /** See [isBypassEnabled]. */ fun setBypassEnabled(isBypassEnabled: Boolean) @@ -70,19 +74,18 @@ interface AuthenticationRepository { fun setFailedAuthenticationAttempts(failedAuthenticationAttempts: Int) } -class AuthenticationRepositoryImpl @Inject constructor() : AuthenticationRepository { - // TODO(b/280883900): get data from real data sources in SysUI. +class AuthenticationRepositoryImpl +@Inject +constructor( + private val getSecurityMode: Function, + @Background private val backgroundDispatcher: CoroutineDispatcher, + private val userRepository: UserRepository, + private val lockPatternUtils: LockPatternUtils, +) : AuthenticationRepository { private val _isUnlocked = MutableStateFlow(false) override val isUnlocked: StateFlow = _isUnlocked.asStateFlow() - private val _authenticationMethod = - MutableStateFlow( - AuthenticationMethodModel.Pin(listOf(1, 2, 3, 4), autoConfirm = false) - ) - override val authenticationMethod: StateFlow = - _authenticationMethod.asStateFlow() - private val _isBypassEnabled = MutableStateFlow(false) override val isBypassEnabled: StateFlow = _isBypassEnabled.asStateFlow() @@ -90,6 +93,41 @@ class AuthenticationRepositoryImpl @Inject constructor() : AuthenticationReposit override val failedAuthenticationAttempts: StateFlow = _failedAuthenticationAttempts.asStateFlow() + override suspend fun getAuthenticationMethod(): AuthenticationMethodModel { + return withContext(backgroundDispatcher) { + val selectedUserId = userRepository.getSelectedUserInfo().id + when (getSecurityMode.apply(selectedUserId)) { + KeyguardSecurityModel.SecurityMode.PIN, + KeyguardSecurityModel.SecurityMode.SimPin -> + AuthenticationMethodModel.Pin( + code = listOf(1, 2, 3, 4), // TODO(b/280883900): remove this + autoConfirm = lockPatternUtils.isAutoPinConfirmEnabled(selectedUserId), + ) + KeyguardSecurityModel.SecurityMode.Password, + KeyguardSecurityModel.SecurityMode.SimPuk -> + AuthenticationMethodModel.Password( + password = "password", // TODO(b/280883900): remove this + ) + KeyguardSecurityModel.SecurityMode.Pattern -> + AuthenticationMethodModel.Pattern( + coordinates = + listOf( + AuthenticationMethodModel.Pattern.PatternCoordinate(2, 0), + AuthenticationMethodModel.Pattern.PatternCoordinate(2, 1), + AuthenticationMethodModel.Pattern.PatternCoordinate(2, 2), + AuthenticationMethodModel.Pattern.PatternCoordinate(1, 1), + AuthenticationMethodModel.Pattern.PatternCoordinate(0, 0), + AuthenticationMethodModel.Pattern.PatternCoordinate(0, 1), + AuthenticationMethodModel.Pattern.PatternCoordinate(0, 2), + ), // TODO(b/280883900): remove this + ) + KeyguardSecurityModel.SecurityMode.None -> AuthenticationMethodModel.None + KeyguardSecurityModel.SecurityMode.Invalid -> error("Invalid security mode!") + null -> error("Invalid security is null!") + } + } + } + override fun setUnlocked(isUnlocked: Boolean) { _isUnlocked.value = isUnlocked } @@ -98,10 +136,6 @@ class AuthenticationRepositoryImpl @Inject constructor() : AuthenticationReposit _isBypassEnabled.value = isBypassEnabled } - override fun setAuthenticationMethod(authenticationMethod: AuthenticationMethodModel) { - _authenticationMethod.value = authenticationMethod - } - override fun setFailedAuthenticationAttempts(failedAuthenticationAttempts: Int) { _failedAuthenticationAttempts.value = failedAuthenticationAttempts } diff --git a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt index 20e82f70d8f5d..9ae275569b101 100644 --- a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt @@ -25,9 +25,8 @@ import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.launch /** Hosts application business logic related to authentication. */ @SysUISingleton @@ -37,12 +36,6 @@ constructor( @Application applicationScope: CoroutineScope, private val repository: AuthenticationRepository, ) { - /** - * The currently-configured authentication method. This determines how the authentication - * challenge is completed in order to unlock an otherwise locked device. - */ - val authenticationMethod: StateFlow = repository.authenticationMethod - /** * Whether the device is unlocked. * @@ -52,20 +45,18 @@ constructor( * Note that this state has no real bearing on whether the lock screen is showing or dismissed. */ val isUnlocked: StateFlow = - combine(authenticationMethod, repository.isUnlocked) { authMethod, isUnlocked -> - isUnlockedWithAuthMethod( - isUnlocked = isUnlocked, - authMethod = authMethod, - ) + repository.isUnlocked + .map { isUnlocked -> + if (getAuthenticationMethod() is AuthenticationMethodModel.None) { + true + } else { + isUnlocked + } } .stateIn( scope = applicationScope, started = SharingStarted.Eagerly, - initialValue = - isUnlockedWithAuthMethod( - isUnlocked = repository.isUnlocked.value, - authMethod = repository.authenticationMethod.value, - ) + initialValue = true, ) /** @@ -82,25 +73,20 @@ constructor( */ val failedAuthenticationAttempts: StateFlow = repository.failedAuthenticationAttempts - init { - // UNLOCKS WHEN AUTH METHOD REMOVED. - // - // Unlocks the device if the auth method becomes None. - applicationScope.launch { - repository.authenticationMethod.collect { - if (it is AuthenticationMethodModel.None) { - unlockDevice() - } - } - } + /** + * Returns the currently-configured authentication method. This determines how the + * authentication challenge is completed in order to unlock an otherwise locked device. + */ + suspend fun getAuthenticationMethod(): AuthenticationMethodModel { + return repository.getAuthenticationMethod() } /** * Returns `true` if the device currently requires authentication before content can be viewed; * `false` if content can be displayed without unlocking first. */ - fun isAuthenticationRequired(): Boolean { - return !isUnlocked.value && authenticationMethod.value.isSecure + suspend fun isAuthenticationRequired(): Boolean { + return !isUnlocked.value && getAuthenticationMethod().isSecure } /** @@ -133,8 +119,8 @@ constructor( * @return `true` if the authentication succeeded and the device is now unlocked; `false` when * authentication failed, `null` if the check was not performed. */ - fun authenticate(input: List, tryAutoConfirm: Boolean = false): Boolean? { - val authMethod = this.authenticationMethod.value + suspend fun authenticate(input: List, tryAutoConfirm: Boolean = false): Boolean? { + val authMethod = getAuthenticationMethod() if (tryAutoConfirm) { if ((authMethod as? AuthenticationMethodModel.Pin)?.autoConfirm != true) { // Do not attempt to authenticate unless the PIN lock is set to auto-confirm. @@ -176,28 +162,12 @@ constructor( repository.setUnlocked(true) } - /** See [authenticationMethod]. */ - fun setAuthenticationMethod(authenticationMethod: AuthenticationMethodModel) { - repository.setAuthenticationMethod(authenticationMethod) - } - /** See [isBypassEnabled]. */ fun toggleBypassEnabled() { repository.setBypassEnabled(!repository.isBypassEnabled.value) } companion object { - private fun isUnlockedWithAuthMethod( - isUnlocked: Boolean, - authMethod: AuthenticationMethodModel, - ): Boolean { - return if (authMethod is AuthenticationMethodModel.None) { - true - } else { - isUnlocked - } - } - /** * Returns a PIN code from the given list. It's assumed the given list elements are all * [Int] in the range [0-9]. diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt index 256c63515fc87..cb841623485c8 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt @@ -68,43 +68,39 @@ constructor( ) ) - /** - * The currently-configured authentication method. This determines how the authentication - * challenge is completed in order to unlock an otherwise locked device. - */ - val authenticationMethod: StateFlow = - authenticationInteractor.authenticationMethod - /** The current authentication throttling state. If `null`, there's no throttling. */ val throttling: StateFlow = repository.throttling init { applicationScope.launch { - combine( - sceneInteractor.currentScene(containerName), - authenticationInteractor.authenticationMethod, - ::Pair, - ) - .collect { (currentScene, authMethod) -> - if (currentScene.key == SceneKey.Bouncer) { - when (authMethod) { - is AuthenticationMethodModel.None -> - sceneInteractor.setCurrentScene( - containerName, - SceneModel(SceneKey.Gone), - ) - is AuthenticationMethodModel.Swipe -> - sceneInteractor.setCurrentScene( - containerName, - SceneModel(SceneKey.Lockscreen), - ) - else -> Unit - } + sceneInteractor.currentScene(containerName).collect { currentScene -> + if (currentScene.key == SceneKey.Bouncer) { + when (getAuthenticationMethod()) { + is AuthenticationMethodModel.None -> + sceneInteractor.setCurrentScene( + containerName, + SceneModel(SceneKey.Gone), + ) + is AuthenticationMethodModel.Swipe -> + sceneInteractor.setCurrentScene( + containerName, + SceneModel(SceneKey.Lockscreen), + ) + else -> Unit } } + } } } + /** + * Returns the currently-configured authentication method. This determines how the + * authentication challenge is completed in order to unlock an otherwise locked device. + */ + suspend fun getAuthenticationMethod(): AuthenticationMethodModel { + return authenticationInteractor.getAuthenticationMethod() + } + /** * Either shows the bouncer or unlocks the device, if the bouncer doesn't need to be shown. * @@ -115,18 +111,20 @@ constructor( containerName: String, message: String? = null, ) { - if (authenticationInteractor.isAuthenticationRequired()) { - repository.setMessage(message ?: promptMessage(authenticationMethod.value)) - sceneInteractor.setCurrentScene( - containerName = containerName, - scene = SceneModel(SceneKey.Bouncer), - ) - } else { - authenticationInteractor.unlockDevice() - sceneInteractor.setCurrentScene( - containerName = containerName, - scene = SceneModel(SceneKey.Gone), - ) + applicationScope.launch { + if (authenticationInteractor.isAuthenticationRequired()) { + repository.setMessage(message ?: promptMessage(getAuthenticationMethod())) + sceneInteractor.setCurrentScene( + containerName = containerName, + scene = SceneModel(SceneKey.Bouncer), + ) + } else { + authenticationInteractor.unlockDevice() + sceneInteractor.setCurrentScene( + containerName = containerName, + scene = SceneModel(SceneKey.Gone), + ) + } } } @@ -135,7 +133,7 @@ constructor( * method. */ fun resetMessage() { - repository.setMessage(promptMessage(authenticationMethod.value)) + applicationScope.launch { repository.setMessage(promptMessage(getAuthenticationMethod())) } } /** Removes the user-facing message. */ @@ -160,7 +158,7 @@ constructor( * @return `true` if the authentication succeeded and the device is now unlocked; `false` when * authentication failed, `null` if the check was not performed. */ - fun authenticate( + suspend fun authenticate( input: List, tryAutoConfirm: Boolean = false, ): Boolean? { @@ -198,7 +196,7 @@ constructor( repository.setThrottling(null) clearMessage() } - else -> repository.setMessage(errorMessage(authenticationMethod.value)) + else -> repository.setMessage(errorMessage(getAuthenticationMethod())) } return isAuthenticated diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt index 527fe6ec847d0..7448f27bef50a 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt @@ -32,6 +32,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch @@ -66,6 +67,7 @@ constructor( private val password: PasswordBouncerViewModel by lazy { PasswordBouncerViewModel( + applicationScope = applicationScope, interactor = interactor, isInputEnabled = isInputEnabled, ) @@ -81,14 +83,25 @@ constructor( } /** View-model for the current UI, based on the current authentication method. */ - val authMethod: StateFlow = - interactor.authenticationMethod - .map { authMethod -> toViewModel(authMethod) } - .stateIn( - scope = applicationScope, - started = SharingStarted.WhileSubscribed(), - initialValue = toViewModel(interactor.authenticationMethod.value), - ) + val authMethod: StateFlow + get() = + flow { + emit(null) + emit(interactor.getAuthenticationMethod()) + } + .map { authMethod -> + when (authMethod) { + is AuthenticationMethodModel.Pin -> pin + is AuthenticationMethodModel.Password -> password + is AuthenticationMethodModel.Pattern -> pattern + else -> null + } + } + .stateIn( + scope = applicationScope, + started = SharingStarted.WhileSubscribed(), + initialValue = null, + ) /** The user-facing message to show in the bouncer. */ val message: StateFlow = @@ -125,7 +138,7 @@ constructor( interactor.throttling .map { model -> model?.let { - when (interactor.authenticationMethod.value) { + when (interactor.getAuthenticationMethod()) { is AuthenticationMethodModel.Pin -> R.string.kg_too_many_failed_pin_attempts_dialog_message is AuthenticationMethodModel.Password -> @@ -161,17 +174,6 @@ constructor( _throttlingDialogMessage.value = null } - private fun toViewModel( - authMethod: AuthenticationMethodModel, - ): AuthMethodBouncerViewModel? { - return when (authMethod) { - is AuthenticationMethodModel.Pin -> pin - is AuthenticationMethodModel.Password -> password - is AuthenticationMethodModel.Pattern -> pattern - else -> null - } - } - private fun toMessageViewModel( message: String?, throttling: AuthenticationThrottledModel?, diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt index 0146e406703c2..ca15f4e063a9e 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt @@ -17,12 +17,15 @@ package com.android.systemui.bouncer.ui.viewmodel import com.android.systemui.bouncer.domain.interactor.BouncerInteractor +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch /** Holds UI state and handles user input for the password bouncer UI. */ class PasswordBouncerViewModel( + private val applicationScope: CoroutineScope, private val interactor: BouncerInteractor, isInputEnabled: StateFlow, ) : @@ -50,10 +53,13 @@ class PasswordBouncerViewModel( /** Notifies that the user has pressed the key for attempting to authenticate the password. */ fun onAuthenticateKeyPressed() { - if (interactor.authenticate(password.value.toCharArray().toList()) != true) { - showFailureAnimation() - } - + val password = _password.value.toCharArray().toList() _password.value = "" + + applicationScope.launch { + if (interactor.authenticate(password) != true) { + showFailureAnimation() + } + } } } diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt index 700703ee35601..5efa6f073f7ac 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt @@ -29,13 +29,15 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch /** Holds UI state and handles user input for the pattern bouncer UI. */ class PatternBouncerViewModel( private val applicationContext: Context, - applicationScope: CoroutineScope, + private val applicationScope: CoroutineScope, private val interactor: BouncerInteractor, isInputEnabled: StateFlow, ) : @@ -69,12 +71,17 @@ class PatternBouncerViewModel( /** Whether the pattern itself should be rendered visibly. */ val isPatternVisible: StateFlow = - interactor.authenticationMethod - .map { authMethod -> isPatternVisible(authMethod) } + flow { + emit(null) + emit(interactor.getAuthenticationMethod()) + } + .map { authMethod -> + (authMethod as? AuthenticationMethodModel.Pattern)?.isPatternVisible ?: false + } .stateIn( scope = applicationScope, started = SharingStarted.Eagerly, - initialValue = isPatternVisible(interactor.authenticationMethod.value), + initialValue = false, ) /** Notifies that the UI has been shown to the user. */ @@ -154,17 +161,15 @@ class PatternBouncerViewModel( /** Notifies that the user has ended the drag gesture across the dot grid. */ fun onDragEnd() { val pattern = _selectedDots.value.map { it.toCoordinate() } - if (interactor.authenticate(pattern) != true) { - showFailureAnimation() - } - _dots.value = defaultDots() _currentDot.value = null _selectedDots.value = linkedSetOf() - } - private fun isPatternVisible(authMethodModel: AuthenticationMethodModel): Boolean { - return (authMethodModel as? AuthenticationMethodModel.Pattern)?.isPatternVisible ?: false + applicationScope.launch { + if (interactor.authenticate(pattern) != true) { + showFailureAnimation() + } + } } private fun defaultDots(): List { diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt index 1944c74f1d6a6..7c96e82c4488c 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt @@ -22,13 +22,14 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch /** Holds UI state and handles user input for the PIN code bouncer UI. */ class PinBouncerViewModel( - applicationScope: CoroutineScope, + private val applicationScope: CoroutineScope, private val interactor: BouncerInteractor, isInputEnabled: StateFlow, ) : @@ -39,40 +40,48 @@ class PinBouncerViewModel( private val mutablePinEntries = MutableStateFlow>(emptyList()) val pinEntries: StateFlow> = mutablePinEntries - /** The length of the hinted PIN, or null if pin length hint should not be shown. */ + /** The length of the hinted PIN, or `null` if pin length hint should not be shown. */ val hintedPinLength: StateFlow = - interactor.authenticationMethod - .map { authMethod -> computeHintedPinLength(authMethod) } - .stateIn( - scope = applicationScope, - started = SharingStarted.Eagerly, - initialValue = computeHintedPinLength(interactor.authenticationMethod.value), - ) - - /** Appearance of the backspace button. */ - val backspaceButtonAppearance: StateFlow = - combine(interactor.authenticationMethod, mutablePinEntries) { authMethod, enteredPin -> - computeBackspaceButtonAppearance(authMethod, enteredPin) + flow { + emit(null) + emit(interactor.getAuthenticationMethod()) + } + .map { authMethod -> + // Hinting is enabled for 6-digit codes only + autoConfirmPinLength(authMethod).takeIf { it == HINTING_PASSCODE_LENGTH } } .stateIn( scope = applicationScope, started = SharingStarted.Eagerly, - initialValue = - computeBackspaceButtonAppearance( - interactor.authenticationMethod.value, - mutablePinEntries.value - ), + initialValue = null, + ) + + /** Appearance of the backspace button. */ + val backspaceButtonAppearance: StateFlow = + mutablePinEntries + .map { mutablePinEntries -> + computeBackspaceButtonAppearance( + interactor.getAuthenticationMethod(), + mutablePinEntries + ) + } + .stateIn( + scope = applicationScope, + started = SharingStarted.Eagerly, + initialValue = ActionButtonAppearance.Hidden, ) /** Appearance of the confirm button. */ val confirmButtonAppearance: StateFlow = - interactor.authenticationMethod + flow { + emit(null) + emit(interactor.getAuthenticationMethod()) + } .map { authMethod -> computeConfirmButtonAppearance(authMethod) } .stateIn( scope = applicationScope, started = SharingStarted.Eagerly, - initialValue = - computeConfirmButtonAppearance(interactor.authenticationMethod.value), + initialValue = ActionButtonAppearance.Hidden, ) /** Notifies that the UI has been shown to the user. */ @@ -111,30 +120,28 @@ class PinBouncerViewModel( private fun tryAuthenticate(useAutoConfirm: Boolean) { val pinCode = mutablePinEntries.value.map { it.input } - val isSuccess = interactor.authenticate(pinCode, useAutoConfirm) ?: return - if (!isSuccess) { - showFailureAnimation() + applicationScope.launch { + val isSuccess = interactor.authenticate(pinCode, useAutoConfirm) ?: return@launch + + if (!isSuccess) { + showFailureAnimation() + } + + mutablePinEntries.value = emptyList() } - - mutablePinEntries.value = emptyList() } - private fun isAutoConfirmEnabled(authMethodModel: AuthenticationMethodModel): Boolean { + private fun isAutoConfirmEnabled(authMethodModel: AuthenticationMethodModel?): Boolean { return (authMethodModel as? AuthenticationMethodModel.Pin)?.autoConfirm == true } - private fun autoConfirmPinLength(authMethodModel: AuthenticationMethodModel): Int? { + private fun autoConfirmPinLength(authMethodModel: AuthenticationMethodModel?): Int? { if (!isAutoConfirmEnabled(authMethodModel)) return null return (authMethodModel as? AuthenticationMethodModel.Pin)?.code?.size } - private fun computeHintedPinLength(authMethodModel: AuthenticationMethodModel): Int? { - // Hinting is enabled for 6-digit codes only - return autoConfirmPinLength(authMethodModel).takeIf { it == HINTING_PASSCODE_LENGTH } - } - private fun computeBackspaceButtonAppearance( authMethodModel: AuthenticationMethodModel, enteredPin: List @@ -149,7 +156,7 @@ class PinBouncerViewModel( } } private fun computeConfirmButtonAppearance( - authMethodModel: AuthenticationMethodModel + authMethodModel: AuthenticationMethodModel? ): ActionButtonAppearance { return if (isAutoConfirmEnabled(authMethodModel)) { ActionButtonAppearance.Hidden diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractor.kt index d0bc25fd26f49..7bbc0d68ff084 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractor.kt @@ -61,23 +61,16 @@ constructor( /** Whether it's currently possible to swipe up to dismiss the lockscreen. */ val isSwipeToDismissEnabled: StateFlow = - combine( - authenticationInteractor.isUnlocked, - authenticationInteractor.authenticationMethod, - ) { isUnlocked, authMethod -> - isSwipeToUnlockEnabled( - isUnlocked = isUnlocked, - authMethod = authMethod, - ) + authenticationInteractor.isUnlocked + .map { isUnlocked -> + !isUnlocked && + authenticationInteractor.getAuthenticationMethod() is + AuthenticationMethodModel.Swipe } .stateIn( scope = applicationScope, started = SharingStarted.WhileSubscribed(), - initialValue = - isSwipeToUnlockEnabled( - isUnlocked = authenticationInteractor.isUnlocked.value, - authMethod = authenticationInteractor.authenticationMethod.value, - ), + initialValue = false, ) init { @@ -124,44 +117,17 @@ constructor( // If switched from the lockscreen to the gone scene and the auth method was a swipe, // unlocks the device. applicationScope.launch { - combine( - authenticationInteractor.authenticationMethod, - sceneInteractor.currentScene(containerName).pairwise(), - ::Pair, - ) - .collect { (authMethod, scenes) -> - val (previousScene, currentScene) = scenes - if ( - authMethod is AuthenticationMethodModel.Swipe && - previousScene.key == SceneKey.Lockscreen && - currentScene.key == SceneKey.Gone - ) { - authenticationInteractor.unlockDevice() - } - } - } - - // DISMISS Lockscreen IF AUTH METHOD IS REMOVED. - // - // If the auth method becomes None while on the lockscreen scene, dismisses the lock - // screen. - applicationScope.launch { - combine( - authenticationInteractor.authenticationMethod, - sceneInteractor.currentScene(containerName), - ::Pair, - ) - .collect { (authMethod, scene) -> - if ( - scene.key == SceneKey.Lockscreen && - authMethod == AuthenticationMethodModel.None - ) { - sceneInteractor.setCurrentScene( - containerName = containerName, - scene = SceneModel(SceneKey.Gone), - ) - } + sceneInteractor.currentScene(containerName).pairwise().collect { + (previousScene, currentScene) -> + if ( + authenticationInteractor.getAuthenticationMethod() is + AuthenticationMethodModel.Swipe && + previousScene.key == SceneKey.Lockscreen && + currentScene.key == SceneKey.Gone + ) { + authenticationInteractor.unlockDevice() } + } } } @@ -170,13 +136,6 @@ constructor( bouncerInteractor.showOrUnlockDevice(containerName = containerName) } - private fun isSwipeToUnlockEnabled( - isUnlocked: Boolean, - authMethod: AuthenticationMethodModel, - ): Boolean { - return !isUnlocked && authMethod is AuthenticationMethodModel.Swipe - } - @AssistedFactory interface Factory { fun create( diff --git a/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt index ac2d492f3320b..c783325539d2d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt @@ -25,7 +25,6 @@ import com.android.systemui.coroutines.collectLastValue import com.android.systemui.scene.SceneTestUtils import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Test @@ -37,8 +36,8 @@ import org.junit.runners.JUnit4 @RunWith(JUnit4::class) class AuthenticationInteractorTest : SysuiTestCase() { - private val testScope = TestScope() - private val utils = SceneTestUtils(this, testScope) + private val utils = SceneTestUtils(this) + private val testScope = utils.testScope private val repository: AuthenticationRepository = utils.authenticationRepository() private val underTest = utils.authenticationInteractor( @@ -46,23 +45,23 @@ class AuthenticationInteractorTest : SysuiTestCase() { ) @Test - fun authMethod() = + fun getAuthenticationMethod() = testScope.runTest { - val authMethod by collectLastValue(underTest.authenticationMethod) - assertThat(authMethod).isEqualTo(AuthenticationMethodModel.Pin(1234)) + assertThat(underTest.getAuthenticationMethod()) + .isEqualTo(AuthenticationMethodModel.Pin(1234)) - underTest.setAuthenticationMethod(AuthenticationMethodModel.Password("password")) - assertThat(authMethod).isEqualTo(AuthenticationMethodModel.Password("password")) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Password("password") + ) + assertThat(underTest.getAuthenticationMethod()) + .isEqualTo(AuthenticationMethodModel.Password("password")) } @Test fun isUnlocked_whenAuthMethodIsNone_isTrue() = testScope.runTest { + utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None) val isUnlocked by collectLastValue(underTest.isUnlocked) - assertThat(isUnlocked).isFalse() - - underTest.setAuthenticationMethod(AuthenticationMethodModel.None) - assertThat(isUnlocked).isTrue() } @@ -108,7 +107,9 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { underTest.lockDevice() runCurrent() - underTest.setAuthenticationMethod(AuthenticationMethodModel.Password("password")) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Password("password") + ) assertThat(underTest.isAuthenticationRequired()).isTrue() } @@ -118,7 +119,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { underTest.lockDevice() runCurrent() - underTest.setAuthenticationMethod(AuthenticationMethodModel.Swipe) + utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Swipe) assertThat(underTest.isAuthenticationRequired()).isFalse() } @@ -128,7 +129,9 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { underTest.unlockDevice() runCurrent() - underTest.setAuthenticationMethod(AuthenticationMethodModel.Password("password")) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Password("password") + ) assertThat(underTest.isAuthenticationRequired()).isFalse() } @@ -138,7 +141,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { underTest.unlockDevice() runCurrent() - underTest.setAuthenticationMethod(AuthenticationMethodModel.Swipe) + utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Swipe) assertThat(underTest.isAuthenticationRequired()).isFalse() } @@ -148,7 +151,9 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) - underTest.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) assertThat(isUnlocked).isFalse() assertThat(underTest.authenticate(listOf(1, 2, 3, 4))).isTrue() @@ -161,7 +166,9 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) - underTest.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) assertThat(isUnlocked).isFalse() assertThat(underTest.authenticate(listOf(9, 8, 7))).isFalse() @@ -174,7 +181,9 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) - underTest.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) assertThat(isUnlocked).isFalse() assertThat(underTest.authenticate(listOf())).isFalse() @@ -187,7 +196,9 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) - underTest.setAuthenticationMethod(AuthenticationMethodModel.Pin(9999999999999999)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(9999999999999999) + ) assertThat(isUnlocked).isFalse() assertThat(underTest.authenticate(List(16) { 9 })).isTrue() @@ -206,7 +217,9 @@ class AuthenticationInteractorTest : SysuiTestCase() { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) - underTest.setAuthenticationMethod(AuthenticationMethodModel.Pin(99999999999999999)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(99999999999999999) + ) assertThat(isUnlocked).isFalse() assertThat(underTest.authenticate(List(17) { 9 })).isFalse() @@ -219,7 +232,9 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) - underTest.setAuthenticationMethod(AuthenticationMethodModel.Password("password")) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Password("password") + ) assertThat(isUnlocked).isFalse() assertThat(underTest.authenticate("password".toList())).isTrue() @@ -232,7 +247,9 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) - underTest.setAuthenticationMethod(AuthenticationMethodModel.Password("password")) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Password("password") + ) assertThat(isUnlocked).isFalse() assertThat(underTest.authenticate("alohomora".toList())).isFalse() @@ -245,7 +262,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) - underTest.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pattern( listOf( AuthenticationMethodModel.Pattern.PatternCoordinate( @@ -293,7 +310,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) - underTest.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pattern( listOf( AuthenticationMethodModel.Pattern.PatternCoordinate( @@ -341,7 +358,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) - underTest.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pin(1234, autoConfirm = true) ) assertThat(isUnlocked).isFalse() @@ -356,7 +373,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) - underTest.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pin(1234, autoConfirm = true) ) assertThat(isUnlocked).isFalse() @@ -371,7 +388,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) - underTest.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pin(1234, autoConfirm = true) ) assertThat(isUnlocked).isFalse() @@ -386,7 +403,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) - underTest.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pin(1234, autoConfirm = true) ) assertThat(isUnlocked).isFalse() @@ -402,7 +419,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) - underTest.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pin(1234, autoConfirm = true) ) assertThat(isUnlocked).isFalse() @@ -417,7 +434,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) - underTest.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pin(1234, autoConfirm = false) ) assertThat(isUnlocked).isFalse() @@ -432,22 +449,13 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) - underTest.setAuthenticationMethod(AuthenticationMethodModel.Password("password")) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Password("password") + ) assertThat(isUnlocked).isFalse() assertThat(underTest.authenticate("password".toList(), tryAutoConfirm = true)).isNull() assertThat(isUnlocked).isFalse() assertThat(failedAttemptCount).isEqualTo(0) } - - @Test - fun unlocksDevice_whenAuthMethodBecomesNone() = - testScope.runTest { - val isUnlocked by collectLastValue(underTest.isUnlocked) - assertThat(isUnlocked).isFalse() - - repository.setAuthenticationMethod(AuthenticationMethodModel.None) - - assertThat(isUnlocked).isTrue() - } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt index 9483667909d59..92cf0a51082d3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt @@ -26,7 +26,6 @@ import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.scene.shared.model.SceneModel import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest @@ -40,8 +39,8 @@ import org.junit.runners.JUnit4 @RunWith(JUnit4::class) class BouncerInteractorTest : SysuiTestCase() { - private val testScope = TestScope() - private val utils = SceneTestUtils(this, testScope) + private val utils = SceneTestUtils(this) + private val testScope = utils.testScope private val authenticationInteractor = utils.authenticationInteractor( repository = utils.authenticationRepository(), @@ -69,7 +68,9 @@ class BouncerInteractorTest : SysuiTestCase() { val currentScene by collectLastValue(sceneInteractor.currentScene("container1")) val message by collectLastValue(underTest.message) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.lockDevice() underTest.showOrUnlockDevice("container1") assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer)) @@ -100,7 +101,7 @@ class BouncerInteractorTest : SysuiTestCase() { val currentScene by collectLastValue(sceneInteractor.currentScene("container1")) val message by collectLastValue(underTest.message) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pin(1234, autoConfirm = true) ) authenticationInteractor.lockDevice() @@ -130,7 +131,7 @@ class BouncerInteractorTest : SysuiTestCase() { val currentScene by collectLastValue(sceneInteractor.currentScene("container1")) val message by collectLastValue(underTest.message) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pin(1234, autoConfirm = false) ) authenticationInteractor.lockDevice() @@ -154,7 +155,7 @@ class BouncerInteractorTest : SysuiTestCase() { testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene("container1")) val message by collectLastValue(underTest.message) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Password("password") ) authenticationInteractor.lockDevice() @@ -186,7 +187,7 @@ class BouncerInteractorTest : SysuiTestCase() { testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene("container1")) val message by collectLastValue(underTest.message) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pattern(emptyList()) ) authenticationInteractor.lockDevice() @@ -222,7 +223,9 @@ class BouncerInteractorTest : SysuiTestCase() { fun showOrUnlockDevice_notLocked_switchesToGoneScene() = testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene("container1")) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.unlockDevice() runCurrent() @@ -235,7 +238,7 @@ class BouncerInteractorTest : SysuiTestCase() { fun showOrUnlockDevice_authMethodNotSecure_switchesToGoneScene() = testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene("container1")) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Swipe) + utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Swipe) authenticationInteractor.lockDevice() underTest.showOrUnlockDevice("container1") @@ -248,7 +251,7 @@ class BouncerInteractorTest : SysuiTestCase() { testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene("container1")) val message by collectLastValue(underTest.message) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Password("password") ) authenticationInteractor.lockDevice() @@ -266,7 +269,9 @@ class BouncerInteractorTest : SysuiTestCase() { val throttling by collectLastValue(underTest.throttling) val message by collectLastValue(underTest.message) val isUnlocked by collectLastValue(authenticationInteractor.isUnlocked) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) assertThat(throttling).isNull() assertThat(message).isEqualTo("") assertThat(isUnlocked).isFalse() diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt index b53e03419df3b..22ac1b678dccc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt @@ -24,7 +24,6 @@ import com.android.systemui.scene.SceneTestUtils import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.runner.RunWith @@ -35,8 +34,8 @@ import org.junit.runners.JUnit4 @RunWith(JUnit4::class) class AuthMethodBouncerViewModelTest : SysuiTestCase() { - private val testScope = TestScope() - private val utils = SceneTestUtils(this, testScope) + private val utils = SceneTestUtils(this) + private val testScope = utils.testScope private val authenticationInteractor = utils.authenticationInteractor( utils.authenticationRepository(), @@ -55,7 +54,9 @@ class AuthMethodBouncerViewModelTest : SysuiTestCase() { @Test fun animateFailure() = testScope.runTest { - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) val animateFailure by collectLastValue(underTest.animateFailure) assertThat(animateFailure).isFalse() diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt index c6074962ee8e1..53f972e64bcd8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt @@ -26,7 +26,6 @@ import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.flatMapLatest -import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runTest import org.junit.Test @@ -38,8 +37,8 @@ import org.junit.runners.JUnit4 @RunWith(JUnit4::class) class BouncerViewModelTest : SysuiTestCase() { - private val testScope = TestScope() - private val utils = SceneTestUtils(this, testScope) + private val utils = SceneTestUtils(this) + private val testScope = utils.testScope private val authenticationInteractor = utils.authenticationInteractor( repository = utils.authenticationRepository(), @@ -54,11 +53,11 @@ class BouncerViewModelTest : SysuiTestCase() { @Test fun authMethod_nonNullForSecureMethods_nullForNotSecureMethods() = testScope.runTest { - val authMethodViewModel: AuthMethodBouncerViewModel? by - collectLastValue(underTest.authMethod) authMethodsToTest().forEach { authMethod -> - authenticationInteractor.setAuthenticationMethod(authMethod) + utils.authenticationRepository.setAuthenticationMethod(authMethod) + val authMethodViewModel: AuthMethodBouncerViewModel? by + collectLastValue(underTest.authMethod) if (authMethod.isSecure) { assertThat(authMethodViewModel).isNotNull() } else { @@ -75,13 +74,13 @@ class BouncerViewModelTest : SysuiTestCase() { collectLastValue(underTest.authMethod) // First pass, populate our "seen" map: authMethodsToTest().forEach { authMethod -> - authenticationInteractor.setAuthenticationMethod(authMethod) + utils.authenticationRepository.setAuthenticationMethod(authMethod) authMethodViewModel?.let { seen[authMethod] = it } } // Second pass, assert same instances are reused: authMethodsToTest().forEach { authMethod -> - authenticationInteractor.setAuthenticationMethod(authMethod) + utils.authenticationRepository.setAuthenticationMethod(authMethod) authMethodViewModel?.let { assertThat(it).isSameInstanceAs(seen[authMethod]) } } } @@ -97,7 +96,9 @@ class BouncerViewModelTest : SysuiTestCase() { testScope.runTest { val message by collectLastValue(underTest.message) val throttling by collectLastValue(bouncerInteractor.throttling) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) assertThat(message?.isUpdateAnimated).isTrue() repeat(BouncerInteractor.THROTTLE_EVERY) { @@ -120,7 +121,9 @@ class BouncerViewModelTest : SysuiTestCase() { } ) val throttling by collectLastValue(bouncerInteractor.throttling) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) assertThat(isInputEnabled).isTrue() repeat(BouncerInteractor.THROTTLE_EVERY) { @@ -137,7 +140,9 @@ class BouncerViewModelTest : SysuiTestCase() { fun throttlingDialogMessage() = testScope.runTest { val throttlingDialogMessage by collectLastValue(underTest.throttlingDialogMessage) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) repeat(BouncerInteractor.THROTTLE_EVERY) { // Wrong PIN. diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt index f436aa309ac50..7d65c80d9fe8d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt @@ -28,7 +28,7 @@ import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test @@ -40,8 +40,8 @@ import org.junit.runners.JUnit4 @RunWith(JUnit4::class) class PasswordBouncerViewModelTest : SysuiTestCase() { - private val testScope = TestScope() - private val utils = SceneTestUtils(this, testScope) + private val utils = SceneTestUtils(this) + private val testScope = utils.testScope private val authenticationInteractor = utils.authenticationInteractor( repository = utils.authenticationRepository(), @@ -58,6 +58,7 @@ class PasswordBouncerViewModelTest : SysuiTestCase() { ) private val underTest = PasswordBouncerViewModel( + applicationScope = testScope.backgroundScope, interactor = bouncerInteractor, isInputEnabled = MutableStateFlow(true).asStateFlow(), ) @@ -75,7 +76,7 @@ class PasswordBouncerViewModelTest : SysuiTestCase() { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME)) val message by collectLastValue(bouncerViewModel.message) val password by collectLastValue(underTest.password) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Password("password") ) authenticationInteractor.lockDevice() @@ -98,7 +99,7 @@ class PasswordBouncerViewModelTest : SysuiTestCase() { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME)) val message by collectLastValue(bouncerViewModel.message) val password by collectLastValue(underTest.password) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Password("password") ) authenticationInteractor.lockDevice() @@ -106,6 +107,7 @@ class PasswordBouncerViewModelTest : SysuiTestCase() { assertThat(isUnlocked).isFalse() assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer)) underTest.onShown() + runCurrent() underTest.onPasswordInputChanged("password") @@ -120,7 +122,7 @@ class PasswordBouncerViewModelTest : SysuiTestCase() { testScope.runTest { val isUnlocked by collectLastValue(authenticationInteractor.isUnlocked) val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME)) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Password("password") ) authenticationInteractor.lockDevice() @@ -143,7 +145,7 @@ class PasswordBouncerViewModelTest : SysuiTestCase() { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME)) val message by collectLastValue(bouncerViewModel.message) val password by collectLastValue(underTest.password) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Password("password") ) authenticationInteractor.lockDevice() @@ -168,7 +170,7 @@ class PasswordBouncerViewModelTest : SysuiTestCase() { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME)) val message by collectLastValue(bouncerViewModel.message) val password by collectLastValue(underTest.password) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Password("password") ) authenticationInteractor.lockDevice() diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt index d7d7154705edc..9f163584be8c7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt @@ -29,7 +29,7 @@ import com.google.common.truth.Truth.assertWithMessage import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test @@ -41,8 +41,8 @@ import org.junit.runners.JUnit4 @RunWith(JUnit4::class) class PatternBouncerViewModelTest : SysuiTestCase() { - private val testScope = TestScope() - private val utils = SceneTestUtils(this, testScope) + private val utils = SceneTestUtils(this) + private val testScope = utils.testScope private val authenticationInteractor = utils.authenticationInteractor( repository = utils.authenticationRepository(), @@ -79,7 +79,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() { val message by collectLastValue(bouncerViewModel.message) val selectedDots by collectLastValue(underTest.selectedDots) val currentDot by collectLastValue(underTest.currentDot) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pattern(CORRECT_PATTERN) ) authenticationInteractor.lockDevice() @@ -104,7 +104,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() { val message by collectLastValue(bouncerViewModel.message) val selectedDots by collectLastValue(underTest.selectedDots) val currentDot by collectLastValue(underTest.currentDot) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pattern(CORRECT_PATTERN) ) authenticationInteractor.lockDevice() @@ -112,6 +112,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() { assertThat(isUnlocked).isFalse() assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer)) underTest.onShown() + runCurrent() underTest.onDragStart() @@ -129,7 +130,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME)) val selectedDots by collectLastValue(underTest.selectedDots) val currentDot by collectLastValue(underTest.currentDot) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pattern(CORRECT_PATTERN) ) authenticationInteractor.lockDevice() @@ -180,7 +181,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() { val message by collectLastValue(bouncerViewModel.message) val selectedDots by collectLastValue(underTest.selectedDots) val currentDot by collectLastValue(underTest.currentDot) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pattern(CORRECT_PATTERN) ) authenticationInteractor.lockDevice() @@ -215,7 +216,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() { val message by collectLastValue(bouncerViewModel.message) val selectedDots by collectLastValue(underTest.selectedDots) val currentDot by collectLastValue(underTest.currentDot) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pattern(CORRECT_PATTERN) ) authenticationInteractor.lockDevice() diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt index 7e358d27046b5..a9907c0424a67 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt @@ -29,7 +29,7 @@ import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test @@ -41,8 +41,8 @@ import org.junit.runners.JUnit4 @RunWith(JUnit4::class) class PinBouncerViewModelTest : SysuiTestCase() { - private val testScope = TestScope() - private val utils = SceneTestUtils(this, testScope) + private val utils = SceneTestUtils(this) + private val testScope = utils.testScope private val sceneInteractor = utils.sceneInteractor() private val authenticationInteractor = utils.authenticationInteractor( @@ -85,7 +85,6 @@ class PinBouncerViewModelTest : SysuiTestCase() { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME)) val message by collectLastValue(bouncerViewModel.message) val entries by collectLastValue(underTest.pinEntries) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) authenticationInteractor.lockDevice() sceneInteractor.setCurrentScene(CONTAINER_NAME, SceneModel(SceneKey.Bouncer)) assertThat(isUnlocked).isFalse() @@ -106,12 +105,15 @@ class PinBouncerViewModelTest : SysuiTestCase() { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME)) val message by collectLastValue(bouncerViewModel.message) val entries by collectLastValue(underTest.pinEntries) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.lockDevice() sceneInteractor.setCurrentScene(CONTAINER_NAME, SceneModel(SceneKey.Bouncer)) assertThat(isUnlocked).isFalse() assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer)) underTest.onShown() + runCurrent() underTest.onPinButtonClicked(1) @@ -129,12 +131,15 @@ class PinBouncerViewModelTest : SysuiTestCase() { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME)) val message by collectLastValue(bouncerViewModel.message) val entries by collectLastValue(underTest.pinEntries) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.lockDevice() sceneInteractor.setCurrentScene(CONTAINER_NAME, SceneModel(SceneKey.Bouncer)) assertThat(isUnlocked).isFalse() assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer)) underTest.onShown() + runCurrent() underTest.onPinButtonClicked(1) assertThat(entries).hasSize(1) @@ -153,7 +158,9 @@ class PinBouncerViewModelTest : SysuiTestCase() { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME)) val message by collectLastValue(bouncerViewModel.message) val entries by collectLastValue(underTest.pinEntries) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.lockDevice() sceneInteractor.setCurrentScene(CONTAINER_NAME, SceneModel(SceneKey.Bouncer)) assertThat(isUnlocked).isFalse() @@ -180,12 +187,15 @@ class PinBouncerViewModelTest : SysuiTestCase() { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME)) val message by collectLastValue(bouncerViewModel.message) val entries by collectLastValue(underTest.pinEntries) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.lockDevice() sceneInteractor.setCurrentScene(CONTAINER_NAME, SceneModel(SceneKey.Bouncer)) assertThat(isUnlocked).isFalse() assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer)) underTest.onShown() + runCurrent() underTest.onPinButtonClicked(1) underTest.onPinButtonClicked(2) underTest.onPinButtonClicked(3) @@ -204,7 +214,9 @@ class PinBouncerViewModelTest : SysuiTestCase() { testScope.runTest { val isUnlocked by collectLastValue(authenticationInteractor.isUnlocked) val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME)) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.lockDevice() sceneInteractor.setCurrentScene(CONTAINER_NAME, SceneModel(SceneKey.Bouncer)) assertThat(isUnlocked).isFalse() @@ -228,7 +240,9 @@ class PinBouncerViewModelTest : SysuiTestCase() { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME)) val message by collectLastValue(bouncerViewModel.message) val entries by collectLastValue(underTest.pinEntries) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.lockDevice() sceneInteractor.setCurrentScene(CONTAINER_NAME, SceneModel(SceneKey.Bouncer)) assertThat(isUnlocked).isFalse() @@ -255,7 +269,9 @@ class PinBouncerViewModelTest : SysuiTestCase() { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME)) val message by collectLastValue(bouncerViewModel.message) val entries by collectLastValue(underTest.pinEntries) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.lockDevice() sceneInteractor.setCurrentScene(CONTAINER_NAME, SceneModel(SceneKey.Bouncer)) assertThat(isUnlocked).isFalse() @@ -290,7 +306,7 @@ class PinBouncerViewModelTest : SysuiTestCase() { testScope.runTest { val isUnlocked by collectLastValue(authenticationInteractor.isUnlocked) val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME)) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pin(1234, autoConfirm = true) ) authenticationInteractor.lockDevice() @@ -314,7 +330,7 @@ class PinBouncerViewModelTest : SysuiTestCase() { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_NAME)) val message by collectLastValue(bouncerViewModel.message) val entries by collectLastValue(underTest.pinEntries) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pin(1234, autoConfirm = true) ) authenticationInteractor.lockDevice() @@ -338,7 +354,7 @@ class PinBouncerViewModelTest : SysuiTestCase() { testScope.runTest { val backspaceButtonAppearance by collectLastValue(underTest.backspaceButtonAppearance) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pin(1234, autoConfirm = false) ) @@ -349,7 +365,7 @@ class PinBouncerViewModelTest : SysuiTestCase() { fun backspaceButtonAppearance_withAutoConfirmButNoInput_isHidden() = testScope.runTest { val backspaceButtonAppearance by collectLastValue(underTest.backspaceButtonAppearance) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pin(1234, autoConfirm = true) ) @@ -360,7 +376,7 @@ class PinBouncerViewModelTest : SysuiTestCase() { fun backspaceButtonAppearance_withAutoConfirmAndInput_isShownQuiet() = testScope.runTest { val backspaceButtonAppearance by collectLastValue(underTest.backspaceButtonAppearance) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pin(1234, autoConfirm = true) ) @@ -374,7 +390,7 @@ class PinBouncerViewModelTest : SysuiTestCase() { testScope.runTest { val confirmButtonAppearance by collectLastValue(underTest.confirmButtonAppearance) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pin(1234, autoConfirm = false) ) @@ -385,7 +401,7 @@ class PinBouncerViewModelTest : SysuiTestCase() { fun confirmButtonAppearance_withAutoConfirm_isHidden() = testScope.runTest { val confirmButtonAppearance by collectLastValue(underTest.confirmButtonAppearance) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pin(1234, autoConfirm = true) ) @@ -396,7 +412,7 @@ class PinBouncerViewModelTest : SysuiTestCase() { fun hintedPinLength_withoutAutoConfirm_isNull() = testScope.runTest { val hintedPinLength by collectLastValue(underTest.hintedPinLength) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pin(1234, autoConfirm = false) ) @@ -407,7 +423,7 @@ class PinBouncerViewModelTest : SysuiTestCase() { fun hintedPinLength_withAutoConfirmPinLessThanSixDigits_isNull() = testScope.runTest { val hintedPinLength by collectLastValue(underTest.hintedPinLength) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pin(12345, autoConfirm = true) ) @@ -418,7 +434,7 @@ class PinBouncerViewModelTest : SysuiTestCase() { fun hintedPinLength_withAutoConfirmPinExactlySixDigits_isSix() = testScope.runTest { val hintedPinLength by collectLastValue(underTest.hintedPinLength) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pin(123456, autoConfirm = true) ) @@ -429,7 +445,7 @@ class PinBouncerViewModelTest : SysuiTestCase() { fun hintedPinLength_withAutoConfirmPinMoreThanSixDigits_isNull() = testScope.runTest { val hintedPinLength by collectLastValue(underTest.hintedPinLength) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Pin(1234567, autoConfirm = true) ) diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractorTest.kt index 65781c4979441..c9fce94928e6c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LockscreenSceneInteractorTest.kt @@ -26,7 +26,6 @@ import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.scene.shared.model.SceneModel import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Test @@ -38,8 +37,8 @@ import org.junit.runners.JUnit4 @RunWith(JUnit4::class) class LockscreenSceneInteractorTest : SysuiTestCase() { - private val testScope = TestScope() - private val utils = SceneTestUtils(this, testScope) + private val utils = SceneTestUtils(this) + private val testScope = utils.testScope private val sceneInteractor = utils.sceneInteractor() private val authenticationInteractor = utils.authenticationInteractor( @@ -74,7 +73,7 @@ class LockscreenSceneInteractorTest : SysuiTestCase() { val isSwipeToDismissEnabled by collectLastValue(underTest.isSwipeToDismissEnabled) authenticationInteractor.lockDevice() - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Swipe) + utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Swipe) assertThat(isSwipeToDismissEnabled).isTrue() } @@ -85,7 +84,7 @@ class LockscreenSceneInteractorTest : SysuiTestCase() { val isSwipeToDismissEnabled by collectLastValue(underTest.isSwipeToDismissEnabled) authenticationInteractor.unlockDevice() - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Swipe) + utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Swipe) assertThat(isSwipeToDismissEnabled).isFalse() } @@ -95,7 +94,9 @@ class LockscreenSceneInteractorTest : SysuiTestCase() { testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1)) authenticationInteractor.lockDevice() - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen)) underTest.dismissLockscreen() @@ -108,7 +109,9 @@ class LockscreenSceneInteractorTest : SysuiTestCase() { testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1)) authenticationInteractor.unlockDevice() - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen)) underTest.dismissLockscreen() @@ -121,7 +124,7 @@ class LockscreenSceneInteractorTest : SysuiTestCase() { testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1)) authenticationInteractor.lockDevice() - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Swipe) + utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Swipe) assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen)) underTest.dismissLockscreen() @@ -182,7 +185,7 @@ class LockscreenSceneInteractorTest : SysuiTestCase() { testScope.runTest { val isUnlocked by collectLastValue(authenticationInteractor.isUnlocked) sceneInteractor.setCurrentScene(CONTAINER_1, SceneModel(SceneKey.Lockscreen)) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Swipe) + utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Swipe) assertThat(isUnlocked).isFalse() sceneInteractor.setCurrentScene(CONTAINER_1, SceneModel(SceneKey.Gone)) @@ -195,7 +198,9 @@ class LockscreenSceneInteractorTest : SysuiTestCase() { testScope.runTest { val isUnlocked by collectLastValue(authenticationInteractor.isUnlocked) sceneInteractor.setCurrentScene(CONTAINER_1, SceneModel(SceneKey.Lockscreen)) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) assertThat(isUnlocked).isFalse() sceneInteractor.setCurrentScene(CONTAINER_1, SceneModel(SceneKey.Gone)) @@ -210,7 +215,7 @@ class LockscreenSceneInteractorTest : SysuiTestCase() { runCurrent() sceneInteractor.setCurrentScene(CONTAINER_1, SceneModel(SceneKey.Shade)) runCurrent() - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Swipe) + utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Swipe) runCurrent() assertThat(isUnlocked).isFalse() @@ -219,30 +224,17 @@ class LockscreenSceneInteractorTest : SysuiTestCase() { assertThat(isUnlocked).isFalse() } - @Test - fun authMethodChangedToNone_onLockScreenScene_dismissesLockScreen() = - testScope.runTest { - val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1)) - sceneInteractor.setCurrentScene(CONTAINER_1, SceneModel(SceneKey.Lockscreen)) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Swipe) - assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen)) - - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.None) - - assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone)) - } - @Test fun authMethodChangedToNone_notOnLockScreenScene_doesNotDismissLockScreen() = testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1)) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Swipe) + utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Swipe) runCurrent() sceneInteractor.setCurrentScene(CONTAINER_1, SceneModel(SceneKey.QuickSettings)) runCurrent() assertThat(currentScene).isEqualTo(SceneModel(SceneKey.QuickSettings)) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.None) + utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None) assertThat(currentScene).isEqualTo(SceneModel(SceneKey.QuickSettings)) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt index f0ea0077596ad..e8c01f0f7cf05 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt @@ -29,7 +29,6 @@ import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.scene.shared.model.SceneModel import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Test @@ -41,8 +40,8 @@ import org.junit.runners.JUnit4 @RunWith(JUnit4::class) class LockscreenSceneViewModelTest : SysuiTestCase() { - private val testScope = TestScope() - private val utils = SceneTestUtils(this, testScope) + private val utils = SceneTestUtils(this) + private val testScope = utils.testScope private val sceneInteractor = utils.sceneInteractor() private val authenticationInteractor = utils.authenticationInteractor( @@ -73,7 +72,7 @@ class LockscreenSceneViewModelTest : SysuiTestCase() { fun lockButtonIcon_whenLocked() = testScope.runTest { val lockButtonIcon by collectLastValue(underTest.lockButtonIcon) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Password("password") ) authenticationInteractor.lockDevice() @@ -86,7 +85,7 @@ class LockscreenSceneViewModelTest : SysuiTestCase() { fun lockButtonIcon_whenUnlocked() = testScope.runTest { val lockButtonIcon by collectLastValue(underTest.lockButtonIcon) - authenticationInteractor.setAuthenticationMethod( + utils.authenticationRepository.setAuthenticationMethod( AuthenticationMethodModel.Password("password") ) authenticationInteractor.unlockDevice() @@ -99,7 +98,7 @@ class LockscreenSceneViewModelTest : SysuiTestCase() { fun upTransitionSceneKey_swipeToUnlockedEnabled_gone() = testScope.runTest { val upTransitionSceneKey by collectLastValue(underTest.upDestinationSceneKey) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Swipe) + utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Swipe) authenticationInteractor.lockDevice() assertThat(upTransitionSceneKey).isEqualTo(SceneKey.Gone) @@ -109,7 +108,9 @@ class LockscreenSceneViewModelTest : SysuiTestCase() { fun upTransitionSceneKey_swipeToUnlockedNotEnabled_bouncer() = testScope.runTest { val upTransitionSceneKey by collectLastValue(underTest.upDestinationSceneKey) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.lockDevice() assertThat(upTransitionSceneKey).isEqualTo(SceneKey.Bouncer) @@ -119,7 +120,9 @@ class LockscreenSceneViewModelTest : SysuiTestCase() { fun onLockButtonClicked_deviceLockedSecurely_switchesToBouncer() = testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1)) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.lockDevice() runCurrent() @@ -132,7 +135,9 @@ class LockscreenSceneViewModelTest : SysuiTestCase() { fun onContentClicked_deviceUnlocked_switchesToGone() = testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1)) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.unlockDevice() runCurrent() @@ -145,7 +150,9 @@ class LockscreenSceneViewModelTest : SysuiTestCase() { fun onContentClicked_deviceLockedSecurely_switchesToBouncer() = testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1)) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.lockDevice() runCurrent() @@ -158,7 +165,9 @@ class LockscreenSceneViewModelTest : SysuiTestCase() { fun onLockButtonClicked_deviceUnlocked_switchesToGone() = testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1)) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.unlockDevice() runCurrent() diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt index 05a16994e021c..1f9ec941b7a8b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt @@ -27,7 +27,6 @@ import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.scene.shared.model.SceneModel import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Test @@ -39,8 +38,8 @@ import org.junit.runners.JUnit4 @RunWith(JUnit4::class) class QuickSettingsSceneViewModelTest : SysuiTestCase() { - private val testScope = TestScope() - private val utils = SceneTestUtils(this, testScope) + private val utils = SceneTestUtils(this) + private val testScope = utils.testScope private val sceneInteractor = utils.sceneInteractor() private val authenticationInteractor = utils.authenticationInteractor( @@ -70,7 +69,9 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { fun onContentClicked_deviceUnlocked_switchesToGone() = testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1)) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.unlockDevice() runCurrent() @@ -83,7 +84,9 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { fun onContentClicked_deviceLockedSecurely_switchesToBouncer() = testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1)) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.lockDevice() runCurrent() diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt index f8e1a9d12657e..aaa0816555fc0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt @@ -27,7 +27,6 @@ import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.scene.shared.model.SceneModel import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Test @@ -39,8 +38,8 @@ import org.junit.runners.JUnit4 @RunWith(JUnit4::class) class ShadeSceneViewModelTest : SysuiTestCase() { - private val testScope = TestScope() - private val utils = SceneTestUtils(this, testScope) + private val utils = SceneTestUtils(this) + private val testScope = utils.testScope private val sceneInteractor = utils.sceneInteractor() private val authenticationInteractor = utils.authenticationInteractor( @@ -71,7 +70,9 @@ class ShadeSceneViewModelTest : SysuiTestCase() { fun upTransitionSceneKey_deviceLocked_lockScreen() = testScope.runTest { val upTransitionSceneKey by collectLastValue(underTest.upDestinationSceneKey) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.lockDevice() assertThat(upTransitionSceneKey).isEqualTo(SceneKey.Lockscreen) @@ -81,7 +82,9 @@ class ShadeSceneViewModelTest : SysuiTestCase() { fun upTransitionSceneKey_deviceUnlocked_gone() = testScope.runTest { val upTransitionSceneKey by collectLastValue(underTest.upDestinationSceneKey) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.unlockDevice() assertThat(upTransitionSceneKey).isEqualTo(SceneKey.Gone) @@ -91,7 +94,9 @@ class ShadeSceneViewModelTest : SysuiTestCase() { fun onContentClicked_deviceUnlocked_switchesToGone() = testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1)) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.unlockDevice() runCurrent() @@ -104,7 +109,9 @@ class ShadeSceneViewModelTest : SysuiTestCase() { fun onContentClicked_deviceLockedSecurely_switchesToBouncer() = testScope.runTest { val currentScene by collectLastValue(sceneInteractor.currentScene(CONTAINER_1)) - authenticationInteractor.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) + utils.authenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.Pin(1234) + ) authenticationInteractor.lockDevice() runCurrent() diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt new file mode 100644 index 0000000000000..a12393ec70926 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.authentication.data.repository + +import com.android.keyguard.KeyguardSecurityModel.SecurityMode +import com.android.systemui.authentication.shared.model.AuthenticationMethodModel + +class FakeAuthenticationRepository( + private val delegate: AuthenticationRepository, + private val onSecurityModeChanged: (SecurityMode) -> Unit, +) : AuthenticationRepository by delegate { + + private var authenticationMethod: AuthenticationMethodModel = DEFAULT_AUTHENTICATION_METHOD + + override suspend fun getAuthenticationMethod(): AuthenticationMethodModel { + return authenticationMethod + } + + fun setAuthenticationMethod(authenticationMethod: AuthenticationMethodModel) { + this.authenticationMethod = authenticationMethod + onSecurityModeChanged(authenticationMethod.toSecurityMode()) + } + + companion object { + val DEFAULT_AUTHENTICATION_METHOD = + AuthenticationMethodModel.Pin(listOf(1, 2, 3, 4), autoConfirm = false) + + fun AuthenticationMethodModel.toSecurityMode(): SecurityMode { + return when (this) { + is AuthenticationMethodModel.Pin -> SecurityMode.PIN + is AuthenticationMethodModel.Password -> SecurityMode.Password + is AuthenticationMethodModel.Pattern -> SecurityMode.Pattern + is AuthenticationMethodModel.Swipe, + is AuthenticationMethodModel.None -> SecurityMode.None + } + } + } +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt index 9c4fd9459b571..6f228f4276fba 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt @@ -16,9 +16,12 @@ package com.android.systemui.scene +import com.android.keyguard.KeyguardSecurityModel.SecurityMode import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.AuthenticationRepository import com.android.systemui.authentication.data.repository.AuthenticationRepositoryImpl +import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository +import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository.Companion.toSecurityMode import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor import com.android.systemui.bouncer.data.repository.BouncerRepository import com.android.systemui.bouncer.domain.interactor.BouncerInteractor @@ -28,8 +31,12 @@ import com.android.systemui.scene.data.repository.SceneContainerRepository import com.android.systemui.scene.domain.interactor.SceneInteractor import com.android.systemui.scene.shared.model.SceneContainerConfig import com.android.systemui.scene.shared.model.SceneKey +import com.android.systemui.user.data.repository.FakeUserRepository +import com.android.systemui.util.mockito.mock import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestDispatcher import kotlinx.coroutines.test.TestScope /** @@ -39,9 +46,23 @@ import kotlinx.coroutines.test.TestScope @OptIn(ExperimentalCoroutinesApi::class) class SceneTestUtils( test: SysuiTestCase, - private val testScope: TestScope? = null, ) { - + val testDispatcher: TestDispatcher by lazy { StandardTestDispatcher() } + val testScope: TestScope by lazy { TestScope(testDispatcher) } + private var securityMode: SecurityMode = + FakeAuthenticationRepository.DEFAULT_AUTHENTICATION_METHOD.toSecurityMode() + val authenticationRepository: FakeAuthenticationRepository by lazy { + FakeAuthenticationRepository( + delegate = + AuthenticationRepositoryImpl( + getSecurityMode = { securityMode }, + backgroundDispatcher = testDispatcher, + userRepository = FakeUserRepository(), + lockPatternUtils = mock(), + ), + onSecurityModeChanged = { securityMode = it }, + ) + } private val context = test.context fun fakeSceneContainerRepository( @@ -82,7 +103,7 @@ class SceneTestUtils( } fun authenticationRepository(): AuthenticationRepository { - return AuthenticationRepositoryImpl() + return authenticationRepository } fun authenticationInteractor( @@ -94,17 +115,6 @@ class SceneTestUtils( ) } - private fun applicationScope(): CoroutineScope { - return checkNotNull(testScope) { - """ - TestScope not initialized, please create a TestScope and inject it into - SceneTestUtils. - """ - .trimIndent() - } - .backgroundScope - } - fun bouncerInteractor( authenticationInteractor: AuthenticationInteractor, sceneInteractor: SceneInteractor, @@ -154,6 +164,10 @@ class SceneTestUtils( ) } + private fun applicationScope(): CoroutineScope { + return testScope.backgroundScope + } + companion object { const val CONTAINER_1 = "container1" const val CONTAINER_2 = "container2"