ChooseLockPattern.java revision afc4ab2ffbb8327ddce9907961295a32cbf49d0f
1afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project/*
2afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
4afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * you may not use this file except in compliance with the License.
6afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * You may obtain a copy of the License at
7afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
8afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
10afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * See the License for the specific language governing permissions and
14afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * limitations under the License.
15afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */
16afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
17afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectpackage com.android.settings;
18afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
19afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport com.google.android.collect.Lists;
20afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
21afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient;
22afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport com.android.internal.widget.LockPatternUtils;
23afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport com.android.internal.widget.LockPatternView;
24afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport static com.android.internal.widget.LockPatternView.DisplayMode;
25afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
26afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.app.Activity;
27afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.content.Intent;
28afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.os.Bundle;
29afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.view.KeyEvent;
30afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.view.View;
31afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.view.Window;
32afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.widget.TextView;
33afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
34afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.util.ArrayList;
35afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.util.Collections;
36afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.util.List;
37afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
38afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project/**
39afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * If the user has a lock pattern set already, makes them confirm the existing one.
40afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
41afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Then, prompts the user to choose a lock pattern:
42afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * - prompts for initial pattern
43afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * - asks for confirmation / restart
44afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * - saves chosen password when confirmed
45afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */
46afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectpublic class ChooseLockPattern extends Activity implements View.OnClickListener{
47afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
48afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /**
49afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * Used by the choose lock pattern wizard to indicate the wizard is
50afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * finished, and each activity in the wizard should finish.
51afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * <p>
52afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * Previously, each activity in the wizard would finish itself after
53afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * starting the next activity. However, this leads to broken 'Back'
54afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * behavior. So, now an activity does not finish itself until it gets this
55afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * result.
56afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     */
57afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    static final int RESULT_FINISHED = RESULT_FIRST_USER;
58afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
59afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    // how long after a confirmation message is shown before moving on
60afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    static final int INFORMATION_MSG_TIMEOUT_MS = 3000;
61afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
62afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    // how long we wait to clear a wrong pattern
63afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final int WRONG_PATTERN_CLEAR_TIMEOUT_MS = 2000;
64afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
65afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final int ID_EMPTY_MESSAGE = -1;
66afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
67afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
68afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    protected TextView mHeaderText;
69afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    protected LockPatternView mLockPatternView;
70afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    protected TextView mFooterText;
71afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private TextView mFooterLeftButton;
72afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private TextView mFooterRightButton;
73afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
74afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    protected List<LockPatternView.Cell> mChosenPattern = null;
75afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
76afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    protected LockPatternUtils mLockPatternUtils;
77afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
78afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /**
79afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * The patten used during the help screen to show how to draw a pattern.
80afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     */
81afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private final List<LockPatternView.Cell> mAnimatePattern =
82afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            Collections.unmodifiableList(
83afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                Lists.newArrayList(
84afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                        LockPatternView.Cell.of(0, 0),
85afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                        LockPatternView.Cell.of(0, 1),
86afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                        LockPatternView.Cell.of(1, 1),
87afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                        LockPatternView.Cell.of(2, 1)
88afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    ));
89afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
90afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
91afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /**
92afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * The pattern listener that responds according to a user choosing a new
93afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * lock pattern.
94afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     */
95afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    protected LockPatternView.OnPatternListener mChooseNewLockPatternListener = new LockPatternView.OnPatternListener() {
96afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
97afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            public void onPatternStart() {
98afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                mLockPatternView.removeCallbacks(mClearPatternRunnable);
99afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                patternInProgress();
100afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
101afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
102afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            public void onPatternCleared() {
103afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                mLockPatternView.removeCallbacks(mClearPatternRunnable);
104afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
105afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
106afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            public void onPatternDetected(List<LockPatternView.Cell> pattern) {
107afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                if (mUiStage == Stage.NeedToConfirm || mUiStage == Stage.ConfirmWrong) {
108afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    if (mChosenPattern == null) throw new IllegalStateException("null chosen pattern in stage 'need to confirm");
109afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    if (mChosenPattern.equals(pattern)) {
110afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                        updateStage(Stage.ChoiceConfirmed);
111afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    } else {
112afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                        updateStage(Stage.ConfirmWrong);
113afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    }
114afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                } else if (mUiStage == Stage.Introduction || mUiStage == Stage.ChoiceTooShort){
115afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    if (pattern.size() < LockPatternUtils.MIN_LOCK_PATTERN_SIZE) {
116afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                        updateStage(Stage.ChoiceTooShort);
117afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    } else {
118afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                        mChosenPattern = new ArrayList<LockPatternView.Cell>(pattern);
119afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                        updateStage(Stage.FirstChoiceValid);
120afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    }
121afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                } else {
122afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    throw new IllegalStateException("Unexpected stage " + mUiStage + " when "
123afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                            + "entering the pattern.");
124afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                }
125afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
126afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
127afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            private void patternInProgress() {
128afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                mHeaderText.setText(R.string.lockpattern_recording_inprogress);
129afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                mFooterText.setText("");
130afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                mFooterLeftButton.setEnabled(false);
131afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                mFooterRightButton.setEnabled(false);
132afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
133afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     };
134afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
135afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
136afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /**
137afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * The states of the left footer button.
138afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     */
139afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    enum LeftButtonMode {
140afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        Cancel(R.string.cancel, true),
141afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        CancelDisabled(R.string.cancel, false),
142afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        Retry(R.string.lockpattern_retry_button_text, true),
143afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        RetryDisabled(R.string.lockpattern_retry_button_text, false),
144afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        Gone(ID_EMPTY_MESSAGE, false);
145afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
146afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
147afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        /**
148afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project         * @param text The displayed text for this mode.
149afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project         * @param enabled Whether the button should be enabled.
150afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project         */
151afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        LeftButtonMode(int text, boolean enabled) {
152afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            this.text = text;
153afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            this.enabled = enabled;
154afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
155afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
156afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        final int text;
157afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        final boolean enabled;
158afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
159afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
160afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /**
161afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * The states of the right button.
162afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     */
163afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    enum RightButtonMode {
164afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        Continue(R.string.lockpattern_continue_button_text, true),
165afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        ContinueDisabled(R.string.lockpattern_continue_button_text, false),
166afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        Confirm(R.string.lockpattern_confirm_button_text, true),
167afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        ConfirmDisabled(R.string.lockpattern_confirm_button_text, false),
168afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        Ok(android.R.string.ok, true);
169afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
170afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        /**
171afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project         * @param text The displayed text for this mode.
172afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project         * @param enabled Whether the button should be enabled.
173afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project         */
174afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        RightButtonMode(int text, boolean enabled) {
175afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            this.text = text;
176afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            this.enabled = enabled;
177afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
178afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
179afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        final int text;
180afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        final boolean enabled;
181afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
182afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
183afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /**
184afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * Keep track internally of where the user is in choosing a pattern.
185afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     */
186afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    protected enum Stage {
187afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
188afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        Introduction(
189afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                R.string.lockpattern_recording_intro_header,
190afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                LeftButtonMode.Cancel, RightButtonMode.ContinueDisabled,
191afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                R.string.lockpattern_recording_intro_footer, true),
192afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        HelpScreen(
193afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                R.string.lockpattern_settings_help_how_to_record,
194afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                LeftButtonMode.Gone, RightButtonMode.Ok, ID_EMPTY_MESSAGE, false),
195afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        ChoiceTooShort(
196afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                R.string.lockpattern_recording_incorrect_too_short,
197afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                LeftButtonMode.Retry, RightButtonMode.ContinueDisabled,
198afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                ID_EMPTY_MESSAGE, true),
199afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        FirstChoiceValid(
200afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                R.string.lockpattern_pattern_entered_header,
201afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                LeftButtonMode.Retry, RightButtonMode.Continue, ID_EMPTY_MESSAGE, false),
202afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        NeedToConfirm(
203afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                R.string.lockpattern_need_to_confirm,
204afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                LeftButtonMode.CancelDisabled, RightButtonMode.ConfirmDisabled,
205afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                ID_EMPTY_MESSAGE, true),
206afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        ConfirmWrong(
207afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                R.string.lockpattern_need_to_unlock_wrong,
208afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                LeftButtonMode.Cancel, RightButtonMode.ConfirmDisabled,
209afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                ID_EMPTY_MESSAGE, true),
210afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        ChoiceConfirmed(
211afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                R.string.lockpattern_pattern_confirmed_header,
212afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                LeftButtonMode.Cancel, RightButtonMode.Confirm, ID_EMPTY_MESSAGE, false);
213afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
214afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
215afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        /**
216afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project         * @param headerMessage The message displayed at the top.
217afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project         * @param leftMode The mode of the left button.
218afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project         * @param rightMode The mode of the right button.
219afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project         * @param footerMessage The footer message.
220afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project         * @param patternEnabled Whether the pattern widget is enabled.
221afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project         */
222afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        Stage(int headerMessage,
223afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                LeftButtonMode leftMode,
224afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                RightButtonMode rightMode,
225afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                int footerMessage, boolean patternEnabled) {
226afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            this.headerMessage = headerMessage;
227afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            this.leftMode = leftMode;
228afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            this.rightMode = rightMode;
229afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            this.footerMessage = footerMessage;
230afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            this.patternEnabled = patternEnabled;
231afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
232afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
233afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        final int headerMessage;
234afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        final LeftButtonMode leftMode;
235afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        final RightButtonMode rightMode;
236afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        final int footerMessage;
237afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        final boolean patternEnabled;
238afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
239afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
240afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private Stage mUiStage = Stage.Introduction;
241afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
242afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private Runnable mClearPatternRunnable = new Runnable() {
243afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        public void run() {
244afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            mLockPatternView.clearPattern();
245afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
246afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    };
247afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
248afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final String KEY_UI_STAGE = "uiStage";
249afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final String KEY_PATTERN_CHOICE = "chosenPattern";
250afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
251afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
252afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    protected void onCreate(Bundle savedInstanceState) {
253afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        super.onCreate(savedInstanceState);
254afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
255afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mLockPatternUtils = new LockPatternUtils(getContentResolver());
256afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
257afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        requestWindowFeature(Window.FEATURE_NO_TITLE);
258afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
259afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        setupViews();
260afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
261afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // make it so unhandled touch events within the unlock screen go to the
262afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // lock pattern view.
263afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        final LinearLayoutWithDefaultTouchRecepient topLayout
264afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                = (LinearLayoutWithDefaultTouchRecepient) findViewById(
265afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                R.id.topLayout);
266afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        topLayout.setDefaultTouchRecepient(mLockPatternView);
267afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
268afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (savedInstanceState == null) {
269afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            // first launch
270afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            updateStage(Stage.Introduction);
271afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            if (mLockPatternUtils.savedPatternExists()) {
272afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                confirmPattern();
273afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
274afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        } else {
275afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            // restore from previous state
276afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            final String patternString = savedInstanceState.getString(KEY_PATTERN_CHOICE);
277afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            if (patternString != null) {
278afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                mChosenPattern = LockPatternUtils.stringToPattern(patternString);
279afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
280afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            updateStage(Stage.values()[savedInstanceState.getInt(KEY_UI_STAGE)]);
281afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
282afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
283afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
284afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /**
285afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * Keep all "find view" related stuff confined to this function since in
286afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * case someone needs to subclass and customize.
287afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     */
288afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    protected void setupViews() {
289afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        setContentView(R.layout.choose_lock_pattern);
290afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
291afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mHeaderText = (TextView) findViewById(R.id.headerText);
292afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
293afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
294afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mLockPatternView.setOnPatternListener(mChooseNewLockPatternListener);
295afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
296afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
297afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mFooterText = (TextView) findViewById(R.id.footerText);
298afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
299afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mFooterLeftButton = (TextView) findViewById(R.id.footerLeftButton);
300afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mFooterRightButton = (TextView) findViewById(R.id.footerRightButton);
301afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
302afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mFooterLeftButton.setOnClickListener(this);
303afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mFooterRightButton.setOnClickListener(this);
304afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
305afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
306afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public void onClick(View v) {
307afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (v == mFooterLeftButton) {
308afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            if (mUiStage.leftMode == LeftButtonMode.Retry) {
309afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                mChosenPattern = null;
310afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                mLockPatternView.clearPattern();
311afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                updateStage(Stage.Introduction);
312afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            } else if (mUiStage.leftMode == LeftButtonMode.Cancel) {
313afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                // They are canceling the entire wizard
314afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                setResult(RESULT_FINISHED);
315afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                finish();
316afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            } else {
317afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                throw new IllegalStateException("left footer button pressed, but stage of " +
318afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    mUiStage + " doesn't make sense");
319afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
320afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        } else if (v == mFooterRightButton) {
321afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
322afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            if (mUiStage.rightMode == RightButtonMode.Continue) {
323afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                if (mUiStage != Stage.FirstChoiceValid) {
324afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    throw new IllegalStateException("expected ui stage " + Stage.FirstChoiceValid
325afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                            + " when button is " + RightButtonMode.Continue);
326afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                }
327afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                updateStage(Stage.NeedToConfirm);
328afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            } else if (mUiStage.rightMode == RightButtonMode.Confirm) {
329afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                if (mUiStage != Stage.ChoiceConfirmed) {
330afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    throw new IllegalStateException("expected ui stage " + Stage.ChoiceConfirmed
331afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                            + " when button is " + RightButtonMode.Confirm);
332afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                }
333afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                saveChosenPatternAndFinish();
334afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            } else if (mUiStage.rightMode == RightButtonMode.Ok) {
335afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                if (mUiStage != Stage.HelpScreen) {
336afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    throw new IllegalStateException("Help screen is only mode with ok button, but " +
337afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                            "stage is " + mUiStage);
338afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                }
339afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                mLockPatternView.clearPattern();
340afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                mLockPatternView.setDisplayMode(DisplayMode.Correct);
341afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                updateStage(Stage.Introduction);
342afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
343afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
344afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
345afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
346afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
347afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    public boolean onKeyDown(int keyCode, KeyEvent event) {
348afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
349afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            if (mUiStage == Stage.HelpScreen) {
350afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                updateStage(Stage.Introduction);
351afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                return true;
352afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            }
353afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
354afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (keyCode == KeyEvent.KEYCODE_MENU && mUiStage == Stage.Introduction) {
355afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            updateStage(Stage.HelpScreen);
356afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            return true;
357afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
358afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
359afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        return super.onKeyDown(keyCode, event);
360afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
361afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
362afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /**
363afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * Launch screen to confirm the existing lock pattern.
364afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * @see #onActivityResult(int, int, android.content.Intent)
365afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     */
366afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    protected void confirmPattern() {
367afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        final Intent intent = new Intent();
368afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        intent.setClassName("com.android.settings", "com.android.settings.ConfirmLockPattern");
369afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        startActivityForResult(intent, 55);
370afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
371afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
372afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /**
373afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * @see #confirmPattern
374afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     */
375afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
376afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    protected void onActivityResult(int requestCode, int resultCode,
377afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            Intent data) {
378afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        super.onActivityResult(requestCode, resultCode, data);
379afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
380afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (requestCode != 55) {
381afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            return;
382afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
383afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
384afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (resultCode != Activity.RESULT_OK) {
385afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            setResult(RESULT_FINISHED);
386afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            finish();
387afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
388afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        updateStage(Stage.Introduction);
389afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
390afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
391afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
392afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    protected void onSaveInstanceState(Bundle outState) {
393afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        super.onSaveInstanceState(outState);
394afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
395afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        outState.putInt(KEY_UI_STAGE, mUiStage.ordinal());
396afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (mChosenPattern != null) {
397afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            outState.putString(KEY_PATTERN_CHOICE, LockPatternUtils.patternToString(mChosenPattern));
398afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
399afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
400afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
401afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
402afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /**
403afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * Updates the messages and buttons appropriate to what stage the user
404afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * is at in choosing a view.  This doesn't handle clearing out the pattern;
405afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * the pattern is expected to be in the right state.
406afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     * @param stage
407afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     */
408afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    protected void updateStage(Stage stage) {
409afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
410afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mUiStage = stage;
411afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
412afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // header text, footer text, visibility and
413afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // enabled state all known from the stage
414afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (stage == Stage.ChoiceTooShort) {
415afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            mHeaderText.setText(
416afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    getResources().getString(
417afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                            stage.headerMessage,
418afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                            LockPatternUtils.MIN_LOCK_PATTERN_SIZE));
419afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        } else {
420afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            mHeaderText.setText(stage.headerMessage);
421afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
422afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (stage.footerMessage == ID_EMPTY_MESSAGE) {
423afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            mFooterText.setText("");
424afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        } else {
425afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            mFooterText.setText(stage.footerMessage);
426afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
427afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
428afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (stage.leftMode == LeftButtonMode.Gone) {
429afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            mFooterLeftButton.setVisibility(View.GONE);
430afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        } else {
431afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            mFooterLeftButton.setVisibility(View.VISIBLE);
432afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            mFooterLeftButton.setText(stage.leftMode.text);
433afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            mFooterLeftButton.setEnabled(stage.leftMode.enabled);
434afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
435afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
436afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mFooterRightButton.setText(stage.rightMode.text);
437afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mFooterRightButton.setEnabled(stage.rightMode.enabled);
438afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
439afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // same for whether the patten is enabled
440afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (stage.patternEnabled) {
441afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            mLockPatternView.enableInput();
442afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        } else {
443afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            mLockPatternView.disableInput();
444afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
445afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
446afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // the rest of the stuff varies enough that it is easier just to handle
447afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // on a case by case basis.
448afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mLockPatternView.setDisplayMode(DisplayMode.Correct);
449afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
450afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        switch (mUiStage) {
451afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            case Introduction:
452afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                mLockPatternView.clearPattern();
453afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                break;
454afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            case HelpScreen:
455afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                mLockPatternView.setPattern(DisplayMode.Animate, mAnimatePattern);
456afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                break;
457afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            case ChoiceTooShort:
458afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                mLockPatternView.setDisplayMode(DisplayMode.Wrong);
459afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                postClearPatternRunnable();
460afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                break;
461afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            case FirstChoiceValid:
462afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                break;
463afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            case NeedToConfirm:
464afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                mLockPatternView.clearPattern();
465afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                break;
466afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            case ConfirmWrong:
467afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                mLockPatternView.setDisplayMode(DisplayMode.Wrong);
468afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                postClearPatternRunnable();
469afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                break;
470afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            case ChoiceConfirmed:
471afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                break;
472afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
473afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
474afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
475afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
476afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    // clear the wrong pattern unless they have started a new one
477afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    // already
478afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private void postClearPatternRunnable() {
479afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mLockPatternView.removeCallbacks(mClearPatternRunnable);
480afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mLockPatternView.postDelayed(mClearPatternRunnable, WRONG_PATTERN_CLEAR_TIMEOUT_MS);
481afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
482afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
483afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private void saveChosenPatternAndFinish() {
484afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        boolean patternExistedBefore = mLockPatternUtils.savedPatternExists();
485afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        mLockPatternUtils.saveLockPattern(mChosenPattern);
486afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
487afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // if setting pattern for first time, enable the lock gesture.  otherwise,
488afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // keep the user's setting.
489afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        if (!patternExistedBefore) {
490afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            mLockPatternUtils.setLockPatternEnabled(true);
491afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            mLockPatternUtils.setVisiblePatternEnabled(true);
492afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
493afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
494afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        setResult(RESULT_FINISHED);
495afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        finish();
496afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
497afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project}
498