diff options
| author | 2023-07-19 20:18:13 -0700 | |
|---|---|---|
| committer | 2023-07-21 20:31:34 +0000 | |
| commit | a381768b19847b16f5e68b84935e4505fdded40e (patch) | |
| tree | 3e25efdd4935dd28738687afcc5d4fe074ac690e | |
| parent | eae7134dde0df61d3384d4cb70bb2e1d15c92199 (diff) | |
Minor cleanup: move logic that locks face whenever fingerprint is locked to the interactor
1. This is domain logic that belongs in the face auth interactor
2. When fingerprint state is moved out of KeyguardUpdateMonitor, fingperint interactor would depend on DeviceFaceAuthRepository.isLockedOut if face is class3
Bug: 275788040
Test: atest KeyguardFaceAuthInteractorTest
Test: atest DeviceEntryFaceAuthRepositoryTest
Change-Id: Iede9a41d0ee11fd0f419276efa992b05cba6d3ab
8 files changed, 94 insertions, 19 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt index d1f011ea4f9b..bf1e75b09bac 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt @@ -102,6 +102,9 @@ interface DeviceEntryFaceAuthRepository { /** Whether bypass is currently enabled */ val isBypassEnabled: Flow<Boolean> + /** Set whether face authentication should be locked out or not */ + fun lockoutFaceAuth() + /** * Trigger face authentication. * @@ -199,6 +202,10 @@ constructor( } ?: flowOf(false) + override fun lockoutFaceAuth() { + _isLockedOut.value = true + } + private val faceLockoutResetCallback = object : FaceManager.LockoutResetCallback() { override fun onLockoutReset(sensorId: Int) { @@ -396,7 +403,7 @@ constructor( private val faceAuthCallback = object : FaceManager.AuthenticationCallback() { override fun onAuthenticationFailed() { - _authenticationStatus.value = FailedFaceAuthenticationStatus + _authenticationStatus.value = FailedFaceAuthenticationStatus() _isAuthenticated.value = false faceAuthLogger.authenticationFailed() onFaceAuthRequestCompleted() diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/NoopDeviceEntryFaceAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/NoopDeviceEntryFaceAuthRepository.kt index 27e3a749a6c0..5ef9a9e0482c 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/NoopDeviceEntryFaceAuthRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/NoopDeviceEntryFaceAuthRepository.kt @@ -55,6 +55,8 @@ class NoopDeviceEntryFaceAuthRepository @Inject constructor() : DeviceEntryFaceA override val isBypassEnabled: Flow<Boolean> get() = emptyFlow() + override fun lockoutFaceAuth() = Unit + /** * Trigger face authentication. * diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt index 6e7a20b092f4..84a86ba0aed4 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt @@ -30,6 +30,7 @@ import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository +import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus import com.android.systemui.keyguard.shared.model.TransitionState @@ -67,6 +68,7 @@ constructor( private val featureFlags: FeatureFlags, private val faceAuthenticationLogger: FaceAuthenticationLogger, private val keyguardUpdateMonitor: KeyguardUpdateMonitor, + private val deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository, ) : CoreStartable, KeyguardFaceAuthInteractor { private val listeners: MutableList<FaceAuthenticationListener> = mutableListOf() @@ -117,6 +119,15 @@ constructor( ) } .launchIn(applicationScope) + + deviceEntryFingerprintAuthRepository.isLockedOut + .onEach { + if (it) { + faceAuthenticationLogger.faceLockedOut("Fingerprint locked out") + repository.lockoutFaceAuth() + } + } + .launchIn(applicationScope) } override fun onSwipeUpOnBouncer() { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FaceAuthenticationModels.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FaceAuthenticationModels.kt index d9792cf704c8..3de3666fdc3c 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FaceAuthenticationModels.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FaceAuthenticationModels.kt @@ -23,29 +23,40 @@ import android.os.SystemClock.elapsedRealtime * Authentication status provided by * [com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository] */ -sealed class FaceAuthenticationStatus( - // present to break equality check if the same error occurs repeatedly. - val createdAt: Long = elapsedRealtime() -) +sealed class FaceAuthenticationStatus /** Success authentication status. */ -data class SuccessFaceAuthenticationStatus(val successResult: FaceManager.AuthenticationResult) : - FaceAuthenticationStatus() +data class SuccessFaceAuthenticationStatus( + val successResult: FaceManager.AuthenticationResult, + // present to break equality check if the same error occurs repeatedly. + @JvmField val createdAt: Long = elapsedRealtime() +) : FaceAuthenticationStatus() /** Face authentication help message. */ -data class HelpFaceAuthenticationStatus(val msgId: Int, val msg: String?) : - FaceAuthenticationStatus() +data class HelpFaceAuthenticationStatus( + val msgId: Int, + val msg: String?, // present to break equality check if the same error occurs repeatedly. + @JvmField val createdAt: Long = elapsedRealtime() +) : FaceAuthenticationStatus() /** Face acquired message. */ -data class AcquiredFaceAuthenticationStatus(val acquiredInfo: Int) : FaceAuthenticationStatus() +data class AcquiredFaceAuthenticationStatus( + val acquiredInfo: Int, // present to break equality check if the same error occurs repeatedly. + @JvmField val createdAt: Long = elapsedRealtime() +) : FaceAuthenticationStatus() /** Face authentication failed message. */ -object FailedFaceAuthenticationStatus : FaceAuthenticationStatus() +data class FailedFaceAuthenticationStatus( + // present to break equality check if the same error occurs repeatedly. + @JvmField val createdAt: Long = elapsedRealtime() +) : FaceAuthenticationStatus() /** Face authentication error message */ data class ErrorFaceAuthenticationStatus( val msgId: Int, val msg: String? = null, + // present to break equality check if the same error occurs repeatedly. + @JvmField val createdAt: Long = elapsedRealtime() ) : FaceAuthenticationStatus() { /** * Method that checks if [msgId] is a lockout error. A lockout error means that face @@ -80,5 +91,5 @@ data class FaceDetectionStatus( val userId: Int, val isStrongBiometric: Boolean, // present to break equality check if the same error occurs repeatedly. - val createdAt: Long = elapsedRealtime() + @JvmField val createdAt: Long = elapsedRealtime() ) diff --git a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt index 373f70582612..66067b11a18c 100644 --- a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt @@ -8,6 +8,7 @@ import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.log.core.LogLevel.DEBUG import com.android.systemui.log.dagger.FaceAuthLog +import com.google.errorprone.annotations.CompileTimeConstant import javax.inject.Inject private const val TAG = "DeviceEntryFaceAuthRepositoryLog" @@ -264,4 +265,8 @@ constructor( fun watchdogScheduled() { logBuffer.log(TAG, DEBUG, "FaceManager Biometric watchdog scheduled.") } + + fun faceLockedOut(@CompileTimeConstant reason: String) { + logBuffer.log(TAG, DEBUG, "Face auth has been locked out: $reason") + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt index 8127ac625748..b3f800087bdf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt @@ -265,7 +265,8 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { val successResult = successResult() authenticationCallback.value.onAuthenticationSucceeded(successResult) - assertThat(authStatus()).isEqualTo(SuccessFaceAuthenticationStatus(successResult)) + val response = authStatus() as SuccessFaceAuthenticationStatus + assertThat(response.successResult).isEqualTo(successResult) assertThat(authenticated()).isTrue() assertThat(authRunning()).isFalse() assertThat(canFaceAuthRun()).isFalse() @@ -494,7 +495,9 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { authenticationCallback.value.onAuthenticationHelp(10, "Ignored help msg") authenticationCallback.value.onAuthenticationHelp(11, "Ignored help msg") - assertThat(authStatus()).isEqualTo(HelpFaceAuthenticationStatus(9, "help msg")) + val response = authStatus() as HelpFaceAuthenticationStatus + assertThat(response.msg).isEqualTo("help msg") + assertThat(response.msgId).isEqualTo(response.msgId) } @Test @@ -550,10 +553,8 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { } @Test - fun authenticateDoesNotRunWhenFpIsLockedOut() = - testScope.runTest { - testGatingCheckForFaceAuth { deviceEntryFingerprintAuthRepository.setLockedOut(true) } - } + fun authenticateDoesNotRunWhenFaceIsDisabled() = + testScope.runTest { testGatingCheckForFaceAuth { underTest.lockoutFaceAuth() } } @Test fun authenticateDoesNotRunWhenUserIsCurrentlyTrusted() = @@ -858,6 +859,19 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { } @Test + fun disableFaceUnlockLocksOutFaceUnlock() = + testScope.runTest { + runCurrent() + initCollectors() + assertThat(underTest.isLockedOut.value).isFalse() + + underTest.lockoutFaceAuth() + runCurrent() + + assertThat(underTest.isLockedOut.value).isTrue() + } + + @Test fun detectDoesNotRunWhenFaceAuthNotSupportedInCurrentPosture() = testScope.runTest { testGatingCheckForDetect { @@ -1070,10 +1084,11 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { } private suspend fun TestScope.allPreconditionsToRunFaceAuthAreTrue() { + verify(faceManager, atLeastOnce()) + .addLockoutResetCallback(faceLockoutResetCallback.capture()) biometricSettingsRepository.setFaceEnrolled(true) biometricSettingsRepository.setIsFaceAuthEnabled(true) fakeUserRepository.setUserSwitching(false) - deviceEntryFingerprintAuthRepository.setLockedOut(false) trustRepository.setCurrentUserTrusted(false) keyguardRepository.setKeyguardGoingAway(false) keyguardRepository.setWakefulnessModel( @@ -1087,6 +1102,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { biometricSettingsRepository.setIsUserInLockdown(false) fakeUserRepository.setSelectedUserInfo(primaryUser) biometricSettingsRepository.setIsFaceAuthSupportedInCurrentPosture(true) + faceLockoutResetCallback.value.onLockoutReset(0) bouncerRepository.setAlternateVisible(true) keyguardRepository.setKeyguardShowing(true) runCurrent() diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt index ced0a213ca97..8c9ed5b2ef4e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt @@ -38,6 +38,7 @@ import com.android.systemui.flags.Flags import com.android.systemui.keyguard.DismissCallbackRegistry import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFaceAuthRepository +import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.FakeTrustRepository import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus @@ -73,6 +74,8 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() { private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor private lateinit var faceAuthRepository: FakeDeviceEntryFaceAuthRepository + private lateinit var fakeDeviceEntryFingerprintAuthRepository: + FakeDeviceEntryFingerprintAuthRepository @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor @@ -94,6 +97,7 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() { ) .keyguardTransitionInteractor + fakeDeviceEntryFingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository() underTest = SystemUIKeyguardFaceAuthInteractor( mContext, @@ -127,6 +131,7 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() { featureFlags, FaceAuthenticationLogger(logcatLogBuffer("faceAuthBuffer")), keyguardUpdateMonitor, + fakeDeviceEntryFingerprintAuthRepository ) } @@ -335,4 +340,14 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() { assertThat(faceAuthRepository.runningAuthRequest.value) .isEqualTo(Pair(FaceAuthUiEvent.FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER, false)) } + + @Test + fun faceUnlockIsDisabledWhenFpIsLockedOut() = testScope.runTest { + underTest.start() + + fakeDeviceEntryFingerprintAuthRepository.setLockedOut(true) + runCurrent() + + assertThat(faceAuthRepository.wasDisabled).isTrue() + } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFaceAuthRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFaceAuthRepository.kt index 548169e6cccd..f4c2db1b944e 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFaceAuthRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFaceAuthRepository.kt @@ -27,6 +27,11 @@ import kotlinx.coroutines.flow.filterNotNull class FakeDeviceEntryFaceAuthRepository : DeviceEntryFaceAuthRepository { + private var _wasDisabled: Boolean = false + + val wasDisabled: Boolean + get() = _wasDisabled + override val isAuthenticated = MutableStateFlow(false) override val canRunFaceAuth = MutableStateFlow(false) private val _authenticationStatus = MutableStateFlow<FaceAuthenticationStatus?>(null) @@ -52,6 +57,9 @@ class FakeDeviceEntryFaceAuthRepository : DeviceEntryFaceAuthRepository { override val isAuthRunning: StateFlow<Boolean> = _isAuthRunning override val isBypassEnabled = MutableStateFlow(false) + override fun lockoutFaceAuth() { + _wasDisabled = true + } override suspend fun authenticate(uiEvent: FaceAuthUiEvent, fallbackToDetection: Boolean) { _runningAuthRequest.value = uiEvent to fallbackToDetection |