diff options
| author | 2023-07-18 13:26:51 +0000 | |
|---|---|---|
| committer | 2023-07-18 13:26:51 +0000 | |
| commit | ae0f12ceac877c8bb58025cfecb14e24c943a718 (patch) | |
| tree | ae41524fc910a194f294d07df381a8fcd01a35c5 | |
| parent | bb5b9522b61965a2bac5ab9096c9c3943a88b9b2 (diff) | |
| parent | 5cb7302659b6157e37bc8a3738d2ab0e91a83455 (diff) | |
Merge "Add FingerprintAuthenticationStatus" into udc-qpr-dev am: 7de73f27bb am: 5cb7302659
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/24026553
Change-Id: Ice3ba4ebd9293f8f6e4fe979eda726879d1a794e
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
19 files changed, 409 insertions, 133 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 5e84a57b488f..35198deab55f 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -164,13 +164,13 @@ import com.android.systemui.flags.Flags; import com.android.systemui.keyguard.domain.interactor.FaceAuthenticationListener; import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor; import com.android.systemui.keyguard.shared.constants.TrustAgentUiEvent; -import com.android.systemui.keyguard.shared.model.AcquiredAuthenticationStatus; -import com.android.systemui.keyguard.shared.model.AuthenticationStatus; -import com.android.systemui.keyguard.shared.model.DetectionStatus; -import com.android.systemui.keyguard.shared.model.ErrorAuthenticationStatus; -import com.android.systemui.keyguard.shared.model.FailedAuthenticationStatus; -import com.android.systemui.keyguard.shared.model.HelpAuthenticationStatus; -import com.android.systemui.keyguard.shared.model.SuccessAuthenticationStatus; +import com.android.systemui.keyguard.shared.model.AcquiredFaceAuthenticationStatus; +import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus; +import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus; +import com.android.systemui.keyguard.shared.model.FaceDetectionStatus; +import com.android.systemui.keyguard.shared.model.FailedFaceAuthenticationStatus; +import com.android.systemui.keyguard.shared.model.HelpFaceAuthenticationStatus; +import com.android.systemui.keyguard.shared.model.SuccessFaceAuthenticationStatus; import com.android.systemui.keyguard.shared.model.SysUiFaceAuthenticateOptions; import com.android.systemui.log.SessionTracker; import com.android.systemui.plugins.WeatherData; @@ -1471,27 +1471,31 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private FaceAuthenticationListener mFaceAuthenticationListener = new FaceAuthenticationListener() { @Override - public void onAuthenticationStatusChanged(@NonNull AuthenticationStatus status) { - if (status instanceof AcquiredAuthenticationStatus) { + public void onAuthenticationStatusChanged( + @NonNull FaceAuthenticationStatus status + ) { + if (status instanceof AcquiredFaceAuthenticationStatus) { handleFaceAcquired( - ((AcquiredAuthenticationStatus) status).getAcquiredInfo()); - } else if (status instanceof ErrorAuthenticationStatus) { - ErrorAuthenticationStatus error = (ErrorAuthenticationStatus) status; + ((AcquiredFaceAuthenticationStatus) status).getAcquiredInfo()); + } else if (status instanceof ErrorFaceAuthenticationStatus) { + ErrorFaceAuthenticationStatus error = + (ErrorFaceAuthenticationStatus) status; handleFaceError(error.getMsgId(), error.getMsg()); - } else if (status instanceof FailedAuthenticationStatus) { + } else if (status instanceof FailedFaceAuthenticationStatus) { handleFaceAuthFailed(); - } else if (status instanceof HelpAuthenticationStatus) { - HelpAuthenticationStatus helpMsg = (HelpAuthenticationStatus) status; + } else if (status instanceof HelpFaceAuthenticationStatus) { + HelpFaceAuthenticationStatus helpMsg = + (HelpFaceAuthenticationStatus) status; handleFaceHelp(helpMsg.getMsgId(), helpMsg.getMsg()); - } else if (status instanceof SuccessAuthenticationStatus) { + } else if (status instanceof SuccessFaceAuthenticationStatus) { FaceManager.AuthenticationResult result = - ((SuccessAuthenticationStatus) status).getSuccessResult(); + ((SuccessFaceAuthenticationStatus) status).getSuccessResult(); handleFaceAuthenticated(result.getUserId(), result.isStrongBiometric()); } } @Override - public void onDetectionStatusChanged(@NonNull DetectionStatus status) { + public void onDetectionStatusChanged(@NonNull FaceDetectionStatus status) { handleFaceAuthenticated(status.getUserId(), status.isStrongBiometric()); } }; diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt index 2abdb849cd9a..e3e9b3a3754a 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractor.kt @@ -16,10 +16,10 @@ package com.android.systemui.bouncer.domain.interactor +import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository -import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.time.SystemClock @@ -35,8 +35,8 @@ constructor( private val keyguardStateController: KeyguardStateController, private val bouncerRepository: KeyguardBouncerRepository, private val biometricSettingsRepository: BiometricSettingsRepository, - private val deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository, private val systemClock: SystemClock, + private val keyguardUpdateMonitor: KeyguardUpdateMonitor, ) { var receivedDownTouch = false val isVisible: Flow<Boolean> = bouncerRepository.alternateBouncerVisible @@ -78,7 +78,7 @@ constructor( biometricSettingsRepository.isFingerprintEnrolled.value && biometricSettingsRepository.isStrongBiometricAllowed.value && biometricSettingsRepository.isFingerprintEnabledByDevicePolicy.value && - !deviceEntryFingerprintAuthRepository.isLockedOut.value && + !keyguardUpdateMonitor.isFingerprintLockedOut && !keyguardStateController.isUnlocked && !statusBarStateController.isDozing } 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 a3d1abedcc2c..6edf40f47521 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 @@ -38,13 +38,13 @@ import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor -import com.android.systemui.keyguard.shared.model.AcquiredAuthenticationStatus -import com.android.systemui.keyguard.shared.model.AuthenticationStatus -import com.android.systemui.keyguard.shared.model.DetectionStatus -import com.android.systemui.keyguard.shared.model.ErrorAuthenticationStatus -import com.android.systemui.keyguard.shared.model.FailedAuthenticationStatus -import com.android.systemui.keyguard.shared.model.HelpAuthenticationStatus -import com.android.systemui.keyguard.shared.model.SuccessAuthenticationStatus +import com.android.systemui.keyguard.shared.model.AcquiredFaceAuthenticationStatus +import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus +import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus +import com.android.systemui.keyguard.shared.model.FaceDetectionStatus +import com.android.systemui.keyguard.shared.model.FailedFaceAuthenticationStatus +import com.android.systemui.keyguard.shared.model.HelpFaceAuthenticationStatus +import com.android.systemui.keyguard.shared.model.SuccessFaceAuthenticationStatus import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.log.FaceAuthenticationLogger import com.android.systemui.log.SessionTracker @@ -88,10 +88,10 @@ interface DeviceEntryFaceAuthRepository { val canRunFaceAuth: StateFlow<Boolean> /** Provide the current status of face authentication. */ - val authenticationStatus: Flow<AuthenticationStatus> + val authenticationStatus: Flow<FaceAuthenticationStatus> /** Provide the current status of face detection. */ - val detectionStatus: Flow<DetectionStatus> + val detectionStatus: Flow<FaceDetectionStatus> /** Current state of whether face authentication is locked out or not. */ val isLockedOut: StateFlow<Boolean> @@ -151,13 +151,13 @@ constructor( private var cancelNotReceivedHandlerJob: Job? = null private var halErrorRetryJob: Job? = null - private val _authenticationStatus: MutableStateFlow<AuthenticationStatus?> = + private val _authenticationStatus: MutableStateFlow<FaceAuthenticationStatus?> = MutableStateFlow(null) - override val authenticationStatus: Flow<AuthenticationStatus> + override val authenticationStatus: Flow<FaceAuthenticationStatus> get() = _authenticationStatus.filterNotNull() - private val _detectionStatus = MutableStateFlow<DetectionStatus?>(null) - override val detectionStatus: Flow<DetectionStatus> + private val _detectionStatus = MutableStateFlow<FaceDetectionStatus?>(null) + override val detectionStatus: Flow<FaceDetectionStatus> get() = _detectionStatus.filterNotNull() private val _isLockedOut = MutableStateFlow(false) @@ -396,18 +396,18 @@ constructor( private val faceAuthCallback = object : FaceManager.AuthenticationCallback() { override fun onAuthenticationFailed() { - _authenticationStatus.value = FailedAuthenticationStatus + _authenticationStatus.value = FailedFaceAuthenticationStatus _isAuthenticated.value = false faceAuthLogger.authenticationFailed() onFaceAuthRequestCompleted() } override fun onAuthenticationAcquired(acquireInfo: Int) { - _authenticationStatus.value = AcquiredAuthenticationStatus(acquireInfo) + _authenticationStatus.value = AcquiredFaceAuthenticationStatus(acquireInfo) } override fun onAuthenticationError(errorCode: Int, errString: CharSequence?) { - val errorStatus = ErrorAuthenticationStatus(errorCode, errString.toString()) + val errorStatus = ErrorFaceAuthenticationStatus(errorCode, errString.toString()) if (errorStatus.isLockoutError()) { _isLockedOut.value = true } @@ -433,11 +433,11 @@ constructor( if (faceAcquiredInfoIgnoreList.contains(code)) { return } - _authenticationStatus.value = HelpAuthenticationStatus(code, helpStr.toString()) + _authenticationStatus.value = HelpFaceAuthenticationStatus(code, helpStr.toString()) } override fun onAuthenticationSucceeded(result: FaceManager.AuthenticationResult) { - _authenticationStatus.value = SuccessAuthenticationStatus(result) + _authenticationStatus.value = SuccessFaceAuthenticationStatus(result) _isAuthenticated.value = true faceAuthLogger.faceAuthSuccess(result) onFaceAuthRequestCompleted() @@ -482,7 +482,7 @@ constructor( private val detectionCallback = FaceManager.FaceDetectionCallback { sensorId, userId, isStrong -> faceAuthLogger.faceDetected() - _detectionStatus.value = DetectionStatus(sensorId, userId, isStrong) + _detectionStatus.value = FaceDetectionStatus(sensorId, userId, isStrong) } private var cancellationInProgress = false diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt index 52234b32b83a..616ce39d3fee 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt @@ -21,27 +21,29 @@ import android.hardware.biometrics.BiometricAuthenticator.Modality import android.hardware.biometrics.BiometricSourceType import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitorCallback -import com.android.systemui.Dumpable import com.android.systemui.biometrics.AuthController import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.dump.DumpManager -import java.io.PrintWriter +import com.android.systemui.keyguard.shared.model.AcquiredFingerprintAuthenticationStatus +import com.android.systemui.keyguard.shared.model.ErrorFingerprintAuthenticationStatus +import com.android.systemui.keyguard.shared.model.FailedFingerprintAuthenticationStatus +import com.android.systemui.keyguard.shared.model.FingerprintAuthenticationStatus +import com.android.systemui.keyguard.shared.model.HelpFingerprintAuthenticationStatus +import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.stateIn /** Encapsulates state about device entry fingerprint auth mechanism. */ interface DeviceEntryFingerprintAuthRepository { /** Whether the device entry fingerprint auth is locked out. */ - val isLockedOut: StateFlow<Boolean> + val isLockedOut: Flow<Boolean> /** * Whether the fingerprint sensor is currently listening, this doesn't mean that the user is @@ -53,6 +55,9 @@ interface DeviceEntryFingerprintAuthRepository { * Fingerprint sensor type present on the device, null if fingerprint sensor is not available. */ val availableFpSensorType: Flow<BiometricType?> + + /** Provide the current status of fingerprint authentication. */ + val authenticationStatus: Flow<FingerprintAuthenticationStatus> } /** @@ -69,16 +74,7 @@ constructor( val authController: AuthController, val keyguardUpdateMonitor: KeyguardUpdateMonitor, @Application scope: CoroutineScope, - dumpManager: DumpManager, -) : DeviceEntryFingerprintAuthRepository, Dumpable { - - init { - dumpManager.registerDumpable(this) - } - - override fun dump(pw: PrintWriter, args: Array<String?>) { - pw.println("isLockedOut=${isLockedOut.value}") - } +) : DeviceEntryFingerprintAuthRepository { override val availableFpSensorType: Flow<BiometricType?> get() { @@ -114,7 +110,7 @@ constructor( else if (authController.isRearFpsSupported) BiometricType.REAR_FINGERPRINT else null } - override val isLockedOut: StateFlow<Boolean> = + override val isLockedOut: Flow<Boolean> = conflatedCallbackFlow { val sendLockoutUpdate = fun() { @@ -138,7 +134,7 @@ constructor( sendLockoutUpdate() awaitClose { keyguardUpdateMonitor.removeCallback(callback) } } - .stateIn(scope, started = SharingStarted.Eagerly, initialValue = false) + .stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = false) override val isRunning: Flow<Boolean> get() = conflatedCallbackFlow { @@ -166,6 +162,93 @@ constructor( awaitClose { keyguardUpdateMonitor.removeCallback(callback) } } + override val authenticationStatus: Flow<FingerprintAuthenticationStatus> + get() = conflatedCallbackFlow { + val callback = + object : KeyguardUpdateMonitorCallback() { + override fun onBiometricAuthenticated( + userId: Int, + biometricSourceType: BiometricSourceType, + isStrongBiometric: Boolean, + ) { + + sendUpdateIfFingerprint( + biometricSourceType, + SuccessFingerprintAuthenticationStatus( + userId, + isStrongBiometric, + ), + ) + } + + override fun onBiometricError( + msgId: Int, + errString: String?, + biometricSourceType: BiometricSourceType, + ) { + sendUpdateIfFingerprint( + biometricSourceType, + ErrorFingerprintAuthenticationStatus( + msgId, + errString, + ), + ) + } + + override fun onBiometricHelp( + msgId: Int, + helpString: String?, + biometricSourceType: BiometricSourceType, + ) { + sendUpdateIfFingerprint( + biometricSourceType, + HelpFingerprintAuthenticationStatus( + msgId, + helpString, + ), + ) + } + + override fun onBiometricAuthFailed( + biometricSourceType: BiometricSourceType, + ) { + sendUpdateIfFingerprint( + biometricSourceType, + FailedFingerprintAuthenticationStatus, + ) + } + + override fun onBiometricAcquired( + biometricSourceType: BiometricSourceType, + acquireInfo: Int, + ) { + sendUpdateIfFingerprint( + biometricSourceType, + AcquiredFingerprintAuthenticationStatus( + acquireInfo, + ), + ) + } + + private fun sendUpdateIfFingerprint( + biometricSourceType: BiometricSourceType, + authenticationStatus: FingerprintAuthenticationStatus + ) { + if (biometricSourceType != BiometricSourceType.FINGERPRINT) { + return + } + + trySendWithFailureLogging( + authenticationStatus, + TAG, + "new fingerprint authentication status" + ) + } + } + keyguardUpdateMonitor.registerCallback(callback) + awaitClose { keyguardUpdateMonitor.removeCallback(callback) } + } + companion object { const val TAG = "DeviceEntryFingerprintAuthRepositoryImpl" } 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 abe59b76816f..27e3a749a6c0 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 @@ -18,8 +18,8 @@ package com.android.systemui.keyguard.data.repository import com.android.keyguard.FaceAuthUiEvent import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.keyguard.shared.model.AuthenticationStatus -import com.android.systemui.keyguard.shared.model.DetectionStatus +import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus +import com.android.systemui.keyguard.shared.model.FaceDetectionStatus import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow @@ -40,10 +40,10 @@ class NoopDeviceEntryFaceAuthRepository @Inject constructor() : DeviceEntryFaceA private val _canRunFaceAuth = MutableStateFlow(false) override val canRunFaceAuth: StateFlow<Boolean> = _canRunFaceAuth - override val authenticationStatus: Flow<AuthenticationStatus> + override val authenticationStatus: Flow<FaceAuthenticationStatus> get() = emptyFlow() - override val detectionStatus: Flow<DetectionStatus> + override val detectionStatus: Flow<FaceDetectionStatus> get() = emptyFlow() private val _isLockedOut = MutableStateFlow(false) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt index 74ef7a50fd44..141b13055889 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractor.kt @@ -16,8 +16,8 @@ package com.android.systemui.keyguard.domain.interactor -import com.android.systemui.keyguard.shared.model.AuthenticationStatus -import com.android.systemui.keyguard.shared.model.DetectionStatus +import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus +import com.android.systemui.keyguard.shared.model.FaceDetectionStatus import kotlinx.coroutines.flow.Flow /** @@ -27,10 +27,10 @@ import kotlinx.coroutines.flow.Flow interface KeyguardFaceAuthInteractor { /** Current authentication status */ - val authenticationStatus: Flow<AuthenticationStatus> + val authenticationStatus: Flow<FaceAuthenticationStatus> /** Current detection status */ - val detectionStatus: Flow<DetectionStatus> + val detectionStatus: Flow<FaceDetectionStatus> /** Can face auth be run right now */ fun canFaceAuthRun(): Boolean @@ -72,8 +72,8 @@ interface KeyguardFaceAuthInteractor { */ interface FaceAuthenticationListener { /** Receive face authentication status updates */ - fun onAuthenticationStatusChanged(status: AuthenticationStatus) + fun onAuthenticationStatusChanged(status: FaceAuthenticationStatus) /** Receive status updates whenever face detection runs */ - fun onDetectionStatusChanged(status: DetectionStatus) + fun onDetectionStatusChanged(status: FaceDetectionStatus) } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NoopKeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NoopKeyguardFaceAuthInteractor.kt index 5005b6c7f0df..10dd900e437e 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NoopKeyguardFaceAuthInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NoopKeyguardFaceAuthInteractor.kt @@ -17,8 +17,8 @@ package com.android.systemui.keyguard.domain.interactor import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.keyguard.shared.model.AuthenticationStatus -import com.android.systemui.keyguard.shared.model.DetectionStatus +import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus +import com.android.systemui.keyguard.shared.model.FaceDetectionStatus import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.emptyFlow @@ -31,9 +31,9 @@ import kotlinx.coroutines.flow.emptyFlow */ @SysUISingleton class NoopKeyguardFaceAuthInteractor @Inject constructor() : KeyguardFaceAuthInteractor { - override val authenticationStatus: Flow<AuthenticationStatus> + override val authenticationStatus: Flow<FaceAuthenticationStatus> get() = emptyFlow() - override val detectionStatus: Flow<DetectionStatus> + override val detectionStatus: Flow<FaceDetectionStatus> get() = emptyFlow() override fun canFaceAuthRun(): Boolean = false 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 d467225a9d63..6e7a20b092f4 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,8 +30,8 @@ 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.shared.model.AuthenticationStatus -import com.android.systemui.keyguard.shared.model.ErrorAuthenticationStatus +import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus +import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.log.FaceAuthenticationLogger import com.android.systemui.util.kotlin.pairwise @@ -165,10 +165,10 @@ constructor( repository.cancel() } - private val _authenticationStatusOverride = MutableStateFlow<AuthenticationStatus?>(null) + private val faceAuthenticationStatusOverride = MutableStateFlow<FaceAuthenticationStatus?>(null) /** Provide the status of face authentication */ override val authenticationStatus = - merge(_authenticationStatusOverride.filterNotNull(), repository.authenticationStatus) + merge(faceAuthenticationStatusOverride.filterNotNull(), repository.authenticationStatus) /** Provide the status of face detection */ override val detectionStatus = repository.detectionStatus @@ -176,13 +176,13 @@ constructor( private fun runFaceAuth(uiEvent: FaceAuthUiEvent, fallbackToDetect: Boolean) { if (featureFlags.isEnabled(Flags.FACE_AUTH_REFACTOR)) { if (repository.isLockedOut.value) { - _authenticationStatusOverride.value = - ErrorAuthenticationStatus( + faceAuthenticationStatusOverride.value = + ErrorFaceAuthenticationStatus( BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT, context.resources.getString(R.string.keyguard_face_unlock_unavailable) ) } else { - _authenticationStatusOverride.value = null + faceAuthenticationStatusOverride.value = null applicationScope.launch { faceAuthenticationLogger.authRequested(uiEvent) repository.authenticate(uiEvent, fallbackToDetection = fallbackToDetect) 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 b354cfd27687..0f6d82ed4b5c 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,33 +23,35 @@ import android.os.SystemClock.elapsedRealtime * Authentication status provided by * [com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository] */ -sealed class AuthenticationStatus +sealed class FaceAuthenticationStatus /** Success authentication status. */ -data class SuccessAuthenticationStatus(val successResult: FaceManager.AuthenticationResult) : - AuthenticationStatus() +data class SuccessFaceAuthenticationStatus(val successResult: FaceManager.AuthenticationResult) : + FaceAuthenticationStatus() /** Face authentication help message. */ -data class HelpAuthenticationStatus(val msgId: Int, val msg: String?) : AuthenticationStatus() +data class HelpFaceAuthenticationStatus(val msgId: Int, val msg: String?) : + FaceAuthenticationStatus() /** Face acquired message. */ -data class AcquiredAuthenticationStatus(val acquiredInfo: Int) : AuthenticationStatus() +data class AcquiredFaceAuthenticationStatus(val acquiredInfo: Int) : FaceAuthenticationStatus() /** Face authentication failed message. */ -object FailedAuthenticationStatus : AuthenticationStatus() +object FailedFaceAuthenticationStatus : FaceAuthenticationStatus() /** Face authentication error message */ -data class ErrorAuthenticationStatus( +data class ErrorFaceAuthenticationStatus( val msgId: Int, val msg: String? = null, // present to break equality check if the same error occurs repeatedly. val createdAt: Long = elapsedRealtime() -) : AuthenticationStatus() { +) : FaceAuthenticationStatus() { /** * Method that checks if [msgId] is a lockout error. A lockout error means that face * authentication is locked out. */ - fun isLockoutError() = msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT + fun isLockoutError() = + msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT || msgId == FaceManager.FACE_ERROR_LOCKOUT /** * Method that checks if [msgId] is a cancellation error. This means that face authentication @@ -64,4 +66,4 @@ data class ErrorAuthenticationStatus( } /** Face detection success message. */ -data class DetectionStatus(val sensorId: Int, val userId: Int, val isStrongBiometric: Boolean) +data class FaceDetectionStatus(val sensorId: Int, val userId: Int, val isStrongBiometric: Boolean) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FingerprintAuthenticationModels.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FingerprintAuthenticationModels.kt new file mode 100644 index 000000000000..5fb2cbf16a51 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/FingerprintAuthenticationModels.kt @@ -0,0 +1,52 @@ +/* + * Copyright (C) 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.keyguard.shared.model + +import android.os.SystemClock.elapsedRealtime + +/** + * Fingerprint authentication status provided by + * [com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository] + */ +sealed class FingerprintAuthenticationStatus + +/** Fingerprint authentication success status. */ +data class SuccessFingerprintAuthenticationStatus( + val userId: Int, + val isStrongBiometric: Boolean, +) : FingerprintAuthenticationStatus() + +/** Fingerprint authentication help message. */ +data class HelpFingerprintAuthenticationStatus( + val msgId: Int, + val msg: String?, +) : FingerprintAuthenticationStatus() + +/** Fingerprint acquired message. */ +data class AcquiredFingerprintAuthenticationStatus(val acquiredInfo: Int) : + FingerprintAuthenticationStatus() + +/** Fingerprint authentication failed message. */ +object FailedFingerprintAuthenticationStatus : FingerprintAuthenticationStatus() + +/** Fingerprint authentication error message */ +data class ErrorFingerprintAuthenticationStatus( + val msgId: Int, + val msg: String? = null, + // present to break equality check if the same error occurs repeatedly. + val createdAt: Long = elapsedRealtime(), +) : FingerprintAuthenticationStatus() diff --git a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt index 68cdfb6d5865..373f70582612 100644 --- a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt @@ -4,7 +4,7 @@ import android.hardware.face.FaceManager import android.hardware.face.FaceSensorPropertiesInternal import com.android.keyguard.FaceAuthUiEvent import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.keyguard.shared.model.ErrorAuthenticationStatus +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 @@ -240,7 +240,7 @@ constructor( ) } - fun hardwareError(errorStatus: ErrorAuthenticationStatus) { + fun hardwareError(errorStatus: ErrorFaceAuthenticationStatus) { logBuffer.log( TAG, DEBUG, diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt index eaa31ac1d157..ecc776b98c6c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt @@ -48,6 +48,7 @@ import android.view.WindowMetrics import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.airbnb.lottie.LottieAnimationView +import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.R import com.android.systemui.RoboPilotTest import com.android.systemui.SysuiTestCase @@ -64,7 +65,6 @@ import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepositor import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor import com.android.systemui.dump.DumpManager import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository -import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.concurrency.FakeExecutor @@ -153,8 +153,8 @@ class SideFpsControllerTest : SysuiTestCase() { mock(KeyguardStateController::class.java), keyguardBouncerRepository, FakeBiometricSettingsRepository(), - FakeDeviceEntryFingerprintAuthRepository(), FakeSystemClock(), + mock(KeyguardUpdateMonitor::class.java), ) displayStateInteractor = DisplayStateInteractorImpl( diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt index 9df06dc9e18f..8dfeb3bde0c0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewLegacyControllerWithCoroutinesTest.kt @@ -34,7 +34,6 @@ import com.android.systemui.flags.FakeFeatureFlags 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.DeviceEntryFingerprintAuthRepository import com.android.systemui.keyguard.data.repository.FakeTrustRepository import com.android.systemui.log.table.TableLogBuffer import com.android.systemui.plugins.statusbar.StatusBarStateController @@ -106,8 +105,8 @@ class UdfpsKeyguardViewLegacyControllerWithCoroutinesTest : mock(KeyguardStateController::class.java), keyguardBouncerRepository, mock(BiometricSettingsRepository::class.java), - mock(DeviceEntryFingerprintAuthRepository::class.java), mock(SystemClock::class.java), + mKeyguardUpdateMonitor, ) return createUdfpsKeyguardViewController( /* useModernBouncer */ true, /* useExpandedOverlay */ diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt index 37b9ca49ef57..186df02536ea 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.bouncer.domain.interactor import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest +import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.RoboPilotTest import com.android.systemui.SysuiTestCase import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository @@ -54,6 +55,7 @@ class AlternateBouncerInteractorTest : SysuiTestCase() { @Mock private lateinit var keyguardStateController: KeyguardStateController @Mock private lateinit var systemClock: SystemClock @Mock private lateinit var bouncerLogger: TableLogBuffer + @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor @Before fun setup() { @@ -72,8 +74,8 @@ class AlternateBouncerInteractorTest : SysuiTestCase() { keyguardStateController, bouncerRepository, biometricSettingsRepository, - deviceEntryFingerprintAuthRepository, systemClock, + keyguardUpdateMonitor, ) } @@ -118,7 +120,7 @@ class AlternateBouncerInteractorTest : SysuiTestCase() { @Test fun canShowAlternateBouncerForFingerprint_fingerprintLockedOut() { givenCanShowAlternateBouncer() - deviceEntryFingerprintAuthRepository.setLockedOut(true) + whenever(keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(true) assertFalse(underTest.canShowAlternateBouncerForFingerprint()) } @@ -168,7 +170,7 @@ class AlternateBouncerInteractorTest : SysuiTestCase() { biometricSettingsRepository.setFingerprintEnrolled(true) biometricSettingsRepository.setStrongBiometricAllowed(true) biometricSettingsRepository.setFingerprintEnabledByDevicePolicy(true) - deviceEntryFingerprintAuthRepository.setLockedOut(false) + whenever(keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(false) whenever(keyguardStateController.isUnlocked).thenReturn(false) } 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 020c0b22ba27..47c662c3b4b0 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 @@ -36,6 +36,7 @@ import com.android.internal.logging.UiEventLogger import com.android.keyguard.FaceAuthUiEvent import com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_TRIGGERED_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN import com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER +import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.R import com.android.systemui.RoboPilotTest import com.android.systemui.SysuiTestCase @@ -50,12 +51,12 @@ import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory -import com.android.systemui.keyguard.shared.model.AuthenticationStatus -import com.android.systemui.keyguard.shared.model.DetectionStatus -import com.android.systemui.keyguard.shared.model.ErrorAuthenticationStatus -import com.android.systemui.keyguard.shared.model.HelpAuthenticationStatus +import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus +import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus +import com.android.systemui.keyguard.shared.model.FaceDetectionStatus +import com.android.systemui.keyguard.shared.model.HelpFaceAuthenticationStatus import com.android.systemui.keyguard.shared.model.KeyguardState -import com.android.systemui.keyguard.shared.model.SuccessAuthenticationStatus +import com.android.systemui.keyguard.shared.model.SuccessFaceAuthenticationStatus import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.keyguard.shared.model.WakeSleepReason @@ -113,6 +114,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { @Mock private lateinit var sessionTracker: SessionTracker @Mock private lateinit var uiEventLogger: UiEventLogger @Mock private lateinit var dumpManager: DumpManager + @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor @Captor private lateinit var authenticationCallback: ArgumentCaptor<FaceManager.AuthenticationCallback> @@ -131,8 +133,8 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository private lateinit var testScope: TestScope private lateinit var fakeUserRepository: FakeUserRepository - private lateinit var authStatus: FlowValue<AuthenticationStatus?> - private lateinit var detectStatus: FlowValue<DetectionStatus?> + private lateinit var authStatus: FlowValue<FaceAuthenticationStatus?> + private lateinit var detectStatus: FlowValue<FaceDetectionStatus?> private lateinit var authRunning: FlowValue<Boolean?> private lateinit var bypassEnabled: FlowValue<Boolean?> private lateinit var lockedOut: FlowValue<Boolean?> @@ -175,10 +177,10 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { AlternateBouncerInteractor( bouncerRepository = bouncerRepository, biometricSettingsRepository = biometricSettingsRepository, - deviceEntryFingerprintAuthRepository = deviceEntryFingerprintAuthRepository, systemClock = mock(SystemClock::class.java), keyguardStateController = FakeKeyguardStateController(), statusBarStateController = mock(StatusBarStateController::class.java), + keyguardUpdateMonitor = keyguardUpdateMonitor, ) bypassStateChangedListener = @@ -262,7 +264,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { val successResult = successResult() authenticationCallback.value.onAuthenticationSucceeded(successResult) - assertThat(authStatus()).isEqualTo(SuccessAuthenticationStatus(successResult)) + assertThat(authStatus()).isEqualTo(SuccessFaceAuthenticationStatus(successResult)) assertThat(authenticated()).isTrue() assertThat(authRunning()).isFalse() assertThat(canFaceAuthRun()).isFalse() @@ -383,7 +385,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { detectionCallback.value.onFaceDetected(1, 1, true) - assertThat(detectStatus()).isEqualTo(DetectionStatus(1, 1, true)) + assertThat(detectStatus()).isEqualTo(FaceDetectionStatus(1, 1, true)) } @Test @@ -423,7 +425,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { FACE_ERROR_CANCELED, "First auth attempt cancellation completed" ) - val value = authStatus() as ErrorAuthenticationStatus + val value = authStatus() as ErrorFaceAuthenticationStatus assertThat(value.msgId).isEqualTo(FACE_ERROR_CANCELED) assertThat(value.msg).isEqualTo("First auth attempt cancellation completed") @@ -465,7 +467,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() { authenticationCallback.value.onAuthenticationHelp(10, "Ignored help msg") authenticationCallback.value.onAuthenticationHelp(11, "Ignored help msg") - assertThat(authStatus()).isEqualTo(HelpAuthenticationStatus(9, "help msg")) + assertThat(authStatus()).isEqualTo(HelpFaceAuthenticationStatus(9, "help msg")) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt index 264328b04227..a73b57c3bba2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt @@ -26,7 +26,11 @@ import com.android.systemui.RoboPilotTest import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.AuthController import com.android.systemui.coroutines.collectLastValue -import com.android.systemui.dump.DumpManager +import com.android.systemui.keyguard.shared.model.AcquiredFingerprintAuthenticationStatus +import com.android.systemui.keyguard.shared.model.ErrorFingerprintAuthenticationStatus +import com.android.systemui.keyguard.shared.model.FailedFingerprintAuthenticationStatus +import com.android.systemui.keyguard.shared.model.HelpFingerprintAuthenticationStatus +import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -49,7 +53,6 @@ import org.mockito.MockitoAnnotations @RunWith(AndroidJUnit4::class) class DeviceEntryFingerprintAuthRepositoryTest : SysuiTestCase() { @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor - @Mock private lateinit var dumpManager: DumpManager @Mock private lateinit var authController: AuthController @Captor private lateinit var updateMonitorCallback: ArgumentCaptor<KeyguardUpdateMonitorCallback> @@ -68,7 +71,6 @@ class DeviceEntryFingerprintAuthRepositoryTest : SysuiTestCase() { authController, keyguardUpdateMonitor, testScope.backgroundScope, - dumpManager, ) } @@ -177,4 +179,129 @@ class DeviceEntryFingerprintAuthRepositoryTest : SysuiTestCase() { callback.value.onAllAuthenticatorsRegistered(TYPE_FINGERPRINT) assertThat(availableFpSensorType()).isEqualTo(BiometricType.UNDER_DISPLAY_FINGERPRINT) } + + @Test + fun onFingerprintSuccess_successAuthenticationStatus() = + testScope.runTest { + val authenticationStatus by collectLastValue(underTest.authenticationStatus) + runCurrent() + + verify(keyguardUpdateMonitor).registerCallback(updateMonitorCallback.capture()) + updateMonitorCallback.value.onBiometricAuthenticated( + 0, + BiometricSourceType.FINGERPRINT, + true, + ) + + val status = authenticationStatus as SuccessFingerprintAuthenticationStatus + assertThat(status.userId).isEqualTo(0) + assertThat(status.isStrongBiometric).isEqualTo(true) + } + + @Test + fun onFingerprintFailed_failedAuthenticationStatus() = + testScope.runTest { + val authenticationStatus by collectLastValue(underTest.authenticationStatus) + runCurrent() + + verify(keyguardUpdateMonitor).registerCallback(updateMonitorCallback.capture()) + updateMonitorCallback.value.onBiometricAuthFailed( + BiometricSourceType.FINGERPRINT, + ) + + assertThat(authenticationStatus) + .isInstanceOf(FailedFingerprintAuthenticationStatus::class.java) + } + + @Test + fun onFingerprintError_errorAuthenticationStatus() = + testScope.runTest { + val authenticationStatus by collectLastValue(underTest.authenticationStatus) + runCurrent() + + verify(keyguardUpdateMonitor).registerCallback(updateMonitorCallback.capture()) + updateMonitorCallback.value.onBiometricError( + 1, + "test_string", + BiometricSourceType.FINGERPRINT, + ) + + val status = authenticationStatus as ErrorFingerprintAuthenticationStatus + assertThat(status.msgId).isEqualTo(1) + assertThat(status.msg).isEqualTo("test_string") + } + + @Test + fun onFingerprintHelp_helpAuthenticationStatus() = + testScope.runTest { + val authenticationStatus by collectLastValue(underTest.authenticationStatus) + runCurrent() + + verify(keyguardUpdateMonitor).registerCallback(updateMonitorCallback.capture()) + updateMonitorCallback.value.onBiometricHelp( + 1, + "test_string", + BiometricSourceType.FINGERPRINT, + ) + + val status = authenticationStatus as HelpFingerprintAuthenticationStatus + assertThat(status.msgId).isEqualTo(1) + assertThat(status.msg).isEqualTo("test_string") + } + + @Test + fun onFingerprintAcquired_acquiredAuthenticationStatus() = + testScope.runTest { + val authenticationStatus by collectLastValue(underTest.authenticationStatus) + runCurrent() + + verify(keyguardUpdateMonitor).registerCallback(updateMonitorCallback.capture()) + updateMonitorCallback.value.onBiometricAcquired( + BiometricSourceType.FINGERPRINT, + 5, + ) + + val status = authenticationStatus as AcquiredFingerprintAuthenticationStatus + assertThat(status.acquiredInfo).isEqualTo(5) + } + + @Test + fun onFaceCallbacks_fingerprintAuthenticationStatusIsUnchanged() = + testScope.runTest { + val authenticationStatus by collectLastValue(underTest.authenticationStatus) + runCurrent() + + verify(keyguardUpdateMonitor).registerCallback(updateMonitorCallback.capture()) + updateMonitorCallback.value.onBiometricAuthenticated( + 0, + BiometricSourceType.FACE, + true, + ) + assertThat(authenticationStatus).isNull() + + updateMonitorCallback.value.onBiometricAuthFailed( + BiometricSourceType.FACE, + ) + assertThat(authenticationStatus).isNull() + + updateMonitorCallback.value.onBiometricHelp( + 1, + "test_string", + BiometricSourceType.FACE, + ) + assertThat(authenticationStatus).isNull() + + updateMonitorCallback.value.onBiometricAcquired( + BiometricSourceType.FACE, + 5, + ) + assertThat(authenticationStatus).isNull() + + updateMonitorCallback.value.onBiometricError( + 1, + "test_string", + BiometricSourceType.FACE, + ) + assertThat(authenticationStatus).isNull() + } } 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 3e81cd336824..ced0a213ca97 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,10 +38,9 @@ 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.ErrorAuthenticationStatus +import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionStep @@ -121,8 +120,8 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() { mock(KeyguardStateController::class.java), bouncerRepository, mock(BiometricSettingsRepository::class.java), - FakeDeviceEntryFingerprintAuthRepository(), FakeSystemClock(), + keyguardUpdateMonitor, ), keyguardTransitionInteractor, featureFlags, @@ -160,7 +159,7 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() { underTest.onDeviceLifted() - val outputValue = authenticationStatus()!! as ErrorAuthenticationStatus + val outputValue = authenticationStatus()!! as ErrorFaceAuthenticationStatus assertThat(outputValue.msgId) .isEqualTo(BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT) assertThat(outputValue.msg).isEqualTo("Face Unlock unavailable") 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 2715aaa82253..548169e6cccd 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 @@ -17,8 +17,8 @@ package com.android.systemui.keyguard.data.repository import com.android.keyguard.FaceAuthUiEvent -import com.android.systemui.keyguard.shared.model.AuthenticationStatus -import com.android.systemui.keyguard.shared.model.DetectionStatus +import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus +import com.android.systemui.keyguard.shared.model.FaceDetectionStatus import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -29,16 +29,16 @@ class FakeDeviceEntryFaceAuthRepository : DeviceEntryFaceAuthRepository { override val isAuthenticated = MutableStateFlow(false) override val canRunFaceAuth = MutableStateFlow(false) - private val _authenticationStatus = MutableStateFlow<AuthenticationStatus?>(null) - override val authenticationStatus: Flow<AuthenticationStatus> = + private val _authenticationStatus = MutableStateFlow<FaceAuthenticationStatus?>(null) + override val authenticationStatus: Flow<FaceAuthenticationStatus> = _authenticationStatus.filterNotNull() - fun setAuthenticationStatus(status: AuthenticationStatus) { + fun setAuthenticationStatus(status: FaceAuthenticationStatus) { _authenticationStatus.value = status } - private val _detectionStatus = MutableStateFlow<DetectionStatus?>(null) - override val detectionStatus: Flow<DetectionStatus> + private val _detectionStatus = MutableStateFlow<FaceDetectionStatus?>(null) + override val detectionStatus: Flow<FaceDetectionStatus> get() = _detectionStatus.filterNotNull() - fun setDetectionStatus(status: DetectionStatus) { + fun setDetectionStatus(status: FaceDetectionStatus) { _detectionStatus.value = status } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFingerprintAuthRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFingerprintAuthRepository.kt index 4bfd3d64c98e..38791caf5bfc 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFingerprintAuthRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFingerprintAuthRepository.kt @@ -17,32 +17,38 @@ package com.android.systemui.keyguard.data.repository +import com.android.systemui.keyguard.shared.model.FingerprintAuthenticationStatus import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.filterNotNull class FakeDeviceEntryFingerprintAuthRepository : DeviceEntryFingerprintAuthRepository { private val _isLockedOut = MutableStateFlow(false) override val isLockedOut: StateFlow<Boolean> = _isLockedOut.asStateFlow() - - private val _isRunning = MutableStateFlow(false) - override val isRunning: Flow<Boolean> - get() = _isRunning - - private var fpSensorType = MutableStateFlow<BiometricType?>(null) - override val availableFpSensorType: Flow<BiometricType?> - get() = fpSensorType - fun setLockedOut(lockedOut: Boolean) { _isLockedOut.value = lockedOut } + private val _isRunning = MutableStateFlow(false) + override val isRunning: Flow<Boolean> + get() = _isRunning fun setIsRunning(value: Boolean) { _isRunning.value = value } + private var fpSensorType = MutableStateFlow<BiometricType?>(null) + override val availableFpSensorType: Flow<BiometricType?> + get() = fpSensorType fun setAvailableFpSensorType(value: BiometricType?) { fpSensorType.value = value } + + private var _authenticationStatus = MutableStateFlow<FingerprintAuthenticationStatus?>(null) + override val authenticationStatus: Flow<FingerprintAuthenticationStatus> + get() = _authenticationStatus.filterNotNull() + fun setAuthenticationStatus(status: FingerprintAuthenticationStatus) { + _authenticationStatus.value = status + } } |