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

Commit 067085a1 authored by Kevin Chyn's avatar Kevin Chyn
Browse files

Add protected method to authenticate using BP for a specific user

This is analogous to one of the FingerprintManager internal APIs. A
signature permission is required if a user wants to authenticate
using a different userId

Bug: 119296586

Test: BiometricPromptDemo still works for primary and work profile

Change-Id: I16383a588833ccf673d62ed1fc580c412beb4929
parent d60f2b04
Loading
Loading
Loading
Loading
+30 −4
Original line number Diff line number Diff line
@@ -425,6 +425,31 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
        public void onAuthenticationAcquired(int acquireInfo) {}
    }

    /**
     * Authenticates for the given user.
     * @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
     * @hide
     */
    @RequiresPermission(USE_BIOMETRIC_INTERNAL)
    public void authenticateUser(@NonNull CancellationSignal cancel,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull AuthenticationCallback callback,
            int userId) {
        if (cancel == null) {
            throw new IllegalArgumentException("Must supply a cancellation signal");
        }
        if (executor == null) {
            throw new IllegalArgumentException("Must supply an executor");
        }
        if (callback == null) {
            throw new IllegalArgumentException("Must supply a callback");
        }
        authenticateInternal(null /* crypto */, cancel, executor, callback, userId);
    }

    /**
     * This call warms up the biometric hardware, displays a system-provided dialog, and starts
     * scanning for a biometric. It terminates when {@link
@@ -465,7 +490,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
        if (callback == null) {
            throw new IllegalArgumentException("Must supply a callback");
        }
        authenticateInternal(crypto, cancel, executor, callback);
        authenticateInternal(crypto, cancel, executor, callback, mContext.getUserId());
    }

    /**
@@ -502,7 +527,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
        if (callback == null) {
            throw new IllegalArgumentException("Must supply a callback");
        }
        authenticateInternal(null /* crypto */, cancel, executor, callback);
        authenticateInternal(null /* crypto */, cancel, executor, callback, mContext.getUserId());
    }

    private void cancelAuthentication() {
@@ -518,7 +543,8 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
    private void authenticateInternal(@Nullable CryptoObject crypto,
            @NonNull CancellationSignal cancel,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull AuthenticationCallback callback) {
            @NonNull AuthenticationCallback callback,
            int userId) {
        try {
            if (cancel.isCanceled()) {
                Log.w(TAG, "Authentication already canceled");
@@ -531,7 +557,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
            mExecutor = executor;
            mAuthenticationCallback = callback;
            final long sessionId = crypto != null ? crypto.getOpId() : 0;
            mService.authenticate(mToken, sessionId, mContext.getUserId(),
            mService.authenticate(mToken, sessionId, userId,
                    mBiometricServiceReceiver, 0 /* flags */, mContext.getOpPackageName(),
                    mBundle, mDialogReceiver);
        } catch (RemoteException e) {
+14 −7
Original line number Diff line number Diff line
@@ -246,9 +246,20 @@ public class BiometricService extends SystemService {
        public void authenticate(IBinder token, long sessionId, int userId,
                IBiometricServiceReceiver receiver, int flags, String opPackageName,
                Bundle bundle, IBiometricPromptReceiver dialogReceiver) throws RemoteException {
            // Check the USE_BIOMETRIC permission here. In the BiometricServiceBase, check do the
            // AppOps and foreground check.
            final int callingUid = Binder.getCallingUid();
            final int callingPid = Binder.getCallingPid();
            final int callingUserId = UserHandle.getCallingUserId();

            // In the BiometricServiceBase, check do the AppOps and foreground check.
            if (userId == callingUserId) {
                // Check the USE_BIOMETRIC permission here.
                checkPermission();
            } else {
                // Only allow internal clients to authenticate with a different userId
                Slog.w(TAG, "User " + callingUserId + " is requesting authentication of userid: "
                        + userId);
                checkInternalPermission();
            }

            if (token == null || receiver == null || opPackageName == null || bundle == null
                    || dialogReceiver == null) {
@@ -262,10 +273,6 @@ public class BiometricService extends SystemService {
                checkInternalPermission();
            }

            final int callingUid = Binder.getCallingUid();
            final int callingPid = Binder.getCallingPid();
            final int callingUserId = UserHandle.getCallingUserId();

            mHandler.post(() -> {
                final Pair<Integer, Integer> result = checkAndGetBiometricModality(callingUserId);
                final int modality = result.first;