summaryrefslogtreecommitdiffstats
path: root/src/com/android
diff options
context:
space:
mode:
authorJim Miller <jaggies@google.com>2009-12-22 19:04:57 -0800
committerJim Miller <jaggies@google.com>2010-01-11 15:51:59 -0800
commit00d2476d8fc122b4eef59d6be6f7aa41e9c56fde (patch)
treeb0eb0da4a8fcf173d8fc7d5632f0776722dbb0c7 /src/com/android
parent8edfd3a76be936b255484dc20bbeba0050e66e75 (diff)
downloadpackages_apps_settings-00d2476d8fc122b4eef59d6be6f7aa41e9c56fde.zip
packages_apps_settings-00d2476d8fc122b4eef59d6be6f7aa41e9c56fde.tar.gz
packages_apps_settings-00d2476d8fc122b4eef59d6be6f7aa41e9c56fde.tar.bz2
Fix 2332563: Add password-lock support to lockscreen
Diffstat (limited to 'src/com/android')
-rw-r--r--src/com/android/settings/ChooseLockPassword.java232
-rw-r--r--src/com/android/settings/ChooseLockPattern.java108
-rw-r--r--src/com/android/settings/ChooseLockSettingsHelper.java85
-rw-r--r--src/com/android/settings/ConfirmLockPassword.java114
-rw-r--r--src/com/android/settings/SecuritySettings.java153
5 files changed, 541 insertions, 151 deletions
diff --git a/src/com/android/settings/ChooseLockPassword.java b/src/com/android/settings/ChooseLockPassword.java
new file mode 100644
index 0000000..4a8b543
--- /dev/null
+++ b/src/com/android/settings/ChooseLockPassword.java
@@ -0,0 +1,232 @@
+/*
+ * 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.
+ */
+
+package com.android.settings;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.ChooseLockPattern.LeftButtonMode;
+import com.android.settings.ChooseLockPattern.RightButtonMode;
+import com.android.settings.ChooseLockPattern.Stage;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+
+
+public class ChooseLockPassword extends Activity implements OnClickListener {
+ private final int digitIds[] = new int[] { R.id.zero, R.id.one, R.id.two, R.id.three,
+ R.id.four, R.id.five, R.id.six, R.id.seven, R.id.eight, R.id.nine };
+ private TextView mPasswordTextView;
+ private int mPasswordMinLength = 4;
+ private int mPasswordMaxLength = 8;
+ private LockPatternUtils mLockPatternUtils;
+ private int mRequestedMode = LockPatternUtils.MODE_PIN;
+ private ChooseLockSettingsHelper mChooseLockSettingsHelper;
+ private com.android.settings.ChooseLockPassword.Stage mUiStage = Stage.Introduction;
+ private TextView mHeaderText;
+ private String mFirstPin;
+ public static final String PASSWORD_MIN_KEY = "lockscreen.password_min";
+ public static final String PASSWORD_MAX_KEY = "lockscreen.password_max";
+ private static Handler mHandler = new Handler();
+ private static final int CONFIRM_EXISTING_REQUEST = 58;
+ static final int RESULT_FINISHED = RESULT_FIRST_USER;
+ private static final long ERROR_MESSAGE_TIMEOUT = 3000;
+
+ /**
+ * Keep track internally of where the user is in choosing a pattern.
+ */
+ protected enum Stage {
+
+ Introduction(R.string.lockpassword_choose_your_password_header),
+ NeedToConfirm(R.string.lockpassword_confirm_your_password_header),
+ ConfirmWrong(R.string.lockpassword_confirm_passwords_dont_match),
+ ChoiceConfirmed(R.string.lockpassword_password_confirmed_header);
+
+ /**
+ * @param headerMessage The message displayed at the top.
+ */
+ Stage(int headerMessage) {
+ this.headerMessage = headerMessage;
+ }
+
+ final int headerMessage;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mLockPatternUtils = new LockPatternUtils(getContentResolver());
+ mRequestedMode = getIntent().getIntExtra("password_mode", mRequestedMode);
+ mPasswordMinLength = getIntent().getIntExtra("password_min_length", mPasswordMinLength);
+ mPasswordMaxLength = getIntent().getIntExtra("password_max_length", mPasswordMaxLength);
+ initViews();
+ mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this);
+ if (savedInstanceState == null) {
+ updateStage(Stage.Introduction);
+ mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST);
+ }
+ }
+
+ private void initViews() {
+ if (LockPatternUtils.MODE_PIN == mRequestedMode
+ || LockPatternUtils.MODE_PASSWORD == mRequestedMode) {
+ setContentView(R.layout.choose_lock_pin);
+ // TODO: alphanumeric layout
+ // setContentView(R.layout.choose_lock_password);
+ for (int i = 0; i < digitIds.length; i++) {
+ Button button = (Button) findViewById(digitIds[i]);
+ button.setOnClickListener(this);
+ button.setText(Integer.toString(i));
+ }
+ findViewById(R.id.ok).setOnClickListener(this);
+ findViewById(R.id.cancel).setOnClickListener(this);
+ }
+ findViewById(R.id.backspace).setOnClickListener(this);
+ mPasswordTextView = (TextView) findViewById(R.id.pinDisplay);
+ mHeaderText = (TextView) findViewById(R.id.headerText);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode,
+ Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ switch (requestCode) {
+ case CONFIRM_EXISTING_REQUEST:
+ if (resultCode != Activity.RESULT_OK) {
+ setResult(RESULT_FINISHED);
+ finish();
+ }
+ break;
+ }
+ }
+
+ protected void updateStage(Stage stage) {
+ mHeaderText.setText(stage.headerMessage);
+ mPasswordTextView.setText("");
+ mUiStage = stage;
+ }
+
+ /**
+ * Validates PIN and returns a message to display if PIN fails test.
+ * @param pin
+ * @return message id to display to user
+ */
+ private String validatePassword(String pin) {
+ if (pin.length() < mPasswordMinLength) {
+ return getString(R.string.pin_password_too_short, mPasswordMinLength);
+ }
+ if (pin.length() > mPasswordMaxLength) {
+ return getString(R.string.pin_password_too_long, mPasswordMaxLength);
+ }
+ if (LockPatternUtils.MODE_PIN == mRequestedMode) {
+ Pattern p = Pattern.compile("[0-9]+");
+ Matcher m = p.matcher(pin);
+ if (!m.find()) {
+ return getString(R.string.pin_password_contains_non_digits);
+ }
+ } else if (LockPatternUtils.MODE_PASSWORD == mRequestedMode) {
+ // allow Latin-1 characters only
+ for (int i = 0; i < pin.length(); i++) {
+ char c = pin.charAt(i);
+ if (c <= 32 || c > 127) {
+ return getString(R.string.pin_password_illegal_character);
+ }
+ }
+ }
+ return null;
+ }
+
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.ok:
+ {
+ final String pin = mPasswordTextView.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);
+ finish();
+ } else {
+ int msg = R.string.lockpassword_confirm_passwords_dont_match;
+ errorMsg = getString(msg);
+ }
+ }
+ if (errorMsg != null) {
+ showError(errorMsg, Stage.Introduction);
+ }
+ }
+ break;
+
+ case R.id.backspace:
+ {
+ final Editable digits = mPasswordTextView.getEditableText();
+ final int len = digits.length();
+ if (len > 0) {
+ digits.delete(len-1, len);
+ }
+ }
+ break;
+
+ case R.id.cancel:
+ finish();
+ break;
+
+ default:
+ // Digits
+ for (int i = 0; i < digitIds.length; i++) {
+ if (v.getId() == digitIds[i]) {
+ mPasswordTextView.append(Integer.toString(i));
+ return;
+ }
+ }
+ break;
+ }
+ }
+
+ private void showError(String msg, final Stage next) {
+ mHeaderText.setText(msg);
+ mPasswordTextView.setText("");
+ mHandler.postDelayed(new Runnable() {
+ public void run() {
+ updateStage(next);
+ }
+ }, ERROR_MESSAGE_TIMEOUT);
+ }
+}
diff --git a/src/com/android/settings/ChooseLockPattern.java b/src/com/android/settings/ChooseLockPattern.java
index f103c6b..859d96b 100644
--- a/src/com/android/settings/ChooseLockPattern.java
+++ b/src/com/android/settings/ChooseLockPattern.java
@@ -45,7 +45,6 @@ import java.util.List;
* - saves chosen password when confirmed
*/
public class ChooseLockPattern extends Activity implements View.OnClickListener{
-
/**
* Used by the choose lock pattern wizard to indicate the wizard is
* finished, and each activity in the wizard should finish.
@@ -56,7 +55,9 @@ public class ChooseLockPattern extends Activity implements View.OnClickListener{
* result.
*/
static final int RESULT_FINISHED = RESULT_FIRST_USER;
-
+
+ public static final int CONFIRM_EXISTING_REQUEST = 55;
+
// how long after a confirmation message is shown before moving on
static final int INFORMATION_MSG_TIMEOUT_MS = 3000;
@@ -65,29 +66,38 @@ public class ChooseLockPattern extends Activity implements View.OnClickListener{
private static final int ID_EMPTY_MESSAGE = -1;
-
protected TextView mHeaderText;
protected LockPatternView mLockPatternView;
protected TextView mFooterText;
private TextView mFooterLeftButton;
private TextView mFooterRightButton;
-
protected List<LockPatternView.Cell> mChosenPattern = null;
- protected LockPatternUtils mLockPatternUtils;
-
/**
* The patten used during the help screen to show how to draw a pattern.
*/
private final List<LockPatternView.Cell> mAnimatePattern =
- Collections.unmodifiableList(
- Lists.newArrayList(
- LockPatternView.Cell.of(0, 0),
- LockPatternView.Cell.of(0, 1),
- LockPatternView.Cell.of(1, 1),
- LockPatternView.Cell.of(2, 1)
- ));
+ Collections.unmodifiableList(Lists.newArrayList(
+ LockPatternView.Cell.of(0, 0),
+ LockPatternView.Cell.of(0, 1),
+ LockPatternView.Cell.of(1, 1),
+ LockPatternView.Cell.of(2, 1)
+ ));
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode,
+ Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ switch (requestCode) {
+ case CONFIRM_EXISTING_REQUEST:
+ if (resultCode != Activity.RESULT_OK) {
+ setResult(RESULT_FINISHED);
+ finish();
+ }
+ updateStage(Stage.Introduction);
+ break;
+ }
+ }
/**
* The pattern listener that responds according to a user choosing a new
@@ -125,7 +135,7 @@ public class ChooseLockPattern extends Activity implements View.OnClickListener{
}
}
- public void onPatternCellAdded(List<Cell> pattern) {
+ public void onPatternCellAdded(List<Cell> pattern) {
}
@@ -250,19 +260,19 @@ public class ChooseLockPattern extends Activity implements View.OnClickListener{
}
};
+ private ChooseLockSettingsHelper mChooseLockSettingsHelper;
+
private static final String KEY_UI_STAGE = "uiStage";
private static final String KEY_PATTERN_CHOICE = "chosenPattern";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- mLockPatternUtils = new LockPatternUtils(getContentResolver());
-
+ mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setupViews();
-
+
// make it so unhandled touch events within the unlock screen go to the
// lock pattern view.
final LinearLayoutWithDefaultTouchRecepient topLayout
@@ -271,11 +281,12 @@ public class ChooseLockPattern extends Activity implements View.OnClickListener{
topLayout.setDefaultTouchRecepient(mLockPatternView);
if (savedInstanceState == null) {
- // first launch
- updateStage(Stage.Introduction);
- if (mLockPatternUtils.savedPatternExists()) {
- confirmPattern();
- }
+ // first launch. As a security measure, we're in NeedToConfirm mode until we know
+ // there isn't an existing password or the user confirms their password.
+ updateStage(Stage.NeedToConfirm);
+ if (!mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST)) {
+ updateStage(Stage.Introduction);
+ }
} else {
// restore from previous state
final String patternString = savedInstanceState.getString(KEY_PATTERN_CHOICE);
@@ -285,19 +296,20 @@ public class ChooseLockPattern extends Activity implements View.OnClickListener{
updateStage(Stage.values()[savedInstanceState.getInt(KEY_UI_STAGE)]);
}
}
-
+
/**
* Keep all "find view" related stuff confined to this function since in
* case someone needs to subclass and customize.
*/
protected void setupViews() {
setContentView(R.layout.choose_lock_pattern);
-
+
mHeaderText = (TextView) findViewById(R.id.headerText);
mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
mLockPatternView.setOnPatternListener(mChooseNewLockPatternListener);
- mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
+ mLockPatternView.setTactileFeedbackEnabled(
+ mChooseLockSettingsHelper.utils().isTactileFeedbackEnabled());
mFooterText = (TextView) findViewById(R.id.footerText);
@@ -364,35 +376,6 @@ public class ChooseLockPattern extends Activity implements View.OnClickListener{
return super.onKeyDown(keyCode, event);
}
- /**
- * Launch screen to confirm the existing lock pattern.
- * @see #onActivityResult(int, int, android.content.Intent)
- */
- protected void confirmPattern() {
- final Intent intent = new Intent();
- intent.setClassName("com.android.settings", "com.android.settings.ConfirmLockPattern");
- startActivityForResult(intent, 55);
- }
-
- /**
- * @see #confirmPattern
- */
- @Override
- protected void onActivityResult(int requestCode, int resultCode,
- Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
-
- if (requestCode != 55) {
- return;
- }
-
- if (resultCode != Activity.RESULT_OK) {
- setResult(RESULT_FINISHED);
- finish();
- }
- updateStage(Stage.Introduction);
- }
-
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
@@ -414,7 +397,7 @@ public class ChooseLockPattern extends Activity implements View.OnClickListener{
mUiStage = stage;
- // header text, footer text, visibility and
+ // header text, footer text, visibility and
// enabled state all known from the stage
if (stage == Stage.ChoiceTooShort) {
mHeaderText.setText(
@@ -486,16 +469,17 @@ public class ChooseLockPattern extends Activity implements View.OnClickListener{
}
private void saveChosenPatternAndFinish() {
- final boolean lockVirgin = !mLockPatternUtils.isPatternEverChosen();
+ LockPatternUtils utils = mChooseLockSettingsHelper.utils();
+ final boolean lockVirgin = !utils.isPatternEverChosen();
- mLockPatternUtils.saveLockPattern(mChosenPattern);
- mLockPatternUtils.setLockPatternEnabled(true);
+ utils.saveLockPattern(mChosenPattern);
+ utils.setLockPatternEnabled(true);
if (lockVirgin) {
- mLockPatternUtils.setVisiblePatternEnabled(true);
- mLockPatternUtils.setTactileFeedbackEnabled(false);
+ utils.setVisiblePatternEnabled(true);
+ utils.setTactileFeedbackEnabled(false);
}
-
+
setResult(RESULT_FINISHED);
finish();
}
diff --git a/src/com/android/settings/ChooseLockSettingsHelper.java b/src/com/android/settings/ChooseLockSettingsHelper.java
new file mode 100644
index 0000000..ab2f8c0
--- /dev/null
+++ b/src/com/android/settings/ChooseLockSettingsHelper.java
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+package com.android.settings;
+
+import android.app.Activity;
+import android.content.Intent;
+
+import com.android.internal.widget.LockPatternUtils;
+
+public class ChooseLockSettingsHelper {
+ private LockPatternUtils mLockPatternUtils;
+ private Activity mActivity;
+
+ public ChooseLockSettingsHelper(Activity activity) {
+ mActivity = activity;
+ mLockPatternUtils = new LockPatternUtils(activity.getContentResolver());
+ }
+
+ public LockPatternUtils utils() {
+ return mLockPatternUtils;
+ }
+
+ /**
+ * If a pattern, password or PIN exists, prompt the user before allowing them to change it.
+ * @return true if one exists and we launched an activity to confirm it
+ * @see #onActivityResult(int, int, android.content.Intent)
+ */
+ protected boolean launchConfirmationActivity(int request) {
+ boolean launched = false;
+ switch (mLockPatternUtils.getPasswordMode()) {
+ case LockPatternUtils.MODE_PATTERN:
+ launched = confirmPattern(request);
+ break;
+ case LockPatternUtils.MODE_PIN:
+ case LockPatternUtils.MODE_PASSWORD:
+ launched = confirmPassword(request);
+ break;
+ }
+ return launched;
+ }
+
+ /**
+ * Launch screen to confirm the existing lock pattern.
+ * @see #onActivityResult(int, int, android.content.Intent)
+ * @return true if we launched an activity to confirm pattern
+ */
+ private boolean confirmPattern(int request) {
+ if (!mLockPatternUtils.isLockPatternEnabled() || !mLockPatternUtils.savedPatternExists()) {
+ return false;
+ }
+ final Intent intent = new Intent();
+ intent.setClassName("com.android.settings", "com.android.settings.ConfirmLockPattern");
+ mActivity.startActivityForResult(intent, request);
+ return true;
+ }
+
+ /**
+ * Launch screen to confirm the existing lock password.
+ * @see #onActivityResult(int, int, android.content.Intent)
+ * @return true if we launched an activity to confirm password
+ */
+ private boolean confirmPassword(int request) {
+ if (!mLockPatternUtils.isLockPasswordEnabled()) return false;
+ final Intent intent = new Intent();
+ intent.setClassName("com.android.settings", "com.android.settings.ConfirmLockPassword");
+ mActivity.startActivityForResult(intent, request);
+ return true;
+ }
+
+
+}
diff --git a/src/com/android/settings/ConfirmLockPassword.java b/src/com/android/settings/ConfirmLockPassword.java
new file mode 100644
index 0000000..0cbc158
--- /dev/null
+++ b/src/com/android/settings/ConfirmLockPassword.java
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+
+package com.android.settings;
+
+import com.android.internal.widget.LockPatternUtils;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.text.Editable;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+
+public class ConfirmLockPassword extends Activity implements OnClickListener {
+ private static final long ERROR_MESSAGE_TIMEOUT = 3000;
+ private final int digitIds[] = new int[] { R.id.zero, R.id.one, R.id.two, R.id.three,
+ R.id.four, R.id.five, R.id.six, R.id.seven, R.id.eight, R.id.nine };
+ private TextView mPasswordTextView;
+ private LockPatternUtils mLockPatternUtils;
+ private TextView mHeaderText;
+ private Handler mHandler = new Handler();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mLockPatternUtils = new LockPatternUtils(getContentResolver());
+ initViews();
+ }
+
+ private void initViews() {
+ int mode = mLockPatternUtils.getPasswordMode();
+ if (LockPatternUtils.MODE_PIN == mode || LockPatternUtils.MODE_PASSWORD == mode) {
+ setContentView(R.layout.confirm_lock_pin);
+ for (int i = 0; i < digitIds.length; i++) {
+ Button button = (Button) findViewById(digitIds[i]);
+ button.setOnClickListener(this);
+ button.setText(Integer.toString(i));
+ }
+ findViewById(R.id.ok).setOnClickListener(this);
+ findViewById(R.id.cancel).setOnClickListener(this);
+ }
+ findViewById(R.id.backspace).setOnClickListener(this);
+ mPasswordTextView = (TextView) findViewById(R.id.pinDisplay);
+ mHeaderText = (TextView) findViewById(R.id.headerText);
+ mHeaderText.setText(R.string.lockpassword_confirm_your_password_header);
+ }
+
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.ok:
+ {
+ final String pin = mPasswordTextView.getText().toString();
+ if (mLockPatternUtils.checkPassword(pin)) {
+ setResult(RESULT_OK);
+ finish();
+ } else {
+ showError(R.string.lockpattern_need_to_unlock_wrong);
+ }
+ }
+ break;
+
+ case R.id.backspace:
+ {
+ final Editable digits = mPasswordTextView.getEditableText();
+ final int len = digits.length();
+ if (len > 0) {
+ digits.delete(len-1, len);
+ }
+ }
+ break;
+
+ case R.id.cancel:
+ setResult(RESULT_CANCELED);
+ finish();
+ break;
+
+ default:
+ // Digits
+ for (int i = 0; i < digitIds.length; i++) {
+ if (v.getId() == digitIds[i]) {
+ mPasswordTextView.append(Integer.toString(i));
+ return;
+ }
+ }
+ break;
+ }
+ }
+
+ private void showError(int msg) {
+ mHeaderText.setText(msg);
+ mPasswordTextView.setText(null);
+ mHandler.postDelayed(new Runnable() {
+ public void run() {
+ mHeaderText.setText(R.string.lockpassword_confirm_your_password_header);
+ }
+ }, ERROR_MESSAGE_TIMEOUT);
+ }
+}
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index 0202f4c..fb284fd 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -25,7 +25,6 @@ import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentQueryMap;
import android.content.ContentResolver;
-import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
@@ -35,10 +34,13 @@ import android.os.ICheckinService;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.preference.CheckBoxPreference;
+import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
+import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
+import android.preference.Preference.OnPreferenceChangeListener;
import android.provider.Settings;
import android.security.Credentials;
import android.security.KeyStore;
@@ -56,11 +58,18 @@ import com.android.internal.widget.LockPatternUtils;
public class SecuritySettings extends PreferenceActivity {
// Lock Settings
+ private static final String PACKAGE = "com.android.settings";
+ private static final String LOCK_PATTERN_TUTORIAL = PACKAGE + ".ChooseLockPatternTutorial";
+ private static final String ICC_LOCK_SETTINGS = PACKAGE + ".IccLockSettings";
+ private static final String CHOOSE_LOCK_PATTERN = PACKAGE + ".ChooseLockPattern";
+ private static final String CHOOSE_LOCK_PIN = PACKAGE + ".ChooseLockPassword";
private static final String KEY_LOCK_ENABLED = "lockenabled";
private static final String KEY_VISIBLE_PATTERN = "visiblepattern";
private static final String KEY_TACTILE_FEEDBACK_ENABLED = "tactilefeedback";
- private static final int CONFIRM_PATTERN_THEN_DISABLE_AND_CLEAR_REQUEST_CODE = 55;
+ private static final String KEY_UNLOCK_METHOD = "unlock_method";
+ private static final int UPDATE_PASSWORD_REQUEST = 56;
+ private static final int CONFIRM_EXISTING_REQUEST = 57;
// Encrypted File Systems constants
private static final String PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
@@ -69,11 +78,8 @@ public class SecuritySettings extends PreferenceActivity {
private static final String PREFS_NAME = "location_prefs";
private static final String PREFS_USE_LOCATION = "use_location";
- private LockPatternUtils mLockPatternUtils;
- private CheckBoxPreference mLockEnabled;
private CheckBoxPreference mVisiblePattern;
private CheckBoxPreference mTactileFeedback;
- private Preference mChoosePattern;
private CheckBoxPreference mShowPassword;
@@ -97,6 +103,8 @@ public class SecuritySettings extends PreferenceActivity {
// This is necessary because the Network Location Provider can change settings
// if the user does not confirm enabling the provider.
private ContentQueryMap mContentQueryMap;
+ private ListPreference mUnlockMethod;
+ private ChooseLockSettingsHelper mChooseLockSettingsHelper;
private final class SettingsObserver implements Observer {
public void update(Observable o, Object arg) {
updateToggles();
@@ -108,7 +116,7 @@ public class SecuritySettings extends PreferenceActivity {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.security_settings);
- mLockPatternUtils = new LockPatternUtils(getContentResolver());
+ mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this);
createPreferenceHierarchy();
@@ -131,37 +139,22 @@ public class SecuritySettings extends PreferenceActivity {
// Root
PreferenceScreen root = this.getPreferenceScreen();
- // Inline preferences
- PreferenceCategory inlinePrefCat = new PreferenceCategory(this);
- inlinePrefCat.setTitle(R.string.lock_settings_title);
- root.addPreference(inlinePrefCat);
-
- // change pattern lock
- Intent intent = new Intent();
- intent.setClassName("com.android.settings",
- "com.android.settings.ChooseLockPatternTutorial");
- mChoosePattern = getPreferenceManager().createPreferenceScreen(this);
- mChoosePattern.setIntent(intent);
- inlinePrefCat.addPreference(mChoosePattern);
-
- // autolock toggle
- mLockEnabled = new LockEnabledPref(this);
- mLockEnabled.setTitle(R.string.lockpattern_settings_enable_title);
- mLockEnabled.setSummary(R.string.lockpattern_settings_enable_summary);
- mLockEnabled.setKey(KEY_LOCK_ENABLED);
- inlinePrefCat.addPreference(mLockEnabled);
+ PreferenceManager pm = getPreferenceManager();
+
+ mUnlockMethod = (ListPreference) pm.findPreference(KEY_UNLOCK_METHOD);
+ mUnlockMethod.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ String value = (String) newValue;
+ handleUpdateUnlockMethod(value);
+ return false;
+ }
+ });
// visible pattern
- mVisiblePattern = new CheckBoxPreference(this);
- mVisiblePattern.setKey(KEY_VISIBLE_PATTERN);
- mVisiblePattern.setTitle(R.string.lockpattern_settings_enable_visible_pattern_title);
- inlinePrefCat.addPreference(mVisiblePattern);
+ mVisiblePattern = (CheckBoxPreference) pm.findPreference(KEY_VISIBLE_PATTERN);
// tactile feedback
- mTactileFeedback = new CheckBoxPreference(this);
- mTactileFeedback.setKey(KEY_TACTILE_FEEDBACK_ENABLED);
- mTactileFeedback.setTitle(R.string.lockpattern_settings_enable_tactile_feedback_title);
- inlinePrefCat.addPreference(mTactileFeedback);
+ mTactileFeedback = (CheckBoxPreference) pm.findPreference(KEY_TACTILE_FEEDBACK_ENABLED);
int activePhoneType = TelephonyManager.getDefault().getPhoneType();
@@ -172,10 +165,7 @@ public class SecuritySettings extends PreferenceActivity {
.createPreferenceScreen(this);
simLockPreferences.setTitle(R.string.sim_lock_settings_category);
// Intent to launch SIM lock settings
- intent = new Intent();
- intent.setClassName("com.android.settings", "com.android.settings.IccLockSettings");
- simLockPreferences.setIntent(intent);
-
+ simLockPreferences.setIntent(new Intent().setClassName(PACKAGE, ICC_LOCK_SETTINGS));
PreferenceCategory simLockCat = new PreferenceCategory(this);
simLockCat.setTitle(R.string.sim_lock_settings_title);
root.addPreference(simLockCat);
@@ -209,23 +199,41 @@ public class SecuritySettings extends PreferenceActivity {
return root;
}
+ protected void handleUpdateUnlockMethod(final String value) {
+ final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
+ if ("none".equals(value)) {
+ mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST);
+ } else if ("password".equals(value) || "pin".equals(value)) {
+ final int minLength = 4; // TODO: get from policy store.
+ final int maxLength = 16;
+ final int mode = "password".equals(value)
+ ? LockPatternUtils.MODE_PASSWORD : LockPatternUtils.MODE_PIN;
+ Intent intent = new Intent().setClassName(PACKAGE, CHOOSE_LOCK_PIN);
+ intent.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, mode);
+ intent.putExtra(ChooseLockPassword.PASSWORD_MIN_KEY, minLength);
+ intent.putExtra(ChooseLockPassword.PASSWORD_MAX_KEY, maxLength);
+ startActivityForResult(intent, UPDATE_PASSWORD_REQUEST);
+ } else if ("pattern".equals(value)) {
+ boolean showTutorial = !lockPatternUtils.isPatternEverChosen();
+ Intent intent = new Intent();
+ intent.setClassName(PACKAGE, showTutorial ?
+ LOCK_PATTERN_TUTORIAL : CHOOSE_LOCK_PATTERN);
+ intent.putExtra("key_lock_method", value);
+ startActivityForResult(intent, UPDATE_PASSWORD_REQUEST);
+ }
+ }
+
@Override
protected void onResume() {
super.onResume();
- boolean patternExists = mLockPatternUtils.savedPatternExists();
- mLockEnabled.setEnabled(patternExists);
+ final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
+ boolean patternExists = lockPatternUtils.savedPatternExists();
mVisiblePattern.setEnabled(patternExists);
mTactileFeedback.setEnabled(patternExists);
- mLockEnabled.setChecked(mLockPatternUtils.isLockPatternEnabled());
- mVisiblePattern.setChecked(mLockPatternUtils.isVisiblePatternEnabled());
- mTactileFeedback.setChecked(mLockPatternUtils.isTactileFeedbackEnabled());
-
- int chooseStringRes = mLockPatternUtils.savedPatternExists() ?
- R.string.lockpattern_settings_change_lock_pattern :
- R.string.lockpattern_settings_choose_lock_pattern;
- mChoosePattern.setTitle(chooseStringRes);
+ mVisiblePattern.setChecked(lockPatternUtils.isVisiblePatternEnabled());
+ mTactileFeedback.setChecked(lockPatternUtils.isTactileFeedbackEnabled());
mShowPassword.setChecked(Settings.System.getInt(getContentResolver(),
Settings.System.TEXT_SHOW_PASSWORD, 1) != 0);
@@ -238,12 +246,13 @@ public class SecuritySettings extends PreferenceActivity {
Preference preference) {
final String key = preference.getKey();
+ final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
if (KEY_LOCK_ENABLED.equals(key)) {
- mLockPatternUtils.setLockPatternEnabled(isToggled(preference));
+ lockPatternUtils.setLockPatternEnabled(isToggled(preference));
} else if (KEY_VISIBLE_PATTERN.equals(key)) {
- mLockPatternUtils.setVisiblePatternEnabled(isToggled(preference));
+ lockPatternUtils.setVisiblePatternEnabled(isToggled(preference));
} else if (KEY_TACTILE_FEEDBACK_ENABLED.equals(key)) {
- mLockPatternUtils.setTactileFeedbackEnabled(isToggled(preference));
+ lockPatternUtils.setTactileFeedbackEnabled(isToggled(preference));
} else if (preference == mShowPassword) {
Settings.System.putInt(getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD,
mShowPassword.isChecked() ? 1 : 0);
@@ -265,11 +274,6 @@ public class SecuritySettings extends PreferenceActivity {
return false;
}
- private void showPrivacyPolicy() {
- Intent intent = new Intent("android.settings.TERMS");
- startActivity(intent);
- }
-
/*
* Creates toggles for each available location provider
*/
@@ -292,36 +296,6 @@ public class SecuritySettings extends PreferenceActivity {
}
/**
- * For the user to disable keyguard, we first make them verify their
- * existing pattern.
- */
- private class LockEnabledPref extends CheckBoxPreference {
-
- public LockEnabledPref(Context context) {
- super(context);
- }
-
- @Override
- protected void onClick() {
- if (mLockPatternUtils.savedPatternExists() && isChecked()) {
- confirmPatternThenDisableAndClear();
- } else {
- super.onClick();
- }
- }
- }
-
- /**
- * Launch screen to confirm the existing lock pattern.
- * @see #onActivityResult(int, int, android.content.Intent)
- */
- private void confirmPatternThenDisableAndClear() {
- final Intent intent = new Intent();
- intent.setClassName("com.android.settings", "com.android.settings.ConfirmLockPattern");
- startActivityForResult(intent, CONFIRM_PATTERN_THEN_DISABLE_AND_CLEAR_REQUEST_CODE);
- }
-
- /**
* @see #confirmPatternThenDisableAndClear
*/
@Override
@@ -330,10 +304,11 @@ public class SecuritySettings extends PreferenceActivity {
final boolean resultOk = resultCode == Activity.RESULT_OK;
- if ((requestCode == CONFIRM_PATTERN_THEN_DISABLE_AND_CLEAR_REQUEST_CODE)
- && resultOk) {
- mLockPatternUtils.setLockPatternEnabled(false);
- mLockPatternUtils.saveLockPattern(null);
+ LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
+ if ((requestCode == CONFIRM_EXISTING_REQUEST) && resultOk) {
+ lockPatternUtils.saveLockPassword(null);
+ lockPatternUtils.setLockPatternEnabled(false);
+ lockPatternUtils.saveLockPattern(null);
}
}