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

Commit bdd477a5 authored by Joe Bolinger's avatar Joe Bolinger
Browse files

Add requestId to authentication entry points.

The CancellationSignal passed into the authentication methods is not
associated with the request and can be used to cancel the current
operation, even if it is more recent. The new id prevents outdated
signals from being using.

Note that there are still issues with the Callbacks that are not
addressed (see bug for details).

Bug: 194405579
Bug: 189451155
Bug: 191716671
Test: atest com.android.systemui.biometrics com.android.server.biometrics

Change-Id: Id71be912cc88ae90df8087eb8f1a6fc3e110f883
parent dc498938
Loading
Loading
Loading
Loading
+22 −12
Original line number Diff line number Diff line
@@ -438,9 +438,16 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
    }

    private class OnAuthenticationCancelListener implements CancellationSignal.OnCancelListener {
        private final long mAuthRequestId;

        OnAuthenticationCancelListener(long id) {
            mAuthRequestId = id;
        }

        @Override
        public void onCancel() {
            cancelAuthentication();
            Log.d(TAG, "Cancel BP authentication requested for: " + mAuthRequestId);
            cancelAuthentication(mAuthRequestId);
        }
    }

@@ -853,10 +860,12 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
     * @param userId The user to authenticate
     * @param operationId The keystore operation associated with authentication
     *
     * @return A requestId that can be used to cancel this operation.
     *
     * @hide
     */
    @RequiresPermission(USE_BIOMETRIC_INTERNAL)
    public void authenticateUserForOperation(
    public long authenticateUserForOperation(
            @NonNull CancellationSignal cancel,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull AuthenticationCallback callback,
@@ -871,7 +880,8 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
        if (callback == null) {
            throw new IllegalArgumentException("Must supply a callback");
        }
        authenticateInternal(operationId, cancel, executor, callback, userId);

        return authenticateInternal(operationId, cancel, executor, callback, userId);
    }

    /**
@@ -1002,10 +1012,10 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
        authenticateInternal(null /* crypto */, cancel, executor, callback, mContext.getUserId());
    }

    private void cancelAuthentication() {
    private void cancelAuthentication(long requestId) {
        if (mService != null) {
            try {
                mService.cancelAuthentication(mToken, mContext.getOpPackageName());
                mService.cancelAuthentication(mToken, mContext.getOpPackageName(), requestId);
            } catch (RemoteException e) {
                Log.e(TAG, "Unable to cancel authentication", e);
            }
@@ -1024,7 +1034,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
        authenticateInternal(operationId, cancel, executor, callback, userId);
    }

    private void authenticateInternal(
    private long authenticateInternal(
            long operationId,
            @NonNull CancellationSignal cancel,
            @NonNull @CallbackExecutor Executor executor,
@@ -1040,9 +1050,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
        try {
            if (cancel.isCanceled()) {
                Log.w(TAG, "Authentication already canceled");
                return;
            } else {
                cancel.setOnCancelListener(new OnAuthenticationCancelListener());
                return -1;
            }

            mExecutor = executor;
@@ -1065,14 +1073,16 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
                promptInfo = mPromptInfo;
            }

            mService.authenticate(mToken, operationId, userId, mBiometricServiceReceiver,
                    mContext.getOpPackageName(), promptInfo);

            final long authId = mService.authenticate(mToken, operationId, userId,
                    mBiometricServiceReceiver, mContext.getOpPackageName(), promptInfo);
            cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId));
            return authId;
        } 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)));
            return -1;
        }
    }

+6 −5
Original line number Diff line number Diff line
@@ -41,13 +41,14 @@ interface IAuthService {
    // Retrieve the package where BIometricOrompt's UI is implemented
    String getUiPackage();

    // Requests authentication. The service choose the appropriate biometric to use, and show
    // the corresponding BiometricDialog.
    void authenticate(IBinder token, long sessionId, int userId,
    // Requests authentication. The service chooses the appropriate biometric to use, and shows
    // the corresponding BiometricDialog. A requestId is returned that can be used to cancel
    // this operation.
    long authenticate(IBinder token, long sessionId, int userId,
            IBiometricServiceReceiver receiver, String opPackageName, in PromptInfo promptInfo);

    // Cancel authentication for the given sessionId
    void cancelAuthentication(IBinder token, String opPackageName);
    // Cancel authentication for the given requestId.
    void cancelAuthentication(IBinder token, String opPackageName, long requestId);

    // TODO(b/141025588): Make userId the first arg to be consistent with hasEnrolledBiometrics.
    // Checks if biometrics can be used.
+3 −3
Original line number Diff line number Diff line
@@ -48,13 +48,13 @@ interface IBiometricAuthenticator {
    // startPreparedClient().
    void prepareForAuthentication(boolean requireConfirmation, IBinder token, long operationId,
            int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
            int cookie, boolean allowBackgroundAuthentication);
            long requestId, int cookie, boolean allowBackgroundAuthentication);

    // Starts authentication with the previously prepared client.
    void startPreparedClient(int cookie);

    // Cancels authentication.
    void cancelAuthenticationFromService(IBinder token, String opPackageName);
    // Cancels authentication for the given requestId.
    void cancelAuthenticationFromService(IBinder token, String opPackageName, long requestId);

    // Determine if HAL is loaded and ready
    boolean isHardwareDetected(String opPackageName);
+6 −5
Original line number Diff line number Diff line
@@ -36,13 +36,14 @@ interface IBiometricService {
    // Retrieve static sensor properties for all biometric sensors
    List<SensorPropertiesInternal> getSensorProperties(String opPackageName);

    // Requests authentication. The service choose the appropriate biometric to use, and show
    // the corresponding BiometricDialog.
    void authenticate(IBinder token, long operationId, int userId,
    // Requests authentication. The service chooses the appropriate biometric to use, and shows
    // the corresponding BiometricDialog. A requestId is returned that can be used to cancel
    // this operation.
    long authenticate(IBinder token, long operationId, int userId,
            IBiometricServiceReceiver receiver, String opPackageName, in PromptInfo promptInfo);

    // Cancel authentication for the given session.
    void cancelAuthentication(IBinder token, String opPackageName);
    // Cancel authentication for the given requestId.
    void cancelAuthentication(IBinder token, String opPackageName, long requestId);

    // Checks if biometrics can be used.
    int canAuthenticate(String opPackageName, int userId, int callingUserId, int authenticators);
+34 −29
Original line number Diff line number Diff line
@@ -58,7 +58,7 @@ import java.util.List;
public class FaceManager implements BiometricAuthenticator, BiometricFaceConstants {

    private static final String TAG = "FaceManager";
    private static final boolean DEBUG = true;

    private static final int MSG_ENROLL_RESULT = 100;
    private static final int MSG_ACQUIRED = 101;
    private static final int MSG_AUTHENTICATION_SUCCEEDED = 102;
@@ -207,13 +207,9 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
            throw new IllegalArgumentException("Must supply an authentication callback");
        }

        if (cancel != null) {
            if (cancel.isCanceled()) {
        if (cancel != null && cancel.isCanceled()) {
            Slog.w(TAG, "authentication already canceled");
            return;
            } else {
                cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto));
            }
        }

        if (mService != null) {
@@ -223,17 +219,18 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
                mCryptoObject = crypto;
                final long operationId = crypto != null ? crypto.getOpId() : 0;
                Trace.beginSection("FaceManager#authenticate");
                mService.authenticate(mToken, operationId, userId, mServiceReceiver,
                        mContext.getOpPackageName(), isKeyguardBypassEnabled);
                final long authId = mService.authenticate(mToken, operationId, userId,
                        mServiceReceiver, mContext.getOpPackageName(), isKeyguardBypassEnabled);
                if (cancel != null) {
                    cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId));
                }
            } catch (RemoteException e) {
                Slog.w(TAG, "Remote exception while authenticating: ", e);
                if (callback != null) {
                // Though this may not be a hardware issue, it will cause apps to give up or
                // try again later.
                callback.onAuthenticationError(FACE_ERROR_HW_UNAVAILABLE,
                        getErrorString(mContext, FACE_ERROR_HW_UNAVAILABLE,
                                0 /* vendorCode */));
                }
            } finally {
                Trace.endSection();
            }
@@ -255,14 +252,14 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
        if (cancel.isCanceled()) {
            Slog.w(TAG, "Detection already cancelled");
            return;
        } else {
            cancel.setOnCancelListener(new OnFaceDetectionCancelListener());
        }

        mFaceDetectionCallback = callback;

        try {
            mService.detectFace(mToken, userId, mServiceReceiver, mContext.getOpPackageName());
            final long authId = mService.detectFace(
                    mToken, userId, mServiceReceiver, mContext.getOpPackageName());
            cancel.setOnCancelListener(new OnFaceDetectionCancelListener(authId));
        } catch (RemoteException e) {
            Slog.w(TAG, "Remote exception when requesting finger detect", e);
        }
@@ -726,23 +723,23 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
        }
    }

    private void cancelAuthentication(CryptoObject cryptoObject) {
    private void cancelAuthentication(long requestId) {
        if (mService != null) {
            try {
                mService.cancelAuthentication(mToken, mContext.getOpPackageName());
                mService.cancelAuthentication(mToken, mContext.getOpPackageName(), requestId);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }

    private void cancelFaceDetect() {
    private void cancelFaceDetect(long requestId) {
        if (mService == null) {
            return;
        }

        try {
            mService.cancelFaceDetect(mToken, mContext.getOpPackageName());
            mService.cancelFaceDetect(mToken, mContext.getOpPackageName(), requestId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -1110,22 +1107,30 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
    }

    private class OnAuthenticationCancelListener implements OnCancelListener {
        private final CryptoObject mCrypto;
        private final long mAuthRequestId;

        OnAuthenticationCancelListener(CryptoObject crypto) {
            mCrypto = crypto;
        OnAuthenticationCancelListener(long id) {
            mAuthRequestId = id;
        }

        @Override
        public void onCancel() {
            cancelAuthentication(mCrypto);
            Slog.d(TAG, "Cancel face authentication requested for: " + mAuthRequestId);
            cancelAuthentication(mAuthRequestId);
        }
    }

    private class OnFaceDetectionCancelListener implements OnCancelListener {
        private final long mAuthRequestId;

        OnFaceDetectionCancelListener(long id) {
            mAuthRequestId = id;
        }

        @Override
        public void onCancel() {
            cancelFaceDetect();
            Slog.d(TAG, "Cancel face detect requested for: " + mAuthRequestId);
            cancelFaceDetect(mAuthRequestId);
        }
    }

Loading