• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.keyguard;
17 
18 import android.app.Activity;
19 import android.app.AlertDialog;
20 import android.app.admin.DevicePolicyManager;
21 import android.content.Context;
22 import android.os.UserHandle;
23 import android.os.UserManager;
24 import android.util.AttributeSet;
25 import android.util.Log;
26 import android.util.Slog;
27 import android.view.LayoutInflater;
28 import android.view.View;
29 import android.view.WindowManager;
30 import android.widget.FrameLayout;
31 
32 import com.android.internal.widget.LockPatternUtils;
33 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
34 
35 public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSecurityView {
36     private static final boolean DEBUG = KeyguardConstants.DEBUG;
37     private static final String TAG = "KeyguardSecurityView";
38 
39     private static final int USER_TYPE_PRIMARY = 1;
40     private static final int USER_TYPE_WORK_PROFILE = 2;
41     private static final int USER_TYPE_SECONDARY_USER = 3;
42 
43     private KeyguardSecurityModel mSecurityModel;
44     private boolean mEnableFallback; // TODO: This should get the value from KeyguardPatternView
45     private LockPatternUtils mLockPatternUtils;
46 
47     private KeyguardSecurityViewFlipper mSecurityViewFlipper;
48     private boolean mIsVerifyUnlockOnly;
49     private SecurityMode mCurrentSecuritySelection = SecurityMode.Invalid;
50     private boolean mIsBouncing;
51     private SecurityCallback mSecurityCallback;
52 
53     private final KeyguardUpdateMonitor mUpdateMonitor;
54 
55     // Used to notify the container when something interesting happens.
56     public interface SecurityCallback {
dismiss(boolean authenticated)57         public boolean dismiss(boolean authenticated);
userActivity()58         public void userActivity();
onSecurityModeChanged(SecurityMode securityMode, boolean needsInput)59         public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput);
finish()60         public void finish();
61     }
62 
KeyguardSecurityContainer(Context context, AttributeSet attrs)63     public KeyguardSecurityContainer(Context context, AttributeSet attrs) {
64         this(context, attrs, 0);
65     }
66 
KeyguardSecurityContainer(Context context)67     public KeyguardSecurityContainer(Context context) {
68         this(context, null, 0);
69     }
70 
KeyguardSecurityContainer(Context context, AttributeSet attrs, int defStyle)71     public KeyguardSecurityContainer(Context context, AttributeSet attrs, int defStyle) {
72         super(context, attrs, defStyle);
73         mSecurityModel = new KeyguardSecurityModel(context);
74         mLockPatternUtils = new LockPatternUtils(context);
75         mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
76     }
77 
setSecurityCallback(SecurityCallback callback)78     public void setSecurityCallback(SecurityCallback callback) {
79         mSecurityCallback = callback;
80     }
81 
82     @Override
onResume(int reason)83     public void onResume(int reason) {
84         if (mCurrentSecuritySelection != SecurityMode.None) {
85             getSecurityView(mCurrentSecuritySelection).onResume(reason);
86         }
87     }
88 
89     @Override
onPause()90     public void onPause() {
91         if (mCurrentSecuritySelection != SecurityMode.None) {
92             getSecurityView(mCurrentSecuritySelection).onPause();
93         }
94     }
95 
startAppearAnimation()96     public void startAppearAnimation() {
97         if (mCurrentSecuritySelection != SecurityMode.None) {
98             getSecurityView(mCurrentSecuritySelection).startAppearAnimation();
99         }
100     }
101 
startDisappearAnimation(Runnable onFinishRunnable)102     public boolean startDisappearAnimation(Runnable onFinishRunnable) {
103         if (mCurrentSecuritySelection != SecurityMode.None) {
104             return getSecurityView(mCurrentSecuritySelection).startDisappearAnimation(
105                     onFinishRunnable);
106         }
107         return false;
108     }
109 
updateSecurityViews(boolean isBouncing)110     void updateSecurityViews(boolean isBouncing) {
111         int children = mSecurityViewFlipper.getChildCount();
112         for (int i = 0; i < children; i++) {
113             updateSecurityView(mSecurityViewFlipper.getChildAt(i), isBouncing);
114         }
115     }
116 
announceCurrentSecurityMethod()117     public void announceCurrentSecurityMethod() {
118         View v = (View) getSecurityView(mCurrentSecuritySelection);
119         if (v != null) {
120             v.announceForAccessibility(v.getContentDescription());
121         }
122     }
123 
getCurrentSecurityModeContentDescription()124     public CharSequence getCurrentSecurityModeContentDescription() {
125         View v = (View) getSecurityView(mCurrentSecuritySelection);
126         if (v != null) {
127             return v.getContentDescription();
128         }
129         return "";
130     }
131 
getSecurityView(SecurityMode securityMode)132     private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
133         final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
134         KeyguardSecurityView view = null;
135         final int children = mSecurityViewFlipper.getChildCount();
136         for (int child = 0; child < children; child++) {
137             if (mSecurityViewFlipper.getChildAt(child).getId() == securityViewIdForMode) {
138                 view = ((KeyguardSecurityView)mSecurityViewFlipper.getChildAt(child));
139                 break;
140             }
141         }
142         int layoutId = getLayoutIdFor(securityMode);
143         if (view == null && layoutId != 0) {
144             final LayoutInflater inflater = LayoutInflater.from(mContext);
145             if (DEBUG) Log.v(TAG, "inflating id = " + layoutId);
146             View v = inflater.inflate(layoutId, mSecurityViewFlipper, false);
147             mSecurityViewFlipper.addView(v);
148             updateSecurityView(v, mIsBouncing);
149             view = (KeyguardSecurityView)v;
150         }
151 
152         return view;
153     }
154 
updateSecurityView(View view, boolean isBouncing)155     private void updateSecurityView(View view, boolean isBouncing) {
156         mIsBouncing = isBouncing;
157         if (view instanceof KeyguardSecurityView) {
158             KeyguardSecurityView ksv = (KeyguardSecurityView) view;
159             ksv.setKeyguardCallback(mCallback);
160             ksv.setLockPatternUtils(mLockPatternUtils);
161             if (isBouncing) {
162                 ksv.showBouncer(0);
163             } else {
164                 ksv.hideBouncer(0);
165             }
166         } else {
167             Log.w(TAG, "View " + view + " is not a KeyguardSecurityView");
168         }
169     }
170 
onFinishInflate()171     protected void onFinishInflate() {
172         mSecurityViewFlipper = (KeyguardSecurityViewFlipper) findViewById(R.id.view_flipper);
173         mSecurityViewFlipper.setLockPatternUtils(mLockPatternUtils);
174     }
175 
setLockPatternUtils(LockPatternUtils utils)176     public void setLockPatternUtils(LockPatternUtils utils) {
177         mLockPatternUtils = utils;
178         mSecurityModel.setLockPatternUtils(utils);
179         mSecurityViewFlipper.setLockPatternUtils(mLockPatternUtils);
180     }
181 
showDialog(String title, String message)182     private void showDialog(String title, String message) {
183         final AlertDialog dialog = new AlertDialog.Builder(mContext)
184             .setTitle(title)
185             .setMessage(message)
186             .setNeutralButton(R.string.ok, null)
187             .create();
188         if (!(mContext instanceof Activity)) {
189             dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
190         }
191         dialog.show();
192     }
193 
showTimeoutDialog()194     private void showTimeoutDialog() {
195         int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
196         int messageId = 0;
197 
198         switch (mSecurityModel.getSecurityMode()) {
199             case Pattern:
200                 messageId = R.string.kg_too_many_failed_pattern_attempts_dialog_message;
201                 break;
202             case PIN:
203                 messageId = R.string.kg_too_many_failed_pin_attempts_dialog_message;
204                 break;
205             case Password:
206                 messageId = R.string.kg_too_many_failed_password_attempts_dialog_message;
207                 break;
208             // These don't have timeout dialogs.
209             case Account:
210             case Biometric:
211             case Invalid:
212             case None:
213             case SimPin:
214             case SimPuk:
215                 break;
216         }
217 
218         if (messageId != 0) {
219             final String message = mContext.getString(messageId,
220                     KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts(),
221                     timeoutInSeconds);
222             showDialog(null, message);
223         }
224     }
225 
showAlmostAtWipeDialog(int attempts, int remaining, int userType)226     private void showAlmostAtWipeDialog(int attempts, int remaining, int userType) {
227         String message = null;
228         switch (userType) {
229             case USER_TYPE_PRIMARY:
230                 message = mContext.getString(R.string.kg_failed_attempts_almost_at_wipe,
231                         attempts, remaining);
232                 break;
233             case USER_TYPE_SECONDARY_USER:
234                 message = mContext.getString(R.string.kg_failed_attempts_almost_at_erase_user,
235                         attempts, remaining);
236                 break;
237             case USER_TYPE_WORK_PROFILE:
238                 message = mContext.getString(R.string.kg_failed_attempts_almost_at_erase_profile,
239                         attempts, remaining);
240                 break;
241         }
242         showDialog(null, message);
243     }
244 
showWipeDialog(int attempts, int userType)245     private void showWipeDialog(int attempts, int userType) {
246         String message = null;
247         switch (userType) {
248             case USER_TYPE_PRIMARY:
249                 message = mContext.getString(R.string.kg_failed_attempts_now_wiping,
250                         attempts);
251                 break;
252             case USER_TYPE_SECONDARY_USER:
253                 message = mContext.getString(R.string.kg_failed_attempts_now_erasing_user,
254                         attempts);
255                 break;
256             case USER_TYPE_WORK_PROFILE:
257                 message = mContext.getString(R.string.kg_failed_attempts_now_erasing_profile,
258                         attempts);
259                 break;
260         }
261         showDialog(null, message);
262     }
263 
showAlmostAtAccountLoginDialog()264     private void showAlmostAtAccountLoginDialog() {
265         final int timeoutInSeconds = (int) LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS / 1000;
266         final int count = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
267                 - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
268         String message = mContext.getString(R.string.kg_failed_attempts_almost_at_login,
269                 count, LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT, timeoutInSeconds);
270         showDialog(null, message);
271     }
272 
reportFailedUnlockAttempt()273     private void reportFailedUnlockAttempt() {
274         final KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
275         final int failedAttempts = monitor.getFailedUnlockAttempts() + 1; // +1 for this time
276 
277         if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts);
278 
279         SecurityMode mode = mSecurityModel.getSecurityMode();
280         final boolean usingPattern = mode == KeyguardSecurityModel.SecurityMode.Pattern;
281         final int currentUser = mLockPatternUtils.getCurrentUser();
282         final DevicePolicyManager dpm = mLockPatternUtils.getDevicePolicyManager();
283         final int failedAttemptsBeforeWipe =
284                 dpm.getMaximumFailedPasswordsForWipe(null, currentUser);
285 
286         final int failedAttemptWarning = LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
287                 - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;
288 
289         final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ?
290                 (failedAttemptsBeforeWipe - failedAttempts)
291                 : Integer.MAX_VALUE; // because DPM returns 0 if no restriction
292         boolean showTimeout = false;
293         if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) {
294             // The user has installed a DevicePolicyManager that requests a user/profile to be wiped
295             // N attempts. Once we get below the grace period, we post this dialog every time as a
296             // clear warning until the deletion fires.
297             // Check which profile has the strictest policy for failed password attempts
298             final int expiringUser = dpm.getProfileWithMinimumFailedPasswordsForWipe(currentUser);
299             int userType = USER_TYPE_PRIMARY;
300             if (expiringUser == currentUser) {
301                 if (expiringUser != UserHandle.USER_OWNER) {
302                     userType = USER_TYPE_SECONDARY_USER;
303                 }
304             } else if (expiringUser != UserHandle.USER_NULL) {
305                 userType = USER_TYPE_WORK_PROFILE;
306             } // If USER_NULL, which shouldn't happen, leave it as USER_TYPE_PRIMARY
307             if (remainingBeforeWipe > 0) {
308                 showAlmostAtWipeDialog(failedAttempts, remainingBeforeWipe, userType);
309             } else {
310                 // Too many attempts. The device will be wiped shortly.
311                 Slog.i(TAG, "Too many unlock attempts; user " + expiringUser + " will be wiped!");
312                 showWipeDialog(failedAttempts, userType);
313             }
314         } else {
315             showTimeout =
316                 (failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) == 0;
317             if (usingPattern && mEnableFallback) {
318                 if (failedAttempts == failedAttemptWarning) {
319                     showAlmostAtAccountLoginDialog();
320                     showTimeout = false; // don't show both dialogs
321                 } else if (failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) {
322                     mLockPatternUtils.setPermanentlyLocked(true);
323                     showSecurityScreen(SecurityMode.Account);
324                     // don't show timeout dialog because we show account unlock screen next
325                     showTimeout = false;
326                 }
327             }
328         }
329         monitor.reportFailedUnlockAttempt();
330         mLockPatternUtils.reportFailedPasswordAttempt();
331         if (showTimeout) {
332             showTimeoutDialog();
333         }
334     }
335 
336     /**
337      * Shows the primary security screen for the user. This will be either the multi-selector
338      * or the user's security method.
339      * @param turningOff true if the device is being turned off
340      */
showPrimarySecurityScreen(boolean turningOff)341     void showPrimarySecurityScreen(boolean turningOff) {
342         SecurityMode securityMode = mSecurityModel.getSecurityMode();
343         if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");
344         if (!turningOff &&
345                 KeyguardUpdateMonitor.getInstance(mContext).isAlternateUnlockEnabled()) {
346             // If we're not turning off, then allow biometric alternate.
347             // We'll reload it when the device comes back on.
348             securityMode = mSecurityModel.getAlternateFor(securityMode);
349         }
350         showSecurityScreen(securityMode);
351     }
352 
353     /**
354      * Shows the backup security screen for the current security mode.  This could be used for
355      * password recovery screens but is currently only used for pattern unlock to show the
356      * account unlock screen and biometric unlock to show the user's normal unlock.
357      */
showBackupSecurityScreen()358     private void showBackupSecurityScreen() {
359         if (DEBUG) Log.d(TAG, "showBackupSecurity()");
360         SecurityMode backup = mSecurityModel.getBackupSecurityMode(mCurrentSecuritySelection);
361         showSecurityScreen(backup);
362     }
363 
364     /**
365      * Shows the next security screen if there is one.
366      * @param authenticated true if the user entered the correct authentication
367      * @param authenticated
368      * @return true if keyguard is done
369      */
showNextSecurityScreenOrFinish(boolean authenticated)370     boolean showNextSecurityScreenOrFinish(boolean authenticated) {
371         if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");
372         boolean finish = false;
373         if (mUpdateMonitor.getUserHasTrust(mLockPatternUtils.getCurrentUser())) {
374             finish = true;
375         } else if (SecurityMode.None == mCurrentSecuritySelection) {
376             SecurityMode securityMode = mSecurityModel.getSecurityMode();
377             // Allow an alternate, such as biometric unlock
378             securityMode = mSecurityModel.getAlternateFor(securityMode);
379             if (SecurityMode.None == securityMode) {
380                 finish = true; // no security required
381             } else {
382                 showSecurityScreen(securityMode); // switch to the alternate security view
383             }
384         } else if (authenticated) {
385             switch (mCurrentSecuritySelection) {
386                 case Pattern:
387                 case Password:
388                 case PIN:
389                 case Account:
390                 case Biometric:
391                     finish = true;
392                     break;
393 
394                 case SimPin:
395                 case SimPuk:
396                     // Shortcut for SIM PIN/PUK to go to directly to user's security screen or home
397                     SecurityMode securityMode = mSecurityModel.getSecurityMode();
398                     if (securityMode != SecurityMode.None) {
399                         showSecurityScreen(securityMode);
400                     } else {
401                         finish = true;
402                     }
403                     break;
404 
405                 default:
406                     Log.v(TAG, "Bad security screen " + mCurrentSecuritySelection + ", fail safe");
407                     showPrimarySecurityScreen(false);
408                     break;
409             }
410         }
411         if (finish) {
412             mSecurityCallback.finish();
413         }
414         return finish;
415     }
416 
417     /**
418      * Switches to the given security view unless it's already being shown, in which case
419      * this is a no-op.
420      *
421      * @param securityMode
422      */
showSecurityScreen(SecurityMode securityMode)423     private void showSecurityScreen(SecurityMode securityMode) {
424         if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")");
425 
426         if (securityMode == mCurrentSecuritySelection) return;
427 
428         KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
429         KeyguardSecurityView newView = getSecurityView(securityMode);
430 
431         // Emulate Activity life cycle
432         if (oldView != null) {
433             oldView.onPause();
434             oldView.setKeyguardCallback(mNullCallback); // ignore requests from old view
435         }
436         if (securityMode != SecurityMode.None) {
437             newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
438             newView.setKeyguardCallback(mCallback);
439         }
440 
441         // Find and show this child.
442         final int childCount = mSecurityViewFlipper.getChildCount();
443 
444         final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
445         for (int i = 0; i < childCount; i++) {
446             if (mSecurityViewFlipper.getChildAt(i).getId() == securityViewIdForMode) {
447                 mSecurityViewFlipper.setDisplayedChild(i);
448                 break;
449             }
450         }
451 
452         mCurrentSecuritySelection = securityMode;
453         mSecurityCallback.onSecurityModeChanged(securityMode,
454                 securityMode != SecurityMode.None && newView.needsInput());
455     }
456 
getFlipper()457     private KeyguardSecurityViewFlipper getFlipper() {
458         for (int i = 0; i < getChildCount(); i++) {
459             View child = getChildAt(i);
460             if (child instanceof KeyguardSecurityViewFlipper) {
461                 return (KeyguardSecurityViewFlipper) child;
462             }
463         }
464         return null;
465     }
466 
showBouncer(int duration)467     public void showBouncer(int duration) {
468         KeyguardSecurityViewFlipper flipper = getFlipper();
469         if (flipper != null) {
470             flipper.showBouncer(duration);
471         }
472     }
473 
hideBouncer(int duration)474     public void hideBouncer(int duration) {
475         KeyguardSecurityViewFlipper flipper = getFlipper();
476         if (flipper != null) {
477             flipper.hideBouncer(duration);
478         }
479     }
480 
481     private KeyguardSecurityCallback mCallback = new KeyguardSecurityCallback() {
482 
483         public void userActivity() {
484             if (mSecurityCallback != null) {
485                 mSecurityCallback.userActivity();
486             }
487         }
488 
489         public void dismiss(boolean authenticated) {
490             mSecurityCallback.dismiss(authenticated);
491         }
492 
493         public boolean isVerifyUnlockOnly() {
494             return mIsVerifyUnlockOnly;
495         }
496 
497         public void reportUnlockAttempt(boolean success) {
498             KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);
499             if (success) {
500                 monitor.clearFailedUnlockAttempts();
501                 mLockPatternUtils.reportSuccessfulPasswordAttempt();
502             } else {
503                 if (mCurrentSecuritySelection == SecurityMode.Biometric) {
504                     monitor.reportFailedBiometricUnlockAttempt();
505                 } else {
506                     KeyguardSecurityContainer.this.reportFailedUnlockAttempt();
507                 }
508             }
509         }
510 
511         @Override
512         public void showBackupSecurity() {
513             KeyguardSecurityContainer.this.showBackupSecurityScreen();
514         }
515 
516     };
517 
518     // The following is used to ignore callbacks from SecurityViews that are no longer current
519     // (e.g. face unlock). This avoids unwanted asynchronous events from messing with the
520     // state for the current security method.
521     private KeyguardSecurityCallback mNullCallback = new KeyguardSecurityCallback() {
522         @Override
523         public void userActivity() { }
524         @Override
525         public void showBackupSecurity() { }
526         @Override
527         public void reportUnlockAttempt(boolean success) { }
528         @Override
529         public boolean isVerifyUnlockOnly() { return false; }
530         @Override
531         public void dismiss(boolean securityVerified) { }
532     };
533 
getSecurityViewIdForMode(SecurityMode securityMode)534     private int getSecurityViewIdForMode(SecurityMode securityMode) {
535         switch (securityMode) {
536             case Pattern: return R.id.keyguard_pattern_view;
537             case PIN: return R.id.keyguard_pin_view;
538             case Password: return R.id.keyguard_password_view;
539             case Biometric: return R.id.keyguard_face_unlock_view;
540             case Account: return R.id.keyguard_account_view;
541             case SimPin: return R.id.keyguard_sim_pin_view;
542             case SimPuk: return R.id.keyguard_sim_puk_view;
543         }
544         return 0;
545     }
546 
getLayoutIdFor(SecurityMode securityMode)547     private int getLayoutIdFor(SecurityMode securityMode) {
548         switch (securityMode) {
549             case Pattern: return R.layout.keyguard_pattern_view;
550             case PIN: return R.layout.keyguard_pin_view;
551             case Password: return R.layout.keyguard_password_view;
552             case Biometric: return R.layout.keyguard_face_unlock_view;
553             case Account: return R.layout.keyguard_account_view;
554             case SimPin: return R.layout.keyguard_sim_pin_view;
555             case SimPuk: return R.layout.keyguard_sim_puk_view;
556             default:
557                 return 0;
558         }
559     }
560 
getSecurityMode()561     public SecurityMode getSecurityMode() {
562         return mSecurityModel.getSecurityMode();
563     }
564 
getCurrentSecurityMode()565     public SecurityMode getCurrentSecurityMode() {
566         return mCurrentSecuritySelection;
567     }
568 
verifyUnlock()569     public void verifyUnlock() {
570         mIsVerifyUnlockOnly = true;
571         showSecurityScreen(getSecurityMode());
572     }
573 
getCurrentSecuritySelection()574     public SecurityMode getCurrentSecuritySelection() {
575         return mCurrentSecuritySelection;
576     }
577 
dismiss(boolean authenticated)578     public void dismiss(boolean authenticated) {
579         mCallback.dismiss(authenticated);
580     }
581 
needsInput()582     public boolean needsInput() {
583         return mSecurityViewFlipper.needsInput();
584     }
585 
586     @Override
setKeyguardCallback(KeyguardSecurityCallback callback)587     public void setKeyguardCallback(KeyguardSecurityCallback callback) {
588         mSecurityViewFlipper.setKeyguardCallback(callback);
589     }
590 
591     @Override
reset()592     public void reset() {
593         mSecurityViewFlipper.reset();
594     }
595 
596     @Override
getCallback()597     public KeyguardSecurityCallback getCallback() {
598         return mSecurityViewFlipper.getCallback();
599     }
600 
601     @Override
showUsabilityHint()602     public void showUsabilityHint() {
603         mSecurityViewFlipper.showUsabilityHint();
604     }
605 
606 }
607 
608