Merge "Add auth type to BiometricPrompt.AuthenticationResult"
This commit is contained in:
committed by
Android (Google) Code Review
commit
e0e5852108
@@ -16852,6 +16852,8 @@ package android.hardware.biometrics {
|
||||
method @Nullable public CharSequence getSubtitle();
|
||||
method @NonNull public CharSequence getTitle();
|
||||
method public boolean isConfirmationRequired();
|
||||
field public static final int AUTHENTICATION_RESULT_TYPE_BIOMETRIC = 2; // 0x2
|
||||
field public static final int AUTHENTICATION_RESULT_TYPE_DEVICE_CREDENTIAL = 1; // 0x1
|
||||
field public static final int BIOMETRIC_ACQUIRED_GOOD = 0; // 0x0
|
||||
field public static final int BIOMETRIC_ACQUIRED_IMAGER_DIRTY = 3; // 0x3
|
||||
field public static final int BIOMETRIC_ACQUIRED_INSUFFICIENT = 2; // 0x2
|
||||
@@ -16881,6 +16883,7 @@ package android.hardware.biometrics {
|
||||
}
|
||||
|
||||
public static class BiometricPrompt.AuthenticationResult {
|
||||
method public int getAuthenticationType();
|
||||
method public android.hardware.biometrics.BiometricPrompt.CryptoObject getCryptoObject();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.hardware.biometrics;
|
||||
|
||||
import android.annotation.CallbackExecutor;
|
||||
import android.annotation.NonNull;
|
||||
import android.hardware.biometrics.BiometricPrompt.AuthenticationResultType;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.Parcelable;
|
||||
|
||||
@@ -119,6 +120,7 @@ public interface BiometricAuthenticator {
|
||||
class AuthenticationResult {
|
||||
private Identifier mIdentifier;
|
||||
private CryptoObject mCryptoObject;
|
||||
private @AuthenticationResultType int mAuthenticationType;
|
||||
private int mUserId;
|
||||
|
||||
/**
|
||||
@@ -129,26 +131,40 @@ public interface BiometricAuthenticator {
|
||||
/**
|
||||
* Authentication result
|
||||
* @param crypto
|
||||
* @param authenticationType
|
||||
* @param identifier
|
||||
* @param userId
|
||||
* @hide
|
||||
*/
|
||||
public AuthenticationResult(CryptoObject crypto, Identifier identifier,
|
||||
public AuthenticationResult(CryptoObject crypto,
|
||||
@AuthenticationResultType int authenticationType, Identifier identifier,
|
||||
int userId) {
|
||||
mCryptoObject = crypto;
|
||||
mAuthenticationType = authenticationType;
|
||||
mIdentifier = identifier;
|
||||
mUserId = userId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the crypto object associated with this transaction
|
||||
* @return crypto object provided to {@link BiometricAuthenticator#authenticate(
|
||||
* CryptoObject, CancellationSignal, Executor, AuthenticationCallback)}
|
||||
* Provides the crypto object associated with this transaction.
|
||||
* @return The crypto object provided to {@link BiometricPrompt#authenticate(
|
||||
* BiometricPrompt.CryptoObject, CancellationSignal, Executor,
|
||||
* BiometricPrompt.AuthenticationCallback)}
|
||||
*/
|
||||
public CryptoObject getCryptoObject() {
|
||||
return mCryptoObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the type of authentication (e.g. device credential or biometric) that was
|
||||
* requested from and successfully provided by the user.
|
||||
*
|
||||
* @return An integer value representing the authentication method used.
|
||||
*/
|
||||
public @AuthenticationResultType int getAuthenticationType() {
|
||||
return mAuthenticationType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the biometric identifier associated with this operation. Applications are strongly
|
||||
* discouraged from associating specific identifiers with specific applications or
|
||||
|
||||
@@ -21,6 +21,7 @@ import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
|
||||
import static android.hardware.biometrics.BiometricManager.Authenticators;
|
||||
|
||||
import android.annotation.CallbackExecutor;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
@@ -40,6 +41,8 @@ import android.util.Log;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.security.Signature;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
@@ -397,9 +400,11 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
|
||||
new IBiometricServiceReceiver.Stub() {
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSucceeded() throws RemoteException {
|
||||
public void onAuthenticationSucceeded(@AuthenticationResultType int authenticationType)
|
||||
throws RemoteException {
|
||||
mExecutor.execute(() -> {
|
||||
final AuthenticationResult result = new AuthenticationResult(mCryptoObject);
|
||||
final AuthenticationResult result =
|
||||
new AuthenticationResult(mCryptoObject, authenticationType);
|
||||
mAuthenticationCallback.onAuthenticationSucceeded(result);
|
||||
});
|
||||
}
|
||||
@@ -576,28 +581,62 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
|
||||
}
|
||||
|
||||
/**
|
||||
* Container for callback data from {@link #authenticate( CancellationSignal, Executor,
|
||||
* Authentication type reported by {@link AuthenticationResult} when the user authenticated by
|
||||
* entering their device PIN, pattern, or password.
|
||||
*/
|
||||
public static final int AUTHENTICATION_RESULT_TYPE_DEVICE_CREDENTIAL = 1;
|
||||
|
||||
/**
|
||||
* Authentication type reported by {@link AuthenticationResult} when the user authenticated by
|
||||
* presenting some form of biometric (e.g. fingerprint or face).
|
||||
*/
|
||||
public static final int AUTHENTICATION_RESULT_TYPE_BIOMETRIC = 2;
|
||||
|
||||
/**
|
||||
* An {@link IntDef} representing the type of auth, as reported by {@link AuthenticationResult}.
|
||||
* @hide
|
||||
*/
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({AUTHENTICATION_RESULT_TYPE_DEVICE_CREDENTIAL, AUTHENTICATION_RESULT_TYPE_BIOMETRIC})
|
||||
public @interface AuthenticationResultType {
|
||||
}
|
||||
|
||||
/**
|
||||
* Container for callback data from {@link #authenticate(CancellationSignal, Executor,
|
||||
* AuthenticationCallback)} and {@link #authenticate(CryptoObject, CancellationSignal, Executor,
|
||||
* AuthenticationCallback)}
|
||||
* AuthenticationCallback)}.
|
||||
*/
|
||||
public static class AuthenticationResult extends BiometricAuthenticator.AuthenticationResult {
|
||||
/**
|
||||
* Authentication result
|
||||
* @param crypto
|
||||
* @param authenticationType
|
||||
* @hide
|
||||
*/
|
||||
public AuthenticationResult(CryptoObject crypto) {
|
||||
public AuthenticationResult(CryptoObject crypto,
|
||||
@AuthenticationResultType int authenticationType) {
|
||||
// Identifier and userId is not used for BiometricPrompt.
|
||||
super(crypto, null /* identifier */, 0 /* userId */);
|
||||
super(crypto, authenticationType, null /* identifier */, 0 /* userId */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the crypto object associated with this transaction
|
||||
* @return crypto object provided to {@link #authenticate( CryptoObject, CancellationSignal,
|
||||
* Executor, AuthenticationCallback)}
|
||||
* Provides the crypto object associated with this transaction.
|
||||
* @return The crypto object provided to {@link #authenticate(CryptoObject,
|
||||
* CancellationSignal, Executor, AuthenticationCallback)}
|
||||
*/
|
||||
public CryptoObject getCryptoObject() {
|
||||
return (CryptoObject) super.getCryptoObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the type of authentication (e.g. device credential or biometric) that was
|
||||
* requested from and successfully provided by the user.
|
||||
*
|
||||
* @return An integer value representing the authentication method used.
|
||||
*/
|
||||
public @AuthenticationResultType int getAuthenticationType() {
|
||||
return super.getAuthenticationType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,8 +20,8 @@ package android.hardware.biometrics;
|
||||
* @hide
|
||||
*/
|
||||
oneway interface IBiometricServiceReceiver {
|
||||
// Notify BiometricPrompt that authentication was successful
|
||||
void onAuthenticationSucceeded();
|
||||
// Notify BiometricPrompt that authentication was successful.
|
||||
void onAuthenticationSucceeded(int authenticationType);
|
||||
// Noties that authentication failed.
|
||||
void onAuthenticationFailed();
|
||||
// Notify BiometricPrompt that an error has occurred.
|
||||
|
||||
@@ -1400,7 +1400,8 @@ public class BiometricService extends SystemService {
|
||||
if (mCurrentAuthSession.mTokenEscrow != null) {
|
||||
mKeyStore.addAuthToken(mCurrentAuthSession.mTokenEscrow);
|
||||
}
|
||||
mCurrentAuthSession.mClientReceiver.onAuthenticationSucceeded();
|
||||
mCurrentAuthSession.mClientReceiver.onAuthenticationSucceeded(
|
||||
Utils.getAuthenticationTypeForResult(reason));
|
||||
break;
|
||||
|
||||
case BiometricPrompt.DISMISSED_REASON_NEGATIVE:
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.content.Context;
|
||||
import android.hardware.biometrics.BiometricConstants;
|
||||
import android.hardware.biometrics.BiometricManager;
|
||||
import android.hardware.biometrics.BiometricPrompt;
|
||||
import android.hardware.biometrics.BiometricPrompt.AuthenticationResultType;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
@@ -210,4 +211,30 @@ public class Utils {
|
||||
}
|
||||
return biometricManagerCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@link BiometricPrompt} dismissal reason to an authentication type at the level of
|
||||
* granularity supported by {@link BiometricPrompt.AuthenticationResult}.
|
||||
*
|
||||
* @param reason The reason that the {@link BiometricPrompt} was dismissed. Must be one of:
|
||||
* {@link BiometricPrompt#DISMISSED_REASON_CREDENTIAL_CONFIRMED},
|
||||
* {@link BiometricPrompt#DISMISSED_REASON_BIOMETRIC_CONFIRMED}, or
|
||||
* {@link BiometricPrompt#DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED}
|
||||
* @return An integer representing the authentication type for {@link
|
||||
* BiometricPrompt.AuthenticationResult}.
|
||||
* @throws IllegalArgumentException if given an invalid dismissal reason.
|
||||
*/
|
||||
public static @AuthenticationResultType int getAuthenticationTypeForResult(int reason) {
|
||||
switch (reason) {
|
||||
case BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED:
|
||||
return BiometricPrompt.AUTHENTICATION_RESULT_TYPE_DEVICE_CREDENTIAL;
|
||||
|
||||
case BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED:
|
||||
case BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED:
|
||||
return BiometricPrompt.AUTHENTICATION_RESULT_TYPE_BIOMETRIC;
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported dismissal reason: " + reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -411,7 +411,8 @@ public class BiometricServiceTest {
|
||||
// HAT sent to keystore
|
||||
verify(mBiometricService.mKeyStore).addAuthToken(any(byte[].class));
|
||||
// Send onAuthenticated to client
|
||||
verify(mReceiver1).onAuthenticationSucceeded();
|
||||
verify(mReceiver1).onAuthenticationSucceeded(
|
||||
BiometricPrompt.AUTHENTICATION_RESULT_TYPE_BIOMETRIC);
|
||||
// Current session becomes null
|
||||
assertNull(mBiometricService.mCurrentAuthSession);
|
||||
}
|
||||
@@ -461,7 +462,8 @@ public class BiometricServiceTest {
|
||||
BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED);
|
||||
waitForIdle();
|
||||
verify(mBiometricService.mKeyStore).addAuthToken(any(byte[].class));
|
||||
verify(mReceiver1).onAuthenticationSucceeded();
|
||||
verify(mReceiver1).onAuthenticationSucceeded(
|
||||
BiometricPrompt.AUTHENTICATION_RESULT_TYPE_BIOMETRIC);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -223,4 +223,22 @@ public class UtilsTest {
|
||||
Utils.biometricConstantsToBiometricManager(testCases[i][0]));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAuthenticationTypeForResult_getsCorrectType() {
|
||||
assertEquals(Utils.getAuthenticationTypeForResult(
|
||||
BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED),
|
||||
BiometricPrompt.AUTHENTICATION_RESULT_TYPE_DEVICE_CREDENTIAL);
|
||||
assertEquals(Utils.getAuthenticationTypeForResult(
|
||||
BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED),
|
||||
BiometricPrompt.AUTHENTICATION_RESULT_TYPE_BIOMETRIC);
|
||||
assertEquals(Utils.getAuthenticationTypeForResult(
|
||||
BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED),
|
||||
BiometricPrompt.AUTHENTICATION_RESULT_TYPE_BIOMETRIC);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testGetAuthResultType_throwsForInvalidReason() {
|
||||
Utils.getAuthenticationTypeForResult(BiometricPrompt.DISMISSED_REASON_NEGATIVE);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user