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>
This commit is contained in:
@@ -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());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user