Fix 2332563: Update logic for lockscreen in Settings.

This commit is contained in:
Jim Miller
2010-02-10 19:53:58 -08:00
parent 1982d4922c
commit 122b6c85a9
12 changed files with 523 additions and 159 deletions

View File

@@ -53,6 +53,8 @@
android:gravity="center" android:gravity="center"
android:layout_gravity="center" android:layout_gravity="center"
android:textSize="24sp" android:textSize="24sp"
android:layout_marginTop="5dip"
android:layout_marginBottom="5dip"
android:textAppearance="?android:attr/textAppearanceLarge" android:textAppearance="?android:attr/textAppearanceLarge"
android:background="@drawable/password_field_default" android:background="@drawable/password_field_default"
android:textColor="#ffffffff" android:textColor="#ffffffff"
@@ -77,14 +79,15 @@
<RelativeLayout <RelativeLayout
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:background="@android:drawable/bottom_bar"> android:background="@android:drawable/bottom_bar"
android:visibility="gone">
<Button android:id="@+id/cancel_button" <Button android:id="@+id/cancel_button"
android:layout_width="150dip" android:layout_width="150dip"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="5dip" android:layout_margin="5dip"
android:layout_alignParentLeft="true" android:layout_alignParentLeft="true"
android:text="@string/password_cancel_button_label" android:text="@string/lockpassword_cancel_label"
/> />
<Button android:id="@+id/next_button" <Button android:id="@+id/next_button"
@@ -94,7 +97,7 @@
android:layout_alignParentRight="true" android:layout_alignParentRight="true"
android:drawableRight="@drawable/ic_btn_next" android:drawableRight="@drawable/ic_btn_next"
android:drawablePadding="10dip" android:drawablePadding="10dip"
android:text="@string/password_ok_button_label" android:text="@string/lockpassword_continue_label"
/> />
</RelativeLayout> </RelativeLayout>

View File

@@ -84,7 +84,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="5dip" android:layout_margin="5dip"
android:layout_alignParentLeft="true" android:layout_alignParentLeft="true"
android:text="@string/password_cancel_button_label" android:text="@string/lockpassword_cancel_label"
/> />
<Button android:id="@+id/next_button" <Button android:id="@+id/next_button"
@@ -94,7 +94,7 @@
android:layout_alignParentRight="true" android:layout_alignParentRight="true"
android:drawableRight="@drawable/ic_btn_next" android:drawableRight="@drawable/ic_btn_next"
android:drawablePadding="10dip" android:drawablePadding="10dip"
android:text="@string/password_ok_button_label" android:text="@string/lockpassword_continue_label"
/> />
</RelativeLayout> </RelativeLayout>

View File

@@ -98,22 +98,6 @@
<item>1800000</item> <item>1800000</item>
</string-array> </string-array>
<!-- Unlock method in SecuritySettings --><skip/>
<string-array name="unlock_method_entries">
<item>Password</item>
<item>PIN</item>
<item>Pattern</item>
<item>None</item>
</string-array>
<!-- Do not translate. -->
<string-array name="unlock_method_values" translatable="false">
<item>password</item>
<item>pin</item>
<item>pattern</item>
<item>none</item>
</string-array>
<!-- TTS settings --> <!-- TTS settings -->
<!-- Default speech rate choices --> <!-- Default speech rate choices -->

View File

@@ -516,28 +516,81 @@
<string name="cdma_security_settings_summary">Set My Location, screen unlock, credential storage lock</string> <string name="cdma_security_settings_summary">Set My Location, screen unlock, credential storage lock</string>
<!-- In the security screen, the header title for settings related to Passwords--> <!-- In the security screen, the header title for settings related to Passwords-->
<string name="security_passwords_title">Passwords</string> <string name="security_passwords_title">Passwords</string>
<!-- Name shown for changing the unlock method -->
<string name="unlock_method_title">Unlock Method</string>
<!-- Summary shown for changing the unlock method --> <!-- Unlock settings --><skip />
<string name="unlock_method_summary">Change the method used to unlock your phone</string>
<!-- Error shown in popup when PIN is too short --> <!-- Title for preference that will guide the user through creating an unlock pattern -->
<string name="pin_password_too_short">Password must be at least %d digits</string> <string name="unlock_set_unlock_pattern_title">Set unlock pattern</string>
<!-- Summary for preference that guides the user through creating an unlock pattern -->
<string name="unlock_set_unlock_pattern_summary">Must draw pattern to unlock screen</string>
<!-- Title for preference that guides the user through creating an unlock PIN (Personal Identification Number) -->
<string name="unlock_set_unlock_pin_title">Set unlock PIN</string>
<!-- Summary for preference that guides the user through creating an unlock PIN (Personal Identification Number) -->
<string name="unlock_set_unlock_pin_summary">Must use a numeric PIN to unlock screen</string>
<!-- Title for preference that guides the user through creating an unlock password -->
<string name="unlock_set_unlock_password_title">Set unlock password</string>
<!-- Title for preference that guides the user through creating an unlock password -->
<string name="unlock_set_unlock_password_summary">Must use a password to unlock screen</string>
<!-- Title for option to turn of password/pin/pattern unlock. -->
<string name="unlock_disable_lock_title">Turn off screen lock</string>
<!-- Summary shown under unlock_disable_lock_title when pattern is in use and can be removed -->
<string name="unlock_disable_lock_pattern_summary">Remove unlock pattern</string>
<!-- Summary shown under unlock_disable_lock_title when PIN is in use and can be removed -->
<string name="unlock_disable_lock_pin_summary">Remove unlock PIN</string>
<!-- Summary shown under unlock_disable_lock_title when password is in use and can be removed -->
<string name="unlock_disable_lock_password_summary">Remove unlock password</string>
<!-- Title shown on security settings to allow the user to change their lockscreen pattern -->
<string name="unlock_change_lock_pattern_title">Change unlock pattern</string>
<!-- Title shown on security settings to allow the user to change their lockscreen PIN -->
<string name="unlock_change_lock_pin_title">Change unlock PIN</string>
<!-- Title shown on security settings to allow the user to change their lockscreen password -->
<string name="unlock_change_lock_password_title">Change unlock password</string>
<!-- Hint shown in dialog screen when password is too short -->
<string name="lockpassword_password_too_short">Password must be at least %d characters</string>
<!-- Hint shown in dialog screen when PIN is too short -->
<string name="lockpassword_pin_too_short">PIN must be at least %d characters</string>
<!-- Hint shown after minimum password criteria is met -->
<string name="lockpassword_press_continue">Press Continue when done</string>
<!-- Hint shown after minimum password criteria is met -->
<string name="lockpassword_continue_label">Continue</string>
<!-- Error shown in popup when password is too long -->
<string name="lockpassword_password_too_long">PIN can be no longer than %d digits</string>
<!-- Error shown in popup when PIN is too long --> <!-- Error shown in popup when PIN is too long -->
<string name="pin_password_too_long">Password can be no longer than %d digits</string> <string name="lockpassword_pin_too_long">PIN can be no longer than %d digits</string>
<!-- Error shown when in PIN mode and user enters a non-digit --> <!-- Error shown when in PIN mode and user enters a non-digit -->
<string name="pin_password_illegal_character">PIN must contain only digits 0-9</string> <string name="lockpassword_pin_contains_non_digits">PIN must contain only digits 0-9</string>
<!-- Error shown when in PASSWORD mode and user enters an invalid character --> <!-- Error shown when in PASSWORD mode and user enters an invalid character -->
<string name="pin_password_contains_non_digits">Password contains an illegal character</string> <string name="lockpassword_illegal_character">Password contains an illegal character</string>
<!-- Error shown when in PASSWORD mode and password is all digits -->
<string name="lockpassword_password_requires_alpha">Alpha password must contain at least one letter</string>
<!-- Label for ChoosePassword/PIN OK button -->
<string name="lockpassword_ok_label">OK</string>
<!-- Label for ChoosePassword/PIN OK button -->
<string name="lockpassword_cancel_label">Cancel</string>
<!-- In the security screen, the header title for settings related to device admins --> <!-- In the security screen, the header title for settings related to device admins -->
<string name="device_admin_title">Device administration</string> <string name="device_admin_title">Device administration</string>
<!-- Title of preference to manage device admins --> <!-- Title of preference to manage device admins -->
<string name="manage_device_admin">Select device administrators</string> <string name="manage_device_admin">Select device administrators</string>
<!-- Summary of preference to manage device policies --> <!-- Summary of preference to manage device policies -->
<string name="manage_device_admin_summary">Add or remove device administrators</string> <string name="manage_device_admin_summary">Add or remove device administrators</string>
<!-- Label for ChoosePassword/PIN OK button -->
<string name="password_ok_button_label">OK</string>
<!-- Label for ChoosePassword/PIN OK button -->
<string name="password_cancel_button_label">Cancel</string>
<!-- Bluetooth settings --> <!-- Bluetooth settings -->
<!-- Bluetooth settings check box title on Main Settings screen --> <!-- Bluetooth settings check box title on Main Settings screen -->
@@ -1350,16 +1403,26 @@
<!-- Lock Pattern settings --> <!-- Lock Pattern settings -->
<!-- Header on first screen of choose password/PIN flow --> <!-- Header on first screen of choose password/PIN flow -->
<string name="lockpassword_choose_your_password_header">Choose your password</string> <string name="lockpassword_choose_your_password_header">Choose your password</string>
<!-- Header on first screen of choose password/PIN flow -->
<string name="lockpassword_choose_your_pin_header">Choose your PIN</string>
<!-- Header on password confirm screen --> <!-- Header on password confirm screen -->
<string name="lockpassword_confirm_your_password_header">Confirm password</string> <string name="lockpassword_confirm_your_password_header">Confirm your password</string>
<!-- Header on password confirm screen -->
<string name="lockpassword_confirm_your_pin_header">Confirm your PIN</string>
<!-- Header on password confirm screen if second password doesn't match the first. --> <!-- Header on password confirm screen if second password doesn't match the first. -->
<string name="lockpassword_confirm_passwords_dont_match">Passwords don\'t match</string> <string name="lockpassword_confirm_passwords_dont_match">Passwords don\'t match</string>
<!-- Header shown if passwords match --> <!-- Header on pin confirm screen if second pin doesn't match the first. -->
<string name="lockpassword_password_confirmed_header">Password confirmed</string> <string name="lockpassword_confirm_pins_dont_match">PINs don\'t match</string>
<!-- Toast shown if setting password was successful -->
<string name="lockpassword_password_set_toast">Password has been set</string>
<!-- Toast shown if setting PIN was successful -->
<string name="lockpassword_pin_set_toast">PIN has been set</string>
<!-- Toast shown if setting pattern was successful -->
<string name="lockpassword_pattern_set_toast">Pattern has been set</string>
<!-- Lock Pattern settings --> <!-- Lock Pattern settings -->
<!-- Security & location settings screen, header --> <!-- Security & location settings screen, header -->
<string name="lock_settings_title">Screen unlock pattern</string> <string name="lock_settings_title">Screen unlock</string>
<!-- Security & location settings screen, setting option name --> <!-- Security & location settings screen, setting option name -->
<string name="lockpattern_change_lock_pattern_label">Change unlock pattern</string> <string name="lockpattern_change_lock_pattern_label">Change unlock pattern</string>
<!-- Security & location settings screen, change unlock pattern screen instruction when the user chooses "Change unlock pattern". We first ask the user toe nter the current pattern, and this is the message seen --> <!-- Security & location settings screen, change unlock pattern screen instruction when the user chooses "Change unlock pattern". We first ask the user toe nter the current pattern, and this is the message seen -->

View File

@@ -43,26 +43,4 @@
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory
android:key="security_category"
android:title="@string/lock_settings_title">
<ListPreference
android:key="unlock_method"
android:title="@string/unlock_method_title"
android:summary="@string/unlock_method_summary"
android:persistent="false"
android:entries="@array/unlock_method_entries"
android:entryValues="@array/unlock_method_values"/>
<CheckBoxPreference
android:key="visiblepattern"
android:title="@string/lockpattern_settings_enable_visible_pattern_title"/>
<CheckBoxPreference
android:key="tactilefeedback"
android:title="@string/lockpattern_settings_enable_tactile_feedback_title"/>
</PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:key="security_category"
android:title="@string/lock_settings_title">
<PreferenceScreen
android:key="unlock_set_pattern"
android:title="@string/unlock_set_unlock_pattern_title"
android:summary="@string/unlock_set_unlock_pattern_summary"
android:persistent="false"/>
<PreferenceScreen
android:key="unlock_set_pin"
android:title="@string/unlock_set_unlock_pin_title"
android:summary="@string/unlock_set_unlock_pin_summary"
android:persistent="false"/>
<PreferenceScreen
android:key="unlock_set_password"
android:title="@string/unlock_set_unlock_password_title"
android:summary="@string/unlock_set_unlock_password_summary"
android:persistent="false"/>
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:key="security_category"
android:title="@string/lock_settings_title">
<PreferenceScreen
android:key="unlock_method_disable"
android:title="@string/unlock_disable_lock_title"
android:summary="@string/unlock_disable_lock_password_summary"
android:persistent="false"/>
<PreferenceScreen
android:key="unlock_method_change_current"
android:title="@string/unlock_change_lock_password_title"
android:persistent="false"/>
<CheckBoxPreference
android:key="unlock_tactile_feedback"
android:title="@string/lockpattern_settings_enable_tactile_feedback_title"/>
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:key="security_category"
android:title="@string/lock_settings_title">
<PreferenceScreen
android:key="unlock_method_disable"
android:title="@string/unlock_disable_lock_title"
android:summary="@string/unlock_disable_lock_pattern_summary"
android:persistent="false"/>
<PreferenceScreen
android:key="unlock_method_change_current"
android:title="@string/unlock_change_lock_pattern_title"
android:persistent="false"/>
<CheckBoxPreference
android:key="visiblepattern"
android:title="@string/lockpattern_settings_enable_visible_pattern_title"/>
<CheckBoxPreference
android:key="unlock_tactile_feedback"
android:title="@string/lockpattern_settings_enable_tactile_feedback_title"/>
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2010 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:key="security_category"
android:title="@string/lock_settings_title">
<PreferenceScreen
android:key="unlock_method_disable"
android:title="@string/unlock_disable_lock_title"
android:summary="@string/unlock_disable_lock_pin_summary"
android:persistent="false"/>
<PreferenceScreen
android:key="unlock_method_change_current"
android:title="@string/unlock_change_lock_pin_title"
android:persistent="false"/>
<CheckBoxPreference
android:key="unlock_tactile_feedback"
android:title="@string/lockpattern_settings_enable_tactile_feedback_title"/>
</PreferenceCategory>
</PreferenceScreen>

View File

@@ -34,15 +34,24 @@ import android.inputmethodservice.KeyboardView;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.text.Editable; import android.text.Editable;
import android.text.Selection;
import android.text.Spannable;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
import android.widget.Button; import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
public class ChooseLockPassword extends Activity implements OnClickListener { public class ChooseLockPassword extends Activity implements OnClickListener, OnEditorActionListener,
TextWatcher {
private static final String KEY_FIRST_PIN = "first_pin";
private static final String KEY_UI_STAGE = "ui_stage";
private TextView mPasswordEntry; private TextView mPasswordEntry;
private int mPasswordMinLength = 4; private int mPasswordMinLength = 4;
private int mPasswordMaxLength = 8; private int mPasswordMaxLength = 8;
@@ -54,6 +63,9 @@ public class ChooseLockPassword extends Activity implements OnClickListener {
private String mFirstPin; private String mFirstPin;
private KeyboardView mKeyboardView; private KeyboardView mKeyboardView;
private PasswordEntryKeyboardHelper mKeyboardHelper; private PasswordEntryKeyboardHelper mKeyboardHelper;
private boolean mIsAlphaMode;
private Button mCancelButton;
private Button mNextButton;
public static final String PASSWORD_MIN_KEY = "lockscreen.password_min"; public static final String PASSWORD_MIN_KEY = "lockscreen.password_min";
public static final String PASSWORD_MAX_KEY = "lockscreen.password_max"; public static final String PASSWORD_MAX_KEY = "lockscreen.password_max";
private static Handler mHandler = new Handler(); private static Handler mHandler = new Handler();
@@ -66,19 +78,30 @@ public class ChooseLockPassword extends Activity implements OnClickListener {
*/ */
protected enum Stage { protected enum Stage {
Introduction(R.string.lockpassword_choose_your_password_header), Introduction(R.string.lockpassword_choose_your_password_header,
NeedToConfirm(R.string.lockpassword_confirm_your_password_header), R.string.lockpassword_choose_your_pin_header,
ConfirmWrong(R.string.lockpassword_confirm_passwords_dont_match), R.string.lockpassword_continue_label),
ChoiceConfirmed(R.string.lockpassword_password_confirmed_header);
NeedToConfirm(R.string.lockpassword_confirm_your_password_header,
R.string.lockpassword_confirm_your_pin_header,
R.string.lockpassword_ok_label),
ConfirmWrong(R.string.lockpassword_confirm_passwords_dont_match,
R.string.lockpassword_confirm_pins_dont_match,
R.string.lockpassword_continue_label);
/** /**
* @param headerMessage The message displayed at the top. * @param headerMessage The message displayed at the top.
*/ */
Stage(int headerMessage) { Stage(int hintInAlpha, int hintInNumeric, int nextButtonText) {
this.headerMessage = headerMessage; this.alphaHint = hintInAlpha;
this.numericHint = hintInNumeric;
this.buttonText = nextButtonText;
} }
final int headerMessage; public final int alphaHint;
public final int numericHint;
public final int buttonText;
} }
@Override @Override
@@ -110,15 +133,20 @@ public class ChooseLockPassword extends Activity implements OnClickListener {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
findViewById(R.id.cancel_button).setOnClickListener(this); mCancelButton = (Button) findViewById(R.id.cancel_button);
findViewById(R.id.next_button).setOnClickListener(this); mCancelButton.setOnClickListener(this);
mNextButton = (Button) findViewById(R.id.next_button);
mNextButton.setOnClickListener(this);
mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard); mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
mPasswordEntry = (TextView) findViewById(R.id.password_entry); mPasswordEntry = (TextView) findViewById(R.id.password_entry);
mPasswordEntry.setOnEditorActionListener(this);
mPasswordEntry.addTextChangedListener(this);
final boolean isAlpha = LockPatternUtils.MODE_PASSWORD == mRequestedMode; mIsAlphaMode = LockPatternUtils.MODE_PASSWORD == mRequestedMode;
mKeyboardHelper = new PasswordEntryKeyboardHelper(this, mKeyboardView, mPasswordEntry); mKeyboardHelper = new PasswordEntryKeyboardHelper(this, mKeyboardView, mPasswordEntry);
mKeyboardHelper.setKeyboardMode(isAlpha ? PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA mKeyboardHelper.setKeyboardMode(mIsAlphaMode ?
PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
: PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC); : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
mHeaderText = (TextView) findViewById(R.id.headerText); mHeaderText = (TextView) findViewById(R.id.headerText);
@@ -126,17 +154,28 @@ public class ChooseLockPassword extends Activity implements OnClickListener {
} }
@Override @Override
protected void onPause() { protected void onResume() {
super.onPause(); super.onResume();
updateStage(mUiStage);
mKeyboardView.requestFocus(); mKeyboardView.requestFocus();
} }
@Override @Override
protected void onResume() { protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub super.onSaveInstanceState(outState);
super.onResume(); outState.putString(KEY_UI_STAGE, mUiStage.name());
updateStage(mUiStage); outState.putString(KEY_FIRST_PIN, mFirstPin);
mKeyboardView.requestFocus(); }
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
String state = savedInstanceState.getString(KEY_UI_STAGE);
mFirstPin = savedInstanceState.getString(KEY_FIRST_PIN);
if (state != null) {
mUiStage = Stage.valueOf(state);
updateStage(mUiStage);
}
} }
@Override @Override
@@ -154,9 +193,8 @@ public class ChooseLockPassword extends Activity implements OnClickListener {
} }
protected void updateStage(Stage stage) { protected void updateStage(Stage stage) {
mHeaderText.setText(stage.headerMessage);
mPasswordEntry.setText("");
mUiStage = stage; mUiStage = stage;
updateUi();
} }
/** /**
@@ -166,60 +204,76 @@ public class ChooseLockPassword extends Activity implements OnClickListener {
*/ */
private String validatePassword(String pin) { private String validatePassword(String pin) {
if (pin.length() < mPasswordMinLength) { if (pin.length() < mPasswordMinLength) {
return getString(R.string.pin_password_too_short, mPasswordMinLength); return getString(mIsAlphaMode ?
R.string.lockpassword_password_too_short
: R.string.lockpassword_pin_too_short, mPasswordMinLength);
} }
if (pin.length() > mPasswordMaxLength) { if (pin.length() > mPasswordMaxLength) {
return getString(R.string.pin_password_too_long, mPasswordMaxLength); return getString(mIsAlphaMode ?
R.string.lockpassword_password_too_long
: R.string.lockpassword_pin_too_long, mPasswordMaxLength);
} }
if (LockPatternUtils.MODE_PIN == mRequestedMode) { boolean hasAlpha = false;
Pattern p = Pattern.compile("[0-9]+"); boolean hasDigit = false;
Matcher m = p.matcher(pin); boolean hasSymbol = false;
if (!m.find()) { for (int i = 0; i < pin.length(); i++) {
return getString(R.string.pin_password_contains_non_digits); char c = pin.charAt(i);
// allow non white space Latin-1 characters only
if (c <= 32 || c > 127) {
return getString(R.string.lockpassword_illegal_character);
} }
} else if (LockPatternUtils.MODE_PASSWORD == mRequestedMode) { if (c >= '0' && c <= '9') {
// allow Latin-1 characters only hasDigit = true;
for (int i = 0; i < pin.length(); i++) { } else if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
char c = pin.charAt(i); hasAlpha = true;
if (c <= 32 || c > 127) { } else {
return getString(R.string.pin_password_illegal_character); hasSymbol = true;
}
}
if (LockPatternUtils.MODE_PIN == mRequestedMode && (hasAlpha | hasSymbol)) {
return getString(R.string.lockpassword_pin_contains_non_digits);
} else if (LockPatternUtils.MODE_PASSWORD == mRequestedMode && !hasAlpha) {
// require at least 1 alpha character
return getString(R.string.lockpassword_password_requires_alpha);
}
return null;
}
private void handleNext() {
final String pin = mPasswordEntry.getText().toString();
if (TextUtils.isEmpty(pin)) {
return;
}
String errorMsg = null;
if (mUiStage == Stage.Introduction) {
errorMsg = validatePassword(pin);
if (errorMsg == null) {
mFirstPin = pin;
updateStage(Stage.NeedToConfirm);
mPasswordEntry.setText("");
}
} else if (mUiStage == Stage.NeedToConfirm) {
if (mFirstPin.equals(pin)) {
mLockPatternUtils.clearLock();
mLockPatternUtils.saveLockPassword(pin, mRequestedMode);
finish();
} else {
updateStage(Stage.ConfirmWrong);
CharSequence tmp = mPasswordEntry.getText();
if (tmp != null) {
Selection.setSelection((Spannable) tmp, 0, tmp.length());
} }
} }
} }
return null; if (errorMsg != null) {
showError(errorMsg, mUiStage);
}
} }
public void onClick(View v) { public void onClick(View v) {
switch (v.getId()) { switch (v.getId()) {
case R.id.next_button: case R.id.next_button:
{ handleNext();
final String pin = mPasswordEntry.getText().toString();
if (TextUtils.isEmpty(pin)) {
break;
}
String errorMsg = null;
if (mUiStage == Stage.Introduction) {
errorMsg = validatePassword(pin);
if (errorMsg == null) {
mFirstPin = pin;
updateStage(Stage.NeedToConfirm);
}
} else if (mUiStage == Stage.NeedToConfirm) {
if (mFirstPin.equals(pin)) {
// TODO: move these to LockPatternUtils
mLockPatternUtils.setLockPatternEnabled(false);
mLockPatternUtils.saveLockPattern(null);
mLockPatternUtils.saveLockPassword(pin, mRequestedMode);
finish();
} else {
int msg = R.string.lockpassword_confirm_passwords_dont_match;
errorMsg = getString(msg);
}
}
if (errorMsg != null) {
showError(errorMsg, Stage.Introduction);
}
}
break; break;
case R.id.cancel_button: case R.id.cancel_button:
@@ -230,11 +284,57 @@ public class ChooseLockPassword extends Activity implements OnClickListener {
private void showError(String msg, final Stage next) { private void showError(String msg, final Stage next) {
mHeaderText.setText(msg); mHeaderText.setText(msg);
mPasswordEntry.setText("");
mHandler.postDelayed(new Runnable() { mHandler.postDelayed(new Runnable() {
public void run() { public void run() {
updateStage(next); updateStage(next);
} }
}, ERROR_MESSAGE_TIMEOUT); }, ERROR_MESSAGE_TIMEOUT);
} }
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
// Check if this was the result of hitting the enter key
if (actionId == EditorInfo.IME_NULL) {
handleNext();
return true;
}
return false;
}
/**
* Update the hint based on current Stage and length of password entry
*/
private void updateUi() {
final int length = mPasswordEntry.getText().toString().length();
if (mUiStage == Stage.Introduction && length > 0) {
if (length < mPasswordMinLength) {
String msg = getString(mIsAlphaMode ? R.string.lockpassword_password_too_short
: R.string.lockpassword_pin_too_short, mPasswordMinLength);
mHeaderText.setText(msg);
mNextButton.setEnabled(false);
} else {
mHeaderText.setText(R.string.lockpassword_press_continue);
mNextButton.setEnabled(true);
}
} else {
mHeaderText.setText(mIsAlphaMode ? mUiStage.alphaHint : mUiStage.numericHint);
mNextButton.setEnabled(length > 0);
}
mNextButton.setText(mUiStage.buttonText);
}
public void afterTextChanged(Editable s) {
// Changing the text while error displayed resets to NeedToConfirm state
if (mUiStage == Stage.ConfirmWrong) {
mUiStage = Stage.NeedToConfirm;
}
updateUi();
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
} }

View File

@@ -24,13 +24,17 @@ import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.text.Editable; import android.text.Editable;
import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
import android.widget.Button; import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
public class ConfirmLockPassword extends Activity implements OnClickListener { public class ConfirmLockPassword extends Activity implements OnClickListener,
OnEditorActionListener {
private static final long ERROR_MESSAGE_TIMEOUT = 3000; private static final long ERROR_MESSAGE_TIMEOUT = 3000;
private TextView mPasswordEntry; private TextView mPasswordEntry;
private LockPatternUtils mLockPatternUtils; private LockPatternUtils mLockPatternUtils;
@@ -56,11 +60,13 @@ public class ConfirmLockPassword extends Activity implements OnClickListener {
findViewById(R.id.cancel_button).setOnClickListener(this); findViewById(R.id.cancel_button).setOnClickListener(this);
findViewById(R.id.next_button).setOnClickListener(this); findViewById(R.id.next_button).setOnClickListener(this);
mPasswordEntry = (TextView) findViewById(R.id.password_entry); mPasswordEntry = (TextView) findViewById(R.id.password_entry);
mPasswordEntry.setOnEditorActionListener(this);
mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard); mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
mHeaderText = (TextView) findViewById(R.id.headerText); mHeaderText = (TextView) findViewById(R.id.headerText);
mHeaderText.setText(R.string.lockpassword_confirm_your_password_header);
final boolean isAlpha = final boolean isAlpha =
LockPatternUtils.MODE_PASSWORD == mLockPatternUtils.getPasswordMode(); LockPatternUtils.MODE_PASSWORD == mLockPatternUtils.getPasswordMode();
mHeaderText.setText(isAlpha ? R.string.lockpassword_confirm_your_password_header
: R.string.lockpassword_confirm_your_pin_header);
mKeyboardHelper = new PasswordEntryKeyboardHelper(this, mKeyboardView, mPasswordEntry); mKeyboardHelper = new PasswordEntryKeyboardHelper(this, mKeyboardView, mPasswordEntry);
mKeyboardHelper.setKeyboardMode(isAlpha ? PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA mKeyboardHelper.setKeyboardMode(isAlpha ? PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
: PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC); : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
@@ -80,18 +86,20 @@ public class ConfirmLockPassword extends Activity implements OnClickListener {
mKeyboardView.requestFocus(); mKeyboardView.requestFocus();
} }
private void handleNext() {
final String pin = mPasswordEntry.getText().toString();
if (mLockPatternUtils.checkPassword(pin)) {
setResult(RESULT_OK);
finish();
} else {
showError(R.string.lockpattern_need_to_unlock_wrong);
}
}
public void onClick(View v) { public void onClick(View v) {
switch (v.getId()) { switch (v.getId()) {
case R.id.next_button: case R.id.next_button:
{ handleNext();
final String pin = mPasswordEntry.getText().toString();
if (mLockPatternUtils.checkPassword(pin)) {
setResult(RESULT_OK);
finish();
} else {
showError(R.string.lockpattern_need_to_unlock_wrong);
}
}
break; break;
case R.id.cancel_button: case R.id.cancel_button:
@@ -110,4 +118,13 @@ public class ConfirmLockPassword extends Activity implements OnClickListener {
} }
}, ERROR_MESSAGE_TIMEOUT); }, ERROR_MESSAGE_TIMEOUT);
} }
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
// Check if this was the result of hitting the enter key
if (actionId == EditorInfo.IME_NULL) {
handleNext();
return true;
}
return false;
}
} }

View File

@@ -57,6 +57,11 @@ import com.android.internal.widget.LockPatternUtils;
*/ */
public class SecuritySettings extends PreferenceActivity { public class SecuritySettings extends PreferenceActivity {
private static final String KEY_UNLOCK_SET_PASSWORD = "unlock_set_password";
private static final String KEY_UNLOCK_SET_PIN = "unlock_set_pin";
private static final String KEY_UNLOCK_SET_PATTERN = "unlock_set_pattern";
private static final String KEY_UNLOCK_METHOD_CHANGE_CURRENT = "unlock_method_change_current";
private static final String KEY_UNLOCK_METHOD_DISABLE = "unlock_method_disable";
// Lock Settings // Lock Settings
private static final String PACKAGE = "com.android.settings"; private static final String PACKAGE = "com.android.settings";
private static final String LOCK_PATTERN_TUTORIAL = PACKAGE + ".ChooseLockPatternTutorial"; private static final String LOCK_PATTERN_TUTORIAL = PACKAGE + ".ChooseLockPatternTutorial";
@@ -106,8 +111,10 @@ public class SecuritySettings extends PreferenceActivity {
// This is necessary because the Network Location Provider can change settings // This is necessary because the Network Location Provider can change settings
// if the user does not confirm enabling the provider. // if the user does not confirm enabling the provider.
private ContentQueryMap mContentQueryMap; private ContentQueryMap mContentQueryMap;
private ListPreference mUnlockMethod;
private ChooseLockSettingsHelper mChooseLockSettingsHelper; private ChooseLockSettingsHelper mChooseLockSettingsHelper;
private LockPatternUtils mLockPatternUtils;
private PreferenceScreen mDisableUnlock;
private PreferenceScreen mChangeCurrent;
private final class SettingsObserver implements Observer { private final class SettingsObserver implements Observer {
public void update(Observable o, Object arg) { public void update(Observable o, Object arg) {
updateToggles(); updateToggles();
@@ -117,7 +124,8 @@ public class SecuritySettings extends PreferenceActivity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.security_settings);
mLockPatternUtils = new LockPatternUtils(this);
mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE); mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
@@ -125,10 +133,6 @@ public class SecuritySettings extends PreferenceActivity {
createPreferenceHierarchy(); createPreferenceHierarchy();
mNetwork = (CheckBoxPreference) getPreferenceScreen().findPreference(LOCATION_NETWORK);
mGps = (CheckBoxPreference) getPreferenceScreen().findPreference(LOCATION_GPS);
mAssistedGps = (CheckBoxPreference) getPreferenceScreen().findPreference(ASSISTED_GPS);
updateToggles(); updateToggles();
// listen for Location Manager settings changes // listen for Location Manager settings changes
@@ -141,26 +145,46 @@ public class SecuritySettings extends PreferenceActivity {
} }
private PreferenceScreen createPreferenceHierarchy() { private PreferenceScreen createPreferenceHierarchy() {
// Root
PreferenceScreen root = this.getPreferenceScreen(); PreferenceScreen root = this.getPreferenceScreen();
if (root != null) {
root.removeAll();
}
addPreferencesFromResource(R.xml.security_settings);
root = this.getPreferenceScreen();
mNetwork = (CheckBoxPreference) getPreferenceScreen().findPreference(LOCATION_NETWORK);
mGps = (CheckBoxPreference) getPreferenceScreen().findPreference(LOCATION_GPS);
mAssistedGps = (CheckBoxPreference) getPreferenceScreen().findPreference(ASSISTED_GPS);
PreferenceManager pm = getPreferenceManager(); PreferenceManager pm = getPreferenceManager();
mUnlockMethod = (ListPreference) pm.findPreference(KEY_UNLOCK_METHOD); // Lock screen
mUnlockMethod.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { if (!mLockPatternUtils.isSecure()) {
public boolean onPreferenceChange(Preference preference, Object newValue) { addPreferencesFromResource(R.xml.security_settings_chooser);
String value = (String) newValue; } else {
handleUpdateUnlockMethod(value); final int currentMode = mLockPatternUtils.getPasswordMode();
return false; if (currentMode == LockPatternUtils.MODE_PATTERN) {
addPreferencesFromResource(R.xml.security_settings_pattern);
} else if (currentMode == LockPatternUtils.MODE_PIN) {
addPreferencesFromResource(R.xml.security_settings_pin);
} else if (currentMode == LockPatternUtils.MODE_PASSWORD) {
addPreferencesFromResource(R.xml.security_settings_password);
} }
}); }
// disable current pattern. Should be common to all unlock preference screens.
mDisableUnlock = (PreferenceScreen) pm.findPreference(KEY_UNLOCK_METHOD_DISABLE);
// change current. Should be common to all unlock preference screens
mChangeCurrent = (PreferenceScreen) pm.findPreference(KEY_UNLOCK_METHOD_CHANGE_CURRENT);
// visible pattern // visible pattern
mVisiblePattern = (CheckBoxPreference) pm.findPreference(KEY_VISIBLE_PATTERN); mVisiblePattern = (CheckBoxPreference) pm.findPreference(KEY_VISIBLE_PATTERN);
// tactile feedback // tactile feedback. Should be common to all unlock preference screens.
mTactileFeedback = (CheckBoxPreference) pm.findPreference(KEY_TACTILE_FEEDBACK_ENABLED); mTactileFeedback = (CheckBoxPreference) pm.findPreference(KEY_TACTILE_FEEDBACK_ENABLED);
int activePhoneType = TelephonyManager.getDefault().getPhoneType(); int activePhoneType = TelephonyManager.getDefault().getPhoneType();
// do not display SIM lock for CDMA phone // do not display SIM lock for CDMA phone
@@ -217,7 +241,21 @@ public class SecuritySettings extends PreferenceActivity {
return root; return root;
} }
protected void handleUpdateUnlockMethod(final String value) { protected void handleUpdateUnlockMethod(String value) {
// NULL means update the current password/pattern/pin
if (value == null) {
int mode = mLockPatternUtils.getPasswordMode();
if (LockPatternUtils.MODE_PATTERN == mode) {
value = "pattern";
} else if (LockPatternUtils.MODE_PASSWORD == mode) {
value = "password";
} else if (LockPatternUtils.MODE_PIN == mode) {
value = "pin";
} else {
throw new IllegalStateException("Unknown password mode: " + value);
}
}
if ("none".equals(value)) { if ("none".equals(value)) {
if (mDPM.getPasswordQuality(null) == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { if (mDPM.getPasswordQuality(null) == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST); mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST);
@@ -248,11 +286,14 @@ public class SecuritySettings extends PreferenceActivity {
final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils(); final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
boolean patternExists = lockPatternUtils.savedPatternExists(); boolean patternExists = lockPatternUtils.savedPatternExists();
mVisiblePattern.setEnabled(patternExists); if (mVisiblePattern != null) {
mTactileFeedback.setEnabled(patternExists); mVisiblePattern.setEnabled(patternExists);
mVisiblePattern.setChecked(lockPatternUtils.isVisiblePatternEnabled());
mVisiblePattern.setChecked(lockPatternUtils.isVisiblePatternEnabled()); }
mTactileFeedback.setChecked(lockPatternUtils.isTactileFeedbackEnabled()); if (mTactileFeedback != null) {
mTactileFeedback.setEnabled(patternExists);
mTactileFeedback.setChecked(lockPatternUtils.isTactileFeedbackEnabled());
}
mShowPassword.setChecked(Settings.System.getInt(getContentResolver(), mShowPassword.setChecked(Settings.System.getInt(getContentResolver(),
Settings.System.TEXT_SHOW_PASSWORD, 1) != 0); Settings.System.TEXT_SHOW_PASSWORD, 1) != 0);
@@ -266,7 +307,17 @@ public class SecuritySettings extends PreferenceActivity {
final String key = preference.getKey(); final String key = preference.getKey();
final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils(); final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
if (KEY_LOCK_ENABLED.equals(key)) { if (KEY_UNLOCK_SET_PATTERN.equals(key)) {
handleUpdateUnlockMethod("pattern");
} else if (KEY_UNLOCK_SET_PIN.equals(key)) {
handleUpdateUnlockMethod("pin");
} else if (KEY_UNLOCK_SET_PASSWORD.equals(key)) {
handleUpdateUnlockMethod("password");
} else if (KEY_UNLOCK_METHOD_DISABLE.equals(key)) {
handleUpdateUnlockMethod("none");
} else if (KEY_UNLOCK_METHOD_CHANGE_CURRENT.equals(key)) {
handleUpdateUnlockMethod(null);
} else if (KEY_LOCK_ENABLED.equals(key)) {
lockPatternUtils.setLockPatternEnabled(isToggled(preference)); lockPatternUtils.setLockPatternEnabled(isToggled(preference));
} else if (KEY_VISIBLE_PATTERN.equals(key)) { } else if (KEY_VISIBLE_PATTERN.equals(key)) {
lockPatternUtils.setVisiblePatternEnabled(isToggled(preference)); lockPatternUtils.setVisiblePatternEnabled(isToggled(preference));
@@ -327,6 +378,7 @@ public class SecuritySettings extends PreferenceActivity {
if ((requestCode == CONFIRM_EXISTING_REQUEST) && resultOk) { if ((requestCode == CONFIRM_EXISTING_REQUEST) && resultOk) {
lockPatternUtils.clearLock(); lockPatternUtils.clearLock();
} }
createPreferenceHierarchy();
} }
private class CredentialStorage implements DialogInterface.OnClickListener, private class CredentialStorage implements DialogInterface.OnClickListener,