KeyguardPatternView.java revision c0ae9e67ebe6f1298800feaed1b43e867139a904
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;
26c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wrenimport android.graphics.drawable.Drawable;
27dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.os.Bundle;
28dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.os.CountDownTimer;
29dcb3d84b82cc2448d04e73359a716581bfb657dbJim Millerimport android.os.SystemClock;
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;
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);
131dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mForgotPatternButton.setText(R.string.kg_forgot_pattern_button_text);
132dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mForgotPatternButton.setOnClickListener(new OnClickListener() {
133dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            public void onClick(View v) {
134258341c377b6aa9f1bd29a9b507a97967e432dfeJim Miller                mCallback.showBackupSecurity();
135dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            }
136dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        });
137dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
138dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        setFocusableInTouchMode(true);
139dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
140dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        maybeEnableFallback(mContext);
1410b728244dc87b4a453f2191c2cb37a86e91aee0aJim Miller        mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
142c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren        mEcaView = findViewById(R.id.keyguard_selector_fade_container);
143c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren        View bouncerFrameView = findViewById(R.id.keyguard_bouncer_frame);
144c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren        if (bouncerFrameView != null) {
145c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren            mBouncerFrame = bouncerFrameView.getBackground();
146c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren        }
147dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
148dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
149dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    private void updateFooter(FooterMode mode) {
150dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        switch (mode) {
151dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            case Normal:
152dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                if (DEBUG) Log.d(TAG, "mode normal");
153dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mForgotPatternButton.setVisibility(View.GONE);
154dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                break;
155dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            case ForgotLockPattern:
156dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                if (DEBUG) Log.d(TAG, "mode ForgotLockPattern");
157dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mForgotPatternButton.setVisibility(View.VISIBLE);
158dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                break;
159dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            case VerifyUnlocked:
160dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                if (DEBUG) Log.d(TAG, "mode VerifyUnlocked");
161dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mForgotPatternButton.setVisibility(View.GONE);
162dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
163dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
164dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
165dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    @Override
166d2b82f70fede8c2ec4de34d8e6462ed4ece13c56Jim Miller    public boolean onTouchEvent(MotionEvent ev) {
167d2b82f70fede8c2ec4de34d8e6462ed4ece13c56Jim Miller        boolean result = super.onTouchEvent(ev);
168dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        // as long as the user is entering a pattern (i.e sending a touch event that was handled
169dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        // by this screen), keep poking the wake lock so that the screen will stay on.
170dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        final long elapsed = SystemClock.elapsedRealtime() - mLastPokeTime;
171dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        if (result && (elapsed > (UNLOCK_PATTERN_WAKE_INTERVAL_MS - 100))) {
172dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            mLastPokeTime = SystemClock.elapsedRealtime();
173dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
1745737534abab477cf32b4dd0aa7a72f70ede0502cJim Miller        mTempRect.set(0, 0, 0, 0);
1755737534abab477cf32b4dd0aa7a72f70ede0502cJim Miller        offsetRectIntoDescendantCoords(mLockPatternView, mTempRect);
1765737534abab477cf32b4dd0aa7a72f70ede0502cJim Miller        ev.offsetLocation(mTempRect.left, mTempRect.top);
1775737534abab477cf32b4dd0aa7a72f70ede0502cJim Miller        result = mLockPatternView.dispatchTouchEvent(ev) || result;
1785737534abab477cf32b4dd0aa7a72f70ede0502cJim Miller        ev.offsetLocation(-mTempRect.left, -mTempRect.top);
179dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        return result;
180dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
181dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
182dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    public void reset() {
183dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        // reset lock pattern
184dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternView.enableInput();
185dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternView.setEnabled(true);
186dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternView.clearPattern();
187dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
188dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        // if the user is currently locked out, enforce it.
189dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
190dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        if (deadline != 0) {
191dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            handleAttemptLockout(deadline);
192dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        } else {
1931625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett            displayDefaultSecurityMessage();
194dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
195dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
196dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        // the footer depends on how many total attempts the user has failed
197dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        if (mCallback.isVerifyUnlockOnly()) {
198dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            updateFooter(FooterMode.VerifyUnlocked);
199dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        } else if (mEnableFallback &&
200dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                (mTotalFailedPatternAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
201dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            updateFooter(FooterMode.ForgotLockPattern);
202dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        } else {
203dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            updateFooter(FooterMode.Normal);
204dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
205dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
206dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
207dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
2081625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett    private void displayDefaultSecurityMessage() {
2091625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett        if (KeyguardUpdateMonitor.getInstance(mContext).getMaxBiometricUnlockAttemptsReached()) {
2101625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett            mSecurityMessageDisplay.setMessage(R.string.faceunlock_multiple_failures, true);
2111625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett        } else {
2121625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett            mSecurityMessageDisplay.setMessage(R.string.kg_pattern_instructions, false);
2131625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett        }
2141625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett    }
2151625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett
2166fb841fa219eaae3e87f2fdc05e105d7a1813c42Adam Cohen    @Override
2176fb841fa219eaae3e87f2fdc05e105d7a1813c42Adam Cohen    public void showUsabilityHint() {
2186fb841fa219eaae3e87f2fdc05e105d7a1813c42Adam Cohen    }
2196fb841fa219eaae3e87f2fdc05e105d7a1813c42Adam Cohen
220dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    /** TODO: hook this up */
221dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    public void cleanUp() {
222dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        if (DEBUG) Log.v(TAG, "Cleanup() called on " + this);
223dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternUtils = null;
224dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternView.setOnPatternListener(null);
225dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
226dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
227dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    @Override
228dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    public void onWindowFocusChanged(boolean hasWindowFocus) {
229dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        super.onWindowFocusChanged(hasWindowFocus);
230dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        if (hasWindowFocus) {
231dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            // when timeout dialog closes we want to update our state
232dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            reset();
233dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
234dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
235dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
236dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    private class UnlockPatternListener implements LockPatternView.OnPatternListener {
237dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
238dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        public void onPatternStart() {
239dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            mLockPatternView.removeCallbacks(mCancelPatternRunnable);
240dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
241dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
242dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        public void onPatternCleared() {
243dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
244dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
245dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        public void onPatternCellAdded(List<LockPatternView.Cell> pattern) {
246dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            // To guard against accidental poking of the wakelock, look for
247dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            // the user actually trying to draw a pattern of some minimal length.
248dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
249dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mCallback.userActivity(UNLOCK_PATTERN_WAKE_INTERVAL_MS);
250dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            } else {
251dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                // Give just a little extra time if they hit one of the first few dots
252dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mCallback.userActivity(UNLOCK_PATTERN_WAKE_INTERVAL_FIRST_DOTS_MS);
253dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            }
254dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
255dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
256dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        public void onPatternDetected(List<LockPatternView.Cell> pattern) {
257dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            if (mLockPatternUtils.checkPattern(pattern)) {
258d2b82f70fede8c2ec4de34d8e6462ed4ece13c56Jim Miller                mCallback.reportSuccessfulUnlockAttempt();
259dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct);
260258341c377b6aa9f1bd29a9b507a97967e432dfeJim Miller                mTotalFailedPatternAttempts = 0;
261d2b82f70fede8c2ec4de34d8e6462ed4ece13c56Jim Miller                mCallback.dismiss(true);
262dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            } else {
263dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
264dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    mCallback.userActivity(UNLOCK_PATTERN_WAKE_INTERVAL_MS);
265dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                }
266dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
267dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                if (pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
268dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    mTotalFailedPatternAttempts++;
269dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    mFailedPatternAttemptsSinceLastTimeout++;
270dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    mCallback.reportFailedUnlockAttempt();
271dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                }
272dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                if (mFailedPatternAttemptsSinceLastTimeout
273dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                        >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) {
274dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    long deadline = mLockPatternUtils.setLockoutAttemptDeadline();
275dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    handleAttemptLockout(deadline);
276dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                } else {
2770a4f900463024908220d0c9bf4b291a6e1284846Adam Cohen                    mSecurityMessageDisplay.setMessage(R.string.kg_wrong_pattern, true);
278dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    mLockPatternView.postDelayed(mCancelPatternRunnable, PATTERN_CLEAR_TIMEOUT_MS);
279dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                }
280dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            }
281dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
282dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
283dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
284dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    private void maybeEnableFallback(Context context) {
285dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        // Ask the account manager if we have an account that can be used as a
286dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        // fallback in case the user forgets his pattern.
287dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        AccountAnalyzer accountAnalyzer = new AccountAnalyzer(AccountManager.get(context));
288dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        accountAnalyzer.start();
289dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
290dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
291dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    private class AccountAnalyzer implements AccountManagerCallback<Bundle> {
292dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        private final AccountManager mAccountManager;
293dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        private final Account[] mAccounts;
294dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        private int mAccountIndex;
295dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
296dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        private AccountAnalyzer(AccountManager accountManager) {
297dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            mAccountManager = accountManager;
298dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            mAccounts = accountManager.getAccountsByType("com.google");
299dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
300dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
301dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        private void next() {
302dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            // if we are ready to enable the fallback or if we depleted the list of accounts
303dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            // then finish and get out
3046f131416ba4ff48067dc4e627971391a6b6778c4Adam Cohen            if (mEnableFallback || mAccountIndex >= mAccounts.length) {
305dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                return;
306dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            }
307dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
308dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            // lookup the confirmCredentials intent for the current account
309dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            mAccountManager.confirmCredentials(mAccounts[mAccountIndex], null, null, this, null);
310dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
311dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
312dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        public void start() {
313dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            mEnableFallback = false;
314dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            mAccountIndex = 0;
315dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            next();
316dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
317dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
318dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        public void run(AccountManagerFuture<Bundle> future) {
319dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            try {
320dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                Bundle result = future.getResult();
321dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                if (result.getParcelable(AccountManager.KEY_INTENT) != null) {
322dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    mEnableFallback = true;
323dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                }
324dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            } catch (OperationCanceledException e) {
325dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                // just skip the account if we are unable to query it
326dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            } catch (IOException e) {
327dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                // just skip the account if we are unable to query it
328dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            } catch (AuthenticatorException e) {
329dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                // just skip the account if we are unable to query it
330dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            } finally {
331dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mAccountIndex++;
332dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                next();
333dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            }
334dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
335dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
336dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
337dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    private void handleAttemptLockout(long elapsedRealtimeDeadline) {
338dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternView.clearPattern();
339dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mLockPatternView.setEnabled(false);
340dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        final long elapsedRealtime = SystemClock.elapsedRealtime();
3416f131416ba4ff48067dc4e627971391a6b6778c4Adam Cohen        if (mEnableFallback) {
3426f131416ba4ff48067dc4e627971391a6b6778c4Adam Cohen            updateFooter(FooterMode.ForgotLockPattern);
3436f131416ba4ff48067dc4e627971391a6b6778c4Adam Cohen        }
344258341c377b6aa9f1bd29a9b507a97967e432dfeJim Miller
345dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        mCountdownTimer = new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) {
346dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
347dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            @Override
348dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            public void onTick(long millisUntilFinished) {
349dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                final int secondsRemaining = (int) (millisUntilFinished / 1000);
3500ff7f010f8bfd011f0915031b02739ae3bee401eJim Miller                mSecurityMessageDisplay.setMessage(
3510a4f900463024908220d0c9bf4b291a6e1284846Adam Cohen                        R.string.kg_too_many_failed_attempts_countdown, true, secondsRemaining);
352dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            }
353dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
354dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            @Override
355dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            public void onFinish() {
356dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mLockPatternView.setEnabled(true);
3571625e87e600e8d0752d2f5e1318151a694f1be3eDanielle Millett                displayDefaultSecurityMessage();
358dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                // TODO mUnlockIcon.setVisibility(View.VISIBLE);
359dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                mFailedPatternAttemptsSinceLastTimeout = 0;
360dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                if (mEnableFallback) {
361dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    updateFooter(FooterMode.ForgotLockPattern);
362dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                } else {
363dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                    updateFooter(FooterMode.Normal);
364dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller                }
365dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            }
366dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
367dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }.start();
368dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
369dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
370dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    @Override
371dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    public boolean needsInput() {
372dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        return false;
373dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
374dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
375dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    @Override
376dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    public void onPause() {
377dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        if (mCountdownTimer != null) {
378dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            mCountdownTimer.cancel();
379dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller            mCountdownTimer = null;
380dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        }
381dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
382dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
383dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    @Override
384dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    public void onResume() {
385dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        reset();
386dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
387dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
388dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    @Override
389dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    public KeyguardSecurityCallback getCallback() {
390dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller        return mCallback;
391dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller    }
392dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
393c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren    @Override
394c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren    public void showBouncer(int duration) {
395c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren        KeyguardSecurityViewHelper.
396c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren                showBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
397c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren    }
398dcb3d84b82cc2448d04e73359a716581bfb657dbJim Miller
399c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren    @Override
400c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren    public void hideBouncer(int duration) {
401c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren        KeyguardSecurityViewHelper.
402c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren                hideBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
403c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren    }
404c0ae9e67ebe6f1298800feaed1b43e867139a904Chris Wren}
405