KeyguardPatternView.java revision 2c7bc26a7447e6ac9eadcf328259aa3bb1be2949
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 */
16dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerpackage com.android.internal.policy.impl.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;
26dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.os.Bundle;
27dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.os.CountDownTimer;
28dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.os.SystemClock;
292c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasaniimport android.os.UserHandle;
30dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.util.AttributeSet;
31dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.util.Log;
32dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.view.MotionEvent;
33dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.view.View;
34dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.widget.Button;
353af630c8d18bcf4b23a5a308917319dd04cc8ed2Jim Millerimport android.widget.LinearLayout;
36dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
37dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport com.android.internal.widget.LockPatternUtils;
38dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport com.android.internal.widget.LockPatternView;
39dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport com.android.internal.R;
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;
88dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
89dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    enum FooterMode {
90dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        Normal,
91dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        ForgotLockPattern,
92dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        VerifyUnlocked
93dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
94dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
95dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    public KeyguardPatternView(Context context) {
96dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        this(context, null);
97dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
98dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
99dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    public KeyguardPatternView(Context context, AttributeSet attrs) {
100dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        super(context, attrs);
101dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
102dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
103dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    public void setKeyguardCallback(KeyguardSecurityCallback callback) {
104dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mCallback = callback;
105dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
106dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
107dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    public void setLockPatternUtils(LockPatternUtils utils) {
108dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternUtils = utils;
109dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
110dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
111dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    @Override
112dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    protected void onFinishInflate() {
113dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        super.onFinishInflate();
114dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternUtils = mLockPatternUtils == null
115dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                ? new LockPatternUtils(mContext) : mLockPatternUtils;
116dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
117dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternView = (LockPatternView) findViewById(R.id.lockPatternView);
118dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternView.setSaveEnabled(false);
119dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternView.setFocusable(false);
120dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternView.setOnPatternListener(new UnlockPatternListener());
121dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
122dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        // stealth mode will be the same for the life of this screen
123dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled());
124dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
125dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        // vibrate mode will be the same for the life of this screen
126dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
127dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
128dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mForgotPatternButton = (Button) findViewById(R.id.forgot_password_button);
129dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mForgotPatternButton.setText(R.string.kg_forgot_pattern_button_text);
130dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mForgotPatternButton.setOnClickListener(new OnClickListener() {
131dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            public void onClick(View v) {
132258341c377b6aa9f1bd29a9b507a97967e432dfeJim Miller                mCallback.showBackupSecurity();
133dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            }
134dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        });
135dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
136dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        setFocusableInTouchMode(true);
137dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
138dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        maybeEnableFallback(mContext);
1390b728244dc87b4a453f2191c2cb37a86e91aee0aJim Miller        mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
140dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
141dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
142dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    private void updateFooter(FooterMode mode) {
143dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        switch (mode) {
144dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            case Normal:
145dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                if (DEBUG) Log.d(TAG, "mode normal");
146dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mForgotPatternButton.setVisibility(View.GONE);
147dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                break;
148dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            case ForgotLockPattern:
149dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                if (DEBUG) Log.d(TAG, "mode ForgotLockPattern");
150dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mForgotPatternButton.setVisibility(View.VISIBLE);
151dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                break;
152dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            case VerifyUnlocked:
153dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                if (DEBUG) Log.d(TAG, "mode VerifyUnlocked");
154dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mForgotPatternButton.setVisibility(View.GONE);
155dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
156dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
157dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
158dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    @Override
159d2b82f70fede8c2ec4de34d8e6462ed4ece13c56Jim Miller    public boolean onTouchEvent(MotionEvent ev) {
160d2b82f70fede8c2ec4de34d8e6462ed4ece13c56Jim Miller        boolean result = super.onTouchEvent(ev);
161dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        // as long as the user is entering a pattern (i.e sending a touch event that was handled
162dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        // by this screen), keep poking the wake lock so that the screen will stay on.
163dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        final long elapsed = SystemClock.elapsedRealtime() - mLastPokeTime;
164dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        if (result && (elapsed > (UNLOCK_PATTERN_WAKE_INTERVAL_MS - 100))) {
165dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            mLastPokeTime = SystemClock.elapsedRealtime();
166dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
1675737534abab477cf32b4dd0aa7a72f70ede0502cJim Miller        mTempRect.set(0, 0, 0, 0);
1685737534abab477cf32b4dd0aa7a72f70ede0502cJim Miller        offsetRectIntoDescendantCoords(mLockPatternView, mTempRect);
1695737534abab477cf32b4dd0aa7a72f70ede0502cJim Miller        ev.offsetLocation(mTempRect.left, mTempRect.top);
1705737534abab477cf32b4dd0aa7a72f70ede0502cJim Miller        result = mLockPatternView.dispatchTouchEvent(ev) || result;
1715737534abab477cf32b4dd0aa7a72f70ede0502cJim Miller        ev.offsetLocation(-mTempRect.left, -mTempRect.top);
172dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        return result;
173dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
174dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
175dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    public void reset() {
176dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        // reset lock pattern
177dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternView.enableInput();
178dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternView.setEnabled(true);
179dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternView.clearPattern();
180dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
181dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        // if the user is currently locked out, enforce it.
182dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
183dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        if (deadline != 0) {
184dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            handleAttemptLockout(deadline);
185dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        } else {
1861625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett            displayDefaultSecurityMessage();
187dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
188dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
189dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        // the footer depends on how many total attempts the user has failed
190dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        if (mCallback.isVerifyUnlockOnly()) {
191dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            updateFooter(FooterMode.VerifyUnlocked);
192dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        } else if (mEnableFallback &&
193dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                (mTotalFailedPatternAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
194dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            updateFooter(FooterMode.ForgotLockPattern);
195dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        } else {
196dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            updateFooter(FooterMode.Normal);
197dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
198dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
199dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
200dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
2011625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett    private void displayDefaultSecurityMessage() {
2021625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett        if (KeyguardUpdateMonitor.getInstance(mContext).getMaxBiometricUnlockAttemptsReached()) {
2031625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett            mSecurityMessageDisplay.setMessage(R.string.faceunlock_multiple_failures, true);
2041625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett        } else {
2051625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett            mSecurityMessageDisplay.setMessage(R.string.kg_pattern_instructions, false);
2061625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett        }
2071625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett    }
2081625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett
2096fb841fa219eaae3e87f2fdc05e105d7a1813c42Adam Cohen    @Override
2106fb841fa219eaae3e87f2fdc05e105d7a1813c42Adam Cohen    public void showUsabilityHint() {
2116fb841fa219eaae3e87f2fdc05e105d7a1813c42Adam Cohen    }
2126fb841fa219eaae3e87f2fdc05e105d7a1813c42Adam Cohen
213dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    /** TODO: hook this up */
214dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    public void cleanUp() {
215dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        if (DEBUG) Log.v(TAG, "Cleanup() called on " + this);
216dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternUtils = null;
217dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternView.setOnPatternListener(null);
218dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
219dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
220dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    @Override
221dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    public void onWindowFocusChanged(boolean hasWindowFocus) {
222dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        super.onWindowFocusChanged(hasWindowFocus);
223dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        if (hasWindowFocus) {
224dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            // when timeout dialog closes we want to update our state
225dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            reset();
226dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
227dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
228dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
229dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    private class UnlockPatternListener implements LockPatternView.OnPatternListener {
230dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
231dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        public void onPatternStart() {
232dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            mLockPatternView.removeCallbacks(mCancelPatternRunnable);
233dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
234dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
235dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        public void onPatternCleared() {
236dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
237dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
238dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        public void onPatternCellAdded(List<LockPatternView.Cell> pattern) {
239dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            // To guard against accidental poking of the wakelock, look for
240dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            // the user actually trying to draw a pattern of some minimal length.
241dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
242dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mCallback.userActivity(UNLOCK_PATTERN_WAKE_INTERVAL_MS);
243dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            } else {
244dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                // Give just a little extra time if they hit one of the first few dots
245dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mCallback.userActivity(UNLOCK_PATTERN_WAKE_INTERVAL_FIRST_DOTS_MS);
246dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            }
247dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
248dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
249dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        public void onPatternDetected(List<LockPatternView.Cell> pattern) {
250dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            if (mLockPatternUtils.checkPattern(pattern)) {
251d2b82f70fede8c2ec4de34d8e6462ed4ece13c56Jim Miller                mCallback.reportSuccessfulUnlockAttempt();
252dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct);
253258341c377b6aa9f1bd29a9b507a97967e432dfeJim Miller                mTotalFailedPatternAttempts = 0;
254d2b82f70fede8c2ec4de34d8e6462ed4ece13c56Jim Miller                mCallback.dismiss(true);
255dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            } else {
256dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
257dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    mCallback.userActivity(UNLOCK_PATTERN_WAKE_INTERVAL_MS);
258dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                }
259dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
260dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                if (pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
261dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    mTotalFailedPatternAttempts++;
262dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    mFailedPatternAttemptsSinceLastTimeout++;
263dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    mCallback.reportFailedUnlockAttempt();
264dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                }
265dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                if (mFailedPatternAttemptsSinceLastTimeout
266dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                        >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) {
267dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
268dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    handleAttemptLockout(deadline);
269dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                } else {
2700a4f900463024908220d0c9bf4b291a6e1284846Adam Cohen                    mSecurityMessageDisplay.setMessage(R.string.kg_wrong_pattern, true);
271dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    mLockPatternView.postDelayed(mCancelPatternRunnable, PATTERN_CLEAR_TIMEOUT_MS);
272dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                }
273dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            }
274dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
275dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
276dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
277dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    private void maybeEnableFallback(Context context) {
278dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        // Ask the account manager if we have an account that can be used as a
279dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        // fallback in case the user forgets his pattern.
280dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        AccountAnalyzer accountAnalyzer = new AccountAnalyzer(AccountManager.get(context));
281dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        accountAnalyzer.start();
282dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
283dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
284dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    private class AccountAnalyzer implements AccountManagerCallback<Bundle> {
285dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        private final AccountManager mAccountManager;
286dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        private final Account[] mAccounts;
287dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        private int mAccountIndex;
288dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
289dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        private AccountAnalyzer(AccountManager accountManager) {
290dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            mAccountManager = accountManager;
2912c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani            mAccounts = accountManager.getAccountsByTypeAsUser("com.google",
2922c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani                    new UserHandle(mLockPatternUtils.getCurrentUser()));
293dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
294dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
295dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        private void next() {
296dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            // if we are ready to enable the fallback or if we depleted the list of accounts
297dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            // then finish and get out
2986f131416ba4ff48067dc4e627971391a6b6778c4Adam Cohen            if (mEnableFallback || mAccountIndex >= mAccounts.length) {
299dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                return;
300dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            }
301dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
302dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            // lookup the confirmCredentials intent for the current account
3032c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani            mAccountManager.confirmCredentialsAsUser(mAccounts[mAccountIndex], null, null, this,
3042c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani                    null, new UserHandle(mLockPatternUtils.getCurrentUser()));
305dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
306dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
307dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        public void start() {
308dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            mEnableFallback = false;
309dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            mAccountIndex = 0;
310dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            next();
311dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
312dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
313dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        public void run(AccountManagerFuture<Bundle> future) {
314dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            try {
315dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                Bundle result = future.getResult();
316dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                if (result.getParcelable(AccountManager.KEY_INTENT) != null) {
317dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    mEnableFallback = true;
318dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                }
319dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            } catch (OperationCanceledException e) {
320dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                // just skip the account if we are unable to query it
321dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            } catch (IOException e) {
322dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                // just skip the account if we are unable to query it
323dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            } catch (AuthenticatorException e) {
324dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                // just skip the account if we are unable to query it
325dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            } finally {
326dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mAccountIndex++;
327dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                next();
328dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            }
329dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
330dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
331dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
332dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    private void handleAttemptLockout(long elapsedRealtimeDeadline) {
333dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternView.clearPattern();
334dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternView.setEnabled(false);
335dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        final long elapsedRealtime = SystemClock.elapsedRealtime();
3366f131416ba4ff48067dc4e627971391a6b6778c4Adam Cohen        if (mEnableFallback) {
3376f131416ba4ff48067dc4e627971391a6b6778c4Adam Cohen            updateFooter(FooterMode.ForgotLockPattern);
3386f131416ba4ff48067dc4e627971391a6b6778c4Adam Cohen        }
339258341c377b6aa9f1bd29a9b507a97967e432dfeJim Miller
340dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mCountdownTimer = new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) {
341dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
342dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            @Override
343dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            public void onTick(long millisUntilFinished) {
344dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                final int secondsRemaining = (int) (millisUntilFinished / 1000);
3450ff7f010f8bfd011f0915031b02739ae3bee401eJim Miller                mSecurityMessageDisplay.setMessage(
3460a4f900463024908220d0c9bf4b291a6e1284846Adam Cohen                        R.string.kg_too_many_failed_attempts_countdown, true, secondsRemaining);
347dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            }
348dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
349dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            @Override
350dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            public void onFinish() {
351dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mLockPatternView.setEnabled(true);
3521625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett                displayDefaultSecurityMessage();
353dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                // TODO mUnlockIcon.setVisibility(View.VISIBLE);
354dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mFailedPatternAttemptsSinceLastTimeout = 0;
355dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                if (mEnableFallback) {
356dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    updateFooter(FooterMode.ForgotLockPattern);
357dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                } else {
358dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    updateFooter(FooterMode.Normal);
359dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                }
360dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            }
361dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
362dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }.start();
363dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
364dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
365dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    @Override
366dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    public boolean needsInput() {
367dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        return false;
368dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
369dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
370dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    @Override
371dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    public void onPause() {
372dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        if (mCountdownTimer != null) {
373dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            mCountdownTimer.cancel();
374dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            mCountdownTimer = null;
375dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
376dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
377dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
378dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    @Override
379dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    public void onResume() {
380dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        reset();
381dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
382dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
383dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    @Override
384dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    public KeyguardSecurityCallback getCallback() {
385dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        return mCallback;
386dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
387dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller}
388dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
389dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
390dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
391