Merge "Add FingerprintAuthenticationStatus" into udc-qpr-dev am: 7de73f27bb
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/24026553 Change-Id: I0da7cb7af5497e93a2dc98f0b08333a2b446db79 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.FaceAuthenticationListener;
|
||||||
import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
|
import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
|
||||||
import com.android.systemui.keyguard.shared.constants.TrustAgentUiEvent;
|
import com.android.systemui.keyguard.shared.constants.TrustAgentUiEvent;
|
||||||
import com.android.systemui.keyguard.shared.model.AcquiredAuthenticationStatus;
|
import com.android.systemui.keyguard.shared.model.AcquiredFaceAuthenticationStatus;
|
||||||
import com.android.systemui.keyguard.shared.model.AuthenticationStatus;
|
import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus;
|
||||||
import com.android.systemui.keyguard.shared.model.DetectionStatus;
|
import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus;
|
||||||
import com.android.systemui.keyguard.shared.model.ErrorAuthenticationStatus;
|
import com.android.systemui.keyguard.shared.model.FaceDetectionStatus;
|
||||||
import com.android.systemui.keyguard.shared.model.FailedAuthenticationStatus;
|
import com.android.systemui.keyguard.shared.model.FailedFaceAuthenticationStatus;
|
||||||
import com.android.systemui.keyguard.shared.model.HelpAuthenticationStatus;
|
import com.android.systemui.keyguard.shared.model.HelpFaceAuthenticationStatus;
|
||||||
import com.android.systemui.keyguard.shared.model.SuccessAuthenticationStatus;
|
import com.android.systemui.keyguard.shared.model.SuccessFaceAuthenticationStatus;
|
||||||
import com.android.systemui.keyguard.shared.model.SysUiFaceAuthenticateOptions;
|
import com.android.systemui.keyguard.shared.model.SysUiFaceAuthenticateOptions;
|
||||||
import com.android.systemui.log.SessionTracker;
|
import com.android.systemui.log.SessionTracker;
|
||||||
import com.android.systemui.plugins.WeatherData;
|
import com.android.systemui.plugins.WeatherData;
|
||||||
@@ -1471,27 +1471,31 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
private FaceAuthenticationListener mFaceAuthenticationListener =
|
private FaceAuthenticationListener mFaceAuthenticationListener =
|
||||||
new FaceAuthenticationListener() {
|
new FaceAuthenticationListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onAuthenticationStatusChanged(@NonNull AuthenticationStatus status) {
|
public void onAuthenticationStatusChanged(
|
||||||
if (status instanceof AcquiredAuthenticationStatus) {
|
@NonNull FaceAuthenticationStatus status
|
||||||
|
) {
|
||||||
|
if (status instanceof AcquiredFaceAuthenticationStatus) {
|
||||||
handleFaceAcquired(
|
handleFaceAcquired(
|
||||||
((AcquiredAuthenticationStatus) status).getAcquiredInfo());
|
((AcquiredFaceAuthenticationStatus) status).getAcquiredInfo());
|
||||||
} else if (status instanceof ErrorAuthenticationStatus) {
|
} else if (status instanceof ErrorFaceAuthenticationStatus) {
|
||||||
ErrorAuthenticationStatus error = (ErrorAuthenticationStatus) status;
|
ErrorFaceAuthenticationStatus error =
|
||||||
|
(ErrorFaceAuthenticationStatus) status;
|
||||||
handleFaceError(error.getMsgId(), error.getMsg());
|
handleFaceError(error.getMsgId(), error.getMsg());
|
||||||
} else if (status instanceof FailedAuthenticationStatus) {
|
} else if (status instanceof FailedFaceAuthenticationStatus) {
|
||||||
handleFaceAuthFailed();
|
handleFaceAuthFailed();
|
||||||
} else if (status instanceof HelpAuthenticationStatus) {
|
} else if (status instanceof HelpFaceAuthenticationStatus) {
|
||||||
HelpAuthenticationStatus helpMsg = (HelpAuthenticationStatus) status;
|
HelpFaceAuthenticationStatus helpMsg =
|
||||||
|
(HelpFaceAuthenticationStatus) status;
|
||||||
handleFaceHelp(helpMsg.getMsgId(), helpMsg.getMsg());
|
handleFaceHelp(helpMsg.getMsgId(), helpMsg.getMsg());
|
||||||
} else if (status instanceof SuccessAuthenticationStatus) {
|
} else if (status instanceof SuccessFaceAuthenticationStatus) {
|
||||||
FaceManager.AuthenticationResult result =
|
FaceManager.AuthenticationResult result =
|
||||||
((SuccessAuthenticationStatus) status).getSuccessResult();
|
((SuccessFaceAuthenticationStatus) status).getSuccessResult();
|
||||||
handleFaceAuthenticated(result.getUserId(), result.isStrongBiometric());
|
handleFaceAuthenticated(result.getUserId(), result.isStrongBiometric());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDetectionStatusChanged(@NonNull DetectionStatus status) {
|
public void onDetectionStatusChanged(@NonNull FaceDetectionStatus status) {
|
||||||
handleFaceAuthenticated(status.getUserId(), status.isStrongBiometric());
|
handleFaceAuthenticated(status.getUserId(), status.isStrongBiometric());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,10 +16,10 @@
|
|||||||
|
|
||||||
package com.android.systemui.bouncer.domain.interactor
|
package com.android.systemui.bouncer.domain.interactor
|
||||||
|
|
||||||
|
import com.android.keyguard.KeyguardUpdateMonitor
|
||||||
import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
|
import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
|
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.plugins.statusbar.StatusBarStateController
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController
|
import com.android.systemui.statusbar.policy.KeyguardStateController
|
||||||
import com.android.systemui.util.time.SystemClock
|
import com.android.systemui.util.time.SystemClock
|
||||||
@@ -35,8 +35,8 @@ constructor(
|
|||||||
private val keyguardStateController: KeyguardStateController,
|
private val keyguardStateController: KeyguardStateController,
|
||||||
private val bouncerRepository: KeyguardBouncerRepository,
|
private val bouncerRepository: KeyguardBouncerRepository,
|
||||||
private val biometricSettingsRepository: BiometricSettingsRepository,
|
private val biometricSettingsRepository: BiometricSettingsRepository,
|
||||||
private val deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
|
|
||||||
private val systemClock: SystemClock,
|
private val systemClock: SystemClock,
|
||||||
|
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
|
||||||
) {
|
) {
|
||||||
var receivedDownTouch = false
|
var receivedDownTouch = false
|
||||||
val isVisible: Flow<Boolean> = bouncerRepository.alternateBouncerVisible
|
val isVisible: Flow<Boolean> = bouncerRepository.alternateBouncerVisible
|
||||||
@@ -78,7 +78,7 @@ constructor(
|
|||||||
biometricSettingsRepository.isFingerprintEnrolled.value &&
|
biometricSettingsRepository.isFingerprintEnrolled.value &&
|
||||||
biometricSettingsRepository.isStrongBiometricAllowed.value &&
|
biometricSettingsRepository.isStrongBiometricAllowed.value &&
|
||||||
biometricSettingsRepository.isFingerprintEnabledByDevicePolicy.value &&
|
biometricSettingsRepository.isFingerprintEnabledByDevicePolicy.value &&
|
||||||
!deviceEntryFingerprintAuthRepository.isLockedOut.value &&
|
!keyguardUpdateMonitor.isFingerprintLockedOut &&
|
||||||
!keyguardStateController.isUnlocked &&
|
!keyguardStateController.isUnlocked &&
|
||||||
!statusBarStateController.isDozing
|
!statusBarStateController.isDozing
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,13 +38,13 @@ import com.android.systemui.flags.FeatureFlags
|
|||||||
import com.android.systemui.flags.Flags
|
import com.android.systemui.flags.Flags
|
||||||
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
|
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
|
||||||
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
|
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
|
||||||
import com.android.systemui.keyguard.shared.model.AcquiredAuthenticationStatus
|
import com.android.systemui.keyguard.shared.model.AcquiredFaceAuthenticationStatus
|
||||||
import com.android.systemui.keyguard.shared.model.AuthenticationStatus
|
import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus
|
||||||
import com.android.systemui.keyguard.shared.model.DetectionStatus
|
import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus
|
||||||
import com.android.systemui.keyguard.shared.model.ErrorAuthenticationStatus
|
import com.android.systemui.keyguard.shared.model.FaceDetectionStatus
|
||||||
import com.android.systemui.keyguard.shared.model.FailedAuthenticationStatus
|
import com.android.systemui.keyguard.shared.model.FailedFaceAuthenticationStatus
|
||||||
import com.android.systemui.keyguard.shared.model.HelpAuthenticationStatus
|
import com.android.systemui.keyguard.shared.model.HelpFaceAuthenticationStatus
|
||||||
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.TransitionState
|
||||||
import com.android.systemui.log.FaceAuthenticationLogger
|
import com.android.systemui.log.FaceAuthenticationLogger
|
||||||
import com.android.systemui.log.SessionTracker
|
import com.android.systemui.log.SessionTracker
|
||||||
@@ -88,10 +88,10 @@ interface DeviceEntryFaceAuthRepository {
|
|||||||
val canRunFaceAuth: StateFlow<Boolean>
|
val canRunFaceAuth: StateFlow<Boolean>
|
||||||
|
|
||||||
/** Provide the current status of face authentication. */
|
/** Provide the current status of face authentication. */
|
||||||
val authenticationStatus: Flow<AuthenticationStatus>
|
val authenticationStatus: Flow<FaceAuthenticationStatus>
|
||||||
|
|
||||||
/** Provide the current status of face detection. */
|
/** 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. */
|
/** Current state of whether face authentication is locked out or not. */
|
||||||
val isLockedOut: StateFlow<Boolean>
|
val isLockedOut: StateFlow<Boolean>
|
||||||
@@ -151,13 +151,13 @@ constructor(
|
|||||||
private var cancelNotReceivedHandlerJob: Job? = null
|
private var cancelNotReceivedHandlerJob: Job? = null
|
||||||
private var halErrorRetryJob: Job? = null
|
private var halErrorRetryJob: Job? = null
|
||||||
|
|
||||||
private val _authenticationStatus: MutableStateFlow<AuthenticationStatus?> =
|
private val _authenticationStatus: MutableStateFlow<FaceAuthenticationStatus?> =
|
||||||
MutableStateFlow(null)
|
MutableStateFlow(null)
|
||||||
override val authenticationStatus: Flow<AuthenticationStatus>
|
override val authenticationStatus: Flow<FaceAuthenticationStatus>
|
||||||
get() = _authenticationStatus.filterNotNull()
|
get() = _authenticationStatus.filterNotNull()
|
||||||
|
|
||||||
private val _detectionStatus = MutableStateFlow<DetectionStatus?>(null)
|
private val _detectionStatus = MutableStateFlow<FaceDetectionStatus?>(null)
|
||||||
override val detectionStatus: Flow<DetectionStatus>
|
override val detectionStatus: Flow<FaceDetectionStatus>
|
||||||
get() = _detectionStatus.filterNotNull()
|
get() = _detectionStatus.filterNotNull()
|
||||||
|
|
||||||
private val _isLockedOut = MutableStateFlow(false)
|
private val _isLockedOut = MutableStateFlow(false)
|
||||||
@@ -396,18 +396,18 @@ constructor(
|
|||||||
private val faceAuthCallback =
|
private val faceAuthCallback =
|
||||||
object : FaceManager.AuthenticationCallback() {
|
object : FaceManager.AuthenticationCallback() {
|
||||||
override fun onAuthenticationFailed() {
|
override fun onAuthenticationFailed() {
|
||||||
_authenticationStatus.value = FailedAuthenticationStatus
|
_authenticationStatus.value = FailedFaceAuthenticationStatus
|
||||||
_isAuthenticated.value = false
|
_isAuthenticated.value = false
|
||||||
faceAuthLogger.authenticationFailed()
|
faceAuthLogger.authenticationFailed()
|
||||||
onFaceAuthRequestCompleted()
|
onFaceAuthRequestCompleted()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAuthenticationAcquired(acquireInfo: Int) {
|
override fun onAuthenticationAcquired(acquireInfo: Int) {
|
||||||
_authenticationStatus.value = AcquiredAuthenticationStatus(acquireInfo)
|
_authenticationStatus.value = AcquiredFaceAuthenticationStatus(acquireInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAuthenticationError(errorCode: Int, errString: CharSequence?) {
|
override fun onAuthenticationError(errorCode: Int, errString: CharSequence?) {
|
||||||
val errorStatus = ErrorAuthenticationStatus(errorCode, errString.toString())
|
val errorStatus = ErrorFaceAuthenticationStatus(errorCode, errString.toString())
|
||||||
if (errorStatus.isLockoutError()) {
|
if (errorStatus.isLockoutError()) {
|
||||||
_isLockedOut.value = true
|
_isLockedOut.value = true
|
||||||
}
|
}
|
||||||
@@ -433,11 +433,11 @@ constructor(
|
|||||||
if (faceAcquiredInfoIgnoreList.contains(code)) {
|
if (faceAcquiredInfoIgnoreList.contains(code)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_authenticationStatus.value = HelpAuthenticationStatus(code, helpStr.toString())
|
_authenticationStatus.value = HelpFaceAuthenticationStatus(code, helpStr.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAuthenticationSucceeded(result: FaceManager.AuthenticationResult) {
|
override fun onAuthenticationSucceeded(result: FaceManager.AuthenticationResult) {
|
||||||
_authenticationStatus.value = SuccessAuthenticationStatus(result)
|
_authenticationStatus.value = SuccessFaceAuthenticationStatus(result)
|
||||||
_isAuthenticated.value = true
|
_isAuthenticated.value = true
|
||||||
faceAuthLogger.faceAuthSuccess(result)
|
faceAuthLogger.faceAuthSuccess(result)
|
||||||
onFaceAuthRequestCompleted()
|
onFaceAuthRequestCompleted()
|
||||||
@@ -482,7 +482,7 @@ constructor(
|
|||||||
private val detectionCallback =
|
private val detectionCallback =
|
||||||
FaceManager.FaceDetectionCallback { sensorId, userId, isStrong ->
|
FaceManager.FaceDetectionCallback { sensorId, userId, isStrong ->
|
||||||
faceAuthLogger.faceDetected()
|
faceAuthLogger.faceDetected()
|
||||||
_detectionStatus.value = DetectionStatus(sensorId, userId, isStrong)
|
_detectionStatus.value = FaceDetectionStatus(sensorId, userId, isStrong)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var cancellationInProgress = false
|
private var cancellationInProgress = false
|
||||||
|
|||||||
@@ -21,27 +21,29 @@ import android.hardware.biometrics.BiometricAuthenticator.Modality
|
|||||||
import android.hardware.biometrics.BiometricSourceType
|
import android.hardware.biometrics.BiometricSourceType
|
||||||
import com.android.keyguard.KeyguardUpdateMonitor
|
import com.android.keyguard.KeyguardUpdateMonitor
|
||||||
import com.android.keyguard.KeyguardUpdateMonitorCallback
|
import com.android.keyguard.KeyguardUpdateMonitorCallback
|
||||||
import com.android.systemui.Dumpable
|
|
||||||
import com.android.systemui.biometrics.AuthController
|
import com.android.systemui.biometrics.AuthController
|
||||||
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
|
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
|
||||||
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
import com.android.systemui.dagger.qualifiers.Application
|
import com.android.systemui.dagger.qualifiers.Application
|
||||||
import com.android.systemui.dump.DumpManager
|
import com.android.systemui.keyguard.shared.model.AcquiredFingerprintAuthenticationStatus
|
||||||
import java.io.PrintWriter
|
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 javax.inject.Inject
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.channels.awaitClose
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
|
||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
|
||||||
/** Encapsulates state about device entry fingerprint auth mechanism. */
|
/** Encapsulates state about device entry fingerprint auth mechanism. */
|
||||||
interface DeviceEntryFingerprintAuthRepository {
|
interface DeviceEntryFingerprintAuthRepository {
|
||||||
/** Whether the device entry fingerprint auth is locked out. */
|
/** 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
|
* 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.
|
* Fingerprint sensor type present on the device, null if fingerprint sensor is not available.
|
||||||
*/
|
*/
|
||||||
val availableFpSensorType: Flow<BiometricType?>
|
val availableFpSensorType: Flow<BiometricType?>
|
||||||
|
|
||||||
|
/** Provide the current status of fingerprint authentication. */
|
||||||
|
val authenticationStatus: Flow<FingerprintAuthenticationStatus>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,16 +74,7 @@ constructor(
|
|||||||
val authController: AuthController,
|
val authController: AuthController,
|
||||||
val keyguardUpdateMonitor: KeyguardUpdateMonitor,
|
val keyguardUpdateMonitor: KeyguardUpdateMonitor,
|
||||||
@Application scope: CoroutineScope,
|
@Application scope: CoroutineScope,
|
||||||
dumpManager: DumpManager,
|
) : DeviceEntryFingerprintAuthRepository {
|
||||||
) : DeviceEntryFingerprintAuthRepository, Dumpable {
|
|
||||||
|
|
||||||
init {
|
|
||||||
dumpManager.registerDumpable(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun dump(pw: PrintWriter, args: Array<String?>) {
|
|
||||||
pw.println("isLockedOut=${isLockedOut.value}")
|
|
||||||
}
|
|
||||||
|
|
||||||
override val availableFpSensorType: Flow<BiometricType?>
|
override val availableFpSensorType: Flow<BiometricType?>
|
||||||
get() {
|
get() {
|
||||||
@@ -114,7 +110,7 @@ constructor(
|
|||||||
else if (authController.isRearFpsSupported) BiometricType.REAR_FINGERPRINT else null
|
else if (authController.isRearFpsSupported) BiometricType.REAR_FINGERPRINT else null
|
||||||
}
|
}
|
||||||
|
|
||||||
override val isLockedOut: StateFlow<Boolean> =
|
override val isLockedOut: Flow<Boolean> =
|
||||||
conflatedCallbackFlow {
|
conflatedCallbackFlow {
|
||||||
val sendLockoutUpdate =
|
val sendLockoutUpdate =
|
||||||
fun() {
|
fun() {
|
||||||
@@ -138,7 +134,7 @@ constructor(
|
|||||||
sendLockoutUpdate()
|
sendLockoutUpdate()
|
||||||
awaitClose { keyguardUpdateMonitor.removeCallback(callback) }
|
awaitClose { keyguardUpdateMonitor.removeCallback(callback) }
|
||||||
}
|
}
|
||||||
.stateIn(scope, started = SharingStarted.Eagerly, initialValue = false)
|
.stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = false)
|
||||||
|
|
||||||
override val isRunning: Flow<Boolean>
|
override val isRunning: Flow<Boolean>
|
||||||
get() = conflatedCallbackFlow {
|
get() = conflatedCallbackFlow {
|
||||||
@@ -166,6 +162,93 @@ constructor(
|
|||||||
awaitClose { keyguardUpdateMonitor.removeCallback(callback) }
|
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 {
|
companion object {
|
||||||
const val TAG = "DeviceEntryFingerprintAuthRepositoryImpl"
|
const val TAG = "DeviceEntryFingerprintAuthRepositoryImpl"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ package com.android.systemui.keyguard.data.repository
|
|||||||
|
|
||||||
import com.android.keyguard.FaceAuthUiEvent
|
import com.android.keyguard.FaceAuthUiEvent
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
import com.android.systemui.keyguard.shared.model.AuthenticationStatus
|
import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus
|
||||||
import com.android.systemui.keyguard.shared.model.DetectionStatus
|
import com.android.systemui.keyguard.shared.model.FaceDetectionStatus
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
@@ -40,10 +40,10 @@ class NoopDeviceEntryFaceAuthRepository @Inject constructor() : DeviceEntryFaceA
|
|||||||
private val _canRunFaceAuth = MutableStateFlow(false)
|
private val _canRunFaceAuth = MutableStateFlow(false)
|
||||||
override val canRunFaceAuth: StateFlow<Boolean> = _canRunFaceAuth
|
override val canRunFaceAuth: StateFlow<Boolean> = _canRunFaceAuth
|
||||||
|
|
||||||
override val authenticationStatus: Flow<AuthenticationStatus>
|
override val authenticationStatus: Flow<FaceAuthenticationStatus>
|
||||||
get() = emptyFlow()
|
get() = emptyFlow()
|
||||||
|
|
||||||
override val detectionStatus: Flow<DetectionStatus>
|
override val detectionStatus: Flow<FaceDetectionStatus>
|
||||||
get() = emptyFlow()
|
get() = emptyFlow()
|
||||||
|
|
||||||
private val _isLockedOut = MutableStateFlow(false)
|
private val _isLockedOut = MutableStateFlow(false)
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
package com.android.systemui.keyguard.domain.interactor
|
package com.android.systemui.keyguard.domain.interactor
|
||||||
|
|
||||||
import com.android.systemui.keyguard.shared.model.AuthenticationStatus
|
import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus
|
||||||
import com.android.systemui.keyguard.shared.model.DetectionStatus
|
import com.android.systemui.keyguard.shared.model.FaceDetectionStatus
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,10 +27,10 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
interface KeyguardFaceAuthInteractor {
|
interface KeyguardFaceAuthInteractor {
|
||||||
|
|
||||||
/** Current authentication status */
|
/** Current authentication status */
|
||||||
val authenticationStatus: Flow<AuthenticationStatus>
|
val authenticationStatus: Flow<FaceAuthenticationStatus>
|
||||||
|
|
||||||
/** Current detection status */
|
/** Current detection status */
|
||||||
val detectionStatus: Flow<DetectionStatus>
|
val detectionStatus: Flow<FaceDetectionStatus>
|
||||||
|
|
||||||
/** Can face auth be run right now */
|
/** Can face auth be run right now */
|
||||||
fun canFaceAuthRun(): Boolean
|
fun canFaceAuthRun(): Boolean
|
||||||
@@ -72,8 +72,8 @@ interface KeyguardFaceAuthInteractor {
|
|||||||
*/
|
*/
|
||||||
interface FaceAuthenticationListener {
|
interface FaceAuthenticationListener {
|
||||||
/** Receive face authentication status updates */
|
/** Receive face authentication status updates */
|
||||||
fun onAuthenticationStatusChanged(status: AuthenticationStatus)
|
fun onAuthenticationStatusChanged(status: FaceAuthenticationStatus)
|
||||||
|
|
||||||
/** Receive status updates whenever face detection runs */
|
/** 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
|
package com.android.systemui.keyguard.domain.interactor
|
||||||
|
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
import com.android.systemui.keyguard.shared.model.AuthenticationStatus
|
import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus
|
||||||
import com.android.systemui.keyguard.shared.model.DetectionStatus
|
import com.android.systemui.keyguard.shared.model.FaceDetectionStatus
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.emptyFlow
|
import kotlinx.coroutines.flow.emptyFlow
|
||||||
@@ -31,9 +31,9 @@ import kotlinx.coroutines.flow.emptyFlow
|
|||||||
*/
|
*/
|
||||||
@SysUISingleton
|
@SysUISingleton
|
||||||
class NoopKeyguardFaceAuthInteractor @Inject constructor() : KeyguardFaceAuthInteractor {
|
class NoopKeyguardFaceAuthInteractor @Inject constructor() : KeyguardFaceAuthInteractor {
|
||||||
override val authenticationStatus: Flow<AuthenticationStatus>
|
override val authenticationStatus: Flow<FaceAuthenticationStatus>
|
||||||
get() = emptyFlow()
|
get() = emptyFlow()
|
||||||
override val detectionStatus: Flow<DetectionStatus>
|
override val detectionStatus: Flow<FaceDetectionStatus>
|
||||||
get() = emptyFlow()
|
get() = emptyFlow()
|
||||||
|
|
||||||
override fun canFaceAuthRun(): Boolean = false
|
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.FeatureFlags
|
||||||
import com.android.systemui.flags.Flags
|
import com.android.systemui.flags.Flags
|
||||||
import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
|
import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
|
||||||
import com.android.systemui.keyguard.shared.model.AuthenticationStatus
|
import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus
|
||||||
import com.android.systemui.keyguard.shared.model.ErrorAuthenticationStatus
|
import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus
|
||||||
import com.android.systemui.keyguard.shared.model.TransitionState
|
import com.android.systemui.keyguard.shared.model.TransitionState
|
||||||
import com.android.systemui.log.FaceAuthenticationLogger
|
import com.android.systemui.log.FaceAuthenticationLogger
|
||||||
import com.android.systemui.util.kotlin.pairwise
|
import com.android.systemui.util.kotlin.pairwise
|
||||||
@@ -165,10 +165,10 @@ constructor(
|
|||||||
repository.cancel()
|
repository.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val _authenticationStatusOverride = MutableStateFlow<AuthenticationStatus?>(null)
|
private val faceAuthenticationStatusOverride = MutableStateFlow<FaceAuthenticationStatus?>(null)
|
||||||
/** Provide the status of face authentication */
|
/** Provide the status of face authentication */
|
||||||
override val authenticationStatus =
|
override val authenticationStatus =
|
||||||
merge(_authenticationStatusOverride.filterNotNull(), repository.authenticationStatus)
|
merge(faceAuthenticationStatusOverride.filterNotNull(), repository.authenticationStatus)
|
||||||
|
|
||||||
/** Provide the status of face detection */
|
/** Provide the status of face detection */
|
||||||
override val detectionStatus = repository.detectionStatus
|
override val detectionStatus = repository.detectionStatus
|
||||||
@@ -176,13 +176,13 @@ constructor(
|
|||||||
private fun runFaceAuth(uiEvent: FaceAuthUiEvent, fallbackToDetect: Boolean) {
|
private fun runFaceAuth(uiEvent: FaceAuthUiEvent, fallbackToDetect: Boolean) {
|
||||||
if (featureFlags.isEnabled(Flags.FACE_AUTH_REFACTOR)) {
|
if (featureFlags.isEnabled(Flags.FACE_AUTH_REFACTOR)) {
|
||||||
if (repository.isLockedOut.value) {
|
if (repository.isLockedOut.value) {
|
||||||
_authenticationStatusOverride.value =
|
faceAuthenticationStatusOverride.value =
|
||||||
ErrorAuthenticationStatus(
|
ErrorFaceAuthenticationStatus(
|
||||||
BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT,
|
BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT,
|
||||||
context.resources.getString(R.string.keyguard_face_unlock_unavailable)
|
context.resources.getString(R.string.keyguard_face_unlock_unavailable)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
_authenticationStatusOverride.value = null
|
faceAuthenticationStatusOverride.value = null
|
||||||
applicationScope.launch {
|
applicationScope.launch {
|
||||||
faceAuthenticationLogger.authRequested(uiEvent)
|
faceAuthenticationLogger.authRequested(uiEvent)
|
||||||
repository.authenticate(uiEvent, fallbackToDetection = fallbackToDetect)
|
repository.authenticate(uiEvent, fallbackToDetection = fallbackToDetect)
|
||||||
|
|||||||
@@ -23,33 +23,35 @@ import android.os.SystemClock.elapsedRealtime
|
|||||||
* Authentication status provided by
|
* Authentication status provided by
|
||||||
* [com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository]
|
* [com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository]
|
||||||
*/
|
*/
|
||||||
sealed class AuthenticationStatus
|
sealed class FaceAuthenticationStatus
|
||||||
|
|
||||||
/** Success authentication status. */
|
/** Success authentication status. */
|
||||||
data class SuccessAuthenticationStatus(val successResult: FaceManager.AuthenticationResult) :
|
data class SuccessFaceAuthenticationStatus(val successResult: FaceManager.AuthenticationResult) :
|
||||||
AuthenticationStatus()
|
FaceAuthenticationStatus()
|
||||||
|
|
||||||
/** Face authentication help message. */
|
/** 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. */
|
/** Face acquired message. */
|
||||||
data class AcquiredAuthenticationStatus(val acquiredInfo: Int) : AuthenticationStatus()
|
data class AcquiredFaceAuthenticationStatus(val acquiredInfo: Int) : FaceAuthenticationStatus()
|
||||||
|
|
||||||
/** Face authentication failed message. */
|
/** Face authentication failed message. */
|
||||||
object FailedAuthenticationStatus : AuthenticationStatus()
|
object FailedFaceAuthenticationStatus : FaceAuthenticationStatus()
|
||||||
|
|
||||||
/** Face authentication error message */
|
/** Face authentication error message */
|
||||||
data class ErrorAuthenticationStatus(
|
data class ErrorFaceAuthenticationStatus(
|
||||||
val msgId: Int,
|
val msgId: Int,
|
||||||
val msg: String? = null,
|
val msg: String? = null,
|
||||||
// present to break equality check if the same error occurs repeatedly.
|
// present to break equality check if the same error occurs repeatedly.
|
||||||
val createdAt: Long = elapsedRealtime()
|
val createdAt: Long = elapsedRealtime()
|
||||||
) : AuthenticationStatus() {
|
) : FaceAuthenticationStatus() {
|
||||||
/**
|
/**
|
||||||
* Method that checks if [msgId] is a lockout error. A lockout error means that face
|
* Method that checks if [msgId] is a lockout error. A lockout error means that face
|
||||||
* authentication is locked out.
|
* 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
|
* 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. */
|
/** 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 android.hardware.face.FaceSensorPropertiesInternal
|
||||||
import com.android.keyguard.FaceAuthUiEvent
|
import com.android.keyguard.FaceAuthUiEvent
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
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.keyguard.shared.model.TransitionStep
|
||||||
import com.android.systemui.log.core.LogLevel.DEBUG
|
import com.android.systemui.log.core.LogLevel.DEBUG
|
||||||
import com.android.systemui.log.dagger.FaceAuthLog
|
import com.android.systemui.log.dagger.FaceAuthLog
|
||||||
@@ -240,7 +240,7 @@ constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hardwareError(errorStatus: ErrorAuthenticationStatus) {
|
fun hardwareError(errorStatus: ErrorFaceAuthenticationStatus) {
|
||||||
logBuffer.log(
|
logBuffer.log(
|
||||||
TAG,
|
TAG,
|
||||||
DEBUG,
|
DEBUG,
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ import android.view.WindowMetrics
|
|||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import com.airbnb.lottie.LottieAnimationView
|
import com.airbnb.lottie.LottieAnimationView
|
||||||
|
import com.android.keyguard.KeyguardUpdateMonitor
|
||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
import com.android.systemui.RoboPilotTest
|
import com.android.systemui.RoboPilotTest
|
||||||
import com.android.systemui.SysuiTestCase
|
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.bouncer.domain.interactor.AlternateBouncerInteractor
|
||||||
import com.android.systemui.dump.DumpManager
|
import com.android.systemui.dump.DumpManager
|
||||||
import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
|
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.plugins.statusbar.StatusBarStateController
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController
|
import com.android.systemui.statusbar.policy.KeyguardStateController
|
||||||
import com.android.systemui.util.concurrency.FakeExecutor
|
import com.android.systemui.util.concurrency.FakeExecutor
|
||||||
@@ -153,8 +153,8 @@ class SideFpsControllerTest : SysuiTestCase() {
|
|||||||
mock(KeyguardStateController::class.java),
|
mock(KeyguardStateController::class.java),
|
||||||
keyguardBouncerRepository,
|
keyguardBouncerRepository,
|
||||||
FakeBiometricSettingsRepository(),
|
FakeBiometricSettingsRepository(),
|
||||||
FakeDeviceEntryFingerprintAuthRepository(),
|
|
||||||
FakeSystemClock(),
|
FakeSystemClock(),
|
||||||
|
mock(KeyguardUpdateMonitor::class.java),
|
||||||
)
|
)
|
||||||
displayStateInteractor =
|
displayStateInteractor =
|
||||||
DisplayStateInteractorImpl(
|
DisplayStateInteractorImpl(
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import com.android.systemui.flags.FakeFeatureFlags
|
|||||||
import com.android.systemui.flags.Flags
|
import com.android.systemui.flags.Flags
|
||||||
import com.android.systemui.keyguard.DismissCallbackRegistry
|
import com.android.systemui.keyguard.DismissCallbackRegistry
|
||||||
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
|
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.keyguard.data.repository.FakeTrustRepository
|
||||||
import com.android.systemui.log.table.TableLogBuffer
|
import com.android.systemui.log.table.TableLogBuffer
|
||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
||||||
@@ -106,8 +105,8 @@ class UdfpsKeyguardViewLegacyControllerWithCoroutinesTest :
|
|||||||
mock(KeyguardStateController::class.java),
|
mock(KeyguardStateController::class.java),
|
||||||
keyguardBouncerRepository,
|
keyguardBouncerRepository,
|
||||||
mock(BiometricSettingsRepository::class.java),
|
mock(BiometricSettingsRepository::class.java),
|
||||||
mock(DeviceEntryFingerprintAuthRepository::class.java),
|
|
||||||
mock(SystemClock::class.java),
|
mock(SystemClock::class.java),
|
||||||
|
mKeyguardUpdateMonitor,
|
||||||
)
|
)
|
||||||
return createUdfpsKeyguardViewController(
|
return createUdfpsKeyguardViewController(
|
||||||
/* useModernBouncer */ true, /* useExpandedOverlay */
|
/* useModernBouncer */ true, /* useExpandedOverlay */
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.systemui.bouncer.domain.interactor
|
|||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.keyguard.KeyguardUpdateMonitor
|
||||||
import com.android.systemui.RoboPilotTest
|
import com.android.systemui.RoboPilotTest
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
|
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 keyguardStateController: KeyguardStateController
|
||||||
@Mock private lateinit var systemClock: SystemClock
|
@Mock private lateinit var systemClock: SystemClock
|
||||||
@Mock private lateinit var bouncerLogger: TableLogBuffer
|
@Mock private lateinit var bouncerLogger: TableLogBuffer
|
||||||
|
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
@@ -72,8 +74,8 @@ class AlternateBouncerInteractorTest : SysuiTestCase() {
|
|||||||
keyguardStateController,
|
keyguardStateController,
|
||||||
bouncerRepository,
|
bouncerRepository,
|
||||||
biometricSettingsRepository,
|
biometricSettingsRepository,
|
||||||
deviceEntryFingerprintAuthRepository,
|
|
||||||
systemClock,
|
systemClock,
|
||||||
|
keyguardUpdateMonitor,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +120,7 @@ class AlternateBouncerInteractorTest : SysuiTestCase() {
|
|||||||
@Test
|
@Test
|
||||||
fun canShowAlternateBouncerForFingerprint_fingerprintLockedOut() {
|
fun canShowAlternateBouncerForFingerprint_fingerprintLockedOut() {
|
||||||
givenCanShowAlternateBouncer()
|
givenCanShowAlternateBouncer()
|
||||||
deviceEntryFingerprintAuthRepository.setLockedOut(true)
|
whenever(keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(true)
|
||||||
|
|
||||||
assertFalse(underTest.canShowAlternateBouncerForFingerprint())
|
assertFalse(underTest.canShowAlternateBouncerForFingerprint())
|
||||||
}
|
}
|
||||||
@@ -168,7 +170,7 @@ class AlternateBouncerInteractorTest : SysuiTestCase() {
|
|||||||
biometricSettingsRepository.setFingerprintEnrolled(true)
|
biometricSettingsRepository.setFingerprintEnrolled(true)
|
||||||
biometricSettingsRepository.setStrongBiometricAllowed(true)
|
biometricSettingsRepository.setStrongBiometricAllowed(true)
|
||||||
biometricSettingsRepository.setFingerprintEnabledByDevicePolicy(true)
|
biometricSettingsRepository.setFingerprintEnabledByDevicePolicy(true)
|
||||||
deviceEntryFingerprintAuthRepository.setLockedOut(false)
|
whenever(keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(false)
|
||||||
whenever(keyguardStateController.isUnlocked).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
|
||||||
import com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_TRIGGERED_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN
|
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.FaceAuthUiEvent.FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER
|
||||||
|
import com.android.keyguard.KeyguardUpdateMonitor
|
||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
import com.android.systemui.RoboPilotTest
|
import com.android.systemui.RoboPilotTest
|
||||||
import com.android.systemui.SysuiTestCase
|
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.KeyguardInteractor
|
||||||
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
|
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
|
||||||
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
|
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
|
||||||
import com.android.systemui.keyguard.shared.model.AuthenticationStatus
|
import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus
|
||||||
import com.android.systemui.keyguard.shared.model.DetectionStatus
|
import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus
|
||||||
import com.android.systemui.keyguard.shared.model.ErrorAuthenticationStatus
|
import com.android.systemui.keyguard.shared.model.FaceDetectionStatus
|
||||||
import com.android.systemui.keyguard.shared.model.HelpAuthenticationStatus
|
import com.android.systemui.keyguard.shared.model.HelpFaceAuthenticationStatus
|
||||||
import com.android.systemui.keyguard.shared.model.KeyguardState
|
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.TransitionState
|
||||||
import com.android.systemui.keyguard.shared.model.TransitionStep
|
import com.android.systemui.keyguard.shared.model.TransitionStep
|
||||||
import com.android.systemui.keyguard.shared.model.WakeSleepReason
|
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 sessionTracker: SessionTracker
|
||||||
@Mock private lateinit var uiEventLogger: UiEventLogger
|
@Mock private lateinit var uiEventLogger: UiEventLogger
|
||||||
@Mock private lateinit var dumpManager: DumpManager
|
@Mock private lateinit var dumpManager: DumpManager
|
||||||
|
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
|
||||||
|
|
||||||
@Captor
|
@Captor
|
||||||
private lateinit var authenticationCallback: ArgumentCaptor<FaceManager.AuthenticationCallback>
|
private lateinit var authenticationCallback: ArgumentCaptor<FaceManager.AuthenticationCallback>
|
||||||
@@ -131,8 +133,8 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
|
|||||||
private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository
|
private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository
|
||||||
private lateinit var testScope: TestScope
|
private lateinit var testScope: TestScope
|
||||||
private lateinit var fakeUserRepository: FakeUserRepository
|
private lateinit var fakeUserRepository: FakeUserRepository
|
||||||
private lateinit var authStatus: FlowValue<AuthenticationStatus?>
|
private lateinit var authStatus: FlowValue<FaceAuthenticationStatus?>
|
||||||
private lateinit var detectStatus: FlowValue<DetectionStatus?>
|
private lateinit var detectStatus: FlowValue<FaceDetectionStatus?>
|
||||||
private lateinit var authRunning: FlowValue<Boolean?>
|
private lateinit var authRunning: FlowValue<Boolean?>
|
||||||
private lateinit var bypassEnabled: FlowValue<Boolean?>
|
private lateinit var bypassEnabled: FlowValue<Boolean?>
|
||||||
private lateinit var lockedOut: FlowValue<Boolean?>
|
private lateinit var lockedOut: FlowValue<Boolean?>
|
||||||
@@ -175,10 +177,10 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
|
|||||||
AlternateBouncerInteractor(
|
AlternateBouncerInteractor(
|
||||||
bouncerRepository = bouncerRepository,
|
bouncerRepository = bouncerRepository,
|
||||||
biometricSettingsRepository = biometricSettingsRepository,
|
biometricSettingsRepository = biometricSettingsRepository,
|
||||||
deviceEntryFingerprintAuthRepository = deviceEntryFingerprintAuthRepository,
|
|
||||||
systemClock = mock(SystemClock::class.java),
|
systemClock = mock(SystemClock::class.java),
|
||||||
keyguardStateController = FakeKeyguardStateController(),
|
keyguardStateController = FakeKeyguardStateController(),
|
||||||
statusBarStateController = mock(StatusBarStateController::class.java),
|
statusBarStateController = mock(StatusBarStateController::class.java),
|
||||||
|
keyguardUpdateMonitor = keyguardUpdateMonitor,
|
||||||
)
|
)
|
||||||
|
|
||||||
bypassStateChangedListener =
|
bypassStateChangedListener =
|
||||||
@@ -262,7 +264,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
|
|||||||
val successResult = successResult()
|
val successResult = successResult()
|
||||||
authenticationCallback.value.onAuthenticationSucceeded(successResult)
|
authenticationCallback.value.onAuthenticationSucceeded(successResult)
|
||||||
|
|
||||||
assertThat(authStatus()).isEqualTo(SuccessAuthenticationStatus(successResult))
|
assertThat(authStatus()).isEqualTo(SuccessFaceAuthenticationStatus(successResult))
|
||||||
assertThat(authenticated()).isTrue()
|
assertThat(authenticated()).isTrue()
|
||||||
assertThat(authRunning()).isFalse()
|
assertThat(authRunning()).isFalse()
|
||||||
assertThat(canFaceAuthRun()).isFalse()
|
assertThat(canFaceAuthRun()).isFalse()
|
||||||
@@ -383,7 +385,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
|
|||||||
|
|
||||||
detectionCallback.value.onFaceDetected(1, 1, true)
|
detectionCallback.value.onFaceDetected(1, 1, true)
|
||||||
|
|
||||||
assertThat(detectStatus()).isEqualTo(DetectionStatus(1, 1, true))
|
assertThat(detectStatus()).isEqualTo(FaceDetectionStatus(1, 1, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -423,7 +425,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
|
|||||||
FACE_ERROR_CANCELED,
|
FACE_ERROR_CANCELED,
|
||||||
"First auth attempt cancellation completed"
|
"First auth attempt cancellation completed"
|
||||||
)
|
)
|
||||||
val value = authStatus() as ErrorAuthenticationStatus
|
val value = authStatus() as ErrorFaceAuthenticationStatus
|
||||||
assertThat(value.msgId).isEqualTo(FACE_ERROR_CANCELED)
|
assertThat(value.msgId).isEqualTo(FACE_ERROR_CANCELED)
|
||||||
assertThat(value.msg).isEqualTo("First auth attempt cancellation completed")
|
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(10, "Ignored help msg")
|
||||||
authenticationCallback.value.onAuthenticationHelp(11, "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
|
@Test
|
||||||
|
|||||||
@@ -26,7 +26,11 @@ import com.android.systemui.RoboPilotTest
|
|||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.biometrics.AuthController
|
import com.android.systemui.biometrics.AuthController
|
||||||
import com.android.systemui.coroutines.collectLastValue
|
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.android.systemui.util.mockito.whenever
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
@@ -49,7 +53,6 @@ import org.mockito.MockitoAnnotations
|
|||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class DeviceEntryFingerprintAuthRepositoryTest : SysuiTestCase() {
|
class DeviceEntryFingerprintAuthRepositoryTest : SysuiTestCase() {
|
||||||
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
|
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
|
||||||
@Mock private lateinit var dumpManager: DumpManager
|
|
||||||
@Mock private lateinit var authController: AuthController
|
@Mock private lateinit var authController: AuthController
|
||||||
@Captor
|
@Captor
|
||||||
private lateinit var updateMonitorCallback: ArgumentCaptor<KeyguardUpdateMonitorCallback>
|
private lateinit var updateMonitorCallback: ArgumentCaptor<KeyguardUpdateMonitorCallback>
|
||||||
@@ -68,7 +71,6 @@ class DeviceEntryFingerprintAuthRepositoryTest : SysuiTestCase() {
|
|||||||
authController,
|
authController,
|
||||||
keyguardUpdateMonitor,
|
keyguardUpdateMonitor,
|
||||||
testScope.backgroundScope,
|
testScope.backgroundScope,
|
||||||
dumpManager,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,4 +179,129 @@ class DeviceEntryFingerprintAuthRepositoryTest : SysuiTestCase() {
|
|||||||
callback.value.onAllAuthenticatorsRegistered(TYPE_FINGERPRINT)
|
callback.value.onAllAuthenticatorsRegistered(TYPE_FINGERPRINT)
|
||||||
assertThat(availableFpSensorType()).isEqualTo(BiometricType.UNDER_DISPLAY_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.DismissCallbackRegistry
|
||||||
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
|
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
|
||||||
import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFaceAuthRepository
|
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.FakeKeyguardTransitionRepository
|
||||||
import com.android.systemui.keyguard.data.repository.FakeTrustRepository
|
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.KeyguardState
|
||||||
import com.android.systemui.keyguard.shared.model.TransitionState
|
import com.android.systemui.keyguard.shared.model.TransitionState
|
||||||
import com.android.systemui.keyguard.shared.model.TransitionStep
|
import com.android.systemui.keyguard.shared.model.TransitionStep
|
||||||
@@ -121,8 +120,8 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
|
|||||||
mock(KeyguardStateController::class.java),
|
mock(KeyguardStateController::class.java),
|
||||||
bouncerRepository,
|
bouncerRepository,
|
||||||
mock(BiometricSettingsRepository::class.java),
|
mock(BiometricSettingsRepository::class.java),
|
||||||
FakeDeviceEntryFingerprintAuthRepository(),
|
|
||||||
FakeSystemClock(),
|
FakeSystemClock(),
|
||||||
|
keyguardUpdateMonitor,
|
||||||
),
|
),
|
||||||
keyguardTransitionInteractor,
|
keyguardTransitionInteractor,
|
||||||
featureFlags,
|
featureFlags,
|
||||||
@@ -160,7 +159,7 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
|
|||||||
|
|
||||||
underTest.onDeviceLifted()
|
underTest.onDeviceLifted()
|
||||||
|
|
||||||
val outputValue = authenticationStatus()!! as ErrorAuthenticationStatus
|
val outputValue = authenticationStatus()!! as ErrorFaceAuthenticationStatus
|
||||||
assertThat(outputValue.msgId)
|
assertThat(outputValue.msgId)
|
||||||
.isEqualTo(BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT)
|
.isEqualTo(BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT)
|
||||||
assertThat(outputValue.msg).isEqualTo("Face Unlock unavailable")
|
assertThat(outputValue.msg).isEqualTo("Face Unlock unavailable")
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
package com.android.systemui.keyguard.data.repository
|
package com.android.systemui.keyguard.data.repository
|
||||||
|
|
||||||
import com.android.keyguard.FaceAuthUiEvent
|
import com.android.keyguard.FaceAuthUiEvent
|
||||||
import com.android.systemui.keyguard.shared.model.AuthenticationStatus
|
import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus
|
||||||
import com.android.systemui.keyguard.shared.model.DetectionStatus
|
import com.android.systemui.keyguard.shared.model.FaceDetectionStatus
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
@@ -29,16 +29,16 @@ class FakeDeviceEntryFaceAuthRepository : DeviceEntryFaceAuthRepository {
|
|||||||
|
|
||||||
override val isAuthenticated = MutableStateFlow(false)
|
override val isAuthenticated = MutableStateFlow(false)
|
||||||
override val canRunFaceAuth = MutableStateFlow(false)
|
override val canRunFaceAuth = MutableStateFlow(false)
|
||||||
private val _authenticationStatus = MutableStateFlow<AuthenticationStatus?>(null)
|
private val _authenticationStatus = MutableStateFlow<FaceAuthenticationStatus?>(null)
|
||||||
override val authenticationStatus: Flow<AuthenticationStatus> =
|
override val authenticationStatus: Flow<FaceAuthenticationStatus> =
|
||||||
_authenticationStatus.filterNotNull()
|
_authenticationStatus.filterNotNull()
|
||||||
fun setAuthenticationStatus(status: AuthenticationStatus) {
|
fun setAuthenticationStatus(status: FaceAuthenticationStatus) {
|
||||||
_authenticationStatus.value = status
|
_authenticationStatus.value = status
|
||||||
}
|
}
|
||||||
private val _detectionStatus = MutableStateFlow<DetectionStatus?>(null)
|
private val _detectionStatus = MutableStateFlow<FaceDetectionStatus?>(null)
|
||||||
override val detectionStatus: Flow<DetectionStatus>
|
override val detectionStatus: Flow<FaceDetectionStatus>
|
||||||
get() = _detectionStatus.filterNotNull()
|
get() = _detectionStatus.filterNotNull()
|
||||||
fun setDetectionStatus(status: DetectionStatus) {
|
fun setDetectionStatus(status: FaceDetectionStatus) {
|
||||||
_detectionStatus.value = status
|
_detectionStatus.value = status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,32 +17,38 @@
|
|||||||
|
|
||||||
package com.android.systemui.keyguard.data.repository
|
package com.android.systemui.keyguard.data.repository
|
||||||
|
|
||||||
|
import com.android.systemui.keyguard.shared.model.FingerprintAuthenticationStatus
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
|
|
||||||
class FakeDeviceEntryFingerprintAuthRepository : DeviceEntryFingerprintAuthRepository {
|
class FakeDeviceEntryFingerprintAuthRepository : DeviceEntryFingerprintAuthRepository {
|
||||||
private val _isLockedOut = MutableStateFlow(false)
|
private val _isLockedOut = MutableStateFlow(false)
|
||||||
override val isLockedOut: StateFlow<Boolean> = _isLockedOut.asStateFlow()
|
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) {
|
fun setLockedOut(lockedOut: Boolean) {
|
||||||
_isLockedOut.value = lockedOut
|
_isLockedOut.value = lockedOut
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val _isRunning = MutableStateFlow(false)
|
||||||
|
override val isRunning: Flow<Boolean>
|
||||||
|
get() = _isRunning
|
||||||
fun setIsRunning(value: Boolean) {
|
fun setIsRunning(value: Boolean) {
|
||||||
_isRunning.value = value
|
_isRunning.value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var fpSensorType = MutableStateFlow<BiometricType?>(null)
|
||||||
|
override val availableFpSensorType: Flow<BiometricType?>
|
||||||
|
get() = fpSensorType
|
||||||
fun setAvailableFpSensorType(value: BiometricType?) {
|
fun setAvailableFpSensorType(value: BiometricType?) {
|
||||||
fpSensorType.value = value
|
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