Extract credential storage dialogs to a new activity.

Since now SecuritySettings is a fragment, not an activity, reacting
to intents is not easier anymore. The new activity is transparent,
and it works just like a dialog. This change also refactor'ed
SecuritySettings by moving some preference construction into
security_settings_misc.xml.

Bug: 3120992
Bug: 2117436
Change-Id: I8bd3fc7faa2a31d100b8d67310f9266260cfc31d
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0f2390c..9caecec 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -626,14 +626,6 @@
                 android:resource="@id/security_settings" />
         </activity>
 
-        <activity android:name="CredentialInstaller"
-                android:theme="@android:style/Theme.Translucent.NoTitleBar">
-            <intent-filter>
-                <action android:name="android.credentials.SYSTEM_INSTALL" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </activity>
-
         <activity android:name="Settings$PrivacySettingsActivity"
                 android:theme="@android:style/Theme.Holo"
                 android:label="@string/privacy_settings_title"
@@ -651,6 +643,18 @@
                 android:resource="@id/privacy_settings" />
         </activity>
 
+        <activity android:name="CredentialStorage"
+                android:theme="@style/Transparent"
+                android:configChanges="orientation|keyboardHidden">
+            <intent-filter>
+                <action android:name="com.android.credentials.UNLOCK" />
+                <action android:name="com.android.credentials.INSTALL" />
+                <action android:name="com.android.credentials.SET_PASSWORD" />
+                <action android:name="com.android.credentials.RESET" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
         <activity android:name="DeviceAdminSettings"
                 android:label="@string/device_admin_settings_title"
                 android:theme="@style/TallTitleBarTheme"
diff --git a/res/layout/credentials_password_dialog.xml b/res/layout/credentials_dialog.xml
similarity index 60%
rename from res/layout/credentials_password_dialog.xml
rename to res/layout/credentials_dialog.xml
index 440a107..506b3d6 100644
--- a/res/layout/credentials_password_dialog.xml
+++ b/res/layout/credentials_dialog.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2011 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.
@@ -18,7 +18,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content">
 
-    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    <LinearLayout
             android:orientation="vertical"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
@@ -27,47 +27,54 @@
         <TextView android:id="@+id/hint"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:textSize="@dimen/vpn_connect_normal_text_size"
-                android:text="@string/credentials_first_time_hint"
-                android:layout_marginBottom="10sp"
-                android:visibility="gone"/>
+                android:layout_marginBottom="10sp"/>
 
         <TextView android:id="@+id/error"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:layout_marginBottom="10sp"
                 android:textColor="@color/red"
                 android:textStyle="bold"
                 android:visibility="gone"/>
 
         <TextView android:id="@+id/old_password_prompt"
-        	android:layout_width="match_parent"
+                android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:text="@string/credentials_old_password"
                 android:visibility="gone"/>
+
         <EditText android:id="@+id/old_password"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:password="True"
-                android:singleLine="True"
+                android:password="true"
+                android:singleLine="true"
                 android:visibility="gone"/>
 
-        <TextView android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/credentials_new_password" />
-        <EditText android:id="@+id/new_password"
+        <LinearLayout android:id="@+id/new_passwords"
+                android:orientation="vertical"
                 android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:password="True"
-                android:singleLine="True"/>
+                android:layout_height="match_parent"
+                android:visibility="gone">
 
-        <TextView android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/credentials_confirm_password" />
-        <EditText android:id="@+id/confirm_password"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:password="True"
-                android:singleLine="True"/>
+            <TextView android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/credentials_new_password"/>
 
+            <EditText android:id="@+id/new_password"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:password="true"
+                    android:singleLine="true"/>
+
+            <TextView android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/credentials_confirm_password"/>
+
+            <EditText android:id="@+id/confirm_password"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:password="true"
+                    android:singleLine="true"/>
+        </LinearLayout>
     </LinearLayout>
 </ScrollView>
diff --git a/res/layout/credentials_unlock_dialog.xml b/res/layout/credentials_unlock_dialog.xml
deleted file mode 100644
index a538807..0000000
--- a/res/layout/credentials_unlock_dialog.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 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.
--->
-
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content">
-
-    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-            android:orientation="vertical"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:padding="15dip">
-
-        <TextView android:id="@+id/hint"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:textSize="@dimen/vpn_connect_normal_text_size"
-                android:text="@string/credentials_unlock_hint"
-                android:layout_marginBottom="10sp"
-                android:visibility="gone"/>
-
-        <TextView android:id="@+id/error"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:textColor="@color/red"
-                android:textStyle="bold"
-                android:visibility="gone"/>
-
-        <EditText android:id="@+id/old_password"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:password="True"
-                android:singleLine="True"/>
-
-    </LinearLayout>
-</ScrollView>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 42c846d..5a2ecca 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2830,55 +2830,55 @@
     <!-- A secret edit field's grayed out value when it has not been set -->
     <string name="vpn_secret_not_set">(not set)</string>
 
-    <!-- Title of preference group for credential storage settings -->
-    <string name="credentials_category">Credential storage</string>
-    <!-- Title of preference to enable/dislable access to credential storage -->
+    <!-- Title of preference group for credential storage settings [CHAR LIMIT=30] -->
+    <string name="credentials_title">Credential storage</string>
+    <!-- Title of preference to enable/dislable access to credential storage [CHAR LIMIT=30] -->
     <string name="credentials_access">Use secure credentials</string>
-    <!-- Summary of preference to enable/dislable access to credential storage -->
+    <!-- Summary of preference to enable/dislable access to credential storage [CHAR LIMIT=NONE] -->
     <string name="credentials_access_summary">Allow applications to access secure certificates and other credentials</string>
-    <!-- Title of dialog to enable/dislable access to credential storage -->
-    <string name="credentials_unlock">Enter password</string>
-    <!-- Description of dialog to enable/dislable access to credential storage -->
-    <string name="credentials_unlock_hint">Enter the credential storage password.</string>
-    <!-- Title of preference to install certificates from SD card [CHAR LIMIT=25] -->
-    <string name="credentials_install_certificates" product="nosdcard">Install from USB storage</string>
-    <!-- Title of preference to install certificates from SD card -->
-    <string name="credentials_install_certificates" product="default">Install from SD card</string>
-    <!-- Summary of preference to install certificates from SD card [CHAR LIMIT=25] -->
-    <string name="credentials_install_certificates_summary" product="nosdcard">Install encrypted certificates from USB storage</string>
-    <!-- Summary of preference to install certificates from SD card -->
-    <string name="credentials_install_certificates_summary" product="default">Install encrypted certificates from SD card</string>
-    <!-- Title of preference to set storage password -->
+    <!-- Title of preference to install certificates from SD card [CHAR LIMIT=30] -->
+    <string name="credentials_install" product="nosdcard">Install from USB storage</string>
+    <!-- Title of preference to install certificates from SD card [CHAR LIMIT=30] -->
+    <string name="credentials_install" product="default">Install from SD card</string>
+    <!-- Summary of preference to install certificates from SD card [CHAR LIMIT=NONE] -->
+    <string name="credentials_install_summary" product="nosdcard">Install certificates from USB storage</string>
+    <!-- Summary of preference to install certificates from SD card [CHAR LIMIT=NONE] -->
+    <string name="credentials_install_summary" product="default">Install certificates from SD card</string>
+    <!-- Title of preference to set the password for credential storage [CHAR LIMIT=30] -->
     <string name="credentials_set_password">Set password</string>
-    <!-- Summary of preference to set storage password -->
-    <string name="credentials_set_password_summary">Set or change the credential storage password</string>
-    <!-- Title of preference to reset credential storage -->
-    <string name="credentials_reset">Clear storage</string>
-    <!-- Summary of preference to reset credential storage -->
-    <string name="credentials_reset_summary">Clear credential storage of all contents and reset its password</string>
-    <!-- Description of dialog to reset the credential storage -->
-    <string name="credentials_reset_hint">Are you sure you want to delete all credentials and reset the credential storage password?</string>
-    <!-- Description for the old-password input box -->
+    <!-- Summary of preference to set the password for credential storage [CHAR LIMIT=NONE] -->
+    <string name="credentials_set_password_summary">Set or change the password for credential storage</string>
+    <!-- Title of preference to reset credential storage [CHAR LIMIT=30] -->
+    <string name="credentials_reset">Clear credentials</string>
+    <!-- Summary of preference to reset credential storage [CHAR LIMIT=NONE] -->
+    <string name="credentials_reset_summary">Remove all the contents and reset the password</string>
+
+    <!-- Title of dialog to enable credential storage [CHAR LIMIT=30] -->
+    <string name="credentials_unlock">Enter password</string>
+    <!-- Description of dialog to enable credential storage [CHAR LIMIT=NONE] -->
+    <string name="credentials_unlock_hint">Enter the password for credential storage.</string>
+    <!-- Description of dialog to set the password for credential storage [CHAR LIMIT=NONE] -->
+    <string name="credentials_password_hint">Set the password for credential storage. It must have at least 8 characters.</string>
+    <!-- Description of the input box for the old password [CHAR LIMIT=30] -->
     <string name="credentials_old_password">Current password:</string>
-    <!-- Description for the new-password input box -->
+    <!-- Description of the input box for the new password [CHAR LIMIT=30] -->
     <string name="credentials_new_password">New password:</string>
-    <!-- Description for the confirm-new-password input box -->
+    <!-- Description of the input box to confirm the new password [CHAR LIMIT=30] -->
     <string name="credentials_confirm_password">Confirm new password:</string>
-    <!-- Description when user set up the storage for the very first time -->
-    <string name="credentials_first_time_hint">Set a password for the credential storage (at least 8 characters).</string>
-    <string name="credentials_wrong_password">Please enter the correct password.</string>
-    <string name="credentials_reset_warning">Please enter the correct password. You have one more try to enter the correct password before the credential storage is erased.</string>
-    <string name="credentials_reset_warning_plural">Please enter the correct password. You have <xliff:g id="number" example="5">%1$d</xliff:g> more tries to enter the correct password before the credential storage is erased.</string>
+    <!-- Description of dialog to reset credential storage [CHAR LIMIT=NONE] -->
+    <string name="credentials_reset_hint">All the contents will be removed, and the password will be reset. Are you sure about that?</string>
+    <!-- Error message [CHAR LIMIT=NONE] -->
     <string name="credentials_passwords_mismatch">Passwords do not match.</string>
-    <string name="credentials_passwords_empty">You must enter and confirm a password.</string>
-    <string name="credentials_password_empty">Please enter the password.</string>
-    <string name="credentials_password_too_short">The password must have at least 8 characters.</string>
-    <!-- toast message -->
-    <string name="credentials_erased">The credential storage is erased.</string>
-    <!-- toast message -->
+    <!-- Error message [CHAR LIMIT=NONE] -->
+    <string name="credentials_wrong_password">Incorrect password.</string>
+    <!-- Error message [CHAR LIMIT=NONE] -->
+    <string name="credentials_reset_warning">Incorrect password. You have one more chance before credential storage is erased.</string>
+    <!-- Error message [CHAR LIMIT=NONE] -->
+    <string name="credentials_reset_warning_plural">Incorrect password. You have <xliff:g id="number" example="5">%1$d</xliff:g> more chances before credential storage is erased.</string>
+    <!-- Toast message [CHAR LIMIT=30] -->
+    <string name="credentials_erased">Credential storage is erased.</string>
+    <!-- Toast message [CHAR LIMIT=30] -->
     <string name="credentials_enabled">Credential storage is enabled.</string>
-    <!-- toast message -->
-    <string name="credentials_disabled">Credential storage is disabled.</string>
 
     <!-- Sound settings screen, setting check box label -->
     <string name="emergency_tone_title">Emergency tone</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index c361fa9..a49cd0a 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -114,4 +114,10 @@
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">wrap_content</item>
     </style>
+
+    <style name="Transparent">
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowIsFloating">true</item>
+    </style>
 </resources>
diff --git a/res/xml/security_settings_misc.xml b/res/xml/security_settings_misc.xml
new file mode 100644
index 0000000..e67542b
--- /dev/null
+++ b/res/xml/security_settings_misc.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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="sim_lock"
+            android:title="@string/sim_lock_settings_title"
+            android:persistent="false">
+
+        <Preference android:title="@string/sim_lock_settings_category"
+                android:persistent="false">
+            <intent android:action="android.intent.action.MAIN"
+                     android:targetPackage="com.android.settings"
+                     android:targetClass="com.android.settings.IccLockSettings"/>
+        </Preference>
+    </PreferenceCategory>
+
+    <PreferenceCategory android:title="@string/security_passwords_title"
+            android:persistent="false">
+
+        <CheckBoxPreference android:key="show_password"
+                android:title="@string/show_password"
+                android:summary="@string/show_password_summary"
+                android:persistent="false"/>
+    </PreferenceCategory>
+
+    <PreferenceCategory android:title="@string/device_admin_title"
+            android:persistent="false">
+        <Preference android:title="@string/manage_device_admin"
+                android:summary="@string/manage_device_admin_summary"
+                android:persistent="false">
+            <intent android:action="android.intent.action.MAIN"
+                    android:targetPackage="com.android.settings"
+                    android:targetClass="com.android.settings.DeviceAdminSettings"/>
+        </Preference>
+    </PreferenceCategory>
+
+    <PreferenceCategory android:title="@string/credentials_title"
+            android:persistent="false">
+        <CheckBoxPreference android:key="enable_credentials"
+                android:title="@string/credentials_access"
+                android:summary="@string/credentials_access_summary"
+                android:persistent="false"/>
+
+        <Preference android:title="@string/credentials_install"
+                android:summary="@string/credentials_install_summary"
+                android:persistent="false">
+            <intent android:action="android.credentials.INSTALL"
+                    android:targetPackage="com.android.certinstaller"
+                    android:targetClass="com.android.certinstaller.CertInstallerMain"/>
+        </Preference>
+
+        <Preference android:title="@string/credentials_set_password"
+                android:summary="@string/credentials_set_password_summary"
+                android:persistent="false">
+            <intent android:action="com.android.credentials.SET_PASSWORD"
+                    android:targetPackage="com.android.settings"
+                    android:targetClass="com.android.settings.CredentialStorage"/>
+        </Preference>
+
+        <Preference android:key="reset_credentials"
+                android:title="@string/credentials_reset"
+                android:summary="@string/credentials_reset_summary"
+                android:persistent="false">
+            <intent android:action="com.android.credentials.RESET"
+                    android:targetPackage="com.android.settings"
+                    android:targetClass="com.android.settings.CredentialStorage"/>
+        </Preference>
+    </PreferenceCategory>
+</PreferenceScreen>
diff --git a/src/com/android/settings/CredentialInstaller.java b/src/com/android/settings/CredentialInstaller.java
deleted file mode 100644
index 7c63b1c..0000000
--- a/src/com/android/settings/CredentialInstaller.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2009 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 android.os.Bundle;
-import android.security.Credentials;
-import android.security.KeyStore;
-import android.util.Log;
-
-/**
- * Installs credentials to the system keystore. It reacts to the
- * {@link Credentials#SYSTEM_INSTALL_ACTION} intent. All the key-value pairs in
- * the intent are installed to the system keystore. For security reason, the
- * current implementation limits that only com.android.certinstaller can use
- * this service.
- */
-public class CredentialInstaller extends Activity {
-    private static final String TAG = "CredentialInstaller";
-    private static final String UNLOCKING = "ulck";
-
-    private KeyStore mKeyStore = KeyStore.getInstance();
-    private boolean mUnlocking = false;
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-
-        if (!"com.android.certinstaller".equals(getCallingPackage())) finish();
-
-        if (isKeyStoreUnlocked()) {
-            install();
-        } else if (!mUnlocking) {
-            mUnlocking = true;
-            Credentials.getInstance().unlock(this);
-            return;
-        }
-        finish();
-    }
-
-    @Override
-    protected void onSaveInstanceState(Bundle outStates) {
-        super.onSaveInstanceState(outStates);
-        outStates.putBoolean(UNLOCKING, mUnlocking);
-    }
-
-    @Override
-    protected void onRestoreInstanceState(Bundle savedStates) {
-        super.onRestoreInstanceState(savedStates);
-        mUnlocking = savedStates.getBoolean(UNLOCKING);
-    }
-
-    private void install() {
-        Intent intent = getIntent();
-        Bundle bundle = (intent == null) ? null : intent.getExtras();
-        if (bundle == null) return;
-        for (String key : bundle.keySet()) {
-            byte[] data = bundle.getByteArray(key);
-            if (data == null) continue;
-            boolean success = mKeyStore.put(key.getBytes(), data);
-            Log.d(TAG, "install " + key + ": " + data.length + "  success? " + success);
-            if (!success) return;
-        }
-        setResult(RESULT_OK);
-    }
-
-    private boolean isKeyStoreUnlocked() {
-        return (mKeyStore.test() == KeyStore.NO_ERROR);
-    }
-}
diff --git a/src/com/android/settings/CredentialStorage.java b/src/com/android/settings/CredentialStorage.java
new file mode 100644
index 0000000..9d5a603
--- /dev/null
+++ b/src/com/android/settings/CredentialStorage.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2011 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.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.security.KeyStore;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.io.UnsupportedEncodingException;
+
+public class CredentialStorage extends Activity implements TextWatcher,
+        DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
+
+    public static final String ACTION_UNLOCK = "com.android.credentials.UNLOCK";
+    public static final String ACTION_SET_PASSWORD = "com.android.credentials.SET_PASSWORD";
+    public static final String ACTION_INSTALL = "com.android.credentials.INSTALL";
+    public static final String ACTION_RESET = "com.android.credentials.RESET";
+
+    private static final String TAG = "CredentialStorage";
+
+    private KeyStore mKeyStore = KeyStore.getInstance();
+    private boolean mSubmit = false;
+    private Bundle mBundle;
+
+    private TextView mOldPassword;
+    private TextView mNewPassword;
+    private TextView mConfirmPassword;
+    private TextView mError;
+    private Button mButton;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Intent intent = getIntent();
+        String action = intent.getAction();
+        int state = mKeyStore.test();
+
+        if (ACTION_RESET.equals(action)) {
+            showResetDialog();
+        } else if (ACTION_SET_PASSWORD.equals(action)) {
+            showPasswordDialog(state == KeyStore.UNINITIALIZED);
+        } else {
+            if (ACTION_INSTALL.equals(action) &&
+                    "com.android.certinstaller".equals(getCallingPackage())) {
+                mBundle = intent.getExtras();
+            }
+            if (state == KeyStore.UNINITIALIZED) {
+                showPasswordDialog(true);
+            } else if (state == KeyStore.LOCKED) {
+                showUnlockDialog();
+            } else {
+                install();
+                finish();
+            }
+        }
+    }
+
+    private void install() {
+        if (mBundle != null && !mBundle.isEmpty()) {
+            try {
+                for (String key : mBundle.keySet()) {
+                    byte[] value = mBundle.getByteArray(key);
+                    if (value != null && !mKeyStore.put(key.getBytes("UTF-8"), value)) {
+                        Log.e(TAG, "Failed to install " + key);
+                        return;
+                    }
+                }
+                setResult(RESULT_OK);
+            } catch (UnsupportedEncodingException e) {
+                // Should never happen.
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    private void showResetDialog() {
+        AlertDialog dialog = new AlertDialog.Builder(this)
+                .setTitle(android.R.string.dialog_alert_title)
+                .setIcon(android.R.drawable.ic_dialog_alert)
+                .setMessage(R.string.credentials_reset_hint)
+                .setNeutralButton(android.R.string.ok, this)
+                .setNegativeButton(android.R.string.cancel, this)
+                .create();
+        dialog.setOnDismissListener(this);
+        dialog.show();
+    }
+
+    private void showPasswordDialog(boolean firstTime) {
+        View view = View.inflate(this, R.layout.credentials_dialog, null);
+
+        ((TextView) view.findViewById(R.id.hint)).setText(R.string.credentials_password_hint);
+        if (!firstTime) {
+            view.findViewById(R.id.old_password_prompt).setVisibility(View.VISIBLE);
+            mOldPassword = (TextView) view.findViewById(R.id.old_password);
+            mOldPassword.setVisibility(View.VISIBLE);
+            mOldPassword.addTextChangedListener(this);
+        }
+        view.findViewById(R.id.new_passwords).setVisibility(View.VISIBLE);
+        mNewPassword = (TextView) view.findViewById(R.id.new_password);
+        mNewPassword.addTextChangedListener(this);
+        mConfirmPassword = (TextView) view.findViewById(R.id.confirm_password);
+        mConfirmPassword.addTextChangedListener(this);
+        mError = (TextView) view.findViewById(R.id.error);
+
+        AlertDialog dialog = new AlertDialog.Builder(this)
+                .setView(view)
+                .setTitle(R.string.credentials_set_password)
+                .setPositiveButton(android.R.string.ok, this)
+                .setNegativeButton(android.R.string.cancel, this)
+                .create();
+        dialog.setOnDismissListener(this);
+        dialog.show();
+        mButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
+        mButton.setEnabled(false);
+    }
+
+    private void showUnlockDialog() {
+        View view = View.inflate(this, R.layout.credentials_dialog, null);
+
+        ((TextView) view.findViewById(R.id.hint)).setText(R.string.credentials_unlock_hint);
+        mOldPassword = (TextView) view.findViewById(R.id.old_password);
+        mOldPassword.setVisibility(View.VISIBLE);
+        mOldPassword.addTextChangedListener(this);
+        mError = (TextView) view.findViewById(R.id.error);
+
+        AlertDialog dialog = new AlertDialog.Builder(this)
+                .setView(view)
+                .setTitle(R.string.credentials_unlock)
+                .setPositiveButton(android.R.string.ok, this)
+                .setNegativeButton(android.R.string.cancel, this)
+                .create();
+        dialog.setOnDismissListener(this);
+        dialog.show();
+        mButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
+        mButton.setEnabled(false);
+    }
+
+    public void afterTextChanged(Editable editable) {
+        if ((mOldPassword == null || mOldPassword.getText().length() > 0) &&
+            (mNewPassword == null || mNewPassword.getText().length() >= 8) &&
+            (mConfirmPassword == null || mConfirmPassword.getText().length() >= 8)) {
+            mButton.setEnabled(true);
+        } else {
+            mButton.setEnabled(false);
+        }
+    }
+
+    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+    }
+
+    public void onTextChanged(CharSequence s,int start, int before, int count) {
+    }
+
+    public void onClick(DialogInterface dialog, int button) {
+        mSubmit = (button == DialogInterface.BUTTON_POSITIVE);
+        if (button == DialogInterface.BUTTON_NEUTRAL) {
+            mKeyStore.reset();
+            Toast.makeText(this, R.string.credentials_erased, Toast.LENGTH_SHORT).show();
+        }
+    }
+
+    public void onDismiss(DialogInterface dialog) {
+        if (mSubmit) {
+            mSubmit = false;
+            mError.setVisibility(View.VISIBLE);
+
+            if (mNewPassword == null) {
+                mKeyStore.unlock(mOldPassword.getText().toString());
+            } else {
+                String newPassword = mNewPassword.getText().toString();
+                String confirmPassword = mConfirmPassword.getText().toString();
+
+                if (!newPassword.equals(confirmPassword)) {
+                    mError.setText(R.string.credentials_passwords_mismatch);
+                    ((AlertDialog) dialog).show();
+                    return;
+                } else if (mOldPassword == null) {
+                    mKeyStore.password(newPassword);
+                } else {
+                    mKeyStore.password(mOldPassword.getText().toString(), newPassword);
+                }
+            }
+
+            int error = mKeyStore.getLastError();
+            if (error == KeyStore.NO_ERROR) {
+                Toast.makeText(this, R.string.credentials_enabled, Toast.LENGTH_SHORT).show();
+                install();
+            } else if (error == KeyStore.UNINITIALIZED) {
+                Toast.makeText(this, R.string.credentials_erased,  Toast.LENGTH_SHORT).show();
+            } else if (error >= KeyStore.WRONG_PASSWORD) {
+                int count = error - KeyStore.WRONG_PASSWORD + 1;
+                if (count > 3) {
+                    mError.setText(R.string.credentials_wrong_password);
+                } else if (count == 1) {
+                    mError.setText(R.string.credentials_reset_warning);
+                } else {
+                    mError.setText(getString(R.string.credentials_reset_warning_plural, count));
+                }
+                ((AlertDialog) dialog).show();
+                return;
+            }
+        }
+        finish();
+    }
+}
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index f8ed599..649c012 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -63,39 +63,32 @@
  */
 public class SecuritySettings extends SettingsPreferenceFragment
         implements OnPreferenceChangeListener {
-    private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change";
-
     private static final String KEY_ENCRYPTION = "encryption";
 
     // Lock Settings
-    private static final String PACKAGE = "com.android.settings";
-    private static final String ICC_LOCK_SETTINGS = PACKAGE + ".IccLockSettings";
-
+    private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change";
     private static final String KEY_LOCK_ENABLED = "lockenabled";
     private static final String KEY_VISIBLE_PATTERN = "visiblepattern";
     private static final String KEY_TACTILE_FEEDBACK_ENABLED = "unlock_tactile_feedback";
     private static final String KEY_SECURITY_CATEGORY = "security_category";
-
-    private CheckBoxPreference mVisiblePattern;
-    private CheckBoxPreference mTactileFeedback;
-
-    private CheckBoxPreference mShowPassword;
+    private static final String KEY_LOCK_AFTER_TIMEOUT = "lock_after_timeout";
+    private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123;
 
     // Location Settings
-    private static final String LOCATION_CATEGORY = "location_category";
-    private static final String LOCATION_NETWORK = "location_network";
-    private static final String LOCATION_GPS = "location_gps";
-    private static final String ASSISTED_GPS = "assisted_gps";
-    private static final String USE_LOCATION = "location_use_for_services";
-    private static final String LOCK_AFTER_TIMEOUT_KEY = "lock_after_timeout";
-    private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123;
-    private static final int FALLBACK_LOCK_AFTER_TIMEOUT_VALUE = 5000; // compatible with pre-Froyo
+    private static final String KEY_LOCATION_CATEGORY = "location_category";
+    private static final String KEY_LOCATION_NETWORK = "location_network";
+    private static final String KEY_LOCATION_GPS = "location_gps";
+    private static final String KEY_ASSISTED_GPS = "assisted_gps";
+    private static final String KEY_USE_LOCATION = "location_use_for_services";
+
+    // Misc Settings
+    private static final String KEY_SIM_LOCK = "sim_lock";
+    private static final String KEY_SHOW_PASSWORD = "show_password";
+    private static final String KEY_ENABLE_CREDENTIALS = "enable_credentials";
+    private static final String KEY_RESET_CREDENTIALS = "reset_credentials";
 
     private static final String TAG = "SecuritySettings";
 
-    // Credential storage
-    private final CredentialStorage mCredentialStorage = new CredentialStorage();
-
     private CheckBoxPreference mNetwork;
     private CheckBoxPreference mGps;
     private CheckBoxPreference mAssistedGps;
@@ -112,13 +105,15 @@
     private LockPatternUtils mLockPatternUtils;
     private ListPreference mLockAfter;
 
-    private SettingsObserver mSettingsObserver;
+    private Observer mSettingsObserver;
 
-    private final class SettingsObserver implements Observer {
-        public void update(Observable o, Object arg) {
-            updateToggles();
-        }
-    }
+    private CheckBoxPreference mVisiblePattern;
+    private CheckBoxPreference mTactileFeedback;
+
+    private CheckBoxPreference mShowPassword;
+
+    private CheckBoxPreference mEnableCredentials;
+    private Preference mResetCredentials;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -129,10 +124,6 @@
         mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
 
         mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());
-
-        createPreferenceHierarchy();
-
-        updateToggles();
     }
 
     @Override
@@ -144,31 +135,33 @@
                 new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
                 null);
         mContentQueryMap = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, null);
-        mContentQueryMap.addObserver(mSettingsObserver = new SettingsObserver());
     }
 
     @Override
     public void onStop() {
         super.onStop();
-        mContentQueryMap.deleteObserver(mSettingsObserver);
+        if (mSettingsObserver != null) {
+            mContentQueryMap.deleteObserver(mSettingsObserver);
+        }
     }
 
     private PreferenceScreen createPreferenceHierarchy() {
-        PreferenceScreen root = this.getPreferenceScreen();
+        PreferenceScreen root = getPreferenceScreen();
         if (root != null) {
             root.removeAll();
         }
         addPreferencesFromResource(R.xml.security_settings);
-        root = this.getPreferenceScreen();
+        root = getPreferenceScreen();
 
-        mNetwork = (CheckBoxPreference) getPreferenceScreen().findPreference(LOCATION_NETWORK);
-        mGps = (CheckBoxPreference) getPreferenceScreen().findPreference(LOCATION_GPS);
-        mAssistedGps = (CheckBoxPreference) getPreferenceScreen().findPreference(ASSISTED_GPS);
+        mNetwork = (CheckBoxPreference) root.findPreference(KEY_LOCATION_NETWORK);
+        mGps = (CheckBoxPreference) root.findPreference(KEY_LOCATION_GPS);
+        mAssistedGps = (CheckBoxPreference) root.findPreference(KEY_ASSISTED_GPS);
         if (GoogleLocationSettingHelper.isAvailable(getActivity())) {
             // GSF present, Add setting for 'Use My Location'
-            PreferenceGroup locationCat = (PreferenceGroup) root.findPreference(LOCATION_CATEGORY);
+            PreferenceGroup locationCat =
+                    (PreferenceGroup) root.findPreference(KEY_LOCATION_CATEGORY);
             CheckBoxPreference useLocation = new CheckBoxPreference(getActivity());
-            useLocation.setKey(USE_LOCATION);
+            useLocation.setKey(KEY_USE_LOCATION);
             useLocation.setTitle(R.string.use_location_title);
             useLocation.setSummaryOn(R.string.use_location_summary_enabled);
             useLocation.setSummaryOff(R.string.use_location_summary_disabled);
@@ -181,8 +174,6 @@
             mUseLocation = useLocation;
         }
 
-        PreferenceManager pm = getPreferenceManager();
-        
         // Add options for device encryption
         // TODO: It still needs to be determined how a device specifies that it supports
         // encryption. That mechanism needs to be checked before adding the following code
@@ -215,98 +206,62 @@
         addPreferencesFromResource(resid);
 
         // lock after preference
-        mLockAfter = setupLockAfterPreference(pm);
-        updateLockAfterPreferenceSummary();
+        mLockAfter = (ListPreference) root.findPreference(KEY_LOCK_AFTER_TIMEOUT);
+        if (mLockAfter != null) {
+            setupLockAfterPreference();
+            updateLockAfterPreferenceSummary();
+        }
 
         // visible pattern
-        mVisiblePattern = (CheckBoxPreference) pm.findPreference(KEY_VISIBLE_PATTERN);
+        mVisiblePattern = (CheckBoxPreference) root.findPreference(KEY_VISIBLE_PATTERN);
 
         // tactile feedback. Should be common to all unlock preference screens.
-        mTactileFeedback = (CheckBoxPreference) pm.findPreference(KEY_TACTILE_FEEDBACK_ENABLED);
+        mTactileFeedback = (CheckBoxPreference) root.findPreference(KEY_TACTILE_FEEDBACK_ENABLED);
         if (!((Vibrator) getSystemService(Context.VIBRATOR_SERVICE)).hasVibrator()) {
             PreferenceGroup securityCategory = (PreferenceGroup)
-                    pm.findPreference(KEY_SECURITY_CATEGORY);
+                    root.findPreference(KEY_SECURITY_CATEGORY);
             if (securityCategory != null && mTactileFeedback != null) {
                 securityCategory.removePreference(mTactileFeedback);
             }
         }
 
-        int activePhoneType = TelephonyManager.getDefault().getPhoneType();
+        // Append the rest of the settings
+        addPreferencesFromResource(R.xml.security_settings_misc);
 
-        // do not display SIM lock for CDMA phone
-        if (TelephonyManager.PHONE_TYPE_CDMA != activePhoneType)
-        {
-            PreferenceScreen simLockPreferences = getPreferenceManager()
-                    .createPreferenceScreen(getActivity());
-            simLockPreferences.setTitle(R.string.sim_lock_settings_category);
-            // Intent to launch SIM lock settings
-            simLockPreferences.setIntent(new Intent().setClassName(PACKAGE, ICC_LOCK_SETTINGS));
-            PreferenceCategory simLockCat = new PreferenceCategory(getActivity());
-            simLockCat.setTitle(R.string.sim_lock_settings_title);
-            root.addPreference(simLockCat);
-            simLockCat.addPreference(simLockPreferences);
+        // Do not display SIM lock for CDMA phone
+        if (TelephonyManager.PHONE_TYPE_CDMA == TelephonyManager.getDefault().getPhoneType()) {
+            root.removePreference(root.findPreference(KEY_SIM_LOCK));
         }
 
-        // Passwords
-        PreferenceCategory passwordsCat = new PreferenceCategory(getActivity());
-        passwordsCat.setTitle(R.string.security_passwords_title);
-        root.addPreference(passwordsCat);
-
-        CheckBoxPreference showPassword = mShowPassword = new CheckBoxPreference(getActivity());
-        showPassword.setKey("show_password");
-        showPassword.setTitle(R.string.show_password);
-        showPassword.setSummary(R.string.show_password_summary);
-        showPassword.setPersistent(false);
-        passwordsCat.addPreference(showPassword);
-
-        // Device policies
-        PreferenceCategory devicePoliciesCat = new PreferenceCategory(getActivity());
-        devicePoliciesCat.setTitle(R.string.device_admin_title);
-        root.addPreference(devicePoliciesCat);
-
-        Preference deviceAdminButton = new Preference(getActivity());
-        deviceAdminButton.setTitle(R.string.manage_device_admin);
-        deviceAdminButton.setSummary(R.string.manage_device_admin_summary);
-        Intent deviceAdminIntent = new Intent();
-        deviceAdminIntent.setClass(getActivity(), DeviceAdminSettings.class);
-        deviceAdminButton.setIntent(deviceAdminIntent);
-        devicePoliciesCat.addPreference(deviceAdminButton);
+        // Show password
+        mShowPassword = (CheckBoxPreference) root.findPreference(KEY_SHOW_PASSWORD);
 
         // Credential storage
-        PreferenceCategory credentialsCat = new PreferenceCategory(getActivity());
-        credentialsCat.setTitle(R.string.credentials_category);
-        root.addPreference(credentialsCat);
-        mCredentialStorage.createPreferences(credentialsCat);
+        mEnableCredentials = (CheckBoxPreference) root.findPreference(KEY_ENABLE_CREDENTIALS);
+        mEnableCredentials.setOnPreferenceChangeListener(this);
+        mResetCredentials = root.findPreference(KEY_RESET_CREDENTIALS);
 
         return root;
     }
 
-    private ListPreference setupLockAfterPreference(PreferenceManager pm) {
-        ListPreference result = (ListPreference) pm.findPreference(LOCK_AFTER_TIMEOUT_KEY);
-        if (result != null) {
-            int lockAfterValue = Settings.Secure.getInt(getContentResolver(),
-                    Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
-                    FALLBACK_LOCK_AFTER_TIMEOUT_VALUE);
-            result.setValue(String.valueOf(lockAfterValue));
-            result.setOnPreferenceChangeListener(this);
-            final long adminTimeout = mDPM != null ? mDPM.getMaximumTimeToLock(null) : 0;
-            final ContentResolver cr = getContentResolver();
-            final long displayTimeout = Math.max(0,
-                    Settings.System.getInt(cr, SCREEN_OFF_TIMEOUT, 0));
-            if (adminTimeout > 0) {
-                // This setting is a slave to display timeout when a device policy is enforced.
-                // As such, maxLockTimeout = adminTimeout - displayTimeout.
-                // If there isn't enough time, shows "immediately" setting.
-                disableUnusableTimeouts(result, Math.max(0, adminTimeout - displayTimeout));
-            }
+    private void setupLockAfterPreference() {
+        // Compatible with pre-Froyo
+        long currentTimeout = Settings.Secure.getLong(getContentResolver(),
+                Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
+        mLockAfter.setValue(String.valueOf(currentTimeout));
+        mLockAfter.setOnPreferenceChangeListener(this);
+        final long adminTimeout = (mDPM != null ? mDPM.getMaximumTimeToLock(null) : 0);
+        final long displayTimeout = Math.max(0,
+                Settings.System.getInt(getContentResolver(), SCREEN_OFF_TIMEOUT, 0));
+        if (adminTimeout > 0) {
+            // This setting is a slave to display timeout when a device policy is enforced.
+            // As such, maxLockTimeout = adminTimeout - displayTimeout.
+            // If there isn't enough time, shows "immediately" setting.
+            disableUnusableTimeouts(Math.max(0, adminTimeout - displayTimeout));
         }
-        return result;
     }
 
     private void updateLockAfterPreferenceSummary() {
-        // Not all security types have a "lock after" preference, so ignore those that don't.
-        if (mLockAfter == null) return;
-
         // Update summary message with current value
         long currentTimeout = Settings.Secure.getLong(getContentResolver(),
                 Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 0);
@@ -319,14 +274,12 @@
                 best = i;
             }
         }
-        String summary = mLockAfter.getContext()
-                .getString(R.string.lock_after_timeout_summary, entries[best]);
-        mLockAfter.setSummary(summary);
+        mLockAfter.setSummary(getString(R.string.lock_after_timeout_summary, entries[best]));
     }
 
-    private static void disableUnusableTimeouts(ListPreference pref, long maxTimeout) {
-        final CharSequence[] entries = pref.getEntries();
-        final CharSequence[] values = pref.getEntryValues();
+    private void disableUnusableTimeouts(long maxTimeout) {
+        final CharSequence[] entries = mLockAfter.getEntries();
+        final CharSequence[] values = mLockAfter.getEntryValues();
         ArrayList<CharSequence> revisedEntries = new ArrayList<CharSequence>();
         ArrayList<CharSequence> revisedValues = new ArrayList<CharSequence>();
         for (int i = 0; i < values.length; i++) {
@@ -337,20 +290,20 @@
             }
         }
         if (revisedEntries.size() != entries.length || revisedValues.size() != values.length) {
-            pref.setEntries(
+            mLockAfter.setEntries(
                     revisedEntries.toArray(new CharSequence[revisedEntries.size()]));
-            pref.setEntryValues(
+            mLockAfter.setEntryValues(
                     revisedValues.toArray(new CharSequence[revisedValues.size()]));
-            final int userPreference = Integer.valueOf(pref.getValue());
+            final int userPreference = Integer.valueOf(mLockAfter.getValue());
             if (userPreference <= maxTimeout) {
-                pref.setValue(String.valueOf(userPreference));
+                mLockAfter.setValue(String.valueOf(userPreference));
             } else {
                 // There will be no highlighted selection since nothing in the list matches
                 // maxTimeout. The user can still select anything less than maxTimeout.
                 // TODO: maybe append maxTimeout to the list and mark selected.
             }
         }
-        pref.setEnabled(revisedEntries.size() > 0);
+        mLockAfter.setEnabled(revisedEntries.size() > 0);
     }
 
     @Override
@@ -360,6 +313,16 @@
         // Make sure we reload the preference hierarchy since some of these settings
         // depend on others...
         createPreferenceHierarchy();
+        updateLocationToggles();
+
+        if (mSettingsObserver == null) {
+            mSettingsObserver = new Observer() {
+                public void update(Observable o, Object arg) {
+                    updateLocationToggles();
+                }
+            };
+            mContentQueryMap.addObserver(mSettingsObserver);
+        }
 
         final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
         if (mVisiblePattern != null) {
@@ -372,7 +335,10 @@
         mShowPassword.setChecked(Settings.System.getInt(getContentResolver(),
                 Settings.System.TEXT_SHOW_PASSWORD, 1) != 0);
 
-        mCredentialStorage.resume();
+        int state = KeyStore.getInstance().test();
+        mEnableCredentials.setChecked(state == KeyStore.NO_ERROR);
+        mEnableCredentials.setEnabled(state != KeyStore.UNINITIALIZED);
+        mResetCredentials.setEnabled(state != KeyStore.UNINITIALIZED);
     }
 
     @Override
@@ -419,7 +385,7 @@
     /*
      * Creates toggles for each available location provider
      */
-    private void updateToggles() {
+    private void updateLocationToggles() {
         ContentResolver res = getContentResolver();
         boolean gpsEnabled = Settings.Secure.isLocationProviderEnabled(
                 res, LocationManager.GPS_PROVIDER);
@@ -453,7 +419,8 @@
 
         public void showPasswordDialog() {
             View view = View.inflate(SecuritySettings.this.getActivity(),
-                    R.layout.credentials_password_dialog, null);
+                    R.layout.credentials_dialog, null);
+            view.findViewById(R.id.new_passwords).setVisibility(View.VISIBLE);
 
             Dialog dialog = new AlertDialog.Builder(SecuritySettings.this.getActivity())
                     .setView(view).setTitle(R.string.credentials_set_password)
@@ -521,7 +488,7 @@
                 if (formatArgs == null || formatArgs.length == 0) {
                     view.setText(stringId);
                 } else {
-                    view.setText(dialog.getContext().getString(stringId, formatArgs));
+                    view.setText(getString(stringId, formatArgs));
                 }
                 view.setVisibility(View.VISIBLE);
             }
@@ -529,299 +496,31 @@
 
     }
 
-    private class CredentialStorage implements DialogInterface.OnClickListener,
-            DialogInterface.OnDismissListener, Preference.OnPreferenceChangeListener,
-            Preference.OnPreferenceClickListener {
-        private static final int MINIMUM_PASSWORD_LENGTH = 8;
-
-        private final KeyStore mKeyStore = KeyStore.getInstance();
-        private int mState;
-        private boolean mSubmit = false;
-        private boolean mExternal = false;
-
-        private CheckBoxPreference mAccessCheckBox;
-        private Preference mInstallButton;
-        private Preference mPasswordButton;
-        private Preference mResetButton;
-
-        void resume() {
-            mState = mKeyStore.test();
-            updatePreferences(mState);
-
-            Intent intent = getActivity().getIntent();
-            if (!mExternal && intent != null &&
-                    Credentials.UNLOCK_ACTION.equals(intent.getAction())) {
-                mExternal = true;
-                if (mState == KeyStore.UNINITIALIZED) {
-                    showPasswordDialog();
-                } else if (mState == KeyStore.LOCKED) {
-                    showUnlockDialog();
-                } else {
-                    // TODO: Verify if this is the right way
-                    SecuritySettings.this.getFragmentManager().popBackStack();
-                }
-            }
-        }
-
-        private void initialize(String password) {
-            mKeyStore.password(password);
-            updatePreferences(KeyStore.NO_ERROR);
-        }
-
-        private void reset() {
-            mKeyStore.reset();
-            updatePreferences(KeyStore.UNINITIALIZED);
-        }
-
-        private void lock() {
-            mKeyStore.lock();
-            updatePreferences(KeyStore.LOCKED);
-        }
-
-        private int unlock(String password) {
-            mKeyStore.unlock(password);
-            return mKeyStore.getLastError();
-        }
-
-        private int changePassword(String oldPassword, String newPassword) {
-            mKeyStore.password(oldPassword, newPassword);
-            return mKeyStore.getLastError();
-        }
-
-        public boolean onPreferenceChange(Preference preference, Object value) {
-            if (preference == mAccessCheckBox) {
-                if ((Boolean) value) {
-                    showUnlockDialog();
-                } else {
-                    lock();
-                }
-                return true;
-            }
-            return false;
-        }
-
-        public boolean onPreferenceClick(Preference preference) {
-            if (preference == mInstallButton) {
-                Credentials.getInstance().installFromSdCard(SecuritySettings.this.getActivity());
-            } else if (preference == mPasswordButton) {
-                showPasswordDialog();
-            } else if (preference == mResetButton) {
-                showResetDialog();
-            } else {
-                return false;
-            }
-            return true;
-        }
-
-        public void onClick(DialogInterface dialog, int button) {
-            mSubmit = (button == DialogInterface.BUTTON_POSITIVE);
-            if (button == DialogInterface.BUTTON_NEUTRAL) {
-                reset();
-            }
-        }
-
-        public void onDismiss(DialogInterface dialog) {
-            // TODO:
-            //if (mSubmit && !isFinishing()) {
-
-            if (mSubmit) {
-                mSubmit = false;
-                if (!checkPassword((Dialog) dialog)) {
-                    ((Dialog) dialog).show();
-                    return;
-                }
-            }
-            updatePreferences(mState);
-            if (mExternal) {
-                // TODO:
-                // finish();
-            }
-        }
-
-        // Return true if there is no error.
-        private boolean checkPassword(Dialog dialog) {
-            String oldPassword = getText(dialog, R.id.old_password);
-            String newPassword = getText(dialog, R.id.new_password);
-            String confirmPassword = getText(dialog, R.id.confirm_password);
-
-            if (oldPassword != null && oldPassword.length() == 0) {
-                showError(dialog, R.string.credentials_password_empty);
-                return false;
-            } else if (newPassword == null) {
-                return !checkError(dialog, unlock(oldPassword));
-            } else if (newPassword.length() == 0 || confirmPassword.length() == 0) {
-                showError(dialog, R.string.credentials_passwords_empty);
-            } else if (newPassword.length() < MINIMUM_PASSWORD_LENGTH) {
-                showError(dialog, R.string.credentials_password_too_short);
-            } else if (!newPassword.equals(confirmPassword)) {
-                showError(dialog, R.string.credentials_passwords_mismatch);
-            } else if (oldPassword == null) {
-                initialize(newPassword);
-                return true;
-            } else {
-                return !checkError(dialog, changePassword(oldPassword, newPassword));
-            }
-            return false;
-        }
-
-        // Return false if there is no error.
-        private boolean checkError(Dialog dialog, int error) {
-            if (error == KeyStore.NO_ERROR) {
-                updatePreferences(KeyStore.NO_ERROR);
-                return false;
-            }
-            if (error == KeyStore.UNINITIALIZED) {
-                updatePreferences(KeyStore.UNINITIALIZED);
-                return false;
-            }
-            if (error < KeyStore.WRONG_PASSWORD) {
-                return false;
-            }
-            int count = error - KeyStore.WRONG_PASSWORD + 1;
-            if (count > 3) {
-                showError(dialog, R.string.credentials_wrong_password);
-            } else if (count == 1) {
-                showError(dialog, R.string.credentials_reset_warning);
-            } else {
-                showError(dialog, R.string.credentials_reset_warning_plural, count);
-            }
-            return true;
-        }
-
-        private String getText(Dialog dialog, int viewId) {
-            TextView view = (TextView) dialog.findViewById(viewId);
-            return (view == null || view.getVisibility() == View.GONE) ? null :
-                            view.getText().toString();
-        }
-
-        private void showError(Dialog dialog, int stringId, Object... formatArgs) {
-            TextView view = (TextView) dialog.findViewById(R.id.error);
-            if (view != null) {
-                if (formatArgs == null || formatArgs.length == 0) {
-                    view.setText(stringId);
-                } else {
-                    view.setText(dialog.getContext().getString(stringId, formatArgs));
-                }
-                view.setVisibility(View.VISIBLE);
-            }
-        }
-
-        private void createPreferences(PreferenceCategory category) {
-            mAccessCheckBox = new CheckBoxPreference(SecuritySettings.this.getActivity());
-            mAccessCheckBox.setTitle(R.string.credentials_access);
-            mAccessCheckBox.setSummary(R.string.credentials_access_summary);
-            mAccessCheckBox.setOnPreferenceChangeListener(this);
-            category.addPreference(mAccessCheckBox);
-
-            mInstallButton = new Preference(SecuritySettings.this.getActivity());
-            mInstallButton.setTitle(R.string.credentials_install_certificates);
-            mInstallButton.setSummary(R.string.credentials_install_certificates_summary);
-            mInstallButton.setOnPreferenceClickListener(this);
-            category.addPreference(mInstallButton);
-
-            mPasswordButton = new Preference(SecuritySettings.this.getActivity());
-            mPasswordButton.setTitle(R.string.credentials_set_password);
-            mPasswordButton.setSummary(R.string.credentials_set_password_summary);
-            mPasswordButton.setOnPreferenceClickListener(this);
-            category.addPreference(mPasswordButton);
-
-            mResetButton = new Preference(SecuritySettings.this.getActivity());
-            mResetButton.setTitle(R.string.credentials_reset);
-            mResetButton.setSummary(R.string.credentials_reset_summary);
-            mResetButton.setOnPreferenceClickListener(this);
-            category.addPreference(mResetButton);
-        }
-
-        private void updatePreferences(int state) {
-            mAccessCheckBox.setEnabled(state != KeyStore.UNINITIALIZED);
-            mAccessCheckBox.setChecked(state == KeyStore.NO_ERROR);
-            mResetButton.setEnabled(state != KeyStore.UNINITIALIZED);
-
-            // Show a toast message if the state is changed.
-            if (mState == state) {
-                return;
-            } else if (state == KeyStore.NO_ERROR) {
-                Toast.makeText(SecuritySettings.this.getActivity(), R.string.credentials_enabled,
-                        Toast.LENGTH_SHORT).show();
-            } else if (state == KeyStore.UNINITIALIZED) {
-                Toast.makeText(SecuritySettings.this.getActivity(), R.string.credentials_erased,
-                        Toast.LENGTH_SHORT).show();
-            } else if (state == KeyStore.LOCKED) {
-                Toast.makeText(SecuritySettings.this.getActivity(), R.string.credentials_disabled,
-                        Toast.LENGTH_SHORT).show();
-            }
-            mState = state;
-        }
-
-        private void showUnlockDialog() {
-            View view = View.inflate(SecuritySettings.this.getActivity(),
-                    R.layout.credentials_unlock_dialog, null);
-
-            // Show extra hint only when the action comes from outside.
-            if (mExternal) {
-                view.findViewById(R.id.hint).setVisibility(View.VISIBLE);
-            }
-
-            Dialog dialog = new AlertDialog.Builder(SecuritySettings.this.getActivity())
-                    .setView(view)
-                    .setTitle(R.string.credentials_unlock)
-                    .setPositiveButton(android.R.string.ok, this)
-                    .setNegativeButton(android.R.string.cancel, this)
-                    .create();
-            dialog.setOnDismissListener(this);
-            dialog.show();
-        }
-
-        private void showPasswordDialog() {
-            View view = View.inflate(SecuritySettings.this.getActivity(),
-                    R.layout.credentials_password_dialog, null);
-
-            if (mState == KeyStore.UNINITIALIZED) {
-                view.findViewById(R.id.hint).setVisibility(View.VISIBLE);
-            } else {
-                view.findViewById(R.id.old_password_prompt).setVisibility(View.VISIBLE);
-                view.findViewById(R.id.old_password).setVisibility(View.VISIBLE);
-            }
-
-            Dialog dialog = new AlertDialog.Builder(SecuritySettings.this.getActivity())
-                    .setView(view)
-                    .setTitle(R.string.credentials_set_password)
-                    .setPositiveButton(android.R.string.ok, this)
-                    .setNegativeButton(android.R.string.cancel, this)
-                    .create();
-            dialog.setOnDismissListener(this);
-            dialog.show();
-        }
-
-        private void showResetDialog() {
-            new AlertDialog.Builder(SecuritySettings.this.getActivity())
-                    .setTitle(android.R.string.dialog_alert_title)
-                    .setIcon(android.R.drawable.ic_dialog_alert)
-                    .setMessage(R.string.credentials_reset_hint)
-                    .setNeutralButton(getResources().getString(android.R.string.ok), this)
-                    .setNegativeButton(getResources().getString(android.R.string.cancel), this)
-                    .create().show();
-        }
-    }
-
     public boolean onPreferenceChange(Preference preference, Object value) {
         if (preference == mLockAfter) {
-            int lockAfter = Integer.parseInt((String) value);
+            int timeout = Integer.parseInt((String) value);
             try {
                 Settings.Secure.putInt(getContentResolver(),
-                        Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, lockAfter);
+                        Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, timeout);
             } catch (NumberFormatException e) {
                 Log.e("SecuritySettings", "could not persist lockAfter timeout setting", e);
             }
             updateLockAfterPreferenceSummary();
         } else if (preference == mUseLocation) {
-            boolean newValue = value == null ? false : (Boolean) value;
+            boolean newValue = (value == null ? false : (Boolean) value);
             GoogleLocationSettingHelper.setUseLocationForServices(getActivity(), newValue);
             // We don't want to change the value immediately here, since the user may click
             // disagree in the dialog that pops up. When the activity we just launched exits, this
             // activity will be restated and the new value re-read, so the checkbox will get its
             // new value then.
             return false;
+        } else if (preference == mEnableCredentials) {
+            if (value != null && (Boolean) value) {
+                getActivity().startActivity(new Intent(CredentialStorage.ACTION_UNLOCK));
+                return false;
+            } else {
+                KeyStore.getInstance().lock();
+            }
         }
         return true;
     }