Loading packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt +12 −5 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.authentication.domain.interactor import android.app.admin.DevicePolicyManager import com.android.systemui.authentication.data.repository.AuthenticationRepository import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.dagger.SysUISingleton Loading Loading @@ -177,15 +178,21 @@ constructor( /** * Returns a PIN code from the given list. It's assumed the given list elements are all * [Int]. * [Int] in the range [0-9]. */ private fun List<Any>.asCode(): Int? { if (isEmpty()) { private fun List<Any>.asCode(): Long? { if (isEmpty() || size > DevicePolicyManager.MAX_PASSWORD_LENGTH) { return null } var code = 0 map { it as Int }.forEach { integer -> code = code * 10 + integer } var code = 0L map { require(it is Int && it in 0..9) { "Pin is required to be Int in range [0..9], but got $it" } it } .forEach { integer -> code = code * 10 + integer } return code } Loading packages/SystemUI/src/com/android/systemui/authentication/shared/model/AuthenticationMethodModel.kt +7 −1 Original line number Diff line number Diff line Loading @@ -32,7 +32,13 @@ sealed class AuthenticationMethodModel( /** The most basic authentication method. The lock screen can be swiped away when displayed. */ object Swipe : AuthenticationMethodModel(isSecure = false) data class Pin(val code: Int) : AuthenticationMethodModel(isSecure = true) /** * Authentication method using a PIN. * * In practice, a pin is restricted to 16 decimal digits , see * [android.app.admin.DevicePolicyManager.MAX_PASSWORD_LENGTH] */ data class Pin(val code: Long) : AuthenticationMethodModel(isSecure = true) data class Password(val password: String) : AuthenticationMethodModel(isSecure = true) Loading packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt +46 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.authentication.domain.interactor import android.app.admin.DevicePolicyManager import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.AuthenticationRepository Loading Loading @@ -168,6 +169,51 @@ class AuthenticationInteractorTest : SysuiTestCase() { assertThat(failedAttemptCount).isEqualTo(1) } @Test fun authenticate_withEmptyPin_returnsFalseAndDoesNotUnlockDevice() = testScope.runTest { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) underTest.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) assertThat(isUnlocked).isFalse() assertThat(underTest.authenticate(listOf())).isFalse() assertThat(isUnlocked).isFalse() assertThat(failedAttemptCount).isEqualTo(1) } @Test fun authenticate_withCorrectMaxLengthPin_returnsTrueAndUnlocksDevice() = testScope.runTest { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) underTest.setAuthenticationMethod(AuthenticationMethodModel.Pin(9999999999999999)) assertThat(isUnlocked).isFalse() assertThat(underTest.authenticate(List(16) { 9 })).isTrue() assertThat(isUnlocked).isTrue() assertThat(failedAttemptCount).isEqualTo(0) } @Test fun authenticate_withCorrectTooLongPin_returnsFalseAndDoesNotUnlockDevice() = testScope.runTest { // Max pin length is 16 digits. To avoid issues with overflows, this test ensures // that all pins > 16 decimal digits are rejected. // If the policy changes, there is work to do in SysUI. assertThat(DevicePolicyManager.MAX_PASSWORD_LENGTH).isLessThan(17) val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) underTest.setAuthenticationMethod(AuthenticationMethodModel.Pin(99999999999999999)) assertThat(isUnlocked).isFalse() assertThat(underTest.authenticate(List(17) { 9 })).isFalse() assertThat(isUnlocked).isFalse() assertThat(failedAttemptCount).isEqualTo(1) } @Test fun authenticate_withCorrectPassword_returnsTrueAndUnlocksDevice() = testScope.runTest { Loading Loading
packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt +12 −5 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.authentication.domain.interactor import android.app.admin.DevicePolicyManager import com.android.systemui.authentication.data.repository.AuthenticationRepository import com.android.systemui.authentication.shared.model.AuthenticationMethodModel import com.android.systemui.dagger.SysUISingleton Loading Loading @@ -177,15 +178,21 @@ constructor( /** * Returns a PIN code from the given list. It's assumed the given list elements are all * [Int]. * [Int] in the range [0-9]. */ private fun List<Any>.asCode(): Int? { if (isEmpty()) { private fun List<Any>.asCode(): Long? { if (isEmpty() || size > DevicePolicyManager.MAX_PASSWORD_LENGTH) { return null } var code = 0 map { it as Int }.forEach { integer -> code = code * 10 + integer } var code = 0L map { require(it is Int && it in 0..9) { "Pin is required to be Int in range [0..9], but got $it" } it } .forEach { integer -> code = code * 10 + integer } return code } Loading
packages/SystemUI/src/com/android/systemui/authentication/shared/model/AuthenticationMethodModel.kt +7 −1 Original line number Diff line number Diff line Loading @@ -32,7 +32,13 @@ sealed class AuthenticationMethodModel( /** The most basic authentication method. The lock screen can be swiped away when displayed. */ object Swipe : AuthenticationMethodModel(isSecure = false) data class Pin(val code: Int) : AuthenticationMethodModel(isSecure = true) /** * Authentication method using a PIN. * * In practice, a pin is restricted to 16 decimal digits , see * [android.app.admin.DevicePolicyManager.MAX_PASSWORD_LENGTH] */ data class Pin(val code: Long) : AuthenticationMethodModel(isSecure = true) data class Password(val password: String) : AuthenticationMethodModel(isSecure = true) Loading
packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt +46 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.authentication.domain.interactor import android.app.admin.DevicePolicyManager import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.authentication.data.repository.AuthenticationRepository Loading Loading @@ -168,6 +169,51 @@ class AuthenticationInteractorTest : SysuiTestCase() { assertThat(failedAttemptCount).isEqualTo(1) } @Test fun authenticate_withEmptyPin_returnsFalseAndDoesNotUnlockDevice() = testScope.runTest { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) underTest.setAuthenticationMethod(AuthenticationMethodModel.Pin(1234)) assertThat(isUnlocked).isFalse() assertThat(underTest.authenticate(listOf())).isFalse() assertThat(isUnlocked).isFalse() assertThat(failedAttemptCount).isEqualTo(1) } @Test fun authenticate_withCorrectMaxLengthPin_returnsTrueAndUnlocksDevice() = testScope.runTest { val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) underTest.setAuthenticationMethod(AuthenticationMethodModel.Pin(9999999999999999)) assertThat(isUnlocked).isFalse() assertThat(underTest.authenticate(List(16) { 9 })).isTrue() assertThat(isUnlocked).isTrue() assertThat(failedAttemptCount).isEqualTo(0) } @Test fun authenticate_withCorrectTooLongPin_returnsFalseAndDoesNotUnlockDevice() = testScope.runTest { // Max pin length is 16 digits. To avoid issues with overflows, this test ensures // that all pins > 16 decimal digits are rejected. // If the policy changes, there is work to do in SysUI. assertThat(DevicePolicyManager.MAX_PASSWORD_LENGTH).isLessThan(17) val failedAttemptCount by collectLastValue(underTest.failedAuthenticationAttempts) val isUnlocked by collectLastValue(underTest.isUnlocked) underTest.setAuthenticationMethod(AuthenticationMethodModel.Pin(99999999999999999)) assertThat(isUnlocked).isFalse() assertThat(underTest.authenticate(List(17) { 9 })).isFalse() assertThat(isUnlocked).isFalse() assertThat(failedAttemptCount).isEqualTo(1) } @Test fun authenticate_withCorrectPassword_returnsTrueAndUnlocksDevice() = testScope.runTest { Loading