/*
 * Copyright (C) 2014 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.systemui.statusbar.phone;

import static com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;

import android.content.Context;
import android.content.res.ColorStateList;
import android.hardware.biometrics.BiometricSourceType;
import android.os.Handler;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;

import com.android.internal.policy.SystemBarUtils;
import com.android.keyguard.KeyguardHostViewController;
import com.android.keyguard.KeyguardSecurityModel;
import com.android.keyguard.KeyguardSecurityView;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
import com.android.keyguard.dagger.KeyguardBouncerComponent;
import com.android.systemui.DejankUtils;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.ListenerSet;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;

/**
 * A class which manages the bouncer on the lockscreen.
 */
public class KeyguardBouncer {

    private static final String TAG = "KeyguardBouncer";
    static final long BOUNCER_FACE_DELAY = 1200;
    public static final float ALPHA_EXPANSION_THRESHOLD = 0.95f;
    public static final float EXPANSION_HIDDEN = 1f;
    public static final float EXPANSION_VISIBLE = 0f;

    protected final Context mContext;
    protected final ViewMediatorCallback mCallback;
    protected final ViewGroup mContainer;
    private final FalsingCollector mFalsingCollector;
    private final DismissCallbackRegistry mDismissCallbackRegistry;
    private final Handler mHandler;
    private final List<BouncerExpansionCallback> mExpansionCallbacks = new ArrayList<>();
    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
    private final KeyguardStateController mKeyguardStateController;
    private final KeyguardSecurityModel mKeyguardSecurityModel;
    private final KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
    private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
            new KeyguardUpdateMonitorCallback() {
                @Override
                public void onStrongAuthStateChanged(int userId) {
                    mBouncerPromptReason = mCallback.getBouncerPromptReason();
                }

                @Override
                public void onLockedOutStateChanged(BiometricSourceType type) {
                    if (type == BiometricSourceType.FINGERPRINT) {
                        mBouncerPromptReason = mCallback.getBouncerPromptReason();
                    }
                }
            };
    private final Runnable mRemoveViewRunnable = this::removeView;
    private final KeyguardBypassController mKeyguardBypassController;
    private KeyguardHostViewController mKeyguardViewController;
    private final ListenerSet<KeyguardResetCallback> mResetCallbacks = new ListenerSet<>();
    private final Runnable mResetRunnable = ()-> {
        if (mKeyguardViewController != null) {
            mKeyguardViewController.resetSecurityContainer();
            for (KeyguardResetCallback callback : mResetCallbacks) {
                callback.onKeyguardReset();
            }
        }
    };

    private int mStatusBarHeight;
    private float mExpansion = EXPANSION_HIDDEN;
    private boolean mShowingSoon;
    private int mBouncerPromptReason;
    private boolean mIsAnimatingAway;
    private boolean mIsScrimmed;
    private boolean mInitialized;

    private KeyguardBouncer(Context context, ViewMediatorCallback callback,
            ViewGroup container,
            DismissCallbackRegistry dismissCallbackRegistry, FalsingCollector falsingCollector,
            BouncerExpansionCallback expansionCallback,
            KeyguardStateController keyguardStateController,
            KeyguardUpdateMonitor keyguardUpdateMonitor,
            KeyguardBypassController keyguardBypassController, @Main Handler handler,
            KeyguardSecurityModel keyguardSecurityModel,
            KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory) {
        mContext = context;
        mCallback = callback;
        mContainer = container;
        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
        mFalsingCollector = falsingCollector;
        mDismissCallbackRegistry = dismissCallbackRegistry;
        mHandler = handler;
        mKeyguardStateController = keyguardStateController;
        mKeyguardSecurityModel = keyguardSecurityModel;
        mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory;
        mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback);
        mKeyguardBypassController = keyguardBypassController;
        mExpansionCallbacks.add(expansionCallback);
    }

    /**
     * Enable/disable only the back button
     */
    public void setBackButtonEnabled(boolean enabled) {
        int vis = mContainer.getSystemUiVisibility();
        if (enabled) {
            vis &= ~View.STATUS_BAR_DISABLE_BACK;
        } else {
            vis |= View.STATUS_BAR_DISABLE_BACK;
        }
        mContainer.setSystemUiVisibility(vis);
    }

    public void show(boolean resetSecuritySelection) {
        show(resetSecuritySelection, true /* scrimmed */);
    }

    /**
     * Shows the bouncer.
     *
     * @param resetSecuritySelection Cleans keyguard view
     * @param isScrimmed true when the bouncer show show scrimmed, false when the user will be
     *                 dragging it and translation should be deferred.
     */
    public void show(boolean resetSecuritySelection, boolean isScrimmed) {
        final int keyguardUserId = KeyguardUpdateMonitor.getCurrentUser();
        if (keyguardUserId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser()) {
            // In split system user mode, we never unlock system user.
            return;
        }

        try {
            Trace.beginSection("KeyguardBouncer#show");

            ensureView();
            mIsScrimmed = isScrimmed;

            // On the keyguard, we want to show the bouncer when the user drags up, but it's
            // not correct to end the falsing session. We still need to verify if those touches
            // are valid.
            // Later, at the end of the animation, when the bouncer is at the top of the screen,
            // onFullyShown() will be called and FalsingManager will stop recording touches.
            if (isScrimmed) {
                setExpansion(EXPANSION_VISIBLE);
            }

            if (resetSecuritySelection) {
                // showPrimarySecurityScreen() updates the current security method. This is needed
                // in case we are already showing and the current security method changed.
                showPrimarySecurityScreen();
            }

            if (mContainer.getVisibility() == View.VISIBLE || mShowingSoon) {
                // Calls to reset must resume the ViewControllers when in fullscreen mode
                if (needsFullscreenBouncer()) {
                    mKeyguardViewController.onResume();
                }
                return;
            }

            final int activeUserId = KeyguardUpdateMonitor.getCurrentUser();
            final boolean isSystemUser =
                UserManager.isSplitSystemUser() && activeUserId == UserHandle.USER_SYSTEM;
            final boolean allowDismissKeyguard = !isSystemUser && activeUserId == keyguardUserId;

            // If allowed, try to dismiss the Keyguard. If no security auth (password/pin/pattern)
            // is set, this will dismiss the whole Keyguard. Otherwise, show the bouncer.
            if (allowDismissKeyguard && mKeyguardViewController.dismiss(activeUserId)) {
                return;
            }

            // This condition may indicate an error on Android, so log it.
            if (!allowDismissKeyguard) {
                Log.w(TAG, "User can't dismiss keyguard: " + activeUserId + " != "
                        + keyguardUserId);
            }

            mShowingSoon = true;

            // Split up the work over multiple frames.
            DejankUtils.removeCallbacks(mResetRunnable);
            if (mKeyguardStateController.isFaceAuthEnabled()
                    && !mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
                            KeyguardUpdateMonitor.getCurrentUser())
                    && !needsFullscreenBouncer()
                    && !mKeyguardUpdateMonitor.userNeedsStrongAuth()
                    && !mKeyguardBypassController.getBypassEnabled()) {
                mHandler.postDelayed(mShowRunnable, BOUNCER_FACE_DELAY);
            } else {
                DejankUtils.postAfterTraversal(mShowRunnable);
            }

            mKeyguardStateController.notifyBouncerShowing(true /* showing */);
            dispatchStartingToShow();
        } finally {
            Trace.endSection();
        }
    }

    public boolean isScrimmed() {
        return mIsScrimmed;
    }

    /**
     * This method must be called at the end of the bouncer animation when
     * the translation is performed manually by the user, otherwise FalsingManager
     * will never be notified and its internal state will be out of sync.
     */
    private void onFullyShown() {
        mFalsingCollector.onBouncerShown();
        if (mKeyguardViewController == null) {
            Log.wtf(TAG, "onFullyShown when view was null");
        } else {
            mKeyguardViewController.onResume();
            mContainer.announceForAccessibility(
                    mKeyguardViewController.getAccessibilityTitleForCurrentMode());
        }
    }

    /**
     * @see #onFullyShown()
     */
    private void onFullyHidden() {
        cancelShowRunnable();
        setVisibility(View.INVISIBLE);
        mFalsingCollector.onBouncerHidden();
        DejankUtils.postAfterTraversal(mResetRunnable);
    }

    private void setVisibility(@View.Visibility int visibility) {
        mContainer.setVisibility(visibility);
        dispatchVisibilityChanged();
    }

    private final Runnable mShowRunnable = new Runnable() {
        @Override
        public void run() {
            setVisibility(View.VISIBLE);
            showPromptReason(mBouncerPromptReason);
            final CharSequence customMessage = mCallback.consumeCustomMessage();
            if (customMessage != null) {
                mKeyguardViewController.showErrorMessage(customMessage);
            }
            mKeyguardViewController.appear(mStatusBarHeight);
            mShowingSoon = false;
            if (mExpansion == EXPANSION_VISIBLE) {
                mKeyguardViewController.onResume();
                mKeyguardViewController.resetSecurityContainer();
                showPromptReason(mBouncerPromptReason);
            }
        }
    };

    /**
     * Show a string explaining why the security view needs to be solved.
     *
     * @param reason a flag indicating which string should be shown, see
     *               {@link KeyguardSecurityView#PROMPT_REASON_NONE}
     *               and {@link KeyguardSecurityView#PROMPT_REASON_RESTART}
     */
    public void showPromptReason(int reason) {
        if (mKeyguardViewController != null) {
            mKeyguardViewController.showPromptReason(reason);
        } else {
            Log.w(TAG, "Trying to show prompt reason on empty bouncer");
        }
    }

    public void showMessage(String message, ColorStateList colorState) {
        if (mKeyguardViewController != null) {
            mKeyguardViewController.showMessage(message, colorState);
        } else {
            Log.w(TAG, "Trying to show message on empty bouncer");
        }
    }

    private void cancelShowRunnable() {
        DejankUtils.removeCallbacks(mShowRunnable);
        mHandler.removeCallbacks(mShowRunnable);
        mShowingSoon = false;
    }

    public void showWithDismissAction(OnDismissAction r, Runnable cancelAction) {
        ensureView();
        setDismissAction(r, cancelAction);
        show(false /* resetSecuritySelection */);
    }

    /**
     * Set the actions to run when the keyguard is dismissed or when the dismiss is cancelled. Those
     * actions will still be run even if this bouncer is not shown, for instance when authenticating
     * with an alternate authenticator like the UDFPS.
     */
    public void setDismissAction(OnDismissAction r, Runnable cancelAction) {
        mKeyguardViewController.setOnDismissAction(r, cancelAction);
    }

    public void hide(boolean destroyView) {
        Trace.beginSection("KeyguardBouncer#hide");
        if (isShowing()) {
            SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
                    SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN);
            mDismissCallbackRegistry.notifyDismissCancelled();
        }
        mIsScrimmed = false;
        mFalsingCollector.onBouncerHidden();
        mKeyguardStateController.notifyBouncerShowing(false /* showing */);
        cancelShowRunnable();
        if (mKeyguardViewController != null) {
            mKeyguardViewController.cancelDismissAction();
            mKeyguardViewController.cleanUp();
        }
        mIsAnimatingAway = false;
        setVisibility(View.INVISIBLE);
        if (destroyView) {

            // We have a ViewFlipper that unregisters a broadcast when being detached, which may
            // be slow because of AM lock contention during unlocking. We can delay it a bit.
            mHandler.postDelayed(mRemoveViewRunnable, 50);
        }
        Trace.endSection();
    }

    /**
     * See {@link StatusBarKeyguardViewManager#startPreHideAnimation}.
     */
    public void startPreHideAnimation(Runnable runnable) {
        mIsAnimatingAway = true;
        if (mKeyguardViewController != null) {
            mKeyguardViewController.startDisappearAnimation(runnable);
        } else if (runnable != null) {
            runnable.run();
        }
    }

    /**
     * Reset the state of the view.
     */
    public void reset() {
        cancelShowRunnable();
        inflateView();
        mFalsingCollector.onBouncerHidden();
    }

    public void onScreenTurnedOff() {
        if (mKeyguardViewController != null && mContainer.getVisibility() == View.VISIBLE) {
            mKeyguardViewController.onPause();
        }
    }

    public boolean isShowing() {
        return (mShowingSoon || mContainer.getVisibility() == View.VISIBLE)
                && mExpansion == EXPANSION_VISIBLE && !isAnimatingAway();
    }

    /**
     * {@link #show(boolean)} was called but we're not showing yet, or being dragged.
     */
    public boolean inTransit() {
        return mShowingSoon || mExpansion != EXPANSION_HIDDEN && mExpansion != EXPANSION_VISIBLE;
    }

    public boolean getShowingSoon() {
        return mShowingSoon;
    }

    /**
     * @return {@code true} when bouncer's pre-hide animation already started but isn't completely
     *         hidden yet, {@code false} otherwise.
     */
    public boolean isAnimatingAway() {
        return mIsAnimatingAway;
    }

    public void prepare() {
        boolean wasInitialized = mInitialized;
        ensureView();
        if (wasInitialized) {
            showPrimarySecurityScreen();
        }
        mBouncerPromptReason = mCallback.getBouncerPromptReason();
    }

    private void showPrimarySecurityScreen() {
        mKeyguardViewController.showPrimarySecurityScreen();
    }

    /**
     * Current notification panel expansion
     * @param fraction 0 when notification panel is collapsed and 1 when expanded.
     * @see StatusBarKeyguardViewManager#onPanelExpansionChanged
     */
    public void setExpansion(float fraction) {
        float oldExpansion = mExpansion;
        boolean expansionChanged = mExpansion != fraction;
        mExpansion = fraction;
        if (mKeyguardViewController != null && !mIsAnimatingAway) {
            mKeyguardViewController.setExpansion(fraction);
        }

        if (fraction == EXPANSION_VISIBLE && oldExpansion != EXPANSION_VISIBLE) {
            onFullyShown();
            dispatchFullyShown();
        } else if (fraction == EXPANSION_HIDDEN && oldExpansion != EXPANSION_HIDDEN) {
            onFullyHidden();
            dispatchFullyHidden();
        } else if (fraction != EXPANSION_VISIBLE && oldExpansion == EXPANSION_VISIBLE) {
            dispatchStartingToHide();
            if (mKeyguardViewController != null) {
                mKeyguardViewController.onStartingToHide();
            }
        }

        if (expansionChanged) {
            dispatchExpansionChanged();
        }
    }

    public boolean willDismissWithAction() {
        return mKeyguardViewController != null && mKeyguardViewController.hasDismissActions();
    }

    public int getTop() {
        if (mKeyguardViewController == null) {
            return 0;
        }

        return mKeyguardViewController.getTop();
    }

    protected void ensureView() {
        // Removal of the view might be deferred to reduce unlock latency,
        // in this case we need to force the removal, otherwise we'll
        // end up in an unpredictable state.
        boolean forceRemoval = mHandler.hasCallbacks(mRemoveViewRunnable);
        if (!mInitialized || forceRemoval) {
            inflateView();
        }
    }

    protected void inflateView() {
        removeView();
        mHandler.removeCallbacks(mRemoveViewRunnable);

        KeyguardBouncerComponent component = mKeyguardBouncerComponentFactory.create(mContainer);
        mKeyguardViewController = component.getKeyguardHostViewController();
        mKeyguardViewController.init();

        mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
        setVisibility(View.INVISIBLE);

        final WindowInsets rootInsets = mContainer.getRootWindowInsets();
        if (rootInsets != null) {
            mContainer.dispatchApplyWindowInsets(rootInsets);
        }
        mInitialized = true;
    }

    protected void removeView() {
        mContainer.removeAllViews();
        mInitialized = false;
    }

    /**
     * @return True if and only if the security method should be shown before showing the
     * notifications on Keyguard, like SIM PIN/PUK.
     */
    public boolean needsFullscreenBouncer() {
        SecurityMode mode = mKeyguardSecurityModel.getSecurityMode(
                KeyguardUpdateMonitor.getCurrentUser());
        return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
    }

    /**
     * Like {@link #needsFullscreenBouncer}, but uses the currently visible security method, which
     * makes this method much faster.
     */
    public boolean isFullscreenBouncer() {
        if (mKeyguardViewController != null) {
            SecurityMode mode = mKeyguardViewController.getCurrentSecurityMode();
            return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
        }
        return false;
    }

    /**
     * WARNING: This method might cause Binder calls.
     */
    public boolean isSecure() {
        return mKeyguardSecurityModel.getSecurityMode(
                KeyguardUpdateMonitor.getCurrentUser()) != SecurityMode.None;
    }

    public boolean shouldDismissOnMenuPressed() {
        return mKeyguardViewController.shouldEnableMenuKey();
    }

    public boolean interceptMediaKey(KeyEvent event) {
        ensureView();
        return mKeyguardViewController.interceptMediaKey(event);
    }

    /**
     * @return true if the pre IME back event should be handled
     */
    public boolean dispatchBackKeyEventPreIme() {
        ensureView();
        return mKeyguardViewController.dispatchBackKeyEventPreIme();
    }

    public void notifyKeyguardAuthenticated(boolean strongAuth) {
        ensureView();
        mKeyguardViewController.finish(strongAuth, KeyguardUpdateMonitor.getCurrentUser());
    }

    private void dispatchFullyShown() {
        for (BouncerExpansionCallback callback : mExpansionCallbacks) {
            callback.onFullyShown();
        }
    }

    private void dispatchStartingToHide() {
        for (BouncerExpansionCallback callback : mExpansionCallbacks) {
            callback.onStartingToHide();
        }
    }

    private void dispatchStartingToShow() {
        for (BouncerExpansionCallback callback : mExpansionCallbacks) {
            callback.onStartingToShow();
        }
    }

    private void dispatchFullyHidden() {
        for (BouncerExpansionCallback callback : mExpansionCallbacks) {
            callback.onFullyHidden();
        }
    }

    private void dispatchExpansionChanged() {
        for (BouncerExpansionCallback callback : mExpansionCallbacks) {
            callback.onExpansionChanged(mExpansion);
        }
    }

    private void dispatchVisibilityChanged() {
        for (BouncerExpansionCallback callback : mExpansionCallbacks) {
            callback.onVisibilityChanged(mContainer.getVisibility() == View.VISIBLE);
        }
    }

    /**
     * Apply keyguard configuration from the currently active resources. This can be called when the
     * device configuration changes, to re-apply some resources that are qualified on the device
     * configuration.
     */
    public void updateResources() {
        if (mKeyguardViewController != null) {
            mKeyguardViewController.updateResources();
        }
    }

    public void dump(PrintWriter pw) {
        pw.println("KeyguardBouncer");
        pw.println("  isShowing(): " + isShowing());
        pw.println("  mStatusBarHeight: " + mStatusBarHeight);
        pw.println("  mExpansion: " + mExpansion);
        pw.println("  mKeyguardViewController; " + mKeyguardViewController);
        pw.println("  mShowingSoon: " + mShowingSoon);
        pw.println("  mBouncerPromptReason: " + mBouncerPromptReason);
        pw.println("  mIsAnimatingAway: " + mIsAnimatingAway);
        pw.println("  mInitialized: " + mInitialized);
    }

    /** Update keyguard position based on a tapped X coordinate. */
    public void updateKeyguardPosition(float x) {
        if (mKeyguardViewController != null) {
            mKeyguardViewController.updateKeyguardPosition(x);
        }
    }

    public void addKeyguardResetCallback(KeyguardResetCallback callback) {
        mResetCallbacks.addIfAbsent(callback);
    }

    public void removeKeyguardResetCallback(KeyguardResetCallback callback) {
        mResetCallbacks.remove(callback);
    }

    /**
     * Adds a callback to listen to bouncer expansion updates.
     */
    public void addBouncerExpansionCallback(BouncerExpansionCallback callback) {
        if (!mExpansionCallbacks.contains(callback)) {
            mExpansionCallbacks.add(callback);
        }
    }

    /**
     * Removes a previously added callback. If the callback was never added, this methood
     * does nothing.
     */
    public void removeBouncerExpansionCallback(BouncerExpansionCallback callback) {
        mExpansionCallbacks.remove(callback);
    }

    public interface BouncerExpansionCallback {
        /**
         * Invoked when the bouncer expansion reaches {@link KeyguardBouncer#EXPANSION_VISIBLE}.
         * This is NOT called each time the bouncer is shown, but rather only when the fully
         * shown amount has changed based on the panel expansion. The bouncer is visibility
         * can still change when the expansion amount hasn't changed.
         * See {@link KeyguardBouncer#isShowing()} for the checks for the bouncer showing state.
         */
        default void onFullyShown() {
        }

        /**
         * Invoked when the bouncer is starting to transition to a hidden state.
         */
        default void onStartingToHide() {
        }

        /**
         * Invoked when the bouncer is starting to transition to a visible state.
         */
        default void onStartingToShow() {
        }

        /**
         * Invoked when the bouncer expansion reaches {@link KeyguardBouncer#EXPANSION_HIDDEN}.
         */
        default void onFullyHidden() {
        }

        /**
         * From 0f {@link KeyguardBouncer#EXPANSION_VISIBLE} when fully visible
         * to 1f {@link KeyguardBouncer#EXPANSION_HIDDEN} when fully hidden
         */
        default void onExpansionChanged(float bouncerHideAmount) {}

        /**
         * Invoked when visibility of KeyguardBouncer has changed.
         * Note the bouncer expansion can be {@link KeyguardBouncer#EXPANSION_VISIBLE}, but the
         * view's visibility can be {@link View.INVISIBLE}.
         */
        default void onVisibilityChanged(boolean isVisible) {}
    }

    public interface KeyguardResetCallback {
        void onKeyguardReset();
    }

    /** Create a {@link KeyguardBouncer} once a container and bouncer callback are available. */
    public static class Factory {
        private final Context mContext;
        private final ViewMediatorCallback mCallback;
        private final DismissCallbackRegistry mDismissCallbackRegistry;
        private final FalsingCollector mFalsingCollector;
        private final KeyguardStateController mKeyguardStateController;
        private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
        private final KeyguardBypassController mKeyguardBypassController;
        private final Handler mHandler;
        private final KeyguardSecurityModel mKeyguardSecurityModel;
        private final KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;

        @Inject
        public Factory(Context context, ViewMediatorCallback callback,
                DismissCallbackRegistry dismissCallbackRegistry, FalsingCollector falsingCollector,
                KeyguardStateController keyguardStateController,
                KeyguardUpdateMonitor keyguardUpdateMonitor,
                KeyguardBypassController keyguardBypassController, @Main Handler handler,
                KeyguardSecurityModel keyguardSecurityModel,
                KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory) {
            mContext = context;
            mCallback = callback;
            mDismissCallbackRegistry = dismissCallbackRegistry;
            mFalsingCollector = falsingCollector;
            mKeyguardStateController = keyguardStateController;
            mKeyguardUpdateMonitor = keyguardUpdateMonitor;
            mKeyguardBypassController = keyguardBypassController;
            mHandler = handler;
            mKeyguardSecurityModel = keyguardSecurityModel;
            mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory;
        }

        /**
         * Construct a KeyguardBouncer that will exist in the given container.
         */
        public KeyguardBouncer create(ViewGroup container,
                BouncerExpansionCallback expansionCallback) {
            return new KeyguardBouncer(mContext, mCallback, container,
                    mDismissCallbackRegistry, mFalsingCollector, expansionCallback,
                    mKeyguardStateController, mKeyguardUpdateMonitor,
                    mKeyguardBypassController, mHandler, mKeyguardSecurityModel,
                    mKeyguardBouncerComponentFactory);
        }
    }
}
