From ace6b8065f6911560b09725e8ded2511778a4399 Mon Sep 17 00:00:00 2001 From: Alejandro Nijamkin Date: Wed, 21 Jun 2023 15:18:18 -0700 Subject: [PATCH] [flexiglass] Hooks up real app state and logic in keyguard (1) - Source auth method from KeyguardSecurityModel, changing it from flow to getter Bug: 280883900 Test: Unit tests still pass. Test: manually verified that changing the screen lock setting in Settings, between PIN, password, and pattern, properly affects Flexiglass in System UI such that the right version of the bouncer UI is displayed. Change-Id: Id457458806dc6ac2720abe21a77d5e50b83836fc --- .../authentication/AuthenticationModule.kt | 13 ++- .../repository/AuthenticationRepository.kt | 80 +++++++++++----- .../interactor/AuthenticationInteractor.kt | 68 ++++---------- .../domain/interactor/BouncerInteractor.kt | 82 ++++++++-------- .../bouncer/ui/viewmodel/BouncerViewModel.kt | 42 +++++---- .../ui/viewmodel/PasswordBouncerViewModel.kt | 14 ++- .../ui/viewmodel/PatternBouncerViewModel.kt | 27 +++--- .../ui/viewmodel/PinBouncerViewModel.kt | 79 +++++++++------- .../interactor/LockscreenSceneInteractor.kt | 73 ++++---------- .../AuthenticationInteractorTest.kt | 94 ++++++++++--------- .../interactor/BouncerInteractorTest.kt | 29 +++--- .../AuthMethodBouncerViewModelTest.kt | 9 +- .../ui/viewmodel/BouncerViewModelTest.kt | 27 +++--- .../viewmodel/PasswordBouncerViewModelTest.kt | 18 ++-- .../viewmodel/PatternBouncerViewModelTest.kt | 17 ++-- .../ui/viewmodel/PinBouncerViewModelTest.kt | 60 +++++++----- .../LockscreenSceneInteractorTest.kt | 44 ++++----- .../viewmodel/LockscreenSceneViewModelTest.kt | 31 +++--- .../QuickSettingsSceneViewModelTest.kt | 13 ++- .../ui/viewmodel/ShadeSceneViewModelTest.kt | 21 +++-- .../FakeAuthenticationRepository.kt | 52 ++++++++++ .../android/systemui/scene/SceneTestUtils.kt | 42 ++++++--- 22 files changed, 521 insertions(+), 414 deletions(-) create mode 100644 packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt 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"