/*
 * Copyright (C) 2018 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 com.android.server.biometrics;

import static android.Manifest.permission.USE_BIOMETRIC;
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
import static android.Manifest.permission.USE_FINGERPRINT;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_IRIS;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE;
import static android.hardware.biometrics.BiometricManager.Authenticators;

import android.app.ActivityManager;
import android.app.IActivityManager;
import android.app.UserSwitchObserver;
import android.app.admin.DevicePolicyManager;
import android.app.trust.ITrustManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricSourceType;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.IBiometricAuthenticator;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
import android.hardware.biometrics.IBiometricService;
import android.hardware.biometrics.IBiometricServiceReceiver;
import android.hardware.biometrics.IBiometricServiceReceiverInternal;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.DeadObjectException;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.security.KeyStore;
import android.text.TextUtils;
import android.util.Pair;
import android.util.Slog;
import android.util.StatsLog;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
import com.android.internal.statusbar.IStatusBarService;
import com.android.server.SystemService;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * System service that arbitrates the modality for BiometricPrompt to use.
 */
public class BiometricService extends SystemService {

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

    private static final int MSG_ON_AUTHENTICATION_SUCCEEDED = 2;
    private static final int MSG_ON_AUTHENTICATION_REJECTED = 3;
    private static final int MSG_ON_ERROR = 4;
    private static final int MSG_ON_ACQUIRED = 5;
    private static final int MSG_ON_DISMISSED = 6;
    private static final int MSG_ON_TRY_AGAIN_PRESSED = 7;
    private static final int MSG_ON_READY_FOR_AUTHENTICATION = 8;
    private static final int MSG_AUTHENTICATE = 9;
    private static final int MSG_CANCEL_AUTHENTICATION = 10;
    private static final int MSG_ON_AUTHENTICATION_TIMED_OUT = 11;
    private static final int MSG_ON_DEVICE_CREDENTIAL_PRESSED = 12;

    /**
     * Authentication either just called and we have not transitioned to the CALLED state, or
     * authentication terminated (success or error).
     */
    static final int STATE_AUTH_IDLE = 0;
    /**
     * Authentication was called and we are waiting for the <Biometric>Services to return their
     * cookies before starting the hardware and showing the BiometricPrompt.
     */
    static final int STATE_AUTH_CALLED = 1;
    /**
     * Authentication started, BiometricPrompt is showing and the hardware is authenticating.
     */
    static final int STATE_AUTH_STARTED = 2;
    /**
     * Authentication is paused, waiting for the user to press "try again" button. Only
     * passive modalities such as Face or Iris should have this state. Note that for passive
     * modalities, the HAL enters the idle state after onAuthenticated(false) which differs from
     * fingerprint.
     */
    static final int STATE_AUTH_PAUSED = 3;
    /**
     * Authentication is successful, but we're waiting for the user to press "confirm" button.
     */
    static final int STATE_AUTH_PENDING_CONFIRM = 5;
    /**
     * Biometric authenticated, waiting for SysUI to finish animation
     */
    static final int STATE_AUTHENTICATED_PENDING_SYSUI = 6;
    /**
     * Biometric error, waiting for SysUI to finish animation
     */
    static final int STATE_ERROR_PENDING_SYSUI = 7;
    /**
     * Device credential in AuthController is showing
     */
    static final int STATE_SHOWING_DEVICE_CREDENTIAL = 8;

    final class AuthSession {
        // Map of Authenticator/Cookie pairs. We expect to receive the cookies back from
        // <Biometric>Services before we can start authenticating. Pairs that have been returned
        // are moved to mModalitiesMatched.
        final HashMap<Integer, Integer> mModalitiesWaiting;
        // Pairs that have been matched.
        final HashMap<Integer, Integer> mModalitiesMatched = new HashMap<>();

        // The following variables are passed to authenticateInternal, which initiates the
        // appropriate <Biometric>Services.
        final IBinder mToken;
        final long mSessionId;
        final int mUserId;
        // Original receiver from BiometricPrompt.
        final IBiometricServiceReceiver mClientReceiver;
        final String mOpPackageName;
        // Info to be shown on BiometricDialog when all cookies are returned.
        final Bundle mBundle;
        final int mCallingUid;
        final int mCallingPid;
        final int mCallingUserId;
        // Continue authentication with the same modality/modalities after "try again" is
        // pressed
        final int mModality;
        final boolean mRequireConfirmation;

        // The current state, which can be either idle, called, or started
        int mState = STATE_AUTH_IDLE;
        // For explicit confirmation, do not send to keystore until the user has confirmed
        // the authentication.
        byte[] mTokenEscrow;
        // Waiting for SystemUI to complete animation
        int mErrorEscrow;
        int mVendorCodeEscrow;

        // Timestamp when authentication started
        private long mStartTimeMs;
        // Timestamp when hardware authentication occurred
        private long mAuthenticatedTimeMs;

        AuthSession(HashMap<Integer, Integer> modalities, IBinder token, long sessionId,
                int userId, IBiometricServiceReceiver receiver, String opPackageName,
                Bundle bundle, int callingUid, int callingPid, int callingUserId,
                int modality, boolean requireConfirmation) {
            mModalitiesWaiting = modalities;
            mToken = token;
            mSessionId = sessionId;
            mUserId = userId;
            mClientReceiver = receiver;
            mOpPackageName = opPackageName;
            mBundle = bundle;
            mCallingUid = callingUid;
            mCallingPid = callingPid;
            mCallingUserId = callingUserId;
            mModality = modality;
            mRequireConfirmation = requireConfirmation;
        }

        boolean isCrypto() {
            return mSessionId != 0;
        }

        boolean containsCookie(int cookie) {
            if (mModalitiesWaiting != null && mModalitiesWaiting.containsValue(cookie)) {
                return true;
            }
            if (mModalitiesMatched != null && mModalitiesMatched.containsValue(cookie)) {
                return true;
            }
            return false;
        }

        boolean isAllowDeviceCredential() {
            return Utils.isDeviceCredentialAllowed(mBundle);
        }
    }

    private final Injector mInjector;
    private final DevicePolicyManager mDevicePolicyManager;
    @VisibleForTesting
    final IBiometricService.Stub mImpl;
    @VisibleForTesting
    final SettingObserver mSettingObserver;
    private final List<EnabledOnKeyguardCallback> mEnabledOnKeyguardCallbacks;
    private final Random mRandom = new Random();

    @VisibleForTesting
    IStatusBarService mStatusBarService;
    @VisibleForTesting
    KeyStore mKeyStore;
    @VisibleForTesting
    ITrustManager mTrustManager;

    // Get and cache the available authenticator (manager) classes. Used since aidl doesn't support
    // polymorphism :/
    final ArrayList<AuthenticatorWrapper> mAuthenticators = new ArrayList<>();

    BiometricStrengthController mBiometricStrengthController;

    // The current authentication session, null if idle/done. We need to track both the current
    // and pending sessions since errors may be sent to either.
    @VisibleForTesting
    AuthSession mCurrentAuthSession;
    @VisibleForTesting
    AuthSession mPendingAuthSession;

    @VisibleForTesting
    final Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_ON_AUTHENTICATION_SUCCEEDED: {
                    SomeArgs args = (SomeArgs) msg.obj;
                    handleAuthenticationSucceeded(
                            (boolean) args.arg1 /* requireConfirmation */,
                            (byte[]) args.arg2 /* token */);
                    args.recycle();
                    break;
                }

                case MSG_ON_AUTHENTICATION_REJECTED: {
                    handleAuthenticationRejected();
                    break;
                }

                case MSG_ON_ERROR: {
                    SomeArgs args = (SomeArgs) msg.obj;
                    handleOnError(
                            args.argi1 /* cookie */,
                            args.argi2 /* modality */,
                            args.argi3 /* error */,
                            args.argi4 /* vendorCode */);
                    args.recycle();
                    break;
                }

                case MSG_ON_ACQUIRED: {
                    SomeArgs args = (SomeArgs) msg.obj;
                    handleOnAcquired(
                            args.argi1 /* acquiredInfo */,
                            (String) args.arg1 /* message */);
                    args.recycle();
                    break;
                }

                case MSG_ON_DISMISSED: {
                    handleOnDismissed(msg.arg1);
                    break;
                }

                case MSG_ON_TRY_AGAIN_PRESSED: {
                    handleOnTryAgainPressed();
                    break;
                }

                case MSG_ON_READY_FOR_AUTHENTICATION: {
                    SomeArgs args = (SomeArgs) msg.obj;
                    handleOnReadyForAuthentication(
                            args.argi1 /* cookie */,
                            (boolean) args.arg1 /* requireConfirmation */,
                            args.argi2 /* userId */);
                    args.recycle();
                    break;
                }

                case MSG_AUTHENTICATE: {
                    SomeArgs args = (SomeArgs) msg.obj;
                    handleAuthenticate(
                            (IBinder) args.arg1 /* token */,
                            (long) args.arg2 /* sessionId */,
                            args.argi1 /* userid */,
                            (IBiometricServiceReceiver) args.arg3 /* receiver */,
                            (String) args.arg4 /* opPackageName */,
                            (Bundle) args.arg5 /* bundle */,
                            args.argi2 /* callingUid */,
                            args.argi3 /* callingPid */,
                            args.argi4 /* callingUserId */);
                    args.recycle();
                    break;
                }

                case MSG_CANCEL_AUTHENTICATION: {
                    SomeArgs args = (SomeArgs) msg.obj;
                    handleCancelAuthentication(
                            (IBinder) args.arg1 /* token */,
                            (String) args.arg2 /* opPackageName */);
                    args.recycle();
                    break;
                }

                case MSG_ON_AUTHENTICATION_TIMED_OUT: {
                    SomeArgs args = (SomeArgs) msg.obj;
                    handleAuthenticationTimedOut(
                            args.argi1 /* modality */,
                            args.argi2 /* error */,
                            args.argi3 /* vendorCode */);
                    args.recycle();
                    break;
                }

                case MSG_ON_DEVICE_CREDENTIAL_PRESSED: {
                    handleOnDeviceCredentialPressed();
                    break;
                }

                default:
                    Slog.e(TAG, "Unknown message: " + msg);
                    break;
            }
        }
    };

    /**
     * Wraps IBiometricAuthenticator implementation and stores information about the authenticator.
     * TODO(b/141025588): Consider refactoring the tests to not rely on this implementation detail.
     */
    @VisibleForTesting
    public static final class AuthenticatorWrapper {
        public final int id;
        public final int OEMStrength; // strength as configured by the OEM
        private int updatedStrength; // strength updated by BiometricStrengthController
        public final int modality;
        public final IBiometricAuthenticator impl;

        AuthenticatorWrapper(int id, int modality, int strength,
                IBiometricAuthenticator impl) {
            this.id = id;
            this.modality = modality;
            this.OEMStrength = strength;
            this.updatedStrength = strength;
            this.impl = impl;
        }

        /**
         * Returns the actual strength, taking any updated strengths into effect. Since more bits
         * means lower strength, the resulting strength is never stronger than the OEM's configured
         * strength.
         * @return a bitfield, see {@link Authenticators}
         */
        public int getActualStrength() {
            return OEMStrength | updatedStrength;
        }

        /**
         * Stores the updated strength, which takes effect whenever {@link #getActualStrength()}
         * is checked.
         * @param newStrength
         */
        public void updateStrength(int newStrength) {
            String log = "updateStrength: Before(" + toString() + ")";
            updatedStrength = newStrength;
            log += " After(" + toString() + ")";
            Slog.d(TAG, log);
        }

        @Override
        public String toString() {
            return "ID(" + id + ")"
                    + " OEMStrength: " + OEMStrength
                    + " updatedStrength: " + updatedStrength
                    + " modality " + modality
                    + " authenticator: " + impl;
        }
    }

    @VisibleForTesting
    public static class SettingObserver extends ContentObserver {

        private static final boolean DEFAULT_KEYGUARD_ENABLED = true;
        private static final boolean DEFAULT_APP_ENABLED = true;
        private static final boolean DEFAULT_ALWAYS_REQUIRE_CONFIRMATION = false;

        private final Uri FACE_UNLOCK_KEYGUARD_ENABLED =
                Settings.Secure.getUriFor(Settings.Secure.FACE_UNLOCK_KEYGUARD_ENABLED);
        private final Uri FACE_UNLOCK_APP_ENABLED =
                Settings.Secure.getUriFor(Settings.Secure.FACE_UNLOCK_APP_ENABLED);
        private final Uri FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION =
                Settings.Secure.getUriFor(Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION);

        private final ContentResolver mContentResolver;
        private final List<BiometricService.EnabledOnKeyguardCallback> mCallbacks;

        private final Map<Integer, Boolean> mFaceEnabledOnKeyguard = new HashMap<>();
        private final Map<Integer, Boolean> mFaceEnabledForApps = new HashMap<>();
        private final Map<Integer, Boolean> mFaceAlwaysRequireConfirmation = new HashMap<>();

        /**
         * Creates a content observer.
         *
         * @param handler The handler to run {@link #onChange} on, or null if none.
         */
        public SettingObserver(Context context, Handler handler,
                List<BiometricService.EnabledOnKeyguardCallback> callbacks) {
            super(handler);
            mContentResolver = context.getContentResolver();
            mCallbacks = callbacks;
            updateContentObserver();
        }

        public void updateContentObserver() {
            mContentResolver.unregisterContentObserver(this);
            mContentResolver.registerContentObserver(FACE_UNLOCK_KEYGUARD_ENABLED,
                    false /* notifyForDescendents */,
                    this /* observer */,
                    UserHandle.USER_ALL);
            mContentResolver.registerContentObserver(FACE_UNLOCK_APP_ENABLED,
                    false /* notifyForDescendents */,
                    this /* observer */,
                    UserHandle.USER_ALL);
            mContentResolver.registerContentObserver(FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
                    false /* notifyForDescendents */,
                    this /* observer */,
                    UserHandle.USER_ALL);
        }

        @Override
        public void onChange(boolean selfChange, Uri uri, int userId) {
            if (FACE_UNLOCK_KEYGUARD_ENABLED.equals(uri)) {
                mFaceEnabledOnKeyguard.put(userId, Settings.Secure.getIntForUser(
                                mContentResolver,
                                Settings.Secure.FACE_UNLOCK_KEYGUARD_ENABLED,
                                DEFAULT_KEYGUARD_ENABLED ? 1 : 0 /* default */,
                                userId) != 0);

                if (userId == ActivityManager.getCurrentUser() && !selfChange) {
                    notifyEnabledOnKeyguardCallbacks(userId);
                }
            } else if (FACE_UNLOCK_APP_ENABLED.equals(uri)) {
                mFaceEnabledForApps.put(userId, Settings.Secure.getIntForUser(
                                mContentResolver,
                                Settings.Secure.FACE_UNLOCK_APP_ENABLED,
                                DEFAULT_APP_ENABLED ? 1 : 0 /* default */,
                                userId) != 0);
            } else if (FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION.equals(uri)) {
                mFaceAlwaysRequireConfirmation.put(userId, Settings.Secure.getIntForUser(
                                mContentResolver,
                                Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
                                DEFAULT_ALWAYS_REQUIRE_CONFIRMATION ? 1 : 0 /* default */,
                                userId) != 0);
            }
        }

        public boolean getFaceEnabledOnKeyguard() {
            final int user = ActivityManager.getCurrentUser();
            if (!mFaceEnabledOnKeyguard.containsKey(user)) {
                onChange(true /* selfChange */, FACE_UNLOCK_KEYGUARD_ENABLED, user);
            }
            return mFaceEnabledOnKeyguard.get(user);
        }

        public boolean getFaceEnabledForApps(int userId) {
            if (!mFaceEnabledForApps.containsKey(userId)) {
                onChange(true /* selfChange */, FACE_UNLOCK_APP_ENABLED, userId);
            }
            return mFaceEnabledForApps.getOrDefault(userId, DEFAULT_APP_ENABLED);
        }

        public boolean getFaceAlwaysRequireConfirmation(int userId) {
            if (!mFaceAlwaysRequireConfirmation.containsKey(userId)) {
                onChange(true /* selfChange */, FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, userId);
            }
            return mFaceAlwaysRequireConfirmation.get(userId);
        }

        public void notifyEnabledOnKeyguardCallbacks(int userId) {
            List<EnabledOnKeyguardCallback> callbacks = mCallbacks;
            for (int i = 0; i < callbacks.size(); i++) {
                callbacks.get(i).notify(BiometricSourceType.FACE,
                        mFaceEnabledOnKeyguard.getOrDefault(userId, DEFAULT_KEYGUARD_ENABLED),
                        userId);
            }
        }
    }

    final class EnabledOnKeyguardCallback implements IBinder.DeathRecipient {

        private final IBiometricEnabledOnKeyguardCallback mCallback;

        EnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback) {
            mCallback = callback;
            try {
                mCallback.asBinder().linkToDeath(EnabledOnKeyguardCallback.this, 0);
            } catch (RemoteException e) {
                Slog.w(TAG, "Unable to linkToDeath", e);
            }
        }

        void notify(BiometricSourceType sourceType, boolean enabled, int userId) {
            try {
                mCallback.onChanged(sourceType, enabled, userId);
            } catch (DeadObjectException e) {
                Slog.w(TAG, "Death while invoking notify", e);
                mEnabledOnKeyguardCallbacks.remove(this);
            } catch (RemoteException e) {
                Slog.w(TAG, "Failed to invoke onChanged", e);
            }
        }

        @Override
        public void binderDied() {
            Slog.e(TAG, "Enabled callback binder died");
            mEnabledOnKeyguardCallbacks.remove(this);
        }
    }

    // Wrap the client's receiver so we can do things with the BiometricDialog first
    @VisibleForTesting
    final IBiometricServiceReceiverInternal mInternalReceiver =
            new IBiometricServiceReceiverInternal.Stub() {
        @Override
        public void onAuthenticationSucceeded(boolean requireConfirmation, byte[] token)
                throws RemoteException {
            SomeArgs args = SomeArgs.obtain();
            args.arg1 = requireConfirmation;
            args.arg2 = token;
            mHandler.obtainMessage(MSG_ON_AUTHENTICATION_SUCCEEDED, args).sendToTarget();
        }

        @Override
        public void onAuthenticationFailed()
                throws RemoteException {
            Slog.v(TAG, "onAuthenticationFailed");
            mHandler.obtainMessage(MSG_ON_AUTHENTICATION_REJECTED).sendToTarget();
        }

        @Override
        public void onError(int cookie, int modality, int error, int vendorCode)
                throws RemoteException {
            // Determine if error is hard or soft error. Certain errors (such as TIMEOUT) are
            // soft errors and we should allow the user to try authenticating again instead of
            // dismissing BiometricPrompt.
            if (error == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT) {
                SomeArgs args = SomeArgs.obtain();
                args.argi1 = modality;
                args.argi2 = error;
                args.argi3 = vendorCode;
                mHandler.obtainMessage(MSG_ON_AUTHENTICATION_TIMED_OUT, args).sendToTarget();
            } else {
                SomeArgs args = SomeArgs.obtain();
                args.argi1 = cookie;
                args.argi2 = modality;
                args.argi3 = error;
                args.argi4 = vendorCode;
                mHandler.obtainMessage(MSG_ON_ERROR, args).sendToTarget();
            }
        }

        @Override
        public void onAcquired(int acquiredInfo, String message) throws RemoteException {
            SomeArgs args = SomeArgs.obtain();
            args.argi1 = acquiredInfo;
            args.arg1 = message;
            mHandler.obtainMessage(MSG_ON_ACQUIRED, args).sendToTarget();
        }

        @Override
        public void onDialogDismissed(int reason) throws RemoteException {
            mHandler.obtainMessage(MSG_ON_DISMISSED, reason, 0 /* arg2 */).sendToTarget();
        }

        @Override
        public void onTryAgainPressed() {
            mHandler.sendEmptyMessage(MSG_ON_TRY_AGAIN_PRESSED);
        }

        @Override
        public void onDeviceCredentialPressed() {
            mHandler.sendEmptyMessage(MSG_ON_DEVICE_CREDENTIAL_PRESSED);
        }
    };


    /**
     * 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.
     */
    private final class BiometricServiceWrapper extends IBiometricService.Stub {
        @Override // Binder call
        public void onReadyForAuthentication(int cookie, boolean requireConfirmation, int userId) {
            checkInternalPermission();

            SomeArgs args = SomeArgs.obtain();
            args.argi1 = cookie;
            args.arg1 = requireConfirmation;
            args.argi2 = userId;
            mHandler.obtainMessage(MSG_ON_READY_FOR_AUTHENTICATION, args).sendToTarget();
        }

        @Override // Binder call
        public void authenticate(IBinder token, long sessionId, int userId,
                IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle)
                throws RemoteException {
            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) {
                Slog.e(TAG, "Unable to authenticate, one or more null arguments");
                return;
            }

            if (!Utils.isValidAuthenticatorConfig(bundle)) {
                throw new SecurityException("Invalid authenticator configuration");
            }

            if (bundle.getBoolean(BiometricPrompt.EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS)) {
                checkInternalPermission();
            }

            Utils.combineAuthenticatorBundles(bundle);

            // Check the usage of this in system server. Need to remove this check if it becomes a
            // public API.
            final boolean useDefaultTitle =
                    bundle.getBoolean(BiometricPrompt.KEY_USE_DEFAULT_TITLE, false);
            if (useDefaultTitle) {
                checkInternalPermission();
                // Set the default title if necessary
                if (TextUtils.isEmpty(bundle.getCharSequence(BiometricPrompt.KEY_TITLE))) {
                    bundle.putCharSequence(BiometricPrompt.KEY_TITLE,
                            getContext().getString(R.string.biometric_dialog_default_title));
                }
            }

            SomeArgs args = SomeArgs.obtain();
            args.arg1 = token;
            args.arg2 = sessionId;
            args.argi1 = userId;
            args.arg3 = receiver;
            args.arg4 = opPackageName;
            args.arg5 = bundle;
            args.argi2 = callingUid;
            args.argi3 = callingPid;
            args.argi4 = callingUserId;

            mHandler.obtainMessage(MSG_AUTHENTICATE, args).sendToTarget();
        }

        @Override // Binder call
        public void cancelAuthentication(IBinder token, String opPackageName)
                throws RemoteException {
            checkPermission();

            SomeArgs args = SomeArgs.obtain();
            args.arg1 = token;
            args.arg2 = opPackageName;
            mHandler.obtainMessage(MSG_CANCEL_AUTHENTICATION, args).sendToTarget();
        }

        @Override // Binder call
        public int canAuthenticate(String opPackageName, int userId,
                @Authenticators.Types int authenticators) {
            Slog.d(TAG, "canAuthenticate: User=" + userId
                    + ", Caller=" + UserHandle.getCallingUserId()
                    + ", Authenticators=" + authenticators);

            if (userId != UserHandle.getCallingUserId()) {
                checkInternalPermission();
            } else {
                checkPermission();
            }


            if (!Utils.isValidAuthenticatorConfig(authenticators)) {
                throw new SecurityException("Invalid authenticator configuration");
            }

            final Bundle bundle = new Bundle();
            bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED, authenticators);

            int biometricConstantsResult = BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE;
            final long ident = Binder.clearCallingIdentity();
            try {
                biometricConstantsResult = checkAndGetAuthenticators(userId, bundle, opPackageName,
                        false /* checkDevicePolicyManager */).second;
                if (biometricConstantsResult != BiometricConstants.BIOMETRIC_SUCCESS
                        && Utils.isDeviceCredentialAllowed(bundle)) {
                    // If there's an issue with biometrics, but device credential is allowed and
                    // set up, return SUCCESS. If device credential isn't set up either, return
                    // ERROR_NO_DEVICE_CREDENTIAL.
                    if (mTrustManager.isDeviceSecure(userId)) {
                        biometricConstantsResult = BiometricConstants.BIOMETRIC_SUCCESS;
                    } else {
                        biometricConstantsResult =
                                BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL;
                    }
                }

            } catch (RemoteException e) {
                Slog.e(TAG, "Remote exception", e);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }

            return Utils.biometricConstantsToBiometricManager(biometricConstantsResult);
        }

        @Override
        public boolean hasEnrolledBiometrics(int userId, String opPackageName) {
            checkInternalPermission();

            final long ident = Binder.clearCallingIdentity();
            try {
                for (AuthenticatorWrapper authenticator : mAuthenticators) {
                    if (authenticator.impl.hasEnrolledTemplates(userId, opPackageName)) {
                        return true;
                    }
                }
            } catch (RemoteException e) {
                Slog.e(TAG, "Remote exception", e);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
            return false;
        }

        @Override
        public void registerAuthenticator(int id, int modality, int strength,
                IBiometricAuthenticator authenticator) {
            checkInternalPermission();

            Slog.d(TAG, "Registering ID: " + id
                    + " Modality: " + modality
                    + " Strength: " + strength);

            if (authenticator == null) {
                throw new IllegalArgumentException("Authenticator must not be null."
                        + " Did you forget to modify the core/res/res/values/xml overlay for"
                        + " config_biometric_sensors?");
            }

            if (strength != Authenticators.BIOMETRIC_STRONG
                    && strength != Authenticators.BIOMETRIC_WEAK) {
                throw new IllegalStateException("Unsupported strength");
            }

            for (AuthenticatorWrapper wrapper : mAuthenticators) {
                if (wrapper.id == id) {
                    throw new IllegalStateException("Cannot register duplicate authenticator");
                }
            }

            // This happens infrequently enough, not worth caching.
            final String[] configs = mInjector.getConfiguration(getContext());
            boolean idFound = false;
            for (int i = 0; i < configs.length; i++) {
                SensorConfig config = new SensorConfig(configs[i]);
                if (config.mId == id) {
                    idFound = true;
                    break;
                }
            }
            if (!idFound) {
                throw new IllegalStateException("Cannot register unknown id");
            }

            mAuthenticators.add(new AuthenticatorWrapper(id, modality, strength, authenticator));
        }

        @Override // Binder call
        public void registerEnabledOnKeyguardCallback(IBiometricEnabledOnKeyguardCallback callback)
                throws RemoteException {
            checkInternalPermission();
            mEnabledOnKeyguardCallbacks.add(new EnabledOnKeyguardCallback(callback));
            try {
                callback.onChanged(BiometricSourceType.FACE,
                        mSettingObserver.getFaceEnabledOnKeyguard(),
                        UserHandle.getCallingUserId());
            } catch (RemoteException e) {
                Slog.w(TAG, "Remote exception", e);
            }
        }

        @Override // Binder call
        public void setActiveUser(int userId) {
            checkInternalPermission();
            final long ident = Binder.clearCallingIdentity();
            try {
                for (AuthenticatorWrapper authenticator : mAuthenticators) {
                    authenticator.impl.setActiveUser(userId);
                }
            } catch (RemoteException e) {
                Slog.e(TAG, "Remote exception", e);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }

        @Override // Binder call
        public void resetLockout(byte[] token) {
            checkInternalPermission();
            final long ident = Binder.clearCallingIdentity();
            try {
                for (AuthenticatorWrapper authenticator : mAuthenticators) {
                    authenticator.impl.resetLockout(token);
                }
            } catch (RemoteException e) {
                Slog.e(TAG, "Remote exception", e);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }
    }

    private void checkInternalPermission() {
        getContext().enforceCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL,
                "Must have USE_BIOMETRIC_INTERNAL permission");
    }

    private void checkPermission() {
        if (getContext().checkCallingOrSelfPermission(USE_FINGERPRINT)
                != PackageManager.PERMISSION_GRANTED) {
            getContext().enforceCallingOrSelfPermission(USE_BIOMETRIC,
                    "Must have USE_BIOMETRIC permission");
        }
    }

    /**
     * Class for injecting dependencies into BiometricService.
     * TODO(b/141025588): Replace with a dependency injection framework (e.g. Guice, Dagger).
     */
    @VisibleForTesting
    public static class Injector {

        @VisibleForTesting
        public IActivityManager getActivityManagerService() {
            return ActivityManager.getService();
        }

        @VisibleForTesting
        public ITrustManager getTrustManager() {
            return ITrustManager.Stub.asInterface(ServiceManager.getService(Context.TRUST_SERVICE));
        }

        @VisibleForTesting
        public IStatusBarService getStatusBarService() {
            return IStatusBarService.Stub.asInterface(
                    ServiceManager.getService(Context.STATUS_BAR_SERVICE));
        }

        /**
         * Allows to mock SettingObserver for testing.
         */
        @VisibleForTesting
        public SettingObserver getSettingObserver(Context context, Handler handler,
                List<EnabledOnKeyguardCallback> callbacks) {
            return new SettingObserver(context, handler, callbacks);
        }

        @VisibleForTesting
        public KeyStore getKeyStore() {
            return KeyStore.getInstance();
        }

        /**
         * Allows to enable/disable debug logs.
         */
        @VisibleForTesting
        public boolean isDebugEnabled(Context context, int userId) {
            return Utils.isDebugEnabled(context, userId);
        }

        /**
         * Allows to stub publishBinderService(...) for testing.
         */
        @VisibleForTesting
        public void publishBinderService(BiometricService service, IBiometricService.Stub impl) {
            service.publishBinderService(Context.BIOMETRIC_SERVICE, impl);
        }

        /**
         * Allows to mock BiometricStrengthController for testing.
         */
        @VisibleForTesting
        public BiometricStrengthController getBiometricStrengthController(
                BiometricService service) {
            return new BiometricStrengthController(service);
        }

        /**
         * Allows to test with various device sensor configurations.
         * @param context System Server context
         * @return the sensor configuration from core/res/res/values/config.xml
         */
        @VisibleForTesting
        public String[] getConfiguration(Context context) {
            return context.getResources().getStringArray(R.array.config_biometric_sensors);
        }
    }

    /**
     * Initializes the system service.
     * <p>
     * Subclasses must define a single argument constructor that accepts the context
     * and passes it to super.
     * </p>
     *
     * @param context The system server context.
     */
    public BiometricService(Context context) {
        this(context, new Injector());
    }

    @VisibleForTesting
    BiometricService(Context context, Injector injector) {
        super(context);

        mInjector = injector;
        mDevicePolicyManager = (DevicePolicyManager) context
                .getSystemService(context.DEVICE_POLICY_SERVICE);
        mImpl = new BiometricServiceWrapper();
        mEnabledOnKeyguardCallbacks = new ArrayList<>();
        mSettingObserver = mInjector.getSettingObserver(context, mHandler,
                mEnabledOnKeyguardCallbacks);

        try {
            injector.getActivityManagerService().registerUserSwitchObserver(
                    new UserSwitchObserver() {
                        @Override
                        public void onUserSwitchComplete(int newUserId) {
                            mSettingObserver.updateContentObserver();
                            mSettingObserver.notifyEnabledOnKeyguardCallbacks(newUserId);
                        }
                    }, BiometricService.class.getName()
            );
        } catch (RemoteException e) {
            Slog.e(TAG, "Failed to register user switch observer", e);
        }
    }

    @Override
    public void onStart() {
        mKeyStore = mInjector.getKeyStore();
        mStatusBarService = mInjector.getStatusBarService();
        mTrustManager = mInjector.getTrustManager();
        mInjector.publishBinderService(this, mImpl);
        mBiometricStrengthController = mInjector.getBiometricStrengthController(this);
        mBiometricStrengthController.startListening();
    }

    /**
     * @param modality one of {@link BiometricAuthenticator#TYPE_FINGERPRINT},
     * {@link BiometricAuthenticator#TYPE_IRIS} or {@link BiometricAuthenticator#TYPE_FACE}
     * @return
     */
    private int mapModalityToDevicePolicyType(int modality) {
        switch (modality) {
            case TYPE_FINGERPRINT:
                return DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT;
            case TYPE_IRIS:
                return DevicePolicyManager.KEYGUARD_DISABLE_IRIS;
            case TYPE_FACE:
                return DevicePolicyManager.KEYGUARD_DISABLE_FACE;
            default:
                Slog.e(TAG, "Error modality=" + modality);
                return DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
        }
    }

    // TODO(joshmccloskey): Update this to throw an error if a new modality is added and this
    // logic is not updated.
    private boolean isBiometricDisabledByDevicePolicy(int modality, int effectiveUserId) {
        final int biometricToCheck = mapModalityToDevicePolicyType(modality);
        if (biometricToCheck == DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE) {
            Slog.e(TAG, "Allowing unknown modality " + modality + " to pass Device Policy check");
            return false;
        }
        final int devicePolicyDisabledFeatures =
                mDevicePolicyManager.getKeyguardDisabledFeatures(null, effectiveUserId);
        final boolean isBiometricDisabled =
                (biometricToCheck & devicePolicyDisabledFeatures) != 0;
        Slog.w(TAG, "isBiometricDisabledByDevicePolicy(" + modality + "," + effectiveUserId
                + ")=" + isBiometricDisabled);
        return isBiometricDisabled;
    }

    /**
     * Checks if there are any available biometrics, and returns the modality. This method also
     * returns errors through the callback (no biometric feature, hardware not detected, no
     * templates enrolled, etc). This service must not start authentication if errors are sent.
     *
     * @param userId the user to check for
     * @param bundle passed from {@link BiometricPrompt}
     * @param opPackageName see {@link android.app.AppOpsManager}
     *
     * @return A pair [Modality, Error] with Modality being one of
     * {@link BiometricAuthenticator#TYPE_NONE},
     * {@link BiometricAuthenticator#TYPE_FINGERPRINT},
     * {@link BiometricAuthenticator#TYPE_IRIS},
     * {@link BiometricAuthenticator#TYPE_FACE}
     * and the error containing one of the {@link BiometricConstants} errors.
     *
     * TODO(kchyn): Update this to handle DEVICE_CREDENTIAL better, reduce duplicate code in callers
     */
    private Pair<Integer, Integer> checkAndGetAuthenticators(int userId, Bundle bundle,
            String opPackageName, boolean checkDevicePolicyManager) throws RemoteException {
        if (!Utils.isBiometricAllowed(bundle)
                && Utils.isDeviceCredentialAllowed(bundle)
                && !mTrustManager.isDeviceSecure(userId)) {
            // If only device credential is being checked, and the user doesn't have one set up
            return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL);
        }

        // Assuming that authenticators are listed in priority-order, the rest of this function
        // will attempt to find the first authenticator that's as strong or stronger than the
        // requested strength, available, enrolled, and enabled. The tricky part is returning the
        // correct error. Error strings that are modality-specific should also respect the
        // priority-order.

        // Find first authenticator that's strong enough, detected, enrolled, and enabled.
        boolean hasSufficientStrength = false;
        boolean isHardwareDetected = false;
        boolean hasTemplatesEnrolled = false;
        boolean enabledForApps = false;

        int modality = TYPE_NONE;
        int firstHwAvailable = TYPE_NONE;
        for (AuthenticatorWrapper authenticator : mAuthenticators) {
            final int actualStrength = authenticator.getActualStrength();
            final int requestedStrength = Utils.getPublicBiometricStrength(bundle);
            if (Utils.isAtLeastStrength(actualStrength, requestedStrength)) {
                hasSufficientStrength = true;
                modality = authenticator.modality;
                if (authenticator.impl.isHardwareDetected(opPackageName)) {
                    isHardwareDetected = true;
                    if (firstHwAvailable == TYPE_NONE) {
                        // Store the first one since we want to return the error in correct
                        // priority order.
                        firstHwAvailable = modality;
                    }
                    if (authenticator.impl.hasEnrolledTemplates(userId, opPackageName)) {
                        hasTemplatesEnrolled = true;
                        // If the device policy manager disables a specific biometric, skip it.
                        if (checkDevicePolicyManager &&
                                isBiometricDisabledByDevicePolicy(modality, userId)) {
                            continue;
                        }
                        if (isEnabledForApp(modality, userId)) {
                            enabledForApps = true;
                            break;
                        }
                    }
                }
            }
        }

        Slog.d(TAG, "checkAndGetAuthenticators: user=" + userId
                + " checkDevicePolicyManager=" + checkDevicePolicyManager
                + " isHardwareDetected=" + isHardwareDetected
                + " hasTemplatesEnrolled=" + hasTemplatesEnrolled
                + " enabledForApps=" + enabledForApps);

        // Check error conditions
        if (!hasSufficientStrength) {
            return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT);
        } else if (!isHardwareDetected) {
            return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE);
        } else if (!hasTemplatesEnrolled) {
            // Return the modality here so the correct error string can be sent. This error is
            // preferred over !enabledForApps
            return new Pair<>(firstHwAvailable, BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS);
        } else if (!enabledForApps) {
            return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE);
        }

        return new Pair<>(modality, BiometricConstants.BIOMETRIC_SUCCESS);
    }

    private boolean isEnabledForApp(int modality, int userId) {
        switch (modality) {
            case TYPE_FINGERPRINT:
                return true;
            case TYPE_IRIS:
                return true;
            case TYPE_FACE:
                return mSettingObserver.getFaceEnabledForApps(userId);
            default:
                Slog.w(TAG, "Unsupported modality: " + modality);
                return false;
        }
    }

    private void logDialogDismissed(int reason) {
        if (reason == BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED) {
            // Explicit auth, authentication confirmed.
            // Latency in this case is authenticated -> confirmed. <Biometric>Service
            // should have the first half (first acquired -> authenticated).
            final long latency = System.currentTimeMillis()
                    - mCurrentAuthSession.mAuthenticatedTimeMs;

            if (LoggableMonitor.DEBUG) {
                Slog.v(LoggableMonitor.TAG, "Confirmed! Modality: " + statsModality()
                        + ", User: " + mCurrentAuthSession.mUserId
                        + ", IsCrypto: " + mCurrentAuthSession.isCrypto()
                        + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT
                        + ", RequireConfirmation: "
                        + mCurrentAuthSession.mRequireConfirmation
                        + ", State: " + StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED
                        + ", Latency: " + latency);
            }

            StatsLog.write(StatsLog.BIOMETRIC_AUTHENTICATED,
                    statsModality(),
                    mCurrentAuthSession.mUserId,
                    mCurrentAuthSession.isCrypto(),
                    BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
                    mCurrentAuthSession.mRequireConfirmation,
                    StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED,
                    latency,
                    mInjector.isDebugEnabled(getContext(), mCurrentAuthSession.mUserId));
        } else {

            final long latency = System.currentTimeMillis() - mCurrentAuthSession.mStartTimeMs;

            int error = reason == BiometricPrompt.DISMISSED_REASON_NEGATIVE
                    ? BiometricConstants.BIOMETRIC_ERROR_NEGATIVE_BUTTON
                    : reason == BiometricPrompt.DISMISSED_REASON_USER_CANCEL
                            ? BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED
                            : 0;
            if (LoggableMonitor.DEBUG) {
                Slog.v(LoggableMonitor.TAG, "Dismissed! Modality: " + statsModality()
                        + ", User: " + mCurrentAuthSession.mUserId
                        + ", IsCrypto: " + mCurrentAuthSession.isCrypto()
                        + ", Action: " + BiometricsProtoEnums.ACTION_AUTHENTICATE
                        + ", Client: " + BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT
                        + ", Error: " + error
                        + ", Latency: " + latency);
            }
            // Auth canceled
            StatsLog.write(StatsLog.BIOMETRIC_ERROR_OCCURRED,
                    statsModality(),
                    mCurrentAuthSession.mUserId,
                    mCurrentAuthSession.isCrypto(),
                    BiometricsProtoEnums.ACTION_AUTHENTICATE,
                    BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
                    error,
                    0 /* vendorCode */,
                    mInjector.isDebugEnabled(getContext(), mCurrentAuthSession.mUserId),
                    latency);
        }
    }

    private int statsModality() {
        int modality = 0;
        if (mCurrentAuthSession == null) {
            return BiometricsProtoEnums.MODALITY_UNKNOWN;
        }
        if ((mCurrentAuthSession.mModality & BiometricAuthenticator.TYPE_FINGERPRINT)
                != 0) {
            modality |= BiometricsProtoEnums.MODALITY_FINGERPRINT;
        }
        if ((mCurrentAuthSession.mModality & BiometricAuthenticator.TYPE_IRIS) != 0) {
            modality |= BiometricsProtoEnums.MODALITY_IRIS;
        }
        if ((mCurrentAuthSession.mModality & BiometricAuthenticator.TYPE_FACE) != 0) {
            modality |= BiometricsProtoEnums.MODALITY_FACE;
        }
        return modality;
    }

    private void handleAuthenticationSucceeded(boolean requireConfirmation, byte[] token) {
        try {
            // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded
            // after user dismissed/canceled dialog).
            if (mCurrentAuthSession == null) {
                Slog.e(TAG, "handleAuthenticationSucceeded: Auth session is null");
                return;
            }

            // Store the auth token and submit it to keystore after the dialog is confirmed /
            // animating away.
            mCurrentAuthSession.mTokenEscrow = token;
            if (!requireConfirmation) {
                mCurrentAuthSession.mState = STATE_AUTHENTICATED_PENDING_SYSUI;
            } else {
                mCurrentAuthSession.mAuthenticatedTimeMs = System.currentTimeMillis();
                mCurrentAuthSession.mState = STATE_AUTH_PENDING_CONFIRM;
            }

            // Notify SysUI that the biometric has been authenticated. SysUI already knows
            // the implicit/explicit state and will react accordingly.
            mStatusBarService.onBiometricAuthenticated();
        } catch (RemoteException e) {
            Slog.e(TAG, "Remote exception", e);
        }
    }

    private void handleAuthenticationRejected() {
        Slog.v(TAG, "handleAuthenticationRejected()");
        try {
            // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded
            // after user dismissed/canceled dialog).
            if (mCurrentAuthSession == null) {
                Slog.e(TAG, "handleAuthenticationRejected: Auth session is null");
                return;
            }

            mStatusBarService.onBiometricError(TYPE_NONE,
                    BiometricConstants.BIOMETRIC_PAUSED_REJECTED, 0 /* vendorCode */);

            // TODO: This logic will need to be updated if BP is multi-modal
            if ((mCurrentAuthSession.mModality & TYPE_FACE) != 0) {
                // Pause authentication. onBiometricAuthenticated(false) causes the
                // dialog to show a "try again" button for passive modalities.
                mCurrentAuthSession.mState = STATE_AUTH_PAUSED;
            }

            mCurrentAuthSession.mClientReceiver.onAuthenticationFailed();
        } catch (RemoteException e) {
            Slog.e(TAG, "Remote exception", e);
        }
    }

    private void handleAuthenticationTimedOut(int modality, int error, int vendorCode) {
        Slog.v(TAG, String.format("handleAuthenticationTimedOut(%d, %d, %d)", modality, error,
                vendorCode));
        try {
            // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded
            // after user dismissed/canceled dialog).
            if (mCurrentAuthSession == null) {
                Slog.e(TAG, "handleAuthenticationTimedOut: Auth session is null");
                return;
            }

            mStatusBarService.onBiometricError(modality, error, vendorCode);
            mCurrentAuthSession.mState = STATE_AUTH_PAUSED;
        } catch (RemoteException e) {
            Slog.e(TAG, "Remote exception", e);
        }
    }

    private void handleOnError(int cookie, int modality, int error, int vendorCode) {
        Slog.d(TAG, "handleOnError: " + error + " cookie: " + cookie);
        // Errors can either be from the current auth session or the pending auth session.
        // The pending auth session may receive errors such as ERROR_LOCKOUT before
        // it becomes the current auth session. Similarly, the current auth session may
        // receive errors such as ERROR_CANCELED while the pending auth session is preparing
        // to be started. Thus we must match error messages with their cookies to be sure
        // of their intended receivers.
        try {
            if (mCurrentAuthSession != null && mCurrentAuthSession.containsCookie(cookie)) {
                mCurrentAuthSession.mErrorEscrow = error;
                mCurrentAuthSession.mVendorCodeEscrow = vendorCode;

                if (mCurrentAuthSession.mState == STATE_AUTH_STARTED) {
                    final boolean errorLockout = error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
                            || error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
                    if (mCurrentAuthSession.isAllowDeviceCredential() && errorLockout) {
                        // SystemUI handles transition from biometric to device credential.
                        mCurrentAuthSession.mState = STATE_SHOWING_DEVICE_CREDENTIAL;
                        mStatusBarService.onBiometricError(modality, error, vendorCode);
                    } else if (error == BiometricConstants.BIOMETRIC_ERROR_CANCELED) {
                        mStatusBarService.hideAuthenticationDialog();
                        // TODO: If multiple authenticators are simultaneously running, this will
                        // need to be modified. Send the error to the client here, instead of doing
                        // a round trip to SystemUI.
                        mCurrentAuthSession.mClientReceiver.onError(modality, error, vendorCode);
                        mCurrentAuthSession = null;
                    } else {
                        mCurrentAuthSession.mState = STATE_ERROR_PENDING_SYSUI;
                        mStatusBarService.onBiometricError(modality, error, vendorCode);
                    }
                } else if (mCurrentAuthSession.mState == STATE_AUTH_PAUSED) {
                    // In the "try again" state, we should forward canceled errors to
                    // the client and and clean up. The only error we should get here is
                    // ERROR_CANCELED due to another client kicking us out.
                    mCurrentAuthSession.mClientReceiver.onError(modality, error, vendorCode);
                    mStatusBarService.hideAuthenticationDialog();
                    mCurrentAuthSession = null;
                } else if (mCurrentAuthSession.mState == STATE_SHOWING_DEVICE_CREDENTIAL) {
                    Slog.d(TAG, "Biometric canceled, ignoring from state: "
                            + mCurrentAuthSession.mState);
                } else {
                    Slog.e(TAG, "Impossible session error state: "
                            + mCurrentAuthSession.mState);
                }
            } else if (mPendingAuthSession != null
                    && mPendingAuthSession.containsCookie(cookie)) {
                if (mPendingAuthSession.mState == STATE_AUTH_CALLED) {
                    // If any error is received while preparing the auth session (lockout, etc),
                    // and if device credential is allowed, just show the credential UI.
                    if (mPendingAuthSession.isAllowDeviceCredential()) {
                        @Authenticators.Types int authenticators =
                                mPendingAuthSession.mBundle.getInt(
                                        BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED, 0);
                        // Disallow biometric and notify SystemUI to show the authentication prompt.
                        authenticators &= ~Authenticators.BIOMETRIC_WEAK;
                        mPendingAuthSession.mBundle.putInt(
                                BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED,
                                authenticators);

                        mCurrentAuthSession = mPendingAuthSession;
                        mCurrentAuthSession.mState = STATE_SHOWING_DEVICE_CREDENTIAL;
                        mPendingAuthSession = null;

                        mStatusBarService.showAuthenticationDialog(
                                mCurrentAuthSession.mBundle,
                                mInternalReceiver,
                                0 /* biometricModality */,
                                false /* requireConfirmation */,
                                mCurrentAuthSession.mUserId,
                                mCurrentAuthSession.mOpPackageName);
                    } else {
                        mPendingAuthSession.mClientReceiver.onError(modality, error, vendorCode);
                        mPendingAuthSession = null;
                    }
                } else {
                    Slog.e(TAG, "Impossible pending session error state: "
                            + mPendingAuthSession.mState);
                }
            } else {
                Slog.e(TAG, "Unknown cookie: " + cookie);
            }
        } catch (RemoteException e) {
            Slog.e(TAG, "Remote exception", e);
        }
    }

    private void handleOnAcquired(int acquiredInfo, String message) {
        // Should never happen, log this to catch bad HAL behavior (e.g. auth succeeded
        // after user dismissed/canceled dialog).
        if (mCurrentAuthSession == null) {
            Slog.e(TAG, "onAcquired(): Auth session is null");
            return;
        }

        if (acquiredInfo != BiometricConstants.BIOMETRIC_ACQUIRED_GOOD) {
            if (message == null) {
                Slog.w(TAG, "Ignoring null message: " + acquiredInfo);
                return;
            }
            try {
                mStatusBarService.onBiometricHelp(message);
            } catch (RemoteException e) {
                Slog.e(TAG, "Remote exception", e);
            }
        }
    }

    private void handleOnDismissed(int reason) {
        if (mCurrentAuthSession == null) {
            Slog.e(TAG, "onDismissed: " + reason + ", auth session null");
            return;
        }

        logDialogDismissed(reason);

        try {
            switch (reason) {
                case BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED:
                case BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED:
                case BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED:
                    if (mCurrentAuthSession.mTokenEscrow != null) {
                        mKeyStore.addAuthToken(mCurrentAuthSession.mTokenEscrow);
                    }
                    mCurrentAuthSession.mClientReceiver.onAuthenticationSucceeded(
                            Utils.getAuthenticationTypeForResult(reason));
                    break;

                case BiometricPrompt.DISMISSED_REASON_NEGATIVE:
                    mCurrentAuthSession.mClientReceiver.onDialogDismissed(reason);
                    // Cancel authentication. Skip the token/package check since we are cancelling
                    // from system server. The interface is permission protected so this is fine.
                    cancelInternal(null /* token */, null /* package */, false /* fromClient */);
                    break;

                case BiometricPrompt.DISMISSED_REASON_USER_CANCEL:
                    mCurrentAuthSession.mClientReceiver.onError(
                            mCurrentAuthSession.mModality,
                            BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
                            0 /* vendorCode */
                    );
                    // Cancel authentication. Skip the token/package check since we are cancelling
                    // from system server. The interface is permission protected so this is fine.
                    cancelInternal(null /* token */, null /* package */, false /* fromClient */);
                    break;

                case BiometricPrompt.DISMISSED_REASON_SERVER_REQUESTED:
                case BiometricPrompt.DISMISSED_REASON_ERROR:
                    mCurrentAuthSession.mClientReceiver.onError(
                            mCurrentAuthSession.mModality,
                            mCurrentAuthSession.mErrorEscrow,
                            mCurrentAuthSession.mVendorCodeEscrow
                    );
                    break;

                default:
                    Slog.w(TAG, "Unhandled reason: " + reason);
                    break;
            }

            // Dialog is gone, auth session is done.
            mCurrentAuthSession = null;

        } catch (RemoteException e) {
            Slog.e(TAG, "Remote exception", e);
        }
    }

    private void handleOnTryAgainPressed() {
        Slog.d(TAG, "onTryAgainPressed");
        // No need to check permission, since it can only be invoked by SystemUI
        // (or system server itself).
        authenticateInternal(mCurrentAuthSession.mToken,
                mCurrentAuthSession.mSessionId,
                mCurrentAuthSession.mUserId,
                mCurrentAuthSession.mClientReceiver,
                mCurrentAuthSession.mOpPackageName,
                mCurrentAuthSession.mBundle,
                mCurrentAuthSession.mCallingUid,
                mCurrentAuthSession.mCallingPid,
                mCurrentAuthSession.mCallingUserId,
                mCurrentAuthSession.mModality);
    }

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

        // Cancel authentication. Skip the token/package check since we are cancelling
        // from system server. The interface is permission protected so this is fine.
        cancelInternal(null /* token */, null /* package */, false /* fromClient */);

        mCurrentAuthSession.mState = STATE_SHOWING_DEVICE_CREDENTIAL;
    }

    /**
     * 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.
     */
    private void handleOnReadyForAuthentication(int cookie, boolean requireConfirmation,
            int userId) {
        if (mPendingAuthSession == null) {
            // Only should happen if a biometric was locked out when authenticate() was invoked.
            // In that case, if device credentials are allowed, the UI is already showing. If not
            // allowed, the error has already been returned to the caller.
            Slog.w(TAG, "Pending auth session null");
            return;
        }

        Iterator it = mPendingAuthSession.mModalitiesWaiting.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<Integer, Integer> pair = (Map.Entry) it.next();
            if (pair.getValue() == cookie) {
                mPendingAuthSession.mModalitiesMatched.put(pair.getKey(), pair.getValue());
                mPendingAuthSession.mModalitiesWaiting.remove(pair.getKey());
                Slog.d(TAG, "Matched cookie: " + cookie + ", "
                        + mPendingAuthSession.mModalitiesWaiting.size() + " remaining");
                break;
            }
        }

        if (mPendingAuthSession.mModalitiesWaiting.isEmpty()) {
            final boolean continuing = mCurrentAuthSession != null
                    && mCurrentAuthSession.mState == STATE_AUTH_PAUSED;

            mCurrentAuthSession = mPendingAuthSession;

            // Time starts when lower layers are ready to start the client.
            mCurrentAuthSession.mStartTimeMs = System.currentTimeMillis();
            mPendingAuthSession = null;

            mCurrentAuthSession.mState = STATE_AUTH_STARTED;
            int modality = TYPE_NONE;
            it = mCurrentAuthSession.mModalitiesMatched.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<Integer, Integer> pair = (Map.Entry) it.next();
                boolean foundAuthenticator = false;
                for (AuthenticatorWrapper authenticator : mAuthenticators) {
                    if (authenticator.modality == pair.getKey()) {
                        foundAuthenticator = true;
                        try {
                            authenticator.impl.startPreparedClient(pair.getValue());
                        } catch (RemoteException e) {
                            Slog.e(TAG, "Remote exception", e);
                        }
                    }
                }
                if (!foundAuthenticator) {
                    Slog.e(TAG, "Unknown modality: " + pair.getKey());
                }
                modality |= pair.getKey();
            }

            if (!continuing) {
                try {
                    mStatusBarService.showAuthenticationDialog(mCurrentAuthSession.mBundle,
                            mInternalReceiver, modality, requireConfirmation, userId,
                            mCurrentAuthSession.mOpPackageName);
                } catch (RemoteException e) {
                    Slog.e(TAG, "Remote exception", e);
                }
            }
        }
    }

    private void handleAuthenticate(IBinder token, long sessionId, int userId,
            IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle,
            int callingUid, int callingPid, int callingUserId) {

        mHandler.post(() -> {
            int modality = TYPE_NONE;
            int result;

            try {
                final boolean checkDevicePolicyManager = bundle.getBoolean(
                        BiometricPrompt.EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS, false);
                final Pair<Integer, Integer> pair = checkAndGetAuthenticators(userId, bundle,
                        opPackageName, checkDevicePolicyManager);
                modality = pair.first;
                result = pair.second;
            } catch (RemoteException e) {
                Slog.e(TAG, "Remote exception", e);
                result = BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE;
            }

            try {
                if (result == BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL) {
                    // If the app allowed device credential but the user hasn't set it up yet,
                    // return this error.
                    receiver.onError(modality, result, 0 /* vendorCode */);
                } else if (result != BiometricConstants.BIOMETRIC_SUCCESS) {
                    if (Utils.isDeviceCredentialAllowed(bundle)) {
                        // If there's a problem with biometrics but device credential is allowed,
                        // only show credential UI.
                        bundle.putInt(BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED,
                                Authenticators.DEVICE_CREDENTIAL);
                        authenticateInternal(token, sessionId, userId, receiver, opPackageName,
                                bundle, callingUid, callingPid, callingUserId, modality);
                    } else {
                        receiver.onError(modality, result, 0 /* vendorCode */);
                    }
                } else {
                    // BIOMETRIC_SUCCESS, proceed to authentication
                    authenticateInternal(token, sessionId, userId, receiver, opPackageName, bundle,
                            callingUid, callingPid, callingUserId, modality);
                }
            } catch (RemoteException e) {
                Slog.e(TAG, "Remote exception", e);
            }
        });
    }

    /**
     * handleAuthenticate() (above) which is called from BiometricPrompt determines which
     * modality/modalities to start authenticating with. authenticateInternal() should only be
     * used for:
     * 1) Preparing <Biometric>Services for authentication when BiometricPrompt#authenticate is,
     * invoked, shortly after which BiometricPrompt is shown and authentication starts
     * 2) Preparing <Biometric>Services for authentication when BiometricPrompt is already shown
     * and the user has pressed "try again"
     */
    private void authenticateInternal(IBinder token, long sessionId, int userId,
            IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle,
            int callingUid, int callingPid, int callingUserId, int modality) {
        boolean requireConfirmation = bundle.getBoolean(
                BiometricPrompt.KEY_REQUIRE_CONFIRMATION, true /* default */);
        if ((modality & TYPE_FACE) != 0) {
            // Check if the user has forced confirmation to be required in Settings.
            requireConfirmation = requireConfirmation
                    || mSettingObserver.getFaceAlwaysRequireConfirmation(userId);
        }
        // Generate random cookies to pass to the services that should prepare to start
        // authenticating. Store the cookie here and wait for all services to "ack"
        // with the cookie. Once all cookies are received, we can show the prompt
        // and let the services start authenticating. The cookie should be non-zero.
        final int cookie = mRandom.nextInt(Integer.MAX_VALUE - 1) + 1;
        final @Authenticators.Types int authenticators = bundle.getInt(
                BiometricPrompt.KEY_AUTHENTICATORS_ALLOWED, 0);
        Slog.d(TAG, "Creating auth session. Modality: " + modality
                + ", cookie: " + cookie
                + ", authenticators: " + authenticators);
        final HashMap<Integer, Integer> modalities = new HashMap<>();

        // If it's only device credential, we don't need to wait - LockSettingsService is
        // always ready to check credential (SystemUI invokes that path).
        if ((authenticators & ~Authenticators.DEVICE_CREDENTIAL) != 0) {
            modalities.put(modality, cookie);
        }
        mPendingAuthSession = new AuthSession(modalities, token, sessionId, userId,
                receiver, opPackageName, bundle, callingUid, callingPid, callingUserId,
                modality, requireConfirmation);

        try {
            if (authenticators == Authenticators.DEVICE_CREDENTIAL) {
                mPendingAuthSession.mState = STATE_SHOWING_DEVICE_CREDENTIAL;
                mCurrentAuthSession = mPendingAuthSession;
                mPendingAuthSession = null;

                mStatusBarService.showAuthenticationDialog(
                        mCurrentAuthSession.mBundle,
                        mInternalReceiver,
                        0 /* biometricModality */,
                        false /* requireConfirmation */,
                        mCurrentAuthSession.mUserId,
                        mCurrentAuthSession.mOpPackageName);
            } else {
                mPendingAuthSession.mState = STATE_AUTH_CALLED;
                for (AuthenticatorWrapper authenticator : mAuthenticators) {
                    // TODO(b/141025588): use ids instead of modalities to avoid ambiguity.
                    if (authenticator.modality == modality) {
                        authenticator.impl.prepareForAuthentication(requireConfirmation, token,
                                sessionId, userId, mInternalReceiver, opPackageName, cookie,
                                callingUid, callingPid, callingUserId);
                        break;
                    }
                }
            }
        } catch (RemoteException e) {
            Slog.e(TAG, "Unable to start authentication", e);
        }
    }

    private void handleCancelAuthentication(IBinder token, String opPackageName) {
        if (token == null || opPackageName == null) {
            Slog.e(TAG, "Unable to cancel, one or more null arguments");
            return;
        }

        if (mCurrentAuthSession != null && mCurrentAuthSession.mState != STATE_AUTH_STARTED) {
            // We need to check the current authenticators state. If we're pending confirm
            // or idle, we need to dismiss the dialog and send an ERROR_CANCELED to the client,
            // since we won't be getting an onError from the driver.
            try {
                // Send error to client
                mCurrentAuthSession.mClientReceiver.onError(
                        mCurrentAuthSession.mModality,
                        BiometricConstants.BIOMETRIC_ERROR_CANCELED,
                        0 /* vendorCode */
                );
                mCurrentAuthSession = null;
                mStatusBarService.hideAuthenticationDialog();
            } catch (RemoteException e) {
                Slog.e(TAG, "Remote exception", e);
            }
        } else {
            cancelInternal(token, opPackageName, true /* fromClient */);
        }
    }

    void cancelInternal(IBinder token, String opPackageName, boolean fromClient) {
        final int callingUid = Binder.getCallingUid();
        final int callingPid = Binder.getCallingPid();
        final int callingUserId = UserHandle.getCallingUserId();

        if (mCurrentAuthSession == null) {
            Slog.w(TAG, "Skipping cancelInternal");
            return;
        } else if (mCurrentAuthSession.mState != STATE_AUTH_STARTED) {
            Slog.w(TAG, "Skipping cancelInternal, state: " + mCurrentAuthSession.mState);
            return;
        }

        // TODO: For multiple modalities, send a single ERROR_CANCELED only when all
        // drivers have canceled authentication.
        for (AuthenticatorWrapper authenticator : mAuthenticators) {
            if ((authenticator.modality & mCurrentAuthSession.mModality) != 0) {
                try {
                    authenticator.impl.cancelAuthenticationFromService(token, opPackageName,
                            callingUid, callingPid, callingUserId, fromClient);
                } catch (RemoteException e) {
                    Slog.e(TAG, "Unable to cancel authentication");
                }
            }
        }
    }
}
