Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c3ec7f61 authored by Arpan Kaphle's avatar Arpan Kaphle Committed by Android (Google) Code Review
Browse files

Merge "General Fallback for BiometricPrompt" into main

parents 4fbf90d5 deea016d
Loading
Loading
Loading
Loading
+18 −18
Original line number Diff line number Diff line
@@ -210,7 +210,7 @@ private fun runBiometricFlow(
    onCancelFlowAndFinish: () -> Unit
) {
    try {
        if (onlyUsingDeviceCredentials(biometricDisplayInfo, context)) {
        if (!canCallBiometricPrompt(biometricDisplayInfo, context)) {
            onBiometricFailureFallback(biometricFlowType)
            return
        }
@@ -250,40 +250,40 @@ private fun getCryptoOpId(biometricDisplayInfo: BiometricDisplayInfo): Int? {
 * consistency because for biometrics to exist, **device credentials must exist**. Thus, fallbacks
 * occur if *only* device credentials are available, to avoid going right into the PIN screen.
 * Note that if device credential is the only available modality but not requested, or if none
 * of the requested modalities are available, we propagate the error to the provider instead of
 * falling back and expect them to handle it as they would prior.
 * // TODO(b/334197980) : Finalize error propagation/not propagation in real use cases
 * of the requested modalities are available, we fallback to the normal flow to ensure a selector
 * shows up.
 * // TODO(b/334197980) : While we already fallback in cases the selector doesn't show, confirm
 * // final plan.
 */
private fun onlyUsingDeviceCredentials(
private fun canCallBiometricPrompt(
    biometricDisplayInfo: BiometricDisplayInfo,
    context: Context
): Boolean {
    val allowedAuthenticators = biometricDisplayInfo.biometricRequestInfo.allowedAuthenticators
    if (allowedAuthenticators == BiometricManager.Authenticators.DEVICE_CREDENTIAL) {
        return true
        return false
    }

    val allowedAuthContainsDeviceCredential = containsBiometricAuthenticatorWithDeviceCredentials(
        allowedAuthenticators)
    val biometricManager = context.getSystemService(Context.BIOMETRIC_SERVICE) as BiometricManager

    if (!allowedAuthContainsDeviceCredential) {
        // At this point, allowed authenticators is requesting biometrics without device creds.
        // Thus, a fallback mechanism will be displayed via our own negative button - "cancel".
        // Beyond this point, fallbacks will occur if none of the stronger authenticators can
        // be used.
    if (biometricManager.canAuthenticate(allowedAuthenticators) !=
        BiometricManager.BIOMETRIC_SUCCESS) {
        return false
    }

    val biometricManager = context.getSystemService(Context.BIOMETRIC_SERVICE) as BiometricManager
    if (ifOnlySupportsAtMostDeviceCredentials(biometricManager)) return false

    if (allowedAuthContainsDeviceCredential &&
        biometricManager.canAuthenticate(Authenticators.BIOMETRIC_WEAK) !=
    return true
}

private fun ifOnlySupportsAtMostDeviceCredentials(biometricManager: BiometricManager): Boolean {
    if (biometricManager.canAuthenticate(Authenticators.BIOMETRIC_WEAK) !=
        BiometricManager.BIOMETRIC_SUCCESS &&
        biometricManager.canAuthenticate(Authenticators.BIOMETRIC_STRONG) !=
        BiometricManager.BIOMETRIC_SUCCESS) {
        BiometricManager.BIOMETRIC_SUCCESS
    ) {
        return true
    }

    return false
}