Merge changes from topic "biometric-security"
* changes: Implementation for BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED Add API constant for BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED
This commit is contained in:
@@ -17033,6 +17033,7 @@ package android.hardware.biometrics {
|
||||
field public static final int BIOMETRIC_ERROR_HW_UNAVAILABLE = 1; // 0x1
|
||||
field public static final int BIOMETRIC_ERROR_NONE_ENROLLED = 11; // 0xb
|
||||
field public static final int BIOMETRIC_ERROR_NO_HARDWARE = 12; // 0xc
|
||||
field public static final int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15; // 0xf
|
||||
field public static final int BIOMETRIC_SUCCESS = 0; // 0x0
|
||||
}
|
||||
|
||||
@@ -17067,6 +17068,7 @@ package android.hardware.biometrics {
|
||||
field public static final int BIOMETRIC_ERROR_NO_BIOMETRICS = 11; // 0xb
|
||||
field public static final int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14; // 0xe
|
||||
field public static final int BIOMETRIC_ERROR_NO_SPACE = 4; // 0x4
|
||||
field public static final int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15; // 0xf
|
||||
field public static final int BIOMETRIC_ERROR_TIMEOUT = 3; // 0x3
|
||||
field public static final int BIOMETRIC_ERROR_UNABLE_TO_PROCESS = 2; // 0x2
|
||||
field public static final int BIOMETRIC_ERROR_USER_CANCELED = 10; // 0xa
|
||||
|
||||
@@ -131,6 +131,14 @@ public interface BiometricConstants {
|
||||
*/
|
||||
int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14;
|
||||
|
||||
/**
|
||||
* A security vulnerability has been discovered and the sensor is unavailable until a
|
||||
* security update has addressed this issue. This error can be received if for example,
|
||||
* authentication was requested with {@link Authenticators#BIOMETRIC_STRONG}, but the
|
||||
* sensor's strength can currently only meet {@link Authenticators#BIOMETRIC_WEAK}.
|
||||
*/
|
||||
int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15;
|
||||
|
||||
/**
|
||||
* This constant is only used by SystemUI. It notifies SystemUI that authentication was paused
|
||||
* because the authentication attempt was unsuccessful.
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.hardware.biometrics;
|
||||
|
||||
import android.app.KeyguardManager;
|
||||
import android.hardware.biometrics.BiometricManager.Authenticators;
|
||||
import android.hardware.face.FaceManager;
|
||||
|
||||
/**
|
||||
@@ -141,6 +142,15 @@ public interface BiometricFaceConstants {
|
||||
*/
|
||||
public static final int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14;
|
||||
|
||||
/**
|
||||
* A security vulnerability has been discovered and the sensor is unavailable until a
|
||||
* security update has addressed this issue. This error can be received if for example,
|
||||
* authentication was requested with {@link Authenticators#BIOMETRIC_STRONG}, but the
|
||||
* sensor's strength can currently only meet {@link Authenticators#BIOMETRIC_WEAK}.
|
||||
* @hide
|
||||
*/
|
||||
int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.hardware.biometrics;
|
||||
|
||||
import android.app.KeyguardManager;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.hardware.biometrics.BiometricManager.Authenticators;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
|
||||
/**
|
||||
@@ -127,6 +128,15 @@ public interface BiometricFingerprintConstants {
|
||||
*/
|
||||
public static final int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14;
|
||||
|
||||
/**
|
||||
* A security vulnerability has been discovered and the sensor is unavailable until a
|
||||
* security update has addressed this issue. This error can be received if for example,
|
||||
* authentication was requested with {@link Authenticators#BIOMETRIC_STRONG}, but the
|
||||
* sensor's strength can currently only meet {@link Authenticators#BIOMETRIC_WEAK}.
|
||||
* @hide
|
||||
*/
|
||||
public static final int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -61,10 +61,20 @@ public class BiometricManager {
|
||||
public static final int BIOMETRIC_ERROR_NO_HARDWARE =
|
||||
BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT;
|
||||
|
||||
/**
|
||||
* A security vulnerability has been discovered and the sensor is unavailable until a
|
||||
* security update has addressed this issue. This error can be received if for example,
|
||||
* authentication was requested with {@link Authenticators#BIOMETRIC_STRONG}, but the
|
||||
* sensor's strength can currently only meet {@link Authenticators#BIOMETRIC_WEAK}.
|
||||
*/
|
||||
public static final int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED =
|
||||
BiometricConstants.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED;
|
||||
|
||||
@IntDef({BIOMETRIC_SUCCESS,
|
||||
BIOMETRIC_ERROR_HW_UNAVAILABLE,
|
||||
BIOMETRIC_ERROR_NONE_ENROLLED,
|
||||
BIOMETRIC_ERROR_NO_HARDWARE})
|
||||
BIOMETRIC_ERROR_NO_HARDWARE,
|
||||
BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED})
|
||||
@interface BiometricError {}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,6 +25,7 @@ import static android.hardware.biometrics.BiometricAuthenticator.TYPE_IRIS;
|
||||
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE;
|
||||
import static android.hardware.biometrics.BiometricManager.Authenticators;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.IActivityManager;
|
||||
import android.app.UserSwitchObserver;
|
||||
@@ -83,6 +84,25 @@ public class BiometricService extends SystemService {
|
||||
static final String TAG = "BiometricService";
|
||||
private static final boolean DEBUG = true;
|
||||
|
||||
private static final int BIOMETRIC_NO_HARDWARE = 0;
|
||||
private static final int BIOMETRIC_OK = 1;
|
||||
private static final int BIOMETRIC_DISABLED_BY_DEVICE_POLICY = 2;
|
||||
private static final int BIOMETRIC_INSUFFICIENT_STRENGTH = 3;
|
||||
private static final int BIOMETRIC_INSUFFICIENT_STRENGTH_AFTER_DOWNGRADE = 4;
|
||||
private static final int BIOMETRIC_HARDWARE_NOT_DETECTED = 5;
|
||||
private static final int BIOMETRIC_NOT_ENROLLED = 6;
|
||||
private static final int BIOMETRIC_NOT_ENABLED_FOR_APPS = 7;
|
||||
|
||||
@IntDef({BIOMETRIC_NO_HARDWARE,
|
||||
BIOMETRIC_OK,
|
||||
BIOMETRIC_DISABLED_BY_DEVICE_POLICY,
|
||||
BIOMETRIC_INSUFFICIENT_STRENGTH,
|
||||
BIOMETRIC_INSUFFICIENT_STRENGTH_AFTER_DOWNGRADE,
|
||||
BIOMETRIC_HARDWARE_NOT_DETECTED,
|
||||
BIOMETRIC_NOT_ENROLLED,
|
||||
BIOMETRIC_NOT_ENABLED_FOR_APPS})
|
||||
@interface BiometricStatus {}
|
||||
|
||||
private static final int MSG_ON_AUTHENTICATION_SUCCEEDED = 2;
|
||||
private static final int MSG_ON_AUTHENTICATION_REJECTED = 3;
|
||||
private static final int MSG_ON_ERROR = 4;
|
||||
@@ -206,7 +226,7 @@ public class BiometricService extends SystemService {
|
||||
}
|
||||
|
||||
boolean isAllowDeviceCredential() {
|
||||
return Utils.isDeviceCredentialAllowed(mBundle);
|
||||
return Utils.isCredentialRequested(mBundle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,16 +392,20 @@ public class BiometricService extends SystemService {
|
||||
* strength.
|
||||
* @return a bitfield, see {@link Authenticators}
|
||||
*/
|
||||
public int getActualStrength() {
|
||||
int getActualStrength() {
|
||||
return OEMStrength | updatedStrength;
|
||||
}
|
||||
|
||||
boolean isDowngraded() {
|
||||
return OEMStrength != updatedStrength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the updated strength, which takes effect whenever {@link #getActualStrength()}
|
||||
* is checked.
|
||||
* @param newStrength
|
||||
*/
|
||||
public void updateStrength(int newStrength) {
|
||||
void updateStrength(int newStrength) {
|
||||
String log = "updateStrength: Before(" + toString() + ")";
|
||||
updatedStrength = newStrength;
|
||||
log += " After(" + toString() + ")";
|
||||
@@ -1007,6 +1031,79 @@ public class BiometricService extends SystemService {
|
||||
return isBiometricDisabled;
|
||||
}
|
||||
|
||||
private static int biometricStatusToBiometricConstant(@BiometricStatus int status) {
|
||||
switch (status) {
|
||||
case BIOMETRIC_NO_HARDWARE:
|
||||
return BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT;
|
||||
case BIOMETRIC_OK:
|
||||
return BiometricConstants.BIOMETRIC_SUCCESS;
|
||||
case BIOMETRIC_DISABLED_BY_DEVICE_POLICY:
|
||||
return BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE;
|
||||
case BIOMETRIC_INSUFFICIENT_STRENGTH:
|
||||
return BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT;
|
||||
case BIOMETRIC_INSUFFICIENT_STRENGTH_AFTER_DOWNGRADE:
|
||||
return BiometricConstants.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED;
|
||||
case BIOMETRIC_HARDWARE_NOT_DETECTED:
|
||||
return BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE;
|
||||
case BIOMETRIC_NOT_ENROLLED:
|
||||
return BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS;
|
||||
case BIOMETRIC_NOT_ENABLED_FOR_APPS:
|
||||
return BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE;
|
||||
default:
|
||||
return BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the status of the authenticator, with errors returned in a specific priority order.
|
||||
* For example, {@link #BIOMETRIC_INSUFFICIENT_STRENGTH_AFTER_DOWNGRADE} is only returned
|
||||
* if it has enrollments, and is enabled for apps.
|
||||
*
|
||||
* We should only return the modality if the authenticator should be exposed. e.g.
|
||||
* BIOMETRIC_NOT_ENROLLED_FOR_APPS should not expose the authenticator's type.
|
||||
*
|
||||
* @return A Pair with `first` being modality, and `second` being @BiometricStatus
|
||||
*/
|
||||
private Pair<Integer, Integer> getStatusForBiometricAuthenticator(
|
||||
AuthenticatorWrapper authenticator, int userId, String opPackageName,
|
||||
boolean checkDevicePolicyManager, int requestedStrength) {
|
||||
if (checkDevicePolicyManager) {
|
||||
if (isBiometricDisabledByDevicePolicy(authenticator.modality, userId)) {
|
||||
return new Pair<>(TYPE_NONE, BIOMETRIC_DISABLED_BY_DEVICE_POLICY);
|
||||
}
|
||||
}
|
||||
|
||||
final boolean wasStrongEnough =
|
||||
Utils.isAtLeastStrength(authenticator.OEMStrength, requestedStrength);
|
||||
final boolean isStrongEnough =
|
||||
Utils.isAtLeastStrength(authenticator.getActualStrength(), requestedStrength);
|
||||
|
||||
if (wasStrongEnough && !isStrongEnough) {
|
||||
return new Pair<>(authenticator.modality,
|
||||
BIOMETRIC_INSUFFICIENT_STRENGTH_AFTER_DOWNGRADE);
|
||||
} else if (!wasStrongEnough) {
|
||||
return new Pair<>(TYPE_NONE, BIOMETRIC_INSUFFICIENT_STRENGTH);
|
||||
}
|
||||
|
||||
try {
|
||||
if (!authenticator.impl.isHardwareDetected(opPackageName)) {
|
||||
return new Pair<>(authenticator.modality, BIOMETRIC_HARDWARE_NOT_DETECTED);
|
||||
}
|
||||
|
||||
if (!authenticator.impl.hasEnrolledTemplates(userId, opPackageName)) {
|
||||
return new Pair<>(authenticator.modality, BIOMETRIC_NOT_ENROLLED);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
return new Pair<>(authenticator.modality, BIOMETRIC_HARDWARE_NOT_DETECTED);
|
||||
}
|
||||
|
||||
if (!isEnabledForApp(authenticator.modality, userId)) {
|
||||
return new Pair<>(TYPE_NONE, BIOMETRIC_NOT_ENABLED_FOR_APPS);
|
||||
}
|
||||
|
||||
return new Pair<>(authenticator.modality, BIOMETRIC_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Depending on the requested authentication (credential/biometric combination), checks their
|
||||
* availability.
|
||||
@@ -1029,10 +1126,9 @@ public class BiometricService extends SystemService {
|
||||
private Pair<Integer, Integer> checkAndGetAuthenticators(int userId, Bundle bundle,
|
||||
String opPackageName, boolean checkDevicePolicyManager) throws RemoteException {
|
||||
|
||||
final boolean biometricRequested = Utils.isBiometricAllowed(bundle);
|
||||
final boolean credentialRequested = Utils.isDeviceCredentialAllowed(bundle);
|
||||
final boolean biometricRequested = Utils.isBiometricRequested(bundle);
|
||||
final boolean credentialRequested = Utils.isCredentialRequested(bundle);
|
||||
|
||||
final boolean biometricOk;
|
||||
final boolean credentialOk = mTrustManager.isDeviceSecure(userId);
|
||||
|
||||
// Assuming that biometric authenticators are listed in priority-order, the rest of this
|
||||
@@ -1041,96 +1137,56 @@ public class BiometricService extends SystemService {
|
||||
// the correct error. Error strings that are modality-specific should also respect the
|
||||
// priority-order.
|
||||
|
||||
// Find first biometric authenticator that's strong enough, detected, enrolled, and enabled.
|
||||
boolean disabledByDevicePolicy = false;
|
||||
boolean hasSufficientStrength = false;
|
||||
boolean isHardwareDetected = false;
|
||||
boolean hasTemplatesEnrolled = false;
|
||||
boolean enabledForApps = false;
|
||||
int firstBiometricModality = TYPE_NONE;
|
||||
@BiometricStatus int firstBiometricStatus = BIOMETRIC_NO_HARDWARE;
|
||||
|
||||
int biometricModality = TYPE_NONE;
|
||||
@BiometricStatus int biometricStatus = BIOMETRIC_NO_HARDWARE;
|
||||
|
||||
int modality = TYPE_NONE;
|
||||
int firstHwAvailable = TYPE_NONE;
|
||||
for (AuthenticatorWrapper authenticator : mAuthenticators) {
|
||||
final int actualStrength = authenticator.getActualStrength();
|
||||
final int requestedStrength = Utils.getPublicBiometricStrength(bundle);
|
||||
Pair<Integer, Integer> result = getStatusForBiometricAuthenticator(
|
||||
authenticator, userId, opPackageName, checkDevicePolicyManager,
|
||||
requestedStrength);
|
||||
|
||||
if (isBiometricDisabledByDevicePolicy(authenticator.modality, userId)) {
|
||||
disabledByDevicePolicy = true;
|
||||
continue;
|
||||
}
|
||||
disabledByDevicePolicy = false;
|
||||
biometricStatus = result.second;
|
||||
|
||||
if (!Utils.isAtLeastStrength(actualStrength, requestedStrength)) {
|
||||
continue;
|
||||
}
|
||||
hasSufficientStrength = true;
|
||||
Slog.d(TAG, "Authenticator ID: " + authenticator.id
|
||||
+ " Modality: " + authenticator.modality
|
||||
+ " ReportedModality: " + result.first
|
||||
+ " Status: " + biometricStatus);
|
||||
|
||||
if (!authenticator.impl.isHardwareDetected(opPackageName)) {
|
||||
continue;
|
||||
}
|
||||
isHardwareDetected = true;
|
||||
|
||||
if (firstHwAvailable == TYPE_NONE) {
|
||||
// Store the first one since we want to return the error in correct
|
||||
// priority order.
|
||||
firstHwAvailable = authenticator.modality;
|
||||
if (firstBiometricModality == TYPE_NONE) {
|
||||
firstBiometricModality = result.first;
|
||||
firstBiometricStatus = biometricStatus;
|
||||
}
|
||||
|
||||
if (!authenticator.impl.hasEnrolledTemplates(userId, opPackageName)) {
|
||||
continue;
|
||||
if (biometricStatus == BIOMETRIC_OK) {
|
||||
biometricModality = result.first;
|
||||
break;
|
||||
}
|
||||
hasTemplatesEnrolled = true;
|
||||
|
||||
if (!isEnabledForApp(authenticator.modality, userId)) {
|
||||
continue;
|
||||
}
|
||||
enabledForApps = true;
|
||||
modality = authenticator.modality;
|
||||
break;
|
||||
}
|
||||
|
||||
biometricOk = !disabledByDevicePolicy
|
||||
&& hasSufficientStrength && isHardwareDetected
|
||||
&& hasTemplatesEnrolled && enabledForApps;
|
||||
|
||||
Slog.d(TAG, "checkAndGetAuthenticators: user=" + userId
|
||||
+ " checkDevicePolicyManager=" + checkDevicePolicyManager
|
||||
+ " isHardwareDetected=" + isHardwareDetected
|
||||
+ " hasTemplatesEnrolled=" + hasTemplatesEnrolled
|
||||
+ " enabledForApps=" + enabledForApps
|
||||
+ " disabledByDevicePolicy=" + disabledByDevicePolicy);
|
||||
|
||||
if (biometricRequested && credentialRequested) {
|
||||
if (credentialOk || biometricOk) {
|
||||
if (!biometricOk) {
|
||||
if (credentialOk || biometricStatus == BIOMETRIC_OK) {
|
||||
if (biometricStatus != BIOMETRIC_OK) {
|
||||
// If there's a problem with biometrics but device credential is
|
||||
// allowed, only show credential UI.
|
||||
bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED,
|
||||
Authenticators.DEVICE_CREDENTIAL);
|
||||
}
|
||||
return new Pair<>(modality, BiometricConstants.BIOMETRIC_SUCCESS);
|
||||
return new Pair<>(biometricModality, BiometricConstants.BIOMETRIC_SUCCESS);
|
||||
} else {
|
||||
return new Pair<>(firstHwAvailable,
|
||||
return new Pair<>(firstBiometricModality,
|
||||
BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS);
|
||||
}
|
||||
} else if (biometricRequested) {
|
||||
if (biometricOk) {
|
||||
return new Pair<>(modality, BiometricConstants.BIOMETRIC_SUCCESS);
|
||||
} else if (disabledByDevicePolicy) {
|
||||
return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE);
|
||||
} else if (!hasSufficientStrength) {
|
||||
return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT);
|
||||
} else if (!isHardwareDetected) {
|
||||
return new Pair<>(firstHwAvailable,
|
||||
BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE);
|
||||
} else if (!hasTemplatesEnrolled) {
|
||||
return new Pair<>(firstHwAvailable,
|
||||
BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS);
|
||||
} else if (!enabledForApps) {
|
||||
return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE);
|
||||
if (biometricStatus == BIOMETRIC_OK) {
|
||||
return new Pair<>(biometricModality,
|
||||
biometricStatusToBiometricConstant(biometricStatus));
|
||||
} else {
|
||||
Slog.e(TAG, "Unexpected case");
|
||||
return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE);
|
||||
return new Pair<>(firstBiometricModality,
|
||||
biometricStatusToBiometricConstant(firstBiometricStatus));
|
||||
}
|
||||
} else if (credentialRequested) {
|
||||
if (credentialOk) {
|
||||
|
||||
@@ -80,7 +80,7 @@ public class Utils {
|
||||
* @param authenticators composed of one or more values from {@link Authenticators}
|
||||
* @return true if device credential is allowed.
|
||||
*/
|
||||
public static boolean isDeviceCredentialAllowed(@Authenticators.Types int authenticators) {
|
||||
public static boolean isCredentialRequested(@Authenticators.Types int authenticators) {
|
||||
return (authenticators & Authenticators.DEVICE_CREDENTIAL) != 0;
|
||||
}
|
||||
|
||||
@@ -88,8 +88,8 @@ public class Utils {
|
||||
* @param bundle should be first processed by {@link #combineAuthenticatorBundles(Bundle)}
|
||||
* @return true if device credential is allowed.
|
||||
*/
|
||||
public static boolean isDeviceCredentialAllowed(Bundle bundle) {
|
||||
return isDeviceCredentialAllowed(bundle.getInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED));
|
||||
public static boolean isCredentialRequested(Bundle bundle) {
|
||||
return isCredentialRequested(bundle.getInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,7 +120,7 @@ public class Utils {
|
||||
* @param bundle should be first processed by {@link #combineAuthenticatorBundles(Bundle)}
|
||||
* @return true if biometric authentication is allowed.
|
||||
*/
|
||||
public static boolean isBiometricAllowed(Bundle bundle) {
|
||||
public static boolean isBiometricRequested(Bundle bundle) {
|
||||
return getPublicBiometricStrength(bundle) != 0;
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ public class Utils {
|
||||
// should be set.
|
||||
final int biometricBits = authenticators & Authenticators.BIOMETRIC_MIN_STRENGTH;
|
||||
if (biometricBits == Authenticators.EMPTY_SET
|
||||
&& isDeviceCredentialAllowed(authenticators)) {
|
||||
&& isCredentialRequested(authenticators)) {
|
||||
return true;
|
||||
} else if (biometricBits == Authenticators.BIOMETRIC_STRONG) {
|
||||
return true;
|
||||
@@ -209,6 +209,9 @@ public class Utils {
|
||||
case BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT:
|
||||
biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE;
|
||||
break;
|
||||
case BiometricConstants.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED:
|
||||
biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED;
|
||||
break;
|
||||
default:
|
||||
Slog.e(BiometricService.TAG, "Unhandled result code: " + biometricConstantsCode);
|
||||
biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE;
|
||||
|
||||
@@ -283,7 +283,7 @@ public class BiometricServiceTest {
|
||||
null /* authenticators */);
|
||||
waitForIdle();
|
||||
verify(mReceiver1).onError(
|
||||
eq(BiometricAuthenticator.TYPE_NONE),
|
||||
eq(BiometricAuthenticator.TYPE_FINGERPRINT),
|
||||
eq(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE),
|
||||
eq(0 /* vendorCode */));
|
||||
}
|
||||
@@ -1117,14 +1117,14 @@ public class BiometricServiceTest {
|
||||
|
||||
// STRONG-only auth is not available
|
||||
int authenticators = Authenticators.BIOMETRIC_STRONG;
|
||||
assertEquals(BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE,
|
||||
assertEquals(BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED,
|
||||
invokeCanAuthenticate(mBiometricService, authenticators));
|
||||
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
|
||||
authenticators);
|
||||
waitForIdle();
|
||||
verify(mReceiver1).onError(
|
||||
eq(BiometricAuthenticator.TYPE_NONE),
|
||||
eq(BiometricPrompt.BIOMETRIC_ERROR_HW_NOT_PRESENT),
|
||||
eq(BiometricAuthenticator.TYPE_FINGERPRINT),
|
||||
eq(BiometricPrompt.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED),
|
||||
eq(0) /* vendorCode */);
|
||||
|
||||
// Request for weak auth works
|
||||
@@ -1154,7 +1154,7 @@ public class BiometricServiceTest {
|
||||
false /* requireConfirmation */,
|
||||
authenticators);
|
||||
waitForIdle();
|
||||
assertTrue(Utils.isDeviceCredentialAllowed(mBiometricService.mCurrentAuthSession.mBundle));
|
||||
assertTrue(Utils.isCredentialRequested(mBiometricService.mCurrentAuthSession.mBundle));
|
||||
verify(mBiometricService.mStatusBarService).showAuthenticationDialog(
|
||||
eq(mBiometricService.mCurrentAuthSession.mBundle),
|
||||
any(IBiometricServiceReceiverInternal.class),
|
||||
@@ -1162,6 +1162,28 @@ public class BiometricServiceTest {
|
||||
anyBoolean() /* requireConfirmation */,
|
||||
anyInt() /* userId */,
|
||||
eq(TEST_PACKAGE_NAME));
|
||||
|
||||
// Un-downgrading the authenticator allows successful strong auth
|
||||
for (BiometricService.AuthenticatorWrapper wrapper : mBiometricService.mAuthenticators) {
|
||||
if (wrapper.id == testId) {
|
||||
wrapper.updateStrength(Authenticators.BIOMETRIC_STRONG);
|
||||
}
|
||||
}
|
||||
|
||||
resetReceiver();
|
||||
authenticators = Authenticators.BIOMETRIC_STRONG;
|
||||
assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
|
||||
invokeCanAuthenticate(mBiometricService, authenticators));
|
||||
invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
|
||||
false /* requireConfirmation */, authenticators);
|
||||
waitForIdle();
|
||||
verify(mBiometricService.mStatusBarService).showAuthenticationDialog(
|
||||
eq(mBiometricService.mCurrentAuthSession.mBundle),
|
||||
any(IBiometricServiceReceiverInternal.class),
|
||||
eq(BiometricAuthenticator.TYPE_FINGERPRINT /* biometricModality */),
|
||||
anyBoolean() /* requireConfirmation */,
|
||||
anyInt() /* userId */,
|
||||
eq(TEST_PACKAGE_NAME));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
@@ -1244,6 +1266,19 @@ public class BiometricServiceTest {
|
||||
BiometricService.STATE_AUTH_STARTED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAuthentication_normalAppIgnoresDevicePolicy() throws Exception {
|
||||
setupAuthForOnly(BiometricAuthenticator.TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
|
||||
when(mDevicePolicyManager
|
||||
.getKeyguardDisabledFeatures(any() /* admin */, anyInt() /* userHandle */))
|
||||
.thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT);
|
||||
invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
|
||||
false /* requireConfirmation */, Authenticators.BIOMETRIC_STRONG);
|
||||
waitForIdle();
|
||||
assertEquals(mBiometricService.mCurrentAuthSession.mState,
|
||||
BiometricService.STATE_AUTH_STARTED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWorkAuthentication_faceWorksIfNotDisabledByDevicePolicyManager()
|
||||
throws Exception {
|
||||
|
||||
@@ -91,31 +91,31 @@ public class UtilsTest {
|
||||
@Test
|
||||
public void testIsDeviceCredentialAllowed_withIntegerFlags() {
|
||||
int authenticators = 0;
|
||||
assertFalse(Utils.isDeviceCredentialAllowed(authenticators));
|
||||
assertFalse(Utils.isCredentialRequested(authenticators));
|
||||
|
||||
authenticators |= Authenticators.DEVICE_CREDENTIAL;
|
||||
assertTrue(Utils.isDeviceCredentialAllowed(authenticators));
|
||||
assertTrue(Utils.isCredentialRequested(authenticators));
|
||||
|
||||
authenticators |= Authenticators.BIOMETRIC_WEAK;
|
||||
assertTrue(Utils.isDeviceCredentialAllowed(authenticators));
|
||||
assertTrue(Utils.isCredentialRequested(authenticators));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsDeviceCredentialAllowed_withBundle() {
|
||||
Bundle bundle = new Bundle();
|
||||
assertFalse(Utils.isDeviceCredentialAllowed(bundle));
|
||||
assertFalse(Utils.isCredentialRequested(bundle));
|
||||
|
||||
int authenticators = 0;
|
||||
bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED, authenticators);
|
||||
assertFalse(Utils.isDeviceCredentialAllowed(bundle));
|
||||
assertFalse(Utils.isCredentialRequested(bundle));
|
||||
|
||||
authenticators |= Authenticators.DEVICE_CREDENTIAL;
|
||||
bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED, authenticators);
|
||||
assertTrue(Utils.isDeviceCredentialAllowed(bundle));
|
||||
assertTrue(Utils.isCredentialRequested(bundle));
|
||||
|
||||
authenticators |= Authenticators.BIOMETRIC_WEAK;
|
||||
bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED, authenticators);
|
||||
assertTrue(Utils.isDeviceCredentialAllowed(bundle));
|
||||
assertTrue(Utils.isCredentialRequested(bundle));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -140,14 +140,14 @@ public class UtilsTest {
|
||||
for (int i = 0; i <= 7; i++) {
|
||||
int authenticators = 1 << i;
|
||||
bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED, authenticators);
|
||||
assertTrue(Utils.isBiometricAllowed(bundle));
|
||||
assertTrue(Utils.isBiometricRequested(bundle));
|
||||
}
|
||||
|
||||
// The rest of the bits are not allowed to integrate with the public APIs
|
||||
for (int i = 8; i < 32; i++) {
|
||||
int authenticators = 1 << i;
|
||||
bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED, authenticators);
|
||||
assertFalse(Utils.isBiometricAllowed(bundle));
|
||||
assertFalse(Utils.isBiometricRequested(bundle));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user