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

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

Merge changes from topic "biometric-linktodeath"

* changes:
  linkToDeath on BiometricPrompt#authenticate
  Fix onError arguments
parents f0057909 c873188f
Loading
Loading
Loading
Loading
+57 −4
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ import java.util.Random;
 * {@link android.hardware.biometrics.BiometricPrompt}, as well as all of the necessary
 * state information for such a session.
 */
final class AuthSession {
final class AuthSession implements IBinder.DeathRecipient {
    private static final String TAG = "BiometricService/AuthSession";

    /**
@@ -93,6 +93,12 @@ final class AuthSession {
     * Device credential in AuthController is showing
     */
    static final int STATE_SHOWING_DEVICE_CREDENTIAL = 8;
    /**
     * The client binder died, and sensors were authenticating at the time. Cancel has been
     * requested and we're waiting for the HAL(s) to send ERROR_CANCELED.
     */
    static final int STATE_CLIENT_DIED_CANCELLING = 9;

    @IntDef({
            STATE_AUTH_IDLE,
            STATE_AUTH_CALLED,
@@ -106,10 +112,20 @@ final class AuthSession {
    @Retention(RetentionPolicy.SOURCE)
    @interface SessionState {}

    /**
     * Notify the holder of the AuthSession that the caller/client's binder has died. The
     * holder (BiometricService) should schedule {@link AuthSession#onClientDied()} to be run
     * on its handler (instead of whatever thread invokes the death recipient callback).
     */
    interface ClientDeathReceiver {
        void onClientDied();
    }

    private final IStatusBarService mStatusBarService;
    private final IBiometricSysuiReceiver mSysuiReceiver;
    private final KeyStore mKeyStore;
    private final Random mRandom;
    private final ClientDeathReceiver mClientDeathReceiver;
    final PreAuthInfo mPreAuthInfo;

    // The following variables are passed to authenticateInternal, which initiates the
@@ -143,14 +159,16 @@ final class AuthSession {
    private long mAuthenticatedTimeMs;

    AuthSession(IStatusBarService statusBarService, IBiometricSysuiReceiver sysuiReceiver,
            KeyStore keystore, Random random, PreAuthInfo preAuthInfo,
            IBinder token, long operationId, int userId, IBiometricSensorReceiver sensorReceiver,
            IBiometricServiceReceiver clientReceiver, String opPackageName, PromptInfo promptInfo,
            KeyStore keystore, Random random, ClientDeathReceiver clientDeathReceiver,
            PreAuthInfo preAuthInfo, IBinder token, long operationId, int userId,
            IBiometricSensorReceiver sensorReceiver, IBiometricServiceReceiver clientReceiver,
            String opPackageName, PromptInfo promptInfo,
            int callingUid, int callingPid, int callingUserId, boolean debugEnabled) {
        mStatusBarService = statusBarService;
        mSysuiReceiver = sysuiReceiver;
        mKeyStore = keystore;
        mRandom = random;
        mClientDeathReceiver = clientDeathReceiver;
        mPreAuthInfo = preAuthInfo;
        mToken = token;
        mOperationId = operationId;
@@ -164,9 +182,21 @@ final class AuthSession {
        mCallingUserId = callingUserId;
        mDebugEnabled = debugEnabled;

        try {
            mClientReceiver.asBinder().linkToDeath(this, 0 /* flags */);
        } catch (RemoteException e) {
            Slog.w(TAG, "Unable to link to death");
        }

        setSensorsToStateUnknown();
    }

    @Override
    public void binderDied() {
        Slog.e(TAG, "Binder died, session: " + this);
        mClientDeathReceiver.onClientDied();
    }

    /**
     * @return bitmask representing the modalities that are running or could be running for the
     * current session.
@@ -379,6 +409,10 @@ final class AuthSession {
                Slog.d(TAG, "Biometric canceled, ignoring from state: " + mState);
                break;

            case STATE_CLIENT_DIED_CANCELLING:
                mStatusBarService.hideAuthenticationDialog();
                return true;

            default:
                Slog.e(TAG, "Unhandled error state, mState: " + mState);
                break;
@@ -486,6 +520,25 @@ final class AuthSession {
        mState = STATE_SHOWING_DEVICE_CREDENTIAL;
    }

    /**
     * @return true if this session is finished and should be set to null.
     */
    boolean onClientDied() {
        try {
            if (mState == STATE_AUTH_STARTED) {
                mState = STATE_CLIENT_DIED_CANCELLING;
                cancelAllSensors();
                return false;
            } else {
                mStatusBarService.hideAuthenticationDialog();
                return true;
            }
        } catch (RemoteException e) {
            Slog.e(TAG, "Remote Exception: " + e);
            return true;
        }
    }

    private void logOnDialogDismissed(@BiometricPrompt.DismissedReason int reason) {
        if (reason == BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED) {
            // Explicit auth, authentication confirmed.
+2 −5
Original line number Diff line number Diff line
@@ -93,11 +93,8 @@ public abstract class AuthenticationClient extends ClientMonitor {

    @Override
    public void binderDied() {
        super.binderDied();
        // When the binder dies, we should stop the client. This probably belongs in
        // ClientMonitor's binderDied(), but testing all the cases would be tricky.
        // AuthenticationClient is the most user-visible case.
        stop(false /* initiatedByClient */);
        final boolean clearListener = !isBiometricPrompt();
        binderDiedInternal(clearListener);
    }

    @Override
+27 −5
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ public class BiometricService extends SystemService {
    private static final int MSG_ON_AUTHENTICATION_TIMED_OUT = 11;
    private static final int MSG_ON_DEVICE_CREDENTIAL_PRESSED = 12;
    private static final int MSG_ON_SYSTEM_EVENT = 13;
    private static final int MSG_CLIENT_DIED = 14;

    private final Injector mInjector;
    private final DevicePolicyManager mDevicePolicyManager;
@@ -215,6 +216,11 @@ public class BiometricService extends SystemService {
                    break;
                }

                case MSG_CLIENT_DIED: {
                    handleClientDied();
                    break;
                }

                default:
                    Slog.e(TAG, "Unknown message: " + msg);
                    break;
@@ -447,11 +453,13 @@ public class BiometricService extends SystemService {
        }
    };

    private final AuthSession.ClientDeathReceiver mClientDeathReceiver = () -> {
        mHandler.sendEmptyMessage(MSG_CLIENT_DIED);
    };

    /**
     * This is just a pass-through service that wraps Fingerprint, Iris, Face services. This service
     * should not carry any state. The reality is we need to keep a tiny amount of state so that
     * cancelAuthentication() can go to the right place.
     * Implementation of the BiometricPrompt/BiometricManager APIs. Handles client requests,
     * sensor arbitration, threading, etc.
     */
    private final class BiometricServiceWrapper extends IBiometricService.Stub {
        @Override // Binder call
@@ -962,6 +970,19 @@ public class BiometricService extends SystemService {
        mCurrentAuthSession.onSystemEvent(event);
    }

    private void handleClientDied() {
        if (mCurrentAuthSession == null) {
            Slog.e(TAG, "Auth session null");
            return;
        }

        Slog.e(TAG, "Session: " + mCurrentAuthSession);
        final boolean finished = mCurrentAuthSession.onClientDied();
        if (finished) {
            mCurrentAuthSession = null;
        }
    }

    /**
     * Invoked when each service has notified that its client is ready to be started. When
     * all biometrics are ready, this invokes the SystemUI dialog through StatusBar.
@@ -1043,8 +1064,9 @@ public class BiometricService extends SystemService {

        final boolean debugEnabled = mInjector.isDebugEnabled(getContext(), userId);
        mCurrentAuthSession = new AuthSession(mStatusBarService, mSysuiReceiver, mKeyStore, mRandom,
                preAuthInfo, token, operationId, userId, mBiometricSensorReceiver, receiver,
                opPackageName, promptInfo, callingUid, callingPid, callingUserId, debugEnabled);
                mClientDeathReceiver, preAuthInfo, token, operationId, userId,
                mBiometricSensorReceiver, receiver, opPackageName, promptInfo, callingUid,
                callingPid, callingUserId, debugEnabled);
        try {
            mCurrentAuthSession.goToInitialState();
        } catch (RemoteException e) {
+7 −1
Original line number Diff line number Diff line
@@ -231,12 +231,18 @@ public abstract class ClientMonitor extends LoggableMonitor implements IBinder.D

    @Override
    public void binderDied() {
        binderDiedInternal(true /* clearListener */);
    }

    void binderDiedInternal(boolean clearListener) {
        // If the current client dies we should cancel the current operation.
        Slog.e(getLogTag(), "Binder died, cancelling client");
        stop(false /* initiatedByClient */);
        mToken = null;
        if (clearListener) {
            mListener = null;
        }
    }

    @Override
    protected void finalize() throws Throwable {
+1 −1
Original line number Diff line number Diff line
@@ -772,7 +772,7 @@ public class FaceService extends BiometricServiceBase {
        public void onError(int error, int vendorCode, int cookie)
                throws RemoteException {
            if (getWrapperReceiver() != null) {
                getWrapperReceiver().onError(cookie, TYPE_FACE, error, vendorCode);
                getWrapperReceiver().onError(getSensorId(), cookie, error, vendorCode);
            }
        }
    }
Loading