diff options
8 files changed, 173 insertions, 103 deletions
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 43fb3630bd19..9eebddb7663b 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 @@ -71,10 +71,23 @@ interface AuthenticationRepository { */ val isBypassEnabled: StateFlow<Boolean> - /** Whether the auto confirm feature is enabled for the currently-selected user. */ + /** + * Whether the auto confirm feature is enabled for the currently-selected user. + * + * Note that the length of the PIN is also important to take into consideration, please see + * [hintedPinLength]. + */ val isAutoConfirmEnabled: StateFlow<Boolean> - /** The length of the PIN for which we should show a hint. */ + /** + * The exact length a PIN should be for us to enable PIN length hinting. + * + * A PIN that's shorter or longer than this is not eligible for the UI to render hints showing + * how many digits the current PIN is, even if [isAutoConfirmEnabled] is enabled. + * + * Note that PIN length hinting is only available if the PIN auto confirmation feature is + * available. + */ val hintedPinLength: Int /** Whether the pattern should be visible for the currently-selected user. */ @@ -171,10 +184,10 @@ constructor( .stateIn( scope = applicationScope, started = SharingStarted.WhileSubscribed(), - initialValue = true, + initialValue = false, ) - override val hintedPinLength: Int = LockPatternUtils.MIN_AUTO_PIN_REQUIREMENT_LENGTH + override val hintedPinLength: Int = 6 override val isPatternVisible: StateFlow<Boolean> = userRepository.selectedUserInfo 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 82674bff6433..3283e406ddb0 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 @@ -37,7 +37,6 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch @@ -103,10 +102,11 @@ constructor( /** The length of the hinted PIN, or `null` if pin length hint should not be shown. */ val hintedPinLength: StateFlow<Int?> = - flow { emit(repository.getPinLength()) } - .map { currentPinLength -> - // Hinting is enabled for 6-digit codes only - currentPinLength.takeIf { repository.hintedPinLength == it } + repository.isAutoConfirmEnabled + .map { isAutoConfirmEnabled -> + repository.getPinLength().takeIf { + isAutoConfirmEnabled && it == repository.hintedPinLength + } } .stateIn( scope = applicationScope, 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 62a484d42dec..8e14237c0586 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 @@ -88,7 +88,7 @@ constructor( /** Whether the auto confirm feature is enabled for the currently-selected user. */ val isAutoConfirmEnabled: StateFlow<Boolean> = authenticationInteractor.isAutoConfirmEnabled - /** The length of the PIN for which we should show a hint. */ + /** The length of the hinted PIN, or `null`, if pin length hint should not be shown. */ val hintedPinLength: StateFlow<Int?> = authenticationInteractor.hintedPinLength /** Whether the pattern should be visible for the currently-selected user. */ 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 c0c690892958..c223c5af6079 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 @@ -164,7 +164,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { testScope.runTest { val isThrottled by collectLastValue(underTest.isThrottled) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) - assertThat(underTest.authenticate(listOf(1, 2, 3, 4))).isTrue() + assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)).isTrue() assertThat(isThrottled).isFalse() } @@ -172,7 +172,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { fun authenticate_withIncorrectPin_returnsFalse() = testScope.runTest { utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) - assertThat(underTest.authenticate(listOf(9, 8, 7))).isFalse() + assertThat(underTest.authenticate(listOf(9, 8, 7, 6, 5, 4))).isFalse() } @Test(expected = IllegalArgumentException::class) @@ -270,7 +270,15 @@ class AuthenticationInteractorTest : SysuiTestCase() { val isThrottled by collectLastValue(underTest.isThrottled) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) utils.authenticationRepository.setAutoConfirmEnabled(true) - assertThat(underTest.authenticate(listOf(1, 2, 3), tryAutoConfirm = true)).isNull() + assertThat( + underTest.authenticate( + FakeAuthenticationRepository.DEFAULT_PIN.toMutableList().apply { + removeLast() + }, + tryAutoConfirm = true + ) + ) + .isNull() assertThat(isThrottled).isFalse() } @@ -280,7 +288,13 @@ class AuthenticationInteractorTest : SysuiTestCase() { val isUnlocked by collectLastValue(underTest.isUnlocked) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) utils.authenticationRepository.setAutoConfirmEnabled(true) - assertThat(underTest.authenticate(listOf(1, 2, 4, 4), tryAutoConfirm = true)).isFalse() + assertThat( + underTest.authenticate( + FakeAuthenticationRepository.DEFAULT_PIN.map { it + 1 }, + tryAutoConfirm = true + ) + ) + .isFalse() assertThat(isUnlocked).isFalse() } @@ -290,7 +304,12 @@ class AuthenticationInteractorTest : SysuiTestCase() { val isUnlocked by collectLastValue(underTest.isUnlocked) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) utils.authenticationRepository.setAutoConfirmEnabled(true) - assertThat(underTest.authenticate(listOf(1, 2, 3, 4, 5), tryAutoConfirm = true)) + assertThat( + underTest.authenticate( + FakeAuthenticationRepository.DEFAULT_PIN + listOf(7), + tryAutoConfirm = true + ) + ) .isFalse() assertThat(isUnlocked).isFalse() } @@ -301,7 +320,13 @@ class AuthenticationInteractorTest : SysuiTestCase() { val isUnlocked by collectLastValue(underTest.isUnlocked) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) utils.authenticationRepository.setAutoConfirmEnabled(true) - assertThat(underTest.authenticate(listOf(1, 2, 3, 4), tryAutoConfirm = true)).isTrue() + assertThat( + underTest.authenticate( + FakeAuthenticationRepository.DEFAULT_PIN, + tryAutoConfirm = true + ) + ) + .isTrue() assertThat(isUnlocked).isTrue() } @@ -311,7 +336,13 @@ class AuthenticationInteractorTest : SysuiTestCase() { val isUnlocked by collectLastValue(underTest.isUnlocked) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) utils.authenticationRepository.setAutoConfirmEnabled(false) - assertThat(underTest.authenticate(listOf(1, 2, 3, 4), tryAutoConfirm = true)).isNull() + assertThat( + underTest.authenticate( + FakeAuthenticationRepository.DEFAULT_PIN, + tryAutoConfirm = true + ) + ) + .isNull() assertThat(isUnlocked).isFalse() } @@ -334,7 +365,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { val throttling by collectLastValue(underTest.throttling) val isThrottled by collectLastValue(underTest.isThrottled) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) - underTest.authenticate(listOf(1, 2, 3, 4)) + underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN) assertThat(isUnlocked).isTrue() assertThat(isThrottled).isFalse() assertThat(throttling).isEqualTo(AuthenticationThrottlingModel()) @@ -366,7 +397,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { ) // Correct PIN, but throttled, so doesn't attempt it: - assertThat(underTest.authenticate(listOf(1, 2, 3, 4))).isNull() + assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)).isNull() assertThat(isUnlocked).isFalse() assertThat(isThrottled).isTrue() assertThat(throttling) @@ -412,9 +443,62 @@ class AuthenticationInteractorTest : SysuiTestCase() { ) // Correct PIN and no longer throttled so unlocks successfully: - assertThat(underTest.authenticate(listOf(1, 2, 3, 4))).isTrue() + assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)).isTrue() assertThat(isUnlocked).isTrue() assertThat(isThrottled).isFalse() assertThat(throttling).isEqualTo(AuthenticationThrottlingModel()) } + + @Test + fun hintedPinLength_withoutAutoConfirm_isNull() = + testScope.runTest { + val hintedPinLength by collectLastValue(underTest.hintedPinLength) + utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) + utils.authenticationRepository.setAutoConfirmEnabled(false) + + assertThat(hintedPinLength).isNull() + } + + @Test + fun hintedPinLength_withAutoConfirmPinTooShort_isNull() = + testScope.runTest { + val hintedPinLength by collectLastValue(underTest.hintedPinLength) + utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) + utils.authenticationRepository.overrideCredential( + buildList { + repeat(utils.authenticationRepository.hintedPinLength - 1) { add(it + 1) } + } + ) + utils.authenticationRepository.setAutoConfirmEnabled(true) + + assertThat(hintedPinLength).isNull() + } + + @Test + fun hintedPinLength_withAutoConfirmPinAtRightLength_isSameLength() = + testScope.runTest { + val hintedPinLength by collectLastValue(underTest.hintedPinLength) + utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) + utils.authenticationRepository.setAutoConfirmEnabled(true) + utils.authenticationRepository.overrideCredential( + buildList { repeat(utils.authenticationRepository.hintedPinLength) { add(it + 1) } } + ) + + assertThat(hintedPinLength).isEqualTo(utils.authenticationRepository.hintedPinLength) + } + + @Test + fun hintedPinLength_withAutoConfirmPinTooLong_isNull() = + testScope.runTest { + val hintedPinLength by collectLastValue(underTest.hintedPinLength) + utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) + utils.authenticationRepository.overrideCredential( + buildList { + repeat(utils.authenticationRepository.hintedPinLength + 1) { add(it + 1) } + } + ) + utils.authenticationRepository.setAutoConfirmEnabled(true) + + assertThat(hintedPinLength).isNull() + } } 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 481f36e8ea38..6babf0490ea9 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 @@ -94,7 +94,7 @@ class BouncerInteractorTest : SysuiTestCase() { assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PIN) // Correct input. - assertThat(underTest.authenticate(listOf(1, 2, 3, 4))).isTrue() + assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)).isTrue() assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone)) } @@ -118,13 +118,20 @@ class BouncerInteractorTest : SysuiTestCase() { assertThat(message).isEmpty() assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer)) - // Wrong 4-digit pin - assertThat(underTest.authenticate(listOf(1, 2, 3, 5), tryAutoConfirm = true)).isFalse() + // Wrong 6-digit pin + assertThat(underTest.authenticate(listOf(1, 2, 3, 5, 5, 6), tryAutoConfirm = true)) + .isFalse() assertThat(message).isEqualTo(MESSAGE_WRONG_PIN) assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer)) // Correct input. - assertThat(underTest.authenticate(listOf(1, 2, 3, 4), tryAutoConfirm = true)).isTrue() + assertThat( + underTest.authenticate( + FakeAuthenticationRepository.DEFAULT_PIN, + tryAutoConfirm = true + ) + ) + .isTrue() assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone)) } @@ -147,7 +154,13 @@ class BouncerInteractorTest : SysuiTestCase() { assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer)) // Correct input. - assertThat(underTest.authenticate(listOf(1, 2, 3, 4), tryAutoConfirm = true)).isNull() + assertThat( + underTest.authenticate( + FakeAuthenticationRepository.DEFAULT_PIN, + tryAutoConfirm = true + ) + ) + .isNull() assertThat(message).isEmpty() assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer)) } @@ -309,7 +322,7 @@ class BouncerInteractorTest : SysuiTestCase() { ) // Correct PIN, but throttled, so doesn't change away from the bouncer scene: - assertThat(underTest.authenticate(listOf(1, 2, 3, 4))).isNull() + assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)).isNull() assertThat(currentScene?.key).isEqualTo(SceneKey.Bouncer) assertTryAgainMessage( message, @@ -339,7 +352,7 @@ class BouncerInteractorTest : SysuiTestCase() { assertThat(currentScene?.key).isEqualTo(SceneKey.Bouncer) // Correct PIN and no longer throttled so changes to the Gone scene: - assertThat(underTest.authenticate(listOf(1, 2, 3, 4))).isTrue() + assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)).isTrue() assertThat(currentScene?.key).isEqualTo(SceneKey.Gone) assertThat(isThrottled).isFalse() assertThat(throttling).isEqualTo(AuthenticationThrottlingModel()) 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 0867558545bd..2cc949326fa0 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 @@ -18,6 +18,7 @@ package com.android.systemui.bouncer.ui.viewmodel import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.coroutines.collectLastValue import com.android.systemui.scene.SceneTestUtils @@ -60,10 +61,9 @@ class AuthMethodBouncerViewModelTest : SysuiTestCase() { assertThat(animateFailure).isFalse() // Wrong PIN: - underTest.onPinButtonClicked(3) - underTest.onPinButtonClicked(4) - underTest.onPinButtonClicked(5) - underTest.onPinButtonClicked(6) + FakeAuthenticationRepository.DEFAULT_PIN.drop(2).forEach { digit -> + underTest.onPinButtonClicked(digit) + } underTest.onAuthenticateButtonClicked() assertThat(animateFailure).isTrue() @@ -71,10 +71,9 @@ class AuthMethodBouncerViewModelTest : SysuiTestCase() { assertThat(animateFailure).isFalse() // Correct PIN: - underTest.onPinButtonClicked(1) - underTest.onPinButtonClicked(2) - underTest.onPinButtonClicked(3) - underTest.onPinButtonClicked(4) + FakeAuthenticationRepository.DEFAULT_PIN.forEach { digit -> + underTest.onPinButtonClicked(digit) + } underTest.onAuthenticateButtonClicked() assertThat(animateFailure).isFalse() } 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 5c6d4c69b50b..45d1af722369 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 @@ -19,6 +19,7 @@ package com.android.systemui.bouncer.ui.viewmodel import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase +import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.coroutines.collectLastValue import com.android.systemui.scene.SceneTestUtils @@ -211,10 +212,9 @@ class PinBouncerViewModelTest : SysuiTestCase() { ) assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer)) underTest.onShown() - underTest.onPinButtonClicked(1) - underTest.onPinButtonClicked(2) - underTest.onPinButtonClicked(3) - underTest.onPinButtonClicked(4) + FakeAuthenticationRepository.DEFAULT_PIN.forEach { digit -> + underTest.onPinButtonClicked(digit) + } underTest.onAuthenticateButtonClicked() @@ -275,10 +275,9 @@ class PinBouncerViewModelTest : SysuiTestCase() { assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer)) // Enter the correct PIN: - underTest.onPinButtonClicked(1) - underTest.onPinButtonClicked(2) - underTest.onPinButtonClicked(3) - underTest.onPinButtonClicked(4) + FakeAuthenticationRepository.DEFAULT_PIN.forEach { digit -> + underTest.onPinButtonClicked(digit) + } assertThat(message?.text).isEmpty() underTest.onAuthenticateButtonClicked() @@ -300,10 +299,9 @@ class PinBouncerViewModelTest : SysuiTestCase() { ) assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer)) underTest.onShown() - underTest.onPinButtonClicked(1) - underTest.onPinButtonClicked(2) - underTest.onPinButtonClicked(3) - underTest.onPinButtonClicked(4) + FakeAuthenticationRepository.DEFAULT_PIN.forEach { digit -> + underTest.onPinButtonClicked(digit) + } assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone)) } @@ -324,10 +322,12 @@ class PinBouncerViewModelTest : SysuiTestCase() { ) assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer)) underTest.onShown() - underTest.onPinButtonClicked(1) - underTest.onPinButtonClicked(2) - underTest.onPinButtonClicked(3) - underTest.onPinButtonClicked(5) // PIN is now wrong! + FakeAuthenticationRepository.DEFAULT_PIN.dropLast(1).forEach { digit -> + underTest.onPinButtonClicked(digit) + } + underTest.onPinButtonClicked( + FakeAuthenticationRepository.DEFAULT_PIN.last() + 1 + ) // PIN is now wrong! assertThat(entries).hasSize(0) assertThat(message?.text).isEqualTo(WRONG_PIN) @@ -386,47 +386,6 @@ class PinBouncerViewModelTest : SysuiTestCase() { assertThat(confirmButtonAppearance).isEqualTo(ActionButtonAppearance.Hidden) } - @Test - fun hintedPinLength_withoutAutoConfirm_isNull() = - testScope.runTest { - val hintedPinLength by collectLastValue(underTest.hintedPinLength) - utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) - utils.authenticationRepository.setAutoConfirmEnabled(false) - - assertThat(hintedPinLength).isNull() - } - - @Test - fun hintedPinLength_withAutoConfirmPinLessThanSixDigits_isNull() = - testScope.runTest { - val hintedPinLength by collectLastValue(underTest.hintedPinLength) - utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) - utils.authenticationRepository.setAutoConfirmEnabled(true) - - assertThat(hintedPinLength).isNull() - } - - @Test - fun hintedPinLength_withAutoConfirmPinExactlySixDigits_isSix() = - testScope.runTest { - val hintedPinLength by collectLastValue(underTest.hintedPinLength) - utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) - utils.authenticationRepository.setAutoConfirmEnabled(true) - utils.authenticationRepository.overrideCredential(listOf(1, 2, 3, 4, 5, 6)) - - assertThat(hintedPinLength).isEqualTo(6) - } - - @Test - fun hintedPinLength_withAutoConfirmPinMoreThanSixDigits_isNull() = - testScope.runTest { - val hintedPinLength by collectLastValue(underTest.hintedPinLength) - utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) - utils.authenticationRepository.setAutoConfirmEnabled(true) - - assertThat(hintedPinLength).isNull() - } - companion object { private const val ENTER_YOUR_PIN = "Enter your pin" private const val WRONG_PIN = "Wrong pin" 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 index bebdd4004c3d..28892baec3c5 100644 --- 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 @@ -40,7 +40,7 @@ class FakeAuthenticationRepository( private val _isUnlocked = MutableStateFlow(false) override val isUnlocked: StateFlow<Boolean> = _isUnlocked.asStateFlow() - override val hintedPinLength: Int = 6 + override val hintedPinLength: Int = HINTING_PIN_LENGTH private val _isPatternVisible = MutableStateFlow(true) override val isPatternVisible: StateFlow<Boolean> = _isPatternVisible.asStateFlow() @@ -82,7 +82,7 @@ class FakeAuthenticationRepository( } override suspend fun getPinLength(): Int { - return (credentialOverride ?: listOf(1, 2, 3, 4)).size + return (credentialOverride ?: DEFAULT_PIN).size } override fun setBypassEnabled(isBypassEnabled: Boolean) { @@ -148,6 +148,15 @@ class FakeAuthenticationRepository( } } + private fun getExpectedCredential(securityMode: SecurityMode): List<Any> { + return when (val credentialType = getCurrentCredentialType(securityMode)) { + LockPatternUtils.CREDENTIAL_TYPE_PIN -> credentialOverride ?: DEFAULT_PIN + LockPatternUtils.CREDENTIAL_TYPE_PASSWORD -> "password".toList() + LockPatternUtils.CREDENTIAL_TYPE_PATTERN -> PATTERN.toCells() + else -> error("Unsupported credential type $credentialType!") + } + } + companion object { val DEFAULT_AUTHENTICATION_METHOD = AuthenticationMethodModel.Pin val PATTERN = @@ -162,6 +171,8 @@ class FakeAuthenticationRepository( ) const val MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING = 5 const val THROTTLE_DURATION_MS = 30000 + const val HINTING_PIN_LENGTH = 6 + val DEFAULT_PIN = buildList { repeat(HINTING_PIN_LENGTH) { add(it + 1) } } private fun AuthenticationMethodModel.toSecurityMode(): SecurityMode { return when (this) { @@ -188,15 +199,6 @@ class FakeAuthenticationRepository( } } - private fun getExpectedCredential(securityMode: SecurityMode): List<Any> { - return when (val credentialType = getCurrentCredentialType(securityMode)) { - LockPatternUtils.CREDENTIAL_TYPE_PIN -> listOf(1, 2, 3, 4) - LockPatternUtils.CREDENTIAL_TYPE_PASSWORD -> "password".toList() - LockPatternUtils.CREDENTIAL_TYPE_PATTERN -> PATTERN.toCells() - else -> error("Unsupported credential type $credentialType!") - } - } - private fun LockscreenCredential.matches(expectedCredential: List<Any>): Boolean { @Suppress("UNCHECKED_CAST") return when { |