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

Commit b92e7e8a authored by Kevin Chyn's avatar Kevin Chyn Committed by Android (Google) Code Review
Browse files

Merge "Make FingerprintManager show BiometricPrompt for UDFPS" into sc-dev

parents 26e3ecaa 45807b0b
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -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;

@@ -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.
     */
@@ -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;

@@ -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;
    }
+65 −12
Original line number Diff line number Diff line
@@ -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;
@@ -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
         *
@@ -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}.
         *
@@ -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,
@@ -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");
        }
@@ -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);
    }

    /**
@@ -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");
@@ -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
@@ -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)));
        }
    }
}
+11 −0
Original line number Diff line number Diff line
@@ -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() {

@@ -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>() {
@@ -93,6 +95,7 @@ public class PromptInfo implements Parcelable {
        dest.writeInt(mAuthenticators);
        dest.writeBoolean(mDisallowBiometricsIfPolicyExists);
        dest.writeBoolean(mReceiveSystemEvents);
        dest.writeInt(mSensorId);
    }

    public boolean containsPrivateApiConfigurations() {
@@ -166,6 +169,10 @@ public class PromptInfo implements Parcelable {
        mReceiveSystemEvents = receiveSystemEvents;
    }

    public void setSensorId(int sensorId) {
        mSensorId = sensorId;
    }

    // Getters

    public CharSequence getTitle() {
@@ -226,4 +233,8 @@ public class PromptInfo implements Parcelable {
    public boolean isReceiveSystemEvents() {
        return mReceiveSystemEvents;
    }

    public int getSensorId() {
        return mSensorId;
    }
}
+22 −29
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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();
@@ -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");
        }
@@ -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);
    }

    /**
@@ -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)
@@ -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);
+2 −0
Original line number Diff line number Diff line
@@ -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