diff options
author | Jim Miller <jaggies@google.com> | 2009-12-22 19:04:57 -0800 |
---|---|---|
committer | Jim Miller <jaggies@google.com> | 2010-01-11 15:51:59 -0800 |
commit | 00d2476d8fc122b4eef59d6be6f7aa41e9c56fde (patch) | |
tree | b0eb0da4a8fcf173d8fc7d5632f0776722dbb0c7 /src/com/android | |
parent | 8edfd3a76be936b255484dc20bbeba0050e66e75 (diff) | |
download | packages_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.java | 232 | ||||
-rw-r--r-- | src/com/android/settings/ChooseLockPattern.java | 108 | ||||
-rw-r--r-- | src/com/android/settings/ChooseLockSettingsHelper.java | 85 | ||||
-rw-r--r-- | src/com/android/settings/ConfirmLockPassword.java | 114 | ||||
-rw-r--r-- | src/com/android/settings/SecuritySettings.java | 153 |
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); } } |