1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.settings;
18
19import com.android.internal.widget.LockPatternUtils;
20import com.android.internal.widget.PasswordEntryKeyboardHelper;
21import com.android.internal.widget.PasswordEntryKeyboardView;
22
23import android.app.Activity;
24import android.app.Fragment;
25import android.app.admin.DevicePolicyManager;
26import android.content.Intent;
27import android.os.Bundle;
28import android.os.Handler;
29import android.preference.PreferenceActivity;
30import android.text.Editable;
31import android.text.InputType;
32import android.text.TextWatcher;
33import android.view.KeyEvent;
34import android.view.LayoutInflater;
35import android.view.View;
36import android.view.View.OnClickListener;
37import android.view.ViewGroup;
38import android.view.inputmethod.EditorInfo;
39import android.widget.Button;
40import android.widget.TextView;
41import android.widget.TextView.OnEditorActionListener;
42
43public class ConfirmLockPassword extends PreferenceActivity {
44
45    @Override
46    public Intent getIntent() {
47        Intent modIntent = new Intent(super.getIntent());
48        modIntent.putExtra(EXTRA_SHOW_FRAGMENT, ConfirmLockPasswordFragment.class.getName());
49        modIntent.putExtra(EXTRA_NO_HEADERS, true);
50        return modIntent;
51    }
52
53    @Override
54    public void onCreate(Bundle savedInstanceState) {
55        // Disable IME on our window since we provide our own keyboard
56        //getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
57                //WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
58        super.onCreate(savedInstanceState);
59        CharSequence msg = getText(R.string.lockpassword_confirm_your_password_header);
60        showBreadCrumbs(msg, msg);
61    }
62
63    public static class ConfirmLockPasswordFragment extends Fragment implements OnClickListener,
64            OnEditorActionListener, TextWatcher {
65        private static final long ERROR_MESSAGE_TIMEOUT = 3000;
66        private TextView mPasswordEntry;
67        private LockPatternUtils mLockPatternUtils;
68        private TextView mHeaderText;
69        private Handler mHandler = new Handler();
70        private PasswordEntryKeyboardHelper mKeyboardHelper;
71        private PasswordEntryKeyboardView mKeyboardView;
72        private Button mContinueButton;
73
74
75        // required constructor for fragments
76        public ConfirmLockPasswordFragment() {
77
78        }
79
80        @Override
81        public void onCreate(Bundle savedInstanceState) {
82            super.onCreate(savedInstanceState);
83            mLockPatternUtils = new LockPatternUtils(getActivity());
84        }
85
86        @Override
87        public View onCreateView(LayoutInflater inflater, ViewGroup container,
88                Bundle savedInstanceState) {
89            final int storedQuality = mLockPatternUtils.getKeyguardStoredPasswordQuality();
90            View view = inflater.inflate(R.layout.confirm_lock_password, null);
91            // Disable IME on our window since we provide our own keyboard
92
93            view.findViewById(R.id.cancel_button).setOnClickListener(this);
94            mContinueButton = (Button) view.findViewById(R.id.next_button);
95            mContinueButton.setOnClickListener(this);
96            mContinueButton.setEnabled(false); // disable until the user enters at least one char
97
98            mPasswordEntry = (TextView) view.findViewById(R.id.password_entry);
99            mPasswordEntry.setOnEditorActionListener(this);
100            mPasswordEntry.addTextChangedListener(this);
101
102            mKeyboardView = (PasswordEntryKeyboardView) view.findViewById(R.id.keyboard);
103            mHeaderText = (TextView) view.findViewById(R.id.headerText);
104            final boolean isAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == storedQuality
105                    || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == storedQuality
106                    || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == storedQuality;
107            mHeaderText.setText(isAlpha ? R.string.lockpassword_confirm_your_password_header
108                    : R.string.lockpassword_confirm_your_pin_header);
109
110            final Activity activity = getActivity();
111            mKeyboardHelper = new PasswordEntryKeyboardHelper(activity,
112                    mKeyboardView, mPasswordEntry);
113            mKeyboardHelper.setKeyboardMode(isAlpha ?
114                    PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
115                    : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
116            mKeyboardView.requestFocus();
117
118            int currentType = mPasswordEntry.getInputType();
119            mPasswordEntry.setInputType(isAlpha ? currentType
120                    : (InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD));
121
122            // Update the breadcrumb (title) if this is embedded in a PreferenceActivity
123            if (activity instanceof PreferenceActivity) {
124                final PreferenceActivity preferenceActivity = (PreferenceActivity) activity;
125                int id = isAlpha ? R.string.lockpassword_confirm_your_password_header
126                        : R.string.lockpassword_confirm_your_pin_header;
127                CharSequence title = getText(id);
128                preferenceActivity.showBreadCrumbs(title, title);
129            }
130
131            return view;
132        }
133
134        @Override
135        public void onPause() {
136            super.onPause();
137            mKeyboardView.requestFocus();
138        }
139
140        @Override
141        public void onResume() {
142            // TODO Auto-generated method stub
143            super.onResume();
144            mKeyboardView.requestFocus();
145        }
146
147        private void handleNext() {
148            final String pin = mPasswordEntry.getText().toString();
149            if (mLockPatternUtils.checkPassword(pin)) {
150
151                Intent intent = new Intent();
152                intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, pin);
153
154                getActivity().setResult(RESULT_OK, intent);
155                getActivity().finish();
156            } else {
157                showError(R.string.lockpattern_need_to_unlock_wrong);
158            }
159        }
160
161        public void onClick(View v) {
162            switch (v.getId()) {
163                case R.id.next_button:
164                    handleNext();
165                    break;
166
167                case R.id.cancel_button:
168                    getActivity().setResult(RESULT_CANCELED);
169                    getActivity().finish();
170                    break;
171            }
172        }
173
174        private void showError(int msg) {
175            mHeaderText.setText(msg);
176            mPasswordEntry.setText(null);
177            mHandler.postDelayed(new Runnable() {
178                public void run() {
179                    mHeaderText.setText(R.string.lockpassword_confirm_your_password_header);
180                }
181            }, ERROR_MESSAGE_TIMEOUT);
182        }
183
184        // {@link OnEditorActionListener} methods.
185        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
186            // Check if this was the result of hitting the enter or "done" key
187            if (actionId == EditorInfo.IME_NULL
188                    || actionId == EditorInfo.IME_ACTION_DONE
189                    || actionId == EditorInfo.IME_ACTION_NEXT) {
190                handleNext();
191                return true;
192            }
193            return false;
194        }
195
196        // {@link TextWatcher} methods.
197        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
198        }
199
200        public void onTextChanged(CharSequence s, int start, int before, int count) {
201        }
202
203        public void afterTextChanged(Editable s) {
204            mContinueButton.setEnabled(mPasswordEntry.getText().length() > 0);
205        }
206    }
207}
208