/*
 * Copyright 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 androidx.biometric;

import static java.lang.annotation.RetentionPolicy.SOURCE;

import android.annotation.SuppressLint;
import android.content.DialogInterface;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;

import java.lang.annotation.Retention;
import java.security.Signature;
import java.util.concurrent.Executor;

import javax.crypto.Cipher;
import javax.crypto.Mac;

/**
 * A class that manages a system-provided biometric prompt. On devices running P and above, this
 * will show a system-provided authentication prompt, using a device's supported biometric
 * (fingerprint, iris, face, etc). On devices before P, this will show a dialog prompting for
 * fingerprint authentication. The prompt will persist across configuration changes unless
 * explicitly canceled by the client. For security reasons, the prompt will automatically dismiss
 * when the application is no longer in the foreground.
 *
 * To persist authentication across configuration changes, developers should (re)create the
 * BiometricPrompt every time the activity/fragment is created. Instantiating the library with a new
 * callback early in the fragment/activity lifecycle (e.g. onCreate) allows the ongoing authenticate
 * session's callbacks to be received by the new fragment/activity. Note that
 * {@link BiometricPrompt#cancelAuthentication()} should not be called, and
 * {@link BiometricPrompt#authenticate(PromptInfo)} or
 * {@link BiometricPrompt#authenticate(PromptInfo, CryptoObject)} does not need to be invoked after
 * the new activity/fragment is created, since we are keeping/continuing the same session.
 */
@SuppressLint("SyntheticAccessor")
public class BiometricPrompt implements BiometricConstants {

    private static final String TAG = "BiometricPromptCompat";
    private static final boolean DEBUG = false;
    // In order to keep consistent behavior between versions, we need to send
    // FingerprintDialogFragment a message indicating whether or not to dismiss the UI instantly.
    private static final int DELAY_MILLIS = 500;

    static final String DIALOG_FRAGMENT_TAG = "FingerprintDialogFragment";
    static final String FINGERPRINT_HELPER_FRAGMENT_TAG = "FingerprintHelperFragment";
    static final String BIOMETRIC_FRAGMENT_TAG = "BiometricFragment";
    static final String KEY_TITLE = "title";
    static final String KEY_SUBTITLE = "subtitle";
    static final String KEY_DESCRIPTION = "description";
    static final String KEY_NEGATIVE_TEXT = "negative_text";
    static final String KEY_REQUIRE_CONFIRMATION = "require_confirmation";
    static final String KEY_ALLOW_DEVICE_CREDENTIAL = "allow_device_credential";

    @Retention(SOURCE)
    @IntDef({ERROR_HW_UNAVAILABLE,
            ERROR_UNABLE_TO_PROCESS,
            ERROR_TIMEOUT,
            ERROR_NO_SPACE,
            ERROR_CANCELED,
            ERROR_LOCKOUT,
            ERROR_VENDOR,
            ERROR_LOCKOUT_PERMANENT,
            ERROR_USER_CANCELED,
            ERROR_NO_BIOMETRICS,
            ERROR_HW_NOT_PRESENT,
            ERROR_NEGATIVE_BUTTON,
            ERROR_NO_DEVICE_CREDENTIAL})
    private @interface BiometricError {}

    /**
     * A wrapper class for the crypto objects supported by BiometricPrompt. Currently the
     * framework supports {@link Signature}, {@link Cipher}, and {@link Mac} objects.
     */
    public static class CryptoObject {
        private final Signature mSignature;
        private final Cipher mCipher;
        private final Mac mMac;

        public CryptoObject(@NonNull Signature signature) {
            mSignature = signature;
            mCipher = null;
            mMac = null;
        }

        public CryptoObject(@NonNull Cipher cipher) {
            mCipher = cipher;
            mSignature = null;
            mMac = null;
        }

        public CryptoObject(@NonNull Mac mac) {
            mMac = mac;
            mCipher = null;
            mSignature = null;
        }

        /**
         * Get {@link Signature} object.
         * @return {@link Signature} object or null if this doesn't contain one.
         */
        @Nullable
        public Signature getSignature() {
            return mSignature;
        }

        /**
         * Get {@link Cipher} object.
         * @return {@link Cipher} object or null if this doesn't contain one.
         */
        @Nullable
        public Cipher getCipher() {
            return mCipher;
        }

        /**
         * Get {@link Mac} object.
         * @return {@link Mac} object or null if this doesn't contain one.
         */
        @Nullable
        public Mac getMac() {
            return mMac;
        }
    }

    /**
     * Container for callback data from {@link #authenticate(PromptInfo)} and
     * {@link #authenticate(PromptInfo, CryptoObject)}.
     */
    public static class AuthenticationResult {
        private final CryptoObject mCryptoObject;

        /**
         * @param crypto
         */
        AuthenticationResult(CryptoObject crypto) {
            mCryptoObject = crypto;
        }

        /**
         * Obtain the crypto object associated with this transaction
         * @return crypto object provided to {@link #authenticate(PromptInfo, CryptoObject)}.
         */
        @Nullable
        public CryptoObject getCryptoObject() {
            return mCryptoObject;
        }
    }

    /**
     * Callback structure provided to {@link BiometricPrompt}. Users of {@link
     * BiometricPrompt} must provide an implementation of this for listening to
     * fingerprint events.
     */
    public abstract static class AuthenticationCallback {
        /**
         * Called when an unrecoverable error has been encountered and the operation is complete.
         * No further actions will be made on this object.
         * @param errorCode An integer identifying the error message. The error message will usually
         *                  be one of the BIOMETRIC_ERROR constants.
         * @param errString A human-readable error string that can be shown on an UI
         */
        public void onAuthenticationError(@BiometricError int errorCode,
                @NonNull CharSequence errString) {}

        /**
         * Called when a biometric is recognized.
         * @param result An object containing authentication-related data
         */
        public void onAuthenticationSucceeded(@NonNull AuthenticationResult result) {}

        /**
         * Called when a biometric is valid but not recognized.
         */

        public void onAuthenticationFailed() {}
    }

    /**
     * A class that contains a builder which returns the {@link PromptInfo} to be used in
     * {@link #authenticate(PromptInfo, CryptoObject)} and {@link #authenticate(PromptInfo)}.
     */
    public static class PromptInfo {

        /**
         * A builder that collects arguments to be shown on the system-provided biometric dialog.
         */
        public static class Builder {
            private final Bundle mBundle = new Bundle();

            /**
             * Required: Set the title to display.
             */
            @NonNull
            public Builder setTitle(@NonNull CharSequence title) {
                mBundle.putCharSequence(KEY_TITLE, title);
                return this;
            }

            /**
             * Optional: Set the subtitle to display.
             */
            @NonNull
            public Builder setSubtitle(@Nullable CharSequence subtitle) {
                mBundle.putCharSequence(KEY_SUBTITLE, subtitle);
                return this;
            }

            /**
             * Optional: Set the description to display.
             */
            @NonNull
            public Builder setDescription(@Nullable CharSequence description) {
                mBundle.putCharSequence(KEY_DESCRIPTION, description);
                return this;
            }

            /**
             * Required: Set the text for the negative button. This would typically be used as a
             * "Cancel" button, but may be also used to show an alternative method for
             * authentication, such as screen that asks for a backup password.
             * @param text
             * @return
             */
            @NonNull
            public Builder setNegativeButtonText(@NonNull CharSequence text) {
                mBundle.putCharSequence(KEY_NEGATIVE_TEXT, text);
                return this;
            }

            /**
             * Optional: A hint to the system to require user confirmation after a biometric has
             * been authenticated. For example, implicit modalities like Face and
             * Iris authentication are passive, meaning they don't require an explicit user action
             * to complete. When set to 'false', the user action (e.g. pressing a button)
             * will not be required. BiometricPrompt will require confirmation by default.
             *
             * A typical use case for not requiring confirmation would be for low-risk transactions,
             * such as re-authenticating a recently authenticated application. A typical use case
             * for requiring confirmation would be for authorizing a purchase.
             *
             * Note that this is a hint to the system. The system may choose to ignore the flag. For
             * example, if the user disables implicit authentication in Settings, or if it does not
             * apply to a modality (e.g. Fingerprint). When ignored, the system will default to
             * requiring confirmation.
             *
             * This method only applies to Q and above.
             */
            @NonNull
            public Builder setConfirmationRequired(boolean requireConfirmation) {
                mBundle.putBoolean(KEY_REQUIRE_CONFIRMATION, requireConfirmation);
                return this;
            }

            /**
             * The user will first be prompted to authenticate with biometrics, but also given the
             * option to authenticate with their device PIN, pattern, or password. Developers should
             * first check {@link android.app.KeyguardManager#isDeviceSecure()} before enabling
             * this. If the device is not secure, {@link BiometricPrompt#ERROR_NO_DEVICE_CREDENTIAL}
             * will be returned in
             * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)}}
             *
             * Note that {@link Builder#setNegativeButtonText(CharSequence)} should not be set
             * if this is set to true.
             *
             * @param enable When true, the prompt will fall back to ask for the user's device
             *               credentials (PIN, pattern, or password).
             * @return
             */
            @RequiresApi(29)
            @NonNull
            public Builder setDeviceCredentialAllowed(boolean enable) {
                mBundle.putBoolean(KEY_ALLOW_DEVICE_CREDENTIAL, enable);
                return this;
            }

            /**
             * Creates a {@link BiometricPrompt}.
             * @return a {@link BiometricPrompt}
             * @throws IllegalArgumentException if any of the required fields are not set.
             */
            @NonNull
            public PromptInfo build() {
                final CharSequence title = mBundle.getCharSequence(KEY_TITLE);
                final CharSequence negative = mBundle.getCharSequence(KEY_NEGATIVE_TEXT);
                boolean allowDeviceCredential = mBundle.getBoolean(KEY_ALLOW_DEVICE_CREDENTIAL);

                if (TextUtils.isEmpty(title)) {
                    throw new IllegalArgumentException("Title must be set and non-empty");
                }
                if (TextUtils.isEmpty(negative) && !allowDeviceCredential) {
                    throw new IllegalArgumentException("Negative text must be set and non-empty");
                }
                if (!TextUtils.isEmpty(negative) && allowDeviceCredential) {
                    throw new IllegalArgumentException("Can't have both negative button behavior"
                            + " and device credential enabled");
                }
                return new PromptInfo(mBundle);
            }
        }

        private Bundle mBundle;

        PromptInfo(Bundle bundle) {
            mBundle = bundle;
        }

        Bundle getBundle() {
            return mBundle;
        }

        /**
         * @return See {@link Builder#setTitle(CharSequence)}.
         */
        @NonNull
        public CharSequence getTitle() {
            return mBundle.getCharSequence(KEY_TITLE);
        }

        /**
         * @return See {@link Builder#setSubtitle(CharSequence)}.
         */
        @Nullable
        public CharSequence getSubtitle() {
            return mBundle.getCharSequence(KEY_SUBTITLE);
        }

        /**
         * @return See {@link Builder#setDescription(CharSequence)}.
         */
        @Nullable
        public CharSequence getDescription() {
            return mBundle.getCharSequence(KEY_DESCRIPTION);
        }

        /**
         * @return See {@link Builder#setNegativeButtonText(CharSequence)}.
         */
        @NonNull
        public CharSequence getNegativeButtonText() {
            return mBundle.getCharSequence(KEY_NEGATIVE_TEXT);
        }

        /**
         * @return See {@link Builder#setConfirmationRequired(boolean)}.
         */
        public boolean isConfirmationRequired() {
            return mBundle.getBoolean(KEY_REQUIRE_CONFIRMATION);
        }

        /**
         * @return See {@link Builder#setDeviceCredentialAllowed(boolean)}.
         */
        public boolean isDeviceCredentialAllowed() {
            return mBundle.getBoolean(KEY_ALLOW_DEVICE_CREDENTIAL);
        }
    }

    // Passed in from the client.
    FragmentActivity mFragmentActivity;
    Fragment mFragment;
    final Executor mExecutor;
    final AuthenticationCallback mAuthenticationCallback;

    // Created internally for devices before P.
    FingerprintDialogFragment mFingerprintDialogFragment;
    FingerprintHelperFragment mFingerprintHelperFragment;

    // Created internally for devices P and above.
    BiometricFragment mBiometricFragment;

    // In Q, we must ignore the first onPause if setDeviceCredentialAllowed is true, since
    // the Q implementation launches ConfirmDeviceCredentialActivity which is an activity and
    // puts the client app onPause.
    boolean mPausedOnce;

    /**
     *  A shim to interface with the framework API and simplify the support library's API.
     *  The support library sends onAuthenticationError when the negative button is pressed.
     *  Conveniently, the {@link FingerprintDialogFragment} also uses the
     *  {@DialogInterface.OnClickListener} for its buttons ;)
     */
    final DialogInterface.OnClickListener mNegativeButtonListener =
            new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    mExecutor.execute(new Runnable() {
                        @Override
                        public void run() {
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                                CharSequence errorText =
                                        mBiometricFragment.getNegativeButtonText();
                                mAuthenticationCallback.onAuthenticationError(
                                        ERROR_NEGATIVE_BUTTON,
                                        errorText);
                                mBiometricFragment.cleanup();
                            } else {
                                CharSequence errorText =
                                        mFingerprintDialogFragment.getNegativeButtonText();
                                mAuthenticationCallback.onAuthenticationError(
                                        ERROR_NEGATIVE_BUTTON,
                                        errorText);
                                mFingerprintHelperFragment.cancel(
                                        FingerprintHelperFragment
                                                .USER_CANCELED_FROM_NEGATIVE_BUTTON);
                            }
                        }
                    });
                }
            };

    /**
     * Observe the client's lifecycle. Keep authenticating across configuration changes, but
     * dismiss the prompt if the client goes into the background.
     */
    private final LifecycleObserver mLifecycleObserver = new LifecycleObserver() {
        @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
        void onPause() {
            if (!isChangingConfigurations()) {
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
                    // May be null if no authentication is occurring.
                    if (mFingerprintDialogFragment != null) {
                        mFingerprintDialogFragment.dismiss();
                    }
                    if (mFingerprintHelperFragment != null) {
                        mFingerprintHelperFragment.cancel(
                                FingerprintHelperFragment.USER_CANCELED_FROM_NONE);
                    }
                } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    // TODO(b/123378871): Change == to >= if this bug is not resolved in R.
                    // Ignore the first onPause if setDeviceCredentialAllowed is true, since
                    // the Q implementation launches ConfirmDeviceCredentialActivity which is an
                    // activity and puts the client app onPause.
                    if (mBiometricFragment != null) {
                        if (mBiometricFragment.isDeviceCredentialAllowed()) {
                            if (!mPausedOnce) {
                                mPausedOnce = true;
                            } else {
                                mBiometricFragment.cancel();
                            }
                        } else {
                            mBiometricFragment.cancel();
                        }
                    }
                } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                    if (mBiometricFragment != null) {
                        mBiometricFragment.cancel();
                    }
                }
            }
        }

        @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
        void onResume() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                mBiometricFragment =
                        (BiometricFragment) getFragmentManager().findFragmentByTag(
                                BIOMETRIC_FRAGMENT_TAG);
                if (DEBUG) Log.v(TAG, "BiometricFragment: " + mBiometricFragment);
                if (mBiometricFragment != null) {
                    mBiometricFragment.setCallbacks(mExecutor, mNegativeButtonListener,
                            mAuthenticationCallback);
                }
            } else {
                mFingerprintDialogFragment =
                        (FingerprintDialogFragment) getFragmentManager().findFragmentByTag(
                                DIALOG_FRAGMENT_TAG);
                mFingerprintHelperFragment =
                        (FingerprintHelperFragment) getFragmentManager().findFragmentByTag(
                                FINGERPRINT_HELPER_FRAGMENT_TAG);

                if (DEBUG) Log.v(TAG, "FingerprintDialogFragment: " + mFingerprintDialogFragment);
                if (DEBUG) Log.v(TAG, "FingerprintHelperFragment: " + mFingerprintHelperFragment);
                if (mFingerprintDialogFragment != null && mFingerprintHelperFragment != null) {
                    mFingerprintDialogFragment.setNegativeButtonListener(mNegativeButtonListener);
                    mFingerprintHelperFragment.setCallback(mExecutor, mAuthenticationCallback);
                    mFingerprintHelperFragment.setHandler(mFingerprintDialogFragment.getHandler());
                }
            }
        }
    };

    /**
     * Constructs a {@link BiometricPrompt} which can be used to prompt the user for
     * authentication. The authenticaton prompt created by
     * {@link BiometricPrompt#authenticate(PromptInfo, CryptoObject)} and
     * {@link BiometricPrompt#authenticate(PromptInfo)} will persist across device
     * configuration changes by default. If authentication is in progress, re-creating
     * the {@link BiometricPrompt} can be used to update the {@link Executor} and
     * {@link AuthenticationCallback}. This should be used to update the
     * {@link AuthenticationCallback} after configuration changes.
     * such as {@link FragmentActivity#onCreate(Bundle)}.
     *
     * @param fragmentActivity A reference to the client's activity.
     * @param executor An executor to handle callback events.
     * @param callback An object to receive authentication events.
     */
    @SuppressLint("LambdaLast")
    public BiometricPrompt(@NonNull FragmentActivity fragmentActivity,
            @NonNull Executor executor, @NonNull AuthenticationCallback callback) {
        if (fragmentActivity == null) {
            throw new IllegalArgumentException("FragmentActivity must not be null");
        }
        if (executor == null) {
            throw new IllegalArgumentException("Executor must not be null");
        }
        if (callback == null) {
            throw new IllegalArgumentException("AuthenticationCallback must not be null");
        }
        mFragmentActivity = fragmentActivity;
        mAuthenticationCallback = callback;
        mExecutor = executor;

        mFragmentActivity.getLifecycle().addObserver(mLifecycleObserver);
    }

    /**
     * Constructs a {@link BiometricPrompt} which can be used to prompt the user for
     * authentication. The authenticaton prompt created by
     * {@link BiometricPrompt#authenticate(PromptInfo, CryptoObject)} and
     * {@link BiometricPrompt#authenticate(PromptInfo)} will persist across device
     * configuration changes by default. If authentication is in progress, re-creating
     * the {@link BiometricPrompt} can be used to update the {@link Executor} and
     * {@link AuthenticationCallback}. This should be used to update the
     * {@link AuthenticationCallback} after configuration changes.
     * such as {@link Fragment#onCreate(Bundle)}.
     *
     * @param fragment A reference to the client's fragment.
     * @param executor An executor to handle callback events.
     * @param callback An object to receive authentication events.
     */
    @SuppressLint("LambdaLast")
    public BiometricPrompt(@NonNull Fragment fragment,
            @NonNull Executor executor, @NonNull AuthenticationCallback callback) {
        if (fragment == null) {
            throw new IllegalArgumentException("FragmentActivity must not be null");
        }
        if (executor == null) {
            throw new IllegalArgumentException("Executor must not be null");
        }
        if (callback == null) {
            throw new IllegalArgumentException("AuthenticationCallback must not be null");
        }
        mFragment = fragment;
        mAuthenticationCallback = callback;
        mExecutor = executor;

        mFragment.getLifecycle().addObserver(mLifecycleObserver);
    }

    /**
     * Shows the biometric prompt. The prompt survives lifecycle changes by default. To cancel the
     * authentication, use {@link #cancelAuthentication()}.
     * @param info The information that will be displayed on the prompt. Create this object using
     *             {@link BiometricPrompt.PromptInfo.Builder}.
     * @param crypto The crypto object associated with the authentication.
     */
    public void authenticate(@NonNull PromptInfo info, @NonNull CryptoObject crypto) {
        if (info == null) {
            throw new IllegalArgumentException("PromptInfo can not be null");
        } else if (crypto == null) {
            throw new IllegalArgumentException("CryptoObject can not be null");
        } else if (info.getBundle().getBoolean(KEY_ALLOW_DEVICE_CREDENTIAL)) {
            throw new IllegalArgumentException("Device credential not supported with crypto");
        }
        authenticateInternal(info, crypto);
    }

    /**
     * Shows the biometric prompt. The prompt survives lifecycle changes by default. To cancel the
     * authentication, use {@link #cancelAuthentication()}.
     * @param info The information that will be displayed on the prompt. Create this object using
     *             {@link BiometricPrompt.PromptInfo.Builder}.
     */
    public void authenticate(@NonNull PromptInfo info) {
        if (info == null) {
            throw new IllegalArgumentException("PromptInfo can not be null");
        }
        authenticateInternal(info, null /* crypto */);
    }

    private void authenticateInternal(@NonNull PromptInfo info, @Nullable CryptoObject crypto) {
        final Bundle bundle = info.getBundle();
        final FragmentManager fragmentManager = getFragmentManager();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            mPausedOnce = false;

            BiometricFragment biometricFragment =
                    (BiometricFragment) fragmentManager.findFragmentByTag(
                            BIOMETRIC_FRAGMENT_TAG);
            if (biometricFragment != null) {
                mBiometricFragment = biometricFragment;
            } else {
                mBiometricFragment = BiometricFragment.newInstance();
            }
            mBiometricFragment.setCallbacks(mExecutor, mNegativeButtonListener,
                    mAuthenticationCallback);
            // Set the crypto object.
            mBiometricFragment.setCryptoObject(crypto);
            mBiometricFragment.setBundle(bundle);

            if (biometricFragment == null) {
                // If the fragment hasn't been added before, add it. It will also start the
                // authentication.
                fragmentManager.beginTransaction().add(mBiometricFragment, BIOMETRIC_FRAGMENT_TAG)
                        .commit();
            } else if (mBiometricFragment.isDetached()) {
                // If it's been added before, just re-attach it.
                fragmentManager.beginTransaction().attach(mBiometricFragment).commit();
            }
        } else {
            // Create the UI
            FingerprintDialogFragment fingerprintDialogFragment =
                    (FingerprintDialogFragment) fragmentManager.findFragmentByTag(
                            DIALOG_FRAGMENT_TAG);
            if (fingerprintDialogFragment != null) {
                mFingerprintDialogFragment = fingerprintDialogFragment;
            } else {
                mFingerprintDialogFragment = FingerprintDialogFragment.newInstance();
            }

            mFingerprintDialogFragment.setNegativeButtonListener(mNegativeButtonListener);
            mFingerprintDialogFragment.setBundle(bundle);
            if (fingerprintDialogFragment == null) {
                mFingerprintDialogFragment.show(fragmentManager, DIALOG_FRAGMENT_TAG);
            } else if (mFingerprintDialogFragment.isDetached()) {
                fragmentManager.beginTransaction().attach(mFingerprintDialogFragment).commit();
            }

            // Create the connection to FingerprintManager
            FingerprintHelperFragment fingerprintHelperFragment =
                    (FingerprintHelperFragment) fragmentManager.findFragmentByTag(
                            FINGERPRINT_HELPER_FRAGMENT_TAG);
            if (fingerprintHelperFragment != null) {
                mFingerprintHelperFragment = fingerprintHelperFragment;
            } else {
                mFingerprintHelperFragment = FingerprintHelperFragment.newInstance();
            }

            mFingerprintHelperFragment.setCallback(mExecutor, mAuthenticationCallback);
            final Handler fingerprintDialogHandler = mFingerprintDialogFragment.getHandler();
            mFingerprintHelperFragment.setHandler(fingerprintDialogHandler);
            mFingerprintHelperFragment.setCryptoObject(crypto);
            fingerprintDialogHandler.sendMessageDelayed(
                    fingerprintDialogHandler.obtainMessage(
                            FingerprintDialogFragment.DISPLAYED_FOR_500_MS), DELAY_MILLIS);

            if (fingerprintHelperFragment == null) {
                // If the fragment hasn't been added before, add it. It will also start the
                // authentication.
                fragmentManager.beginTransaction()
                        .add(mFingerprintHelperFragment, FINGERPRINT_HELPER_FRAGMENT_TAG).commit();
            } else if (mFingerprintHelperFragment.isDetached()) {
                // If it's been added before, just re-attach it.
                fragmentManager.beginTransaction().attach(mFingerprintHelperFragment).commit();
            }
        }
        // For the case when onResume() is being called right after authenticate,
        // we need to make sure that all fragment transactions have been committed.
        fragmentManager.executePendingTransactions();
    }

    /**
     * Cancels the biometric authentication, and dismisses the dialog upon confirmation from the
     * biometric service.
     */
    public void cancelAuthentication() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            if (mBiometricFragment != null) {
                mBiometricFragment.cancel();
            }
        } else {
            if (mFingerprintHelperFragment != null && mFingerprintDialogFragment != null) {
                mFingerprintHelperFragment.cancel(
                        FingerprintHelperFragment.USER_CANCELED_FROM_NONE);
                mFingerprintDialogFragment.dismiss();
            }
        }
    }

    /** Checks if the client is currently changing configurations (e.g., screen orientation). */
    private boolean isChangingConfigurations() {
        return (mFragmentActivity != null && mFragmentActivity.isChangingConfigurations())
                || (mFragment != null && mFragment.getActivity() != null
                && mFragment.getActivity().isChangingConfigurations());
    }

    /**
     * Gets the appropriate fragment manager for the client. This is either the support fragment
     * manager for a client activity or the child fragment manager for a client fragment.
     */
    private FragmentManager getFragmentManager() {
        return mFragmentActivity != null
                ? mFragmentActivity.getSupportFragmentManager()
                : mFragment.getChildFragmentManager();
    }
}
