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

Commit 5a90a653 authored by Kevin Chyn's avatar Kevin Chyn
Browse files

Handle cancellation properly for setDeviceCredentialAllowed(true)

Keep the current auth session until ConfirmDeviceCredential succeeds
or fails. ConfirmDeviceCredential's BP and LSKF screens can be canceled
now.

Bug: 123378871
Bug: 128747871

Test: With modified BiometricPromptDemo, ConfirmDeviceCredential's
      BiometricPrompt and LSKF screens can be canceled

Change-Id: Icaf3f0c55b07fd138a2ee9d214941ea83408f0ee
parent dd07ae57
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -161,6 +161,7 @@ java_defaults {
        ":libcamera_client_framework_aidl",
        "core/java/android/hardware/IConsumerIrService.aidl",
        "core/java/android/hardware/ISerialManager.aidl",
        "core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl",
        "core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl",
        "core/java/android/hardware/biometrics/IBiometricService.aidl",
        "core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl",
+17 −0
Original line number Diff line number Diff line
@@ -207,5 +207,22 @@ public class BiometricManager {
            Slog.w(TAG, "onConfirmDeviceCredentialError(): Service not connected");
        }
    }

    /**
     * TODO(b/123378871): Remove when moved.
     * @hide
     */
    @RequiresPermission(USE_BIOMETRIC_INTERNAL)
    public void registerCancellationCallback(IBiometricConfirmDeviceCredentialCallback callback) {
        if (mService != null) {
            try {
                mService.registerCancellationCallback(callback);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } else {
            Slog.w(TAG, "registerCancellationCallback(): Service not connected");
        }
    }
}
+27 −6
Original line number Diff line number Diff line
@@ -82,6 +82,11 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
     * @hide
     */
    public static final String KEY_ALLOW_DEVICE_CREDENTIAL = "allow_device_credential";
    /**
     * @hide
     */
    public static final String KEY_FROM_CONFIRM_DEVICE_CREDENTIAL
            = "from_confirm_device_credential";

    /**
     * Error/help message will show for this amount of time.
@@ -270,6 +275,17 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
            return this;
        }

        /**
         * TODO(123378871): Remove when moved.
         * @return
         * @hide
         */
        @RequiresPermission(USE_BIOMETRIC_INTERNAL)
        @NonNull public Builder setFromConfirmDeviceCredential() {
            mBundle.putBoolean(KEY_FROM_CONFIRM_DEVICE_CREDENTIAL, true);
            return this;
        }

        /**
         * Creates a {@link BiometricPrompt}.
         * @return a {@link BiometricPrompt}
@@ -494,7 +510,8 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
    public void authenticateUser(@NonNull CancellationSignal cancel,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull AuthenticationCallback callback,
            int userId) {
            int userId,
            IBiometricConfirmDeviceCredentialCallback confirmDeviceCredentialCallback) {
        if (cancel == null) {
            throw new IllegalArgumentException("Must supply a cancellation signal");
        }
@@ -504,7 +521,8 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
        if (callback == null) {
            throw new IllegalArgumentException("Must supply a callback");
        }
        authenticateInternal(null /* crypto */, cancel, executor, callback, userId);
        authenticateInternal(null /* crypto */, cancel, executor, callback, userId,
                confirmDeviceCredentialCallback);
    }

    /**
@@ -555,7 +573,8 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
        if (mBundle.getBoolean(KEY_ALLOW_DEVICE_CREDENTIAL)) {
            throw new IllegalArgumentException("Device credential not supported with crypto");
        }
        authenticateInternal(crypto, cancel, executor, callback, mContext.getUserId());
        authenticateInternal(crypto, cancel, executor, callback, mContext.getUserId(),
                null /* confirmDeviceCredentialCallback */);
    }

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

    private void cancelAuthentication() {
@@ -614,7 +634,8 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
            @NonNull CancellationSignal cancel,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull AuthenticationCallback callback,
            int userId) {
            int userId,
            IBiometricConfirmDeviceCredentialCallback confirmDeviceCredentialCallback) {
        try {
            if (cancel.isCanceled()) {
                Log.w(TAG, "Authentication already canceled");
@@ -629,7 +650,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
            final long sessionId = crypto != null ? crypto.getOpId() : 0;
            if (BiometricManager.hasBiometrics(mContext)) {
                mService.authenticate(mToken, sessionId, userId, mBiometricServiceReceiver,
                        mContext.getOpPackageName(), mBundle);
                        mContext.getOpPackageName(), mBundle, confirmDeviceCredentialCallback);
            } else {
                mExecutor.execute(() -> {
                    callback.onAuthenticationError(BiometricPrompt.BIOMETRIC_ERROR_HW_NOT_PRESENT,
+26 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.hardware.biometrics;

/**
 * Communication channel between ConfirmDeviceCredential / ConfirmLock* and BiometricService.
 * @hide
 */
interface IBiometricConfirmDeviceCredentialCallback {
    // Invoked when authentication should be canceled.
    oneway void cancel();
}
 No newline at end of file
+8 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.hardware.biometrics;

import android.os.Bundle;
import android.hardware.biometrics.IBiometricConfirmDeviceCredentialCallback;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
import android.hardware.biometrics.IBiometricServiceReceiver;

@@ -30,8 +31,10 @@ import android.hardware.biometrics.IBiometricServiceReceiver;
interface IBiometricService {
    // Requests authentication. The service choose the appropriate biometric to use, and show
    // the corresponding BiometricDialog.
    // TODO(b/123378871): Remove callback when moved.
    void authenticate(IBinder token, long sessionId, int userId,
            IBiometricServiceReceiver receiver, String opPackageName, in Bundle bundle);
            IBiometricServiceReceiver receiver, String opPackageName, in Bundle bundle,
            IBiometricConfirmDeviceCredentialCallback callback);

    // Cancel authentication for the given sessionId
    void cancelAuthentication(IBinder token, String opPackageName);
@@ -59,4 +62,8 @@ interface IBiometricService {
    void onConfirmDeviceCredentialSuccess();
    // TODO(b/123378871): Remove when moved.
    void onConfirmDeviceCredentialError(int error, String message);
    // TODO(b/123378871): Remove when moved.
    // When ConfirmLock* is invoked from BiometricPrompt, it needs to register a callback so that
    // it can receive the cancellation signal.
    void registerCancellationCallback(IBiometricConfirmDeviceCredentialCallback callback);
}
Loading