Loading core/java/android/hardware/biometrics/BiometricManager.java +9 −3 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ import android.annotation.SystemService; import android.annotation.TestApi; import android.content.Context; import android.os.RemoteException; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.util.Slog; Loading @@ -46,6 +45,13 @@ public class BiometricManager { private static final String TAG = "BiometricManager"; /** * An ID that should match any biometric sensor on the device. * * @hide */ public static final int SENSOR_ID_ANY = -1; /** * No error detected. */ Loading Loading @@ -139,7 +145,7 @@ public class BiometricManager { * * <p>This corresponds to {@link KeyProperties#AUTH_BIOMETRIC_STRONG} during key generation. * * @see KeyGenParameterSpec.Builder#setUserAuthenticationParameters(int, int) * @see android.security.keystore.KeyGenParameterSpec.Builder */ int BIOMETRIC_STRONG = 0x000F; Loading Loading @@ -182,7 +188,7 @@ public class BiometricManager { * <p>This corresponds to {@link KeyProperties#AUTH_DEVICE_CREDENTIAL} during key * generation. * * @see KeyGenParameterSpec.Builder#setUserAuthenticationParameters(int, int) * @see android.security.keystore.KeyGenParameterSpec.Builder */ int DEVICE_CREDENTIAL = 1 << 15; } Loading core/java/android/hardware/biometrics/BiometricPrompt.java +65 −12 Original line number Diff line number Diff line Loading @@ -36,7 +36,6 @@ import android.os.Parcel; import android.os.RemoteException; import android.os.ServiceManager; import android.security.identity.IdentityCredential; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.text.TextUtils; import android.util.Log; Loading Loading @@ -325,7 +324,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan * request authentication with the proper set of authenticators (e.g. match the * authenticators specified during key generation). * * @see KeyGenParameterSpec.Builder#setUserAuthenticationParameters(int, int) * @see android.security.keystore.KeyGenParameterSpec.Builder * @see KeyProperties#AUTH_BIOMETRIC_STRONG * @see KeyProperties#AUTH_DEVICE_CREDENTIAL * Loading Loading @@ -364,6 +363,21 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan return this; } /** * If set, authenticate using the biometric sensor with the given ID. * * @param sensorId The ID of a biometric sensor, or -1 to allow any sensor (default). * @return This builder. * * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) @NonNull public Builder setSensorId(int sensorId) { mPromptInfo.setSensorId(sensorId); return this; } /** * Creates a {@link BiometricPrompt}. * Loading Loading @@ -589,7 +603,8 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan * * <p>Cryptographic operations in Android can be split into two categories: auth-per-use and * time-based. This is specified during key creation via the timeout parameter of the * {@link KeyGenParameterSpec.Builder#setUserAuthenticationParameters(int, int)} API. * {@code setUserAuthenticationParameters(int, int)} method of {@link * android.security.keystore.KeyGenParameterSpec.Builder}. * * <p>CryptoObjects are used to unlock auth-per-use keys via * {@link BiometricPrompt#authenticate(CryptoObject, CancellationSignal, Executor, Loading Loading @@ -778,6 +793,27 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan @NonNull @CallbackExecutor Executor executor, @NonNull AuthenticationCallback callback, int userId) { authenticateUserForOperation(cancel, executor, callback, userId, 0 /* operationId */); } /** * Authenticates for the given user and keystore operation. * * @param cancel An object that can be used to cancel authentication * @param executor An executor to handle callback events * @param callback An object to receive authentication events * @param userId The user to authenticate * @param operationId The keystore operation associated with authentication * * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) public void authenticateUserForOperation( @NonNull CancellationSignal cancel, @NonNull @CallbackExecutor Executor executor, @NonNull AuthenticationCallback callback, int userId, long operationId) { if (cancel == null) { throw new IllegalArgumentException("Must supply a cancellation signal"); } Loading @@ -787,7 +823,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan if (callback == null) { throw new IllegalArgumentException("Must supply a callback"); } authenticateInternal(null /* crypto */, cancel, executor, callback, userId); authenticateInternal(operationId, cancel, executor, callback, userId); } /** Loading Loading @@ -912,11 +948,31 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan } } private void authenticateInternal(@Nullable CryptoObject crypto, private void authenticateInternal( @Nullable CryptoObject crypto, @NonNull CancellationSignal cancel, @NonNull @CallbackExecutor Executor executor, @NonNull AuthenticationCallback callback, int userId) { mCryptoObject = crypto; final long operationId = crypto != null ? crypto.getOpId() : 0L; authenticateInternal(operationId, cancel, executor, callback, userId); } private void authenticateInternal( long operationId, @NonNull CancellationSignal cancel, @NonNull @CallbackExecutor Executor executor, @NonNull AuthenticationCallback callback, int userId) { // Ensure we don't return the wrong crypto object as an auth result. if (mCryptoObject != null && mCryptoObject.getOpId() != operationId) { Log.w(TAG, "CryptoObject operation ID does not match argument; setting field to null"); mCryptoObject = null; } try { if (cancel.isCanceled()) { Log.w(TAG, "Authentication already canceled"); Loading @@ -925,13 +981,11 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan cancel.setOnCancelListener(new OnAuthenticationCancelListener()); } mCryptoObject = crypto; mExecutor = executor; mAuthenticationCallback = callback; final long operationId = crypto != null ? crypto.getOpId() : 0; final PromptInfo promptInfo; if (crypto != null) { if (operationId != 0L) { // Allowed authenticators should default to BIOMETRIC_STRONG for crypto auth. // Note that we use a new PromptInfo here so as to not overwrite the application's // preference, since it is possible that the same prompt configuration be used Loading @@ -952,10 +1006,9 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan } catch (RemoteException e) { Log.e(TAG, "Remote exception while authenticating", e); mExecutor.execute(() -> { callback.onAuthenticationError(BiometricPrompt.BIOMETRIC_ERROR_HW_UNAVAILABLE, mContext.getString(R.string.biometric_error_hw_unavailable)); }); mExecutor.execute(() -> callback.onAuthenticationError( BiometricPrompt.BIOMETRIC_ERROR_HW_UNAVAILABLE, mContext.getString(R.string.biometric_error_hw_unavailable))); } } } core/java/android/hardware/biometrics/PromptInfo.java +11 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ public class PromptInfo implements Parcelable { private @BiometricManager.Authenticators.Types int mAuthenticators; private boolean mDisallowBiometricsIfPolicyExists; private boolean mReceiveSystemEvents; private int mSensorId = -1; public PromptInfo() { Loading @@ -59,6 +60,7 @@ public class PromptInfo implements Parcelable { mAuthenticators = in.readInt(); mDisallowBiometricsIfPolicyExists = in.readBoolean(); mReceiveSystemEvents = in.readBoolean(); mSensorId = in.readInt(); } public static final Creator<PromptInfo> CREATOR = new Creator<PromptInfo>() { Loading Loading @@ -93,6 +95,7 @@ public class PromptInfo implements Parcelable { dest.writeInt(mAuthenticators); dest.writeBoolean(mDisallowBiometricsIfPolicyExists); dest.writeBoolean(mReceiveSystemEvents); dest.writeInt(mSensorId); } public boolean containsPrivateApiConfigurations() { Loading Loading @@ -166,6 +169,10 @@ public class PromptInfo implements Parcelable { mReceiveSystemEvents = receiveSystemEvents; } public void setSensorId(int sensorId) { mSensorId = sensorId; } // Getters public CharSequence getTitle() { Loading Loading @@ -226,4 +233,8 @@ public class PromptInfo implements Parcelable { public boolean isReceiveSystemEvents() { return mReceiveSystemEvents; } public int getSensorId() { return mSensorId; } } core/java/android/hardware/fingerprint/FingerprintManager.java +22 −29 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ import static android.Manifest.permission.USE_BIOMETRIC; import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; import static android.Manifest.permission.USE_FINGERPRINT; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresFeature; Loading Loading @@ -56,8 +55,6 @@ import android.security.identity.IdentityCredential; import android.util.Slog; import android.view.Surface; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.security.Signature; import java.util.ArrayList; import java.util.List; Loading Loading @@ -98,13 +95,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing */ public static final int SENSOR_ID_ANY = -1; /** * @hide */ @IntDef({SENSOR_ID_ANY}) @Retention(RetentionPolicy.SOURCE) public @interface SensorId {} private IFingerprintService mService; private Context mContext; private IBinder mToken = new Binder(); Loading Loading @@ -508,8 +498,8 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing */ @RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT}) public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, @NonNull AuthenticationCallback callback, Handler handler, @SensorId int sensorId, int userId) { @NonNull AuthenticationCallback callback, Handler handler, int sensorId, int userId) { if (callback == null) { throw new IllegalArgumentException("Must supply an authentication callback"); } Loading Loading @@ -653,15 +643,12 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing */ @RequiresPermission(MANAGE_FINGERPRINT) public void generateChallenge(int userId, GenerateChallengeCallback callback) { final List<FingerprintSensorPropertiesInternal> fingerprintSensorProperties = getSensorPropertiesInternal(); if (fingerprintSensorProperties.isEmpty()) { final FingerprintSensorPropertiesInternal sensorProps = getFirstFingerprintSensor(); if (sensorProps == null) { Slog.e(TAG, "No sensors"); return; } final int sensorId = fingerprintSensorProperties.get(0).sensorId; generateChallenge(sensorId, userId, callback); generateChallenge(sensorProps.sensorId, userId, callback); } /** Loading @@ -681,20 +668,20 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing */ @RequiresPermission(MANAGE_FINGERPRINT) public void revokeChallenge(int userId, long challenge) { if (mService != null) try { final List<FingerprintSensorPropertiesInternal> fingerprintSensorProperties = getSensorPropertiesInternal(); if (fingerprintSensorProperties.isEmpty()) { if (mService != null) { try { final FingerprintSensorPropertiesInternal sensorProps = getFirstFingerprintSensor(); if (sensorProps == null) { Slog.e(TAG, "No sensors"); return; } final int sensorId = fingerprintSensorProperties.get(0).sensorId; mService.revokeChallenge(mToken, sensorId, userId, mContext.getOpPackageName(), challenge); mService.revokeChallenge(mToken, sensorProps.sensorId, userId, mContext.getOpPackageName(), challenge); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } /** * Reset the lockout when user authenticates with strong auth (e.g. PIN, pattern or password) Loading Loading @@ -1161,6 +1148,12 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } } @Nullable private FingerprintSensorPropertiesInternal getFirstFingerprintSensor() { final List<FingerprintSensorPropertiesInternal> allSensors = getSensorPropertiesInternal(); return allSensors.isEmpty() ? null : allSensors.get(0); } private void cancelEnrollment() { if (mService != null) try { mService.cancelEnrollment(mToken); Loading core/res/res/values/strings.xml +2 −0 Original line number Diff line number Diff line Loading @@ -1585,6 +1585,8 @@ <!-- Template to be used to name enrolled fingerprints by default. --> <string name="fingerprint_name_template">Finger <xliff:g id="fingerId" example="1">%d</xliff:g></string> <!-- Subtitle shown on the system-provided biometric dialog, asking the user to authenticate with their fingerprint. [CHAR LIMIT=70] --> <string name="fingerprint_dialog_default_subtitle">Use your fingerprint to continue</string> <!-- Array containing custom error messages from vendor. Vendor is expected to add and translate these strings --> <string-array name="fingerprint_error_vendor"> Loading Loading
core/java/android/hardware/biometrics/BiometricManager.java +9 −3 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ import android.annotation.SystemService; import android.annotation.TestApi; import android.content.Context; import android.os.RemoteException; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.util.Slog; Loading @@ -46,6 +45,13 @@ public class BiometricManager { private static final String TAG = "BiometricManager"; /** * An ID that should match any biometric sensor on the device. * * @hide */ public static final int SENSOR_ID_ANY = -1; /** * No error detected. */ Loading Loading @@ -139,7 +145,7 @@ public class BiometricManager { * * <p>This corresponds to {@link KeyProperties#AUTH_BIOMETRIC_STRONG} during key generation. * * @see KeyGenParameterSpec.Builder#setUserAuthenticationParameters(int, int) * @see android.security.keystore.KeyGenParameterSpec.Builder */ int BIOMETRIC_STRONG = 0x000F; Loading Loading @@ -182,7 +188,7 @@ public class BiometricManager { * <p>This corresponds to {@link KeyProperties#AUTH_DEVICE_CREDENTIAL} during key * generation. * * @see KeyGenParameterSpec.Builder#setUserAuthenticationParameters(int, int) * @see android.security.keystore.KeyGenParameterSpec.Builder */ int DEVICE_CREDENTIAL = 1 << 15; } Loading
core/java/android/hardware/biometrics/BiometricPrompt.java +65 −12 Original line number Diff line number Diff line Loading @@ -36,7 +36,6 @@ import android.os.Parcel; import android.os.RemoteException; import android.os.ServiceManager; import android.security.identity.IdentityCredential; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.text.TextUtils; import android.util.Log; Loading Loading @@ -325,7 +324,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan * request authentication with the proper set of authenticators (e.g. match the * authenticators specified during key generation). * * @see KeyGenParameterSpec.Builder#setUserAuthenticationParameters(int, int) * @see android.security.keystore.KeyGenParameterSpec.Builder * @see KeyProperties#AUTH_BIOMETRIC_STRONG * @see KeyProperties#AUTH_DEVICE_CREDENTIAL * Loading Loading @@ -364,6 +363,21 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan return this; } /** * If set, authenticate using the biometric sensor with the given ID. * * @param sensorId The ID of a biometric sensor, or -1 to allow any sensor (default). * @return This builder. * * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) @NonNull public Builder setSensorId(int sensorId) { mPromptInfo.setSensorId(sensorId); return this; } /** * Creates a {@link BiometricPrompt}. * Loading Loading @@ -589,7 +603,8 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan * * <p>Cryptographic operations in Android can be split into two categories: auth-per-use and * time-based. This is specified during key creation via the timeout parameter of the * {@link KeyGenParameterSpec.Builder#setUserAuthenticationParameters(int, int)} API. * {@code setUserAuthenticationParameters(int, int)} method of {@link * android.security.keystore.KeyGenParameterSpec.Builder}. * * <p>CryptoObjects are used to unlock auth-per-use keys via * {@link BiometricPrompt#authenticate(CryptoObject, CancellationSignal, Executor, Loading Loading @@ -778,6 +793,27 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan @NonNull @CallbackExecutor Executor executor, @NonNull AuthenticationCallback callback, int userId) { authenticateUserForOperation(cancel, executor, callback, userId, 0 /* operationId */); } /** * Authenticates for the given user and keystore operation. * * @param cancel An object that can be used to cancel authentication * @param executor An executor to handle callback events * @param callback An object to receive authentication events * @param userId The user to authenticate * @param operationId The keystore operation associated with authentication * * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) public void authenticateUserForOperation( @NonNull CancellationSignal cancel, @NonNull @CallbackExecutor Executor executor, @NonNull AuthenticationCallback callback, int userId, long operationId) { if (cancel == null) { throw new IllegalArgumentException("Must supply a cancellation signal"); } Loading @@ -787,7 +823,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan if (callback == null) { throw new IllegalArgumentException("Must supply a callback"); } authenticateInternal(null /* crypto */, cancel, executor, callback, userId); authenticateInternal(operationId, cancel, executor, callback, userId); } /** Loading Loading @@ -912,11 +948,31 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan } } private void authenticateInternal(@Nullable CryptoObject crypto, private void authenticateInternal( @Nullable CryptoObject crypto, @NonNull CancellationSignal cancel, @NonNull @CallbackExecutor Executor executor, @NonNull AuthenticationCallback callback, int userId) { mCryptoObject = crypto; final long operationId = crypto != null ? crypto.getOpId() : 0L; authenticateInternal(operationId, cancel, executor, callback, userId); } private void authenticateInternal( long operationId, @NonNull CancellationSignal cancel, @NonNull @CallbackExecutor Executor executor, @NonNull AuthenticationCallback callback, int userId) { // Ensure we don't return the wrong crypto object as an auth result. if (mCryptoObject != null && mCryptoObject.getOpId() != operationId) { Log.w(TAG, "CryptoObject operation ID does not match argument; setting field to null"); mCryptoObject = null; } try { if (cancel.isCanceled()) { Log.w(TAG, "Authentication already canceled"); Loading @@ -925,13 +981,11 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan cancel.setOnCancelListener(new OnAuthenticationCancelListener()); } mCryptoObject = crypto; mExecutor = executor; mAuthenticationCallback = callback; final long operationId = crypto != null ? crypto.getOpId() : 0; final PromptInfo promptInfo; if (crypto != null) { if (operationId != 0L) { // Allowed authenticators should default to BIOMETRIC_STRONG for crypto auth. // Note that we use a new PromptInfo here so as to not overwrite the application's // preference, since it is possible that the same prompt configuration be used Loading @@ -952,10 +1006,9 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan } catch (RemoteException e) { Log.e(TAG, "Remote exception while authenticating", e); mExecutor.execute(() -> { callback.onAuthenticationError(BiometricPrompt.BIOMETRIC_ERROR_HW_UNAVAILABLE, mContext.getString(R.string.biometric_error_hw_unavailable)); }); mExecutor.execute(() -> callback.onAuthenticationError( BiometricPrompt.BIOMETRIC_ERROR_HW_UNAVAILABLE, mContext.getString(R.string.biometric_error_hw_unavailable))); } } }
core/java/android/hardware/biometrics/PromptInfo.java +11 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ public class PromptInfo implements Parcelable { private @BiometricManager.Authenticators.Types int mAuthenticators; private boolean mDisallowBiometricsIfPolicyExists; private boolean mReceiveSystemEvents; private int mSensorId = -1; public PromptInfo() { Loading @@ -59,6 +60,7 @@ public class PromptInfo implements Parcelable { mAuthenticators = in.readInt(); mDisallowBiometricsIfPolicyExists = in.readBoolean(); mReceiveSystemEvents = in.readBoolean(); mSensorId = in.readInt(); } public static final Creator<PromptInfo> CREATOR = new Creator<PromptInfo>() { Loading Loading @@ -93,6 +95,7 @@ public class PromptInfo implements Parcelable { dest.writeInt(mAuthenticators); dest.writeBoolean(mDisallowBiometricsIfPolicyExists); dest.writeBoolean(mReceiveSystemEvents); dest.writeInt(mSensorId); } public boolean containsPrivateApiConfigurations() { Loading Loading @@ -166,6 +169,10 @@ public class PromptInfo implements Parcelable { mReceiveSystemEvents = receiveSystemEvents; } public void setSensorId(int sensorId) { mSensorId = sensorId; } // Getters public CharSequence getTitle() { Loading Loading @@ -226,4 +233,8 @@ public class PromptInfo implements Parcelable { public boolean isReceiveSystemEvents() { return mReceiveSystemEvents; } public int getSensorId() { return mSensorId; } }
core/java/android/hardware/fingerprint/FingerprintManager.java +22 −29 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ import static android.Manifest.permission.USE_BIOMETRIC; import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; import static android.Manifest.permission.USE_FINGERPRINT; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresFeature; Loading Loading @@ -56,8 +55,6 @@ import android.security.identity.IdentityCredential; import android.util.Slog; import android.view.Surface; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.security.Signature; import java.util.ArrayList; import java.util.List; Loading Loading @@ -98,13 +95,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing */ public static final int SENSOR_ID_ANY = -1; /** * @hide */ @IntDef({SENSOR_ID_ANY}) @Retention(RetentionPolicy.SOURCE) public @interface SensorId {} private IFingerprintService mService; private Context mContext; private IBinder mToken = new Binder(); Loading Loading @@ -508,8 +498,8 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing */ @RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT}) public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, @NonNull AuthenticationCallback callback, Handler handler, @SensorId int sensorId, int userId) { @NonNull AuthenticationCallback callback, Handler handler, int sensorId, int userId) { if (callback == null) { throw new IllegalArgumentException("Must supply an authentication callback"); } Loading Loading @@ -653,15 +643,12 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing */ @RequiresPermission(MANAGE_FINGERPRINT) public void generateChallenge(int userId, GenerateChallengeCallback callback) { final List<FingerprintSensorPropertiesInternal> fingerprintSensorProperties = getSensorPropertiesInternal(); if (fingerprintSensorProperties.isEmpty()) { final FingerprintSensorPropertiesInternal sensorProps = getFirstFingerprintSensor(); if (sensorProps == null) { Slog.e(TAG, "No sensors"); return; } final int sensorId = fingerprintSensorProperties.get(0).sensorId; generateChallenge(sensorId, userId, callback); generateChallenge(sensorProps.sensorId, userId, callback); } /** Loading @@ -681,20 +668,20 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing */ @RequiresPermission(MANAGE_FINGERPRINT) public void revokeChallenge(int userId, long challenge) { if (mService != null) try { final List<FingerprintSensorPropertiesInternal> fingerprintSensorProperties = getSensorPropertiesInternal(); if (fingerprintSensorProperties.isEmpty()) { if (mService != null) { try { final FingerprintSensorPropertiesInternal sensorProps = getFirstFingerprintSensor(); if (sensorProps == null) { Slog.e(TAG, "No sensors"); return; } final int sensorId = fingerprintSensorProperties.get(0).sensorId; mService.revokeChallenge(mToken, sensorId, userId, mContext.getOpPackageName(), challenge); mService.revokeChallenge(mToken, sensorProps.sensorId, userId, mContext.getOpPackageName(), challenge); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } /** * Reset the lockout when user authenticates with strong auth (e.g. PIN, pattern or password) Loading Loading @@ -1161,6 +1148,12 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } } @Nullable private FingerprintSensorPropertiesInternal getFirstFingerprintSensor() { final List<FingerprintSensorPropertiesInternal> allSensors = getSensorPropertiesInternal(); return allSensors.isEmpty() ? null : allSensors.get(0); } private void cancelEnrollment() { if (mService != null) try { mService.cancelEnrollment(mToken); Loading
core/res/res/values/strings.xml +2 −0 Original line number Diff line number Diff line Loading @@ -1585,6 +1585,8 @@ <!-- Template to be used to name enrolled fingerprints by default. --> <string name="fingerprint_name_template">Finger <xliff:g id="fingerId" example="1">%d</xliff:g></string> <!-- Subtitle shown on the system-provided biometric dialog, asking the user to authenticate with their fingerprint. [CHAR LIMIT=70] --> <string name="fingerprint_dialog_default_subtitle">Use your fingerprint to continue</string> <!-- Array containing custom error messages from vendor. Vendor is expected to add and translate these strings --> <string-array name="fingerprint_error_vendor"> Loading