1dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller/* 2dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * Copyright (C) 2012 The Android Open Source Project 3dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * 4dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * Licensed under the Apache License, Version 2.0 (the "License"); 5dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * you may not use this file except in compliance with the License. 6dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * You may obtain a copy of the License at 7dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * 8dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * http://www.apache.org/licenses/LICENSE-2.0 9dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * 10dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * Unless required by applicable law or agreed to in writing, software 11dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * distributed under the License is distributed on an "AS IS" BASIS, 12dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * See the License for the specific language governing permissions and 14dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * limitations under the License. 15dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller */ 165ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Millerpackage com.android.keyguard; 17dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 18dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.accounts.Account; 19dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.accounts.AccountManager; 20dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.accounts.AccountManagerCallback; 21dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.accounts.AccountManagerFuture; 22dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.accounts.AuthenticatorException; 23dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.accounts.OperationCanceledException; 24dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.content.Context; 255737534abab477cf32b4dd0aa7a72f70ede0502cJim Millerimport android.graphics.Rect; 26c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wrenimport android.graphics.drawable.Drawable; 27dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.os.Bundle; 28dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.os.CountDownTimer; 29dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.os.SystemClock; 302c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasaniimport android.os.UserHandle; 31dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.util.AttributeSet; 32dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.util.Log; 33dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.view.MotionEvent; 34dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.view.View; 35dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.widget.Button; 363af630c8d18bcf4b23a5a308917319dd04cc8ed2Jim Millerimport android.widget.LinearLayout; 37dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 38dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport com.android.internal.widget.LockPatternUtils; 39dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport com.android.internal.widget.LockPatternView; 40dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 41dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport java.io.IOException; 42dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport java.util.List; 43dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 443af630c8d18bcf4b23a5a308917319dd04cc8ed2Jim Millerpublic class KeyguardPatternView extends LinearLayout implements KeyguardSecurityView { 45dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 46dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private static final String TAG = "SecurityPatternView"; 47dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private static final boolean DEBUG = false; 48dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 49dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // how long before we clear the wrong pattern 50dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private static final int PATTERN_CLEAR_TIMEOUT_MS = 2000; 51dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 52dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // how long we stay awake after each key beyond MIN_PATTERN_BEFORE_POKE_WAKELOCK 53dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private static final int UNLOCK_PATTERN_WAKE_INTERVAL_MS = 7000; 54dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 55dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // how long we stay awake after the user hits the first dot. 56dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private static final int UNLOCK_PATTERN_WAKE_INTERVAL_FIRST_DOTS_MS = 2000; 57dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 58dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // how many cells the user has to cross before we poke the wakelock 59dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private static final int MIN_PATTERN_BEFORE_POKE_WAKELOCK = 2; 60dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 61dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private int mFailedPatternAttemptsSinceLastTimeout = 0; 62dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private int mTotalFailedPatternAttempts = 0; 63dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private CountDownTimer mCountdownTimer = null; 64dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private LockPatternUtils mLockPatternUtils; 65dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private LockPatternView mLockPatternView; 66dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private Button mForgotPatternButton; 67dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private KeyguardSecurityCallback mCallback; 68dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private boolean mEnableFallback; 69dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 70dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller /** 71dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * Keeps track of the last time we poked the wake lock during dispatching of the touch event. 72dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * Initialized to something guaranteed to make us poke the wakelock when the user starts 73dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * drawing the pattern. 74dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * @see #dispatchTouchEvent(android.view.MotionEvent) 75dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller */ 76dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private long mLastPokeTime = -UNLOCK_PATTERN_WAKE_INTERVAL_MS; 77dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 78dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller /** 79dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller * Useful for clearing out the wrong pattern after a delay 80dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller */ 81dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private Runnable mCancelPatternRunnable = new Runnable() { 82dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public void run() { 83dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternView.clearPattern(); 84dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 85dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller }; 865737534abab477cf32b4dd0aa7a72f70ede0502cJim Miller private Rect mTempRect = new Rect(); 870ff7f010f8bfd011f0915031b02739ae3bee401eJim Miller private SecurityMessageDisplay mSecurityMessageDisplay; 88c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren private View mEcaView; 89c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren private Drawable mBouncerFrame; 90dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 91dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller enum FooterMode { 92dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller Normal, 93dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller ForgotLockPattern, 94dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller VerifyUnlocked 95dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 96dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 97dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public KeyguardPatternView(Context context) { 98dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller this(context, null); 99dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 100dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 101dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public KeyguardPatternView(Context context, AttributeSet attrs) { 102dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller super(context, attrs); 103dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 104dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 105dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public void setKeyguardCallback(KeyguardSecurityCallback callback) { 106dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mCallback = callback; 107dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 108dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 109dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public void setLockPatternUtils(LockPatternUtils utils) { 110dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternUtils = utils; 111dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 112dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 113dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller @Override 114dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller protected void onFinishInflate() { 115dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller super.onFinishInflate(); 116dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternUtils = mLockPatternUtils == null 117dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller ? new LockPatternUtils(mContext) : mLockPatternUtils; 118dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 119dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternView = (LockPatternView) findViewById(R.id.lockPatternView); 120dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternView.setSaveEnabled(false); 121dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternView.setFocusable(false); 122dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternView.setOnPatternListener(new UnlockPatternListener()); 123dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 124dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // stealth mode will be the same for the life of this screen 125dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled()); 126dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 127dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // vibrate mode will be the same for the life of this screen 128dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled()); 129dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 130dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mForgotPatternButton = (Button) findViewById(R.id.forgot_password_button); 131b499b1fa082147ad37e1211f32210b44bdbc0750Daniel Sandler // note: some configurations don't have an emergency call area 132b499b1fa082147ad37e1211f32210b44bdbc0750Daniel Sandler if (mForgotPatternButton != null) { 133b499b1fa082147ad37e1211f32210b44bdbc0750Daniel Sandler mForgotPatternButton.setText(R.string.kg_forgot_pattern_button_text); 134b499b1fa082147ad37e1211f32210b44bdbc0750Daniel Sandler mForgotPatternButton.setOnClickListener(new OnClickListener() { 135b499b1fa082147ad37e1211f32210b44bdbc0750Daniel Sandler public void onClick(View v) { 136b499b1fa082147ad37e1211f32210b44bdbc0750Daniel Sandler mCallback.showBackupSecurity(); 137b499b1fa082147ad37e1211f32210b44bdbc0750Daniel Sandler } 138b499b1fa082147ad37e1211f32210b44bdbc0750Daniel Sandler }); 139b499b1fa082147ad37e1211f32210b44bdbc0750Daniel Sandler } 140dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 141dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller setFocusableInTouchMode(true); 142dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 143dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller maybeEnableFallback(mContext); 1440b728244dc87b4a453f2191c2cb37a86e91aee0aJim Miller mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this); 145c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren mEcaView = findViewById(R.id.keyguard_selector_fade_container); 146c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren View bouncerFrameView = findViewById(R.id.keyguard_bouncer_frame); 147c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren if (bouncerFrameView != null) { 148c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren mBouncerFrame = bouncerFrameView.getBackground(); 149c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren } 150dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 151dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 152dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private void updateFooter(FooterMode mode) { 153b499b1fa082147ad37e1211f32210b44bdbc0750Daniel Sandler if (mForgotPatternButton == null) return; // no ECA? no footer 154b499b1fa082147ad37e1211f32210b44bdbc0750Daniel Sandler 155dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller switch (mode) { 156dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller case Normal: 157dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller if (DEBUG) Log.d(TAG, "mode normal"); 158dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mForgotPatternButton.setVisibility(View.GONE); 159dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller break; 160dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller case ForgotLockPattern: 161dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller if (DEBUG) Log.d(TAG, "mode ForgotLockPattern"); 162dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mForgotPatternButton.setVisibility(View.VISIBLE); 163dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller break; 164dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller case VerifyUnlocked: 165dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller if (DEBUG) Log.d(TAG, "mode VerifyUnlocked"); 166dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mForgotPatternButton.setVisibility(View.GONE); 167dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 168dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 169dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 170dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller @Override 171d2b82f70fede8c2ec4de34d8e6462ed4ece13c56Jim Miller public boolean onTouchEvent(MotionEvent ev) { 172d2b82f70fede8c2ec4de34d8e6462ed4ece13c56Jim Miller boolean result = super.onTouchEvent(ev); 173dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // as long as the user is entering a pattern (i.e sending a touch event that was handled 174dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // by this screen), keep poking the wake lock so that the screen will stay on. 175dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller final long elapsed = SystemClock.elapsedRealtime() - mLastPokeTime; 176dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller if (result && (elapsed > (UNLOCK_PATTERN_WAKE_INTERVAL_MS - 100))) { 177dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLastPokeTime = SystemClock.elapsedRealtime(); 178dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 1795737534abab477cf32b4dd0aa7a72f70ede0502cJim Miller mTempRect.set(0, 0, 0, 0); 1805737534abab477cf32b4dd0aa7a72f70ede0502cJim Miller offsetRectIntoDescendantCoords(mLockPatternView, mTempRect); 1815737534abab477cf32b4dd0aa7a72f70ede0502cJim Miller ev.offsetLocation(mTempRect.left, mTempRect.top); 1825737534abab477cf32b4dd0aa7a72f70ede0502cJim Miller result = mLockPatternView.dispatchTouchEvent(ev) || result; 1835737534abab477cf32b4dd0aa7a72f70ede0502cJim Miller ev.offsetLocation(-mTempRect.left, -mTempRect.top); 184dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller return result; 185dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 186dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 187dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public void reset() { 188dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // reset lock pattern 189dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternView.enableInput(); 190dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternView.setEnabled(true); 191dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternView.clearPattern(); 192dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 193dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // if the user is currently locked out, enforce it. 194dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller long deadline = mLockPatternUtils.getLockoutAttemptDeadline(); 195dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller if (deadline != 0) { 196dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller handleAttemptLockout(deadline); 197dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } else { 1981625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett displayDefaultSecurityMessage(); 199dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 200dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 201dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // the footer depends on how many total attempts the user has failed 202dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller if (mCallback.isVerifyUnlockOnly()) { 203dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller updateFooter(FooterMode.VerifyUnlocked); 204dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } else if (mEnableFallback && 205dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller (mTotalFailedPatternAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) { 206dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller updateFooter(FooterMode.ForgotLockPattern); 207dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } else { 208dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller updateFooter(FooterMode.Normal); 209dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 210dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 211dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 212dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 2131625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett private void displayDefaultSecurityMessage() { 2141625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett if (KeyguardUpdateMonitor.getInstance(mContext).getMaxBiometricUnlockAttemptsReached()) { 2151625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett mSecurityMessageDisplay.setMessage(R.string.faceunlock_multiple_failures, true); 2161625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett } else { 2171625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett mSecurityMessageDisplay.setMessage(R.string.kg_pattern_instructions, false); 2181625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett } 2191625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett } 2201625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett 2216fb841fa219eaae3e87f2fdc05e105d7a1813c42Adam Cohen @Override 2226fb841fa219eaae3e87f2fdc05e105d7a1813c42Adam Cohen public void showUsabilityHint() { 2236fb841fa219eaae3e87f2fdc05e105d7a1813c42Adam Cohen } 2246fb841fa219eaae3e87f2fdc05e105d7a1813c42Adam Cohen 225dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller /** TODO: hook this up */ 226dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public void cleanUp() { 227dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller if (DEBUG) Log.v(TAG, "Cleanup() called on " + this); 228dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternUtils = null; 229dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternView.setOnPatternListener(null); 230dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 231dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 232dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller @Override 233dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public void onWindowFocusChanged(boolean hasWindowFocus) { 234dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller super.onWindowFocusChanged(hasWindowFocus); 235dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller if (hasWindowFocus) { 236dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // when timeout dialog closes we want to update our state 237dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller reset(); 238dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 239dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 240dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 241dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private class UnlockPatternListener implements LockPatternView.OnPatternListener { 242dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 243dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public void onPatternStart() { 244dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternView.removeCallbacks(mCancelPatternRunnable); 245dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 246dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 247dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public void onPatternCleared() { 248dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 249dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 250dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public void onPatternCellAdded(List<LockPatternView.Cell> pattern) { 251dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // To guard against accidental poking of the wakelock, look for 252dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // the user actually trying to draw a pattern of some minimal length. 253dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) { 254dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mCallback.userActivity(UNLOCK_PATTERN_WAKE_INTERVAL_MS); 255dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } else { 256dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // Give just a little extra time if they hit one of the first few dots 257dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mCallback.userActivity(UNLOCK_PATTERN_WAKE_INTERVAL_FIRST_DOTS_MS); 258dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 259dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 260dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 261dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public void onPatternDetected(List<LockPatternView.Cell> pattern) { 262dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller if (mLockPatternUtils.checkPattern(pattern)) { 263d2b82f70fede8c2ec4de34d8e6462ed4ece13c56Jim Miller mCallback.reportSuccessfulUnlockAttempt(); 264dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct); 265258341c377b6aa9f1bd29a9b507a97967e432dfeJim Miller mTotalFailedPatternAttempts = 0; 266d2b82f70fede8c2ec4de34d8e6462ed4ece13c56Jim Miller mCallback.dismiss(true); 267dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } else { 268dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) { 269dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mCallback.userActivity(UNLOCK_PATTERN_WAKE_INTERVAL_MS); 270dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 271dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong); 272dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller if (pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) { 273dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mTotalFailedPatternAttempts++; 274dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mFailedPatternAttemptsSinceLastTimeout++; 275dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mCallback.reportFailedUnlockAttempt(); 276dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 277dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller if (mFailedPatternAttemptsSinceLastTimeout 278dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) { 279dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller long deadline = mLockPatternUtils.setLockoutAttemptDeadline(); 280dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller handleAttemptLockout(deadline); 281dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } else { 2820a4f900463024908220d0c9bf4b291a6e1284846Adam Cohen mSecurityMessageDisplay.setMessage(R.string.kg_wrong_pattern, true); 283dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternView.postDelayed(mCancelPatternRunnable, PATTERN_CLEAR_TIMEOUT_MS); 284dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 285dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 286dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 287dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 288dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 289dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private void maybeEnableFallback(Context context) { 290dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // Ask the account manager if we have an account that can be used as a 291dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // fallback in case the user forgets his pattern. 292dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller AccountAnalyzer accountAnalyzer = new AccountAnalyzer(AccountManager.get(context)); 293dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller accountAnalyzer.start(); 294dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 295dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 296dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private class AccountAnalyzer implements AccountManagerCallback<Bundle> { 297dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private final AccountManager mAccountManager; 298dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private final Account[] mAccounts; 299dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private int mAccountIndex; 300dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 301dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private AccountAnalyzer(AccountManager accountManager) { 302dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mAccountManager = accountManager; 3032c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani mAccounts = accountManager.getAccountsByTypeAsUser("com.google", 3042c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani new UserHandle(mLockPatternUtils.getCurrentUser())); 305dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 306dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 307dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private void next() { 308dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // if we are ready to enable the fallback or if we depleted the list of accounts 309dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // then finish and get out 3106f131416ba4ff48067dc4e627971391a6b6778c4Adam Cohen if (mEnableFallback || mAccountIndex >= mAccounts.length) { 311dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller return; 312dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 313dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 314dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // lookup the confirmCredentials intent for the current account 3152c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani mAccountManager.confirmCredentialsAsUser(mAccounts[mAccountIndex], null, null, this, 3162c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani null, new UserHandle(mLockPatternUtils.getCurrentUser())); 317dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 318dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 319dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public void start() { 320dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mEnableFallback = false; 321dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mAccountIndex = 0; 322dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller next(); 323dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 324dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 325dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public void run(AccountManagerFuture<Bundle> future) { 326dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller try { 327dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller Bundle result = future.getResult(); 328dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller if (result.getParcelable(AccountManager.KEY_INTENT) != null) { 329dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mEnableFallback = true; 330dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 331dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } catch (OperationCanceledException e) { 332dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // just skip the account if we are unable to query it 333dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } catch (IOException e) { 334dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // just skip the account if we are unable to query it 335dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } catch (AuthenticatorException e) { 336dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // just skip the account if we are unable to query it 337dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } finally { 338dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mAccountIndex++; 339dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller next(); 340dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 341dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 342dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 343dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 344dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller private void handleAttemptLockout(long elapsedRealtimeDeadline) { 345dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternView.clearPattern(); 346dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternView.setEnabled(false); 347dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller final long elapsedRealtime = SystemClock.elapsedRealtime(); 3486f131416ba4ff48067dc4e627971391a6b6778c4Adam Cohen if (mEnableFallback) { 3496f131416ba4ff48067dc4e627971391a6b6778c4Adam Cohen updateFooter(FooterMode.ForgotLockPattern); 3506f131416ba4ff48067dc4e627971391a6b6778c4Adam Cohen } 351258341c377b6aa9f1bd29a9b507a97967e432dfeJim Miller 352dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mCountdownTimer = new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) { 353dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 354dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller @Override 355dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public void onTick(long millisUntilFinished) { 356dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller final int secondsRemaining = (int) (millisUntilFinished / 1000); 3570ff7f010f8bfd011f0915031b02739ae3bee401eJim Miller mSecurityMessageDisplay.setMessage( 3580a4f900463024908220d0c9bf4b291a6e1284846Adam Cohen R.string.kg_too_many_failed_attempts_countdown, true, secondsRemaining); 359dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 360dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 361dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller @Override 362dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public void onFinish() { 363dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mLockPatternView.setEnabled(true); 3641625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett displayDefaultSecurityMessage(); 365dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller // TODO mUnlockIcon.setVisibility(View.VISIBLE); 366dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mFailedPatternAttemptsSinceLastTimeout = 0; 367dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller if (mEnableFallback) { 368dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller updateFooter(FooterMode.ForgotLockPattern); 369dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } else { 370dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller updateFooter(FooterMode.Normal); 371dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 372dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 373dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 374dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller }.start(); 375dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 376dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 377dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller @Override 378dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public boolean needsInput() { 379dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller return false; 380dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 381dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 382dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller @Override 383dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public void onPause() { 384dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller if (mCountdownTimer != null) { 385dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mCountdownTimer.cancel(); 386dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller mCountdownTimer = null; 387dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 388dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 389dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 390dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller @Override 391a042ac90640c0c3fd3c5349083b86bbfd6319b64Chris Wren public void onResume(int reason) { 392dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller reset(); 393dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 394dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 395dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller @Override 396dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller public KeyguardSecurityCallback getCallback() { 397dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller return mCallback; 398dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller } 399dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 400c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren @Override 401c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren public void showBouncer(int duration) { 402c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren KeyguardSecurityViewHelper. 403c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren showBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration); 404c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren } 405dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller 406c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren @Override 407c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren public void hideBouncer(int duration) { 408c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren KeyguardSecurityViewHelper. 409c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren hideBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration); 410c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren } 411c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren} 412