• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 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 
17 package com.android.keyguard;
18 
19 import android.content.Context;
20 import android.graphics.drawable.Drawable;
21 import android.os.CountDownTimer;
22 import android.os.SystemClock;
23 import android.util.AttributeSet;
24 import android.view.HapticFeedbackConstants;
25 import android.view.KeyEvent;
26 import android.view.View;
27 import android.widget.LinearLayout;
28 
29 import com.android.internal.widget.LockPatternUtils;
30 
31 /**
32  * Base class for PIN and password unlock screens.
33  */
34 public abstract class KeyguardAbsKeyInputView extends LinearLayout
35         implements KeyguardSecurityView {
36     protected KeyguardSecurityCallback mCallback;
37     protected LockPatternUtils mLockPatternUtils;
38     protected SecurityMessageDisplay mSecurityMessageDisplay;
39     protected View mEcaView;
40     private Drawable mBouncerFrame;
41     protected boolean mEnableHaptics;
42 
43     // To avoid accidental lockout due to events while the device in in the pocket, ignore
44     // any passwords with length less than or equal to this length.
45     protected static final int MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT = 3;
46 
KeyguardAbsKeyInputView(Context context)47     public KeyguardAbsKeyInputView(Context context) {
48         this(context, null);
49     }
50 
KeyguardAbsKeyInputView(Context context, AttributeSet attrs)51     public KeyguardAbsKeyInputView(Context context, AttributeSet attrs) {
52         super(context, attrs);
53     }
54 
setKeyguardCallback(KeyguardSecurityCallback callback)55     public void setKeyguardCallback(KeyguardSecurityCallback callback) {
56         mCallback = callback;
57     }
58 
setLockPatternUtils(LockPatternUtils utils)59     public void setLockPatternUtils(LockPatternUtils utils) {
60         mLockPatternUtils = utils;
61         mEnableHaptics = mLockPatternUtils.isTactileFeedbackEnabled();
62     }
63 
reset()64     public void reset() {
65         // start fresh
66         resetPasswordText(false /* animate */);
67         // if the user is currently locked out, enforce it.
68         long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
69         if (shouldLockout(deadline)) {
70             handleAttemptLockout(deadline);
71         } else {
72             resetState();
73         }
74     }
75 
76     // Allow subclasses to override this behavior
shouldLockout(long deadline)77     protected boolean shouldLockout(long deadline) {
78         return deadline != 0;
79     }
80 
getPasswordTextViewId()81     protected abstract int getPasswordTextViewId();
resetState()82     protected abstract void resetState();
83 
84     @Override
onFinishInflate()85     protected void onFinishInflate() {
86         mLockPatternUtils = new LockPatternUtils(mContext);
87         mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
88         mEcaView = findViewById(R.id.keyguard_selector_fade_container);
89         View bouncerFrameView = findViewById(R.id.keyguard_bouncer_frame);
90         if (bouncerFrameView != null) {
91             mBouncerFrame = bouncerFrameView.getBackground();
92         }
93     }
94 
95     /*
96      * Override this if you have a different string for "wrong password"
97      *
98      * Note that PIN/PUK have their own implementation of verifyPasswordAndUnlock and so don't need this
99      */
getWrongPasswordStringId()100     protected int getWrongPasswordStringId() {
101         return R.string.kg_wrong_password;
102     }
103 
verifyPasswordAndUnlock()104     protected void verifyPasswordAndUnlock() {
105         String entry = getPasswordText();
106         if (mLockPatternUtils.checkPassword(entry)) {
107             mCallback.reportUnlockAttempt(true);
108             mCallback.dismiss(true);
109         } else {
110             if (entry.length() > MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT ) {
111                 // to avoid accidental lockout, only count attempts that are long enough to be a
112                 // real password. This may require some tweaking.
113                 mCallback.reportUnlockAttempt(false);
114                 int attempts = KeyguardUpdateMonitor.getInstance(mContext).getFailedUnlockAttempts();
115                 if (0 == (attempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
116                     long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
117                     handleAttemptLockout(deadline);
118                 }
119             }
120             mSecurityMessageDisplay.setMessage(getWrongPasswordStringId(), true);
121         }
122         resetPasswordText(true /* animate */);
123     }
124 
resetPasswordText(boolean animate)125     protected abstract void resetPasswordText(boolean animate);
getPasswordText()126     protected abstract String getPasswordText();
setPasswordEntryEnabled(boolean enabled)127     protected abstract void setPasswordEntryEnabled(boolean enabled);
128 
129     // Prevent user from using the PIN/Password entry until scheduled deadline.
handleAttemptLockout(long elapsedRealtimeDeadline)130     protected void handleAttemptLockout(long elapsedRealtimeDeadline) {
131         setPasswordEntryEnabled(false);
132         long elapsedRealtime = SystemClock.elapsedRealtime();
133         new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) {
134 
135             @Override
136             public void onTick(long millisUntilFinished) {
137                 int secondsRemaining = (int) (millisUntilFinished / 1000);
138                 mSecurityMessageDisplay.setMessage(
139                         R.string.kg_too_many_failed_attempts_countdown, true, secondsRemaining);
140             }
141 
142             @Override
143             public void onFinish() {
144                 mSecurityMessageDisplay.setMessage("", false);
145                 resetState();
146             }
147         }.start();
148     }
149 
150     @Override
onKeyDown(int keyCode, KeyEvent event)151     public boolean onKeyDown(int keyCode, KeyEvent event) {
152         mCallback.userActivity();
153         return false;
154     }
155 
156     @Override
needsInput()157     public boolean needsInput() {
158         return false;
159     }
160 
161     @Override
onPause()162     public void onPause() {
163 
164     }
165 
166     @Override
onResume(int reason)167     public void onResume(int reason) {
168         reset();
169     }
170 
171     @Override
getCallback()172     public KeyguardSecurityCallback getCallback() {
173         return mCallback;
174     }
175 
176     // Cause a VIRTUAL_KEY vibration
doHapticKeyClick()177     public void doHapticKeyClick() {
178         if (mEnableHaptics) {
179             performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
180                     HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING
181                     | HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
182         }
183     }
184 
185     @Override
showBouncer(int duration)186     public void showBouncer(int duration) {
187         KeyguardSecurityViewHelper.
188                 showBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
189     }
190 
191     @Override
hideBouncer(int duration)192     public void hideBouncer(int duration) {
193         KeyguardSecurityViewHelper.
194                 hideBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
195     }
196 
197     @Override
startDisappearAnimation(Runnable finishRunnable)198     public boolean startDisappearAnimation(Runnable finishRunnable) {
199         return false;
200     }
201 }
202 
203