blob: 0001cd0a2798d5e3410ac36739855a6cb0c08c0d [file] [log] [blame]
/*
* 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);
if (mKeyguardViewController != null) {
mKeyguardViewController.onBouncerVisibilityChanged(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;
}
/**
* @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's 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);
}
}
}