merge from donut
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c891979..5d89800 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1737,7 +1737,7 @@
     <!-- Description for wifi connectivity -->
     <string name="battery_desc_wifi">Battery used by Wi-Fi</string>
     <!-- Suggestion for wifi connectivity power drain -->
-    <string name="battery_sugg_wifi">Turn off WiFi when not using it or where it is not available</string>
+    <string name="battery_sugg_wifi">Turn off Wi-Fi when not using it or where it is not available</string>
 
     <!-- Description for bluetooth power consumption detail -->
     <string name="battery_desc_bluetooth">Battery used by bluetooth</string>
@@ -1829,7 +1829,7 @@
     <string name="vpn_yes_button">Yes</string>
     <string name="vpn_no_button">No</string>
     <string name="vpn_back_button">Back</string>
-    <string name="vpn_mistake_button">No, it's a mistake</string>
+    <string name="vpn_mistake_button">No</string>
 
     <string name="vpn_menu_done">Save</string>
     <string name="vpn_menu_cancel">Cancel</string>
@@ -1848,7 +1848,10 @@
     <string name="vpn_confirm_edit_profile_cancellation">Are you sure you want to discard the changes made to this profile?</string>
     <string name="vpn_confirm_reconnect">Unable to connect to the network. Do you want to try again?</string>
     <string name="vpn_unknown_server_dialog_msg">Server name cannot be resolved. Do you want to check your server name setting?</string>
+    <string name="vpn_challenge_error_dialog_msg">Challenge error. Do you want to check your secret setting?</string>
+    <string name="vpn_secret_not_set_dialog_msg">One or more secrets are missing in this VPN configuration. Do you want to check your secret setting?</string>
     <string name="vpn_auth_error_dialog_msg">The username or password you entered is incorrect. Do you want to try again?</string>
+    <string name="vpn_remote_hung_up_error_dialog_msg">Server hung up. The username or password you entered could be incorrect. Do you want to try again?</string>
 
     <!-- VPN type selection activity title -->
     <string name="vpn_type_title">Add VPN</string>
@@ -1894,6 +1897,8 @@
     <!-- Complete term -->
     <string name="vpn_l2tp_secret">L2TP secret</string>
     <string name="vpn_a_l2tp_secret">an L2TP secret</string>
+    <string name="vpn_pptp_encryption_title">encryption</string>
+    <string name="vpn_pptp_encryption">PPTP encryption</string>
 
     <!-- Preference title -->
     <string name="vpn_ipsec_presharedkey_title">Set IPSec pre-shared key</string>
@@ -1935,6 +1940,10 @@
     <string name="vpn_settings_title">VPN settings</string>
     <!-- Summary of preference to enter the VPN settings activity -->
     <string name="vpn_settings_summary">Set up &amp; manage Virtual Private Networks (VPNs)</string>
+    <!-- A secret edit field's grayed out value when it has not been modified -->
+    <string name="vpn_secret_unchanged">(unchanged)</string>
+    <!-- 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="cstor_settings_category">Credential storage</string>
@@ -1991,6 +2000,9 @@
     <string name="cstor_name_empty_error">Please enter a name.</string>
     <string name="cstor_name_char_error">Please enter a name that contains only letters and numbers.</string>
     <string name="cstor_storage_error">Unable to save the certificate. Click OK to retry.</string>
+    <string name="cstor_unable_to_save_cert">Unable to save the certificate. The credential storage is not enabled or properly initialized.</string>
+    <string name="cstor_cert_not_saved">The certificate is not saved.</string>
+    <string name="cstor_is_reset">The credential storage is erased.</string>
 
     <!-- toast message -->
     <string name="cstor_is_enabled">Credential storage is enabled.</string>
diff --git a/res/xml/device_info_settings.xml b/res/xml/device_info_settings.xml
index 80370e2..56810b4 100644
--- a/res/xml/device_info_settings.xml
+++ b/res/xml/device_info_settings.xml
@@ -76,12 +76,13 @@
         </PreferenceScreen>
         
         <!-- Contributors -->
+        <!-- 
         <PreferenceScreen
                 android:key="contributors"
                 android:title="@string/contributors_title">
             <intent android:action="android.settings.TEAM" />
         </PreferenceScreen>
-        
+        -->
         <!-- System Tutorial - launches activity -->
         <PreferenceScreen android:key="system_tutorial"
                 android:title="@string/system_tutorial_list_item_title" 
diff --git a/src/com/android/settings/ManageApplications.java b/src/com/android/settings/ManageApplications.java
index 642a48e..0d4895e 100644
--- a/src/com/android/settings/ManageApplications.java
+++ b/src/com/android/settings/ManageApplications.java
@@ -355,7 +355,7 @@
                     Log.w(TAG, "Couldnt find application info for:"+pkgName);
                     break;
                 }
-                mObserver.invokeGetSizeInfo(info);
+                mObserver.invokeGetSizeInfo(pkgName);
                 break;
             case ADD_PKG_DONE:
                 if(localLOGV) Log.i(TAG, "Message ADD_PKG_DONE");
@@ -367,7 +367,12 @@
                 if (status) {
                     size = data.getLong(ATTR_PKG_STATS);
                     formattedSize = data.getString(ATTR_PKG_SIZE_STR);
-                    mAppInfoAdapter.addToList(pkgName, size, formattedSize);
+                    int idx = mAppInfoAdapter.getIndex(pkgName);
+                    if (idx == -1) {
+                        mAppInfoAdapter.addToList(pkgName, size, formattedSize);
+                    } else {
+                        mAppInfoAdapter.updatePackage(pkgName, size, formattedSize);
+                    }
                 }
                 break;
             case REFRESH_LABELS:
@@ -1121,7 +1126,7 @@
             }
             return mSizeComparator;
         }
-        
+
         public void bulkUpdateIcons(Map<String, Drawable> icons) {
             if (icons == null) {
                 return;
@@ -1162,19 +1167,6 @@
             }
         }
 
-        public boolean updateAppLabel(String pkgName, CharSequence label) {
-            if ((pkgName == null) || (label == null)) {
-                return false;
-            }
-            AppInfo aInfo = mCache.getEntry(pkgName);
-            if (aInfo != null) {
-                aInfo.refreshLabel(label);
-                notifyDataSetChanged();
-                return true;
-            }
-            return false;
-        }
-
         private boolean shouldBeInList(int filterOption, ApplicationInfo info) {
             // Match filter here
             if (filterOption == FILTER_APPS_RUNNING) {
@@ -1246,6 +1238,24 @@
             }
         }
 
+        public void updatePackage(String pkgName,
+                long size, String formattedSize) {
+            ApplicationInfo info = null;
+            try {
+                info = mPm.getApplicationInfo(pkgName,
+                        PackageManager.GET_UNINSTALLED_PACKAGES);
+            } catch (NameNotFoundException e) {
+                return;
+            }
+            AppInfo aInfo = mCache.getEntry(pkgName);
+            if (aInfo != null) {
+                aInfo.refreshLabel(info.loadLabel(mPm));
+                aInfo.refreshIcon(info.loadIcon(mPm));
+                aInfo.setSize(size, formattedSize);
+                notifyDataSetChanged();
+            }
+        }
+
         private void removePkgBase(String pkgName) {
             int imax = mAppList.size();
             for (int i = 0; i < imax; i++) {
@@ -1300,7 +1310,7 @@
             for (int i = 0; i < pkgs.length; i++) {
                 AppInfo entry = mCache.getEntry(pkgs[i]);
                 if (entry == null) {
-                    Log.w(TAG, "Entry for package:"+ pkgs[i] +"doesn't exist in map");
+                    if (localLOGV) Log.w(TAG, "Entry for package:"+ pkgs[i] +"doesn't exist in map");
                     continue;
                 }
                 if (entry.setSize(sizes[i], formatted[i])) {
@@ -1311,21 +1321,6 @@
                 notifyDataSetChanged();
             }
         }
-        
-        public void updateAppSize(String pkgName, long size, String formattedSize) {
-            if(pkgName == null) {
-                return;
-            }
-            AppInfo entry = mCache.getEntry(pkgName);
-            if (entry == null) {
-                Log.w(TAG, "Entry for package:"+pkgName+"doesnt exist in map");
-                return;
-            }
-            // Copy the index into the newly updated entry
-            if (entry.setSize(size, formattedSize)) {
-                notifyDataSetChanged();
-            }
-        }
     }
     
     /*
@@ -1371,7 +1366,7 @@
      * and the AppInfo object corresponding to the package name are set on the message
      */
     class PkgSizeObserver extends IPackageStatsObserver.Stub {
-        private ApplicationInfo mAppInfo;
+        String pkgName;
         public void onGetStatsCompleted(PackageStats pStats, boolean pSucceeded) {
             if(DEBUG_PKG_DELAY) {
                 try {
@@ -1379,12 +1374,11 @@
                 } catch (InterruptedException e) {
                 }
             }
-            AppInfo appInfo = null;
             Bundle data = new Bundle();
-            data.putString(ATTR_PKG_NAME, mAppInfo.packageName);
+            data.putString(ATTR_PKG_NAME, pkgName);
             data.putBoolean(ATTR_GET_SIZE_STATUS, pSucceeded);
             if(pSucceeded && pStats != null) {
-                if (localLOGV) Log.i(TAG, "onGetStatsCompleted::"+pStats.packageName+", ("+
+                if (localLOGV) Log.i(TAG, "onGetStatsCompleted::"+pkgName+", ("+
                         pStats.cacheSize+","+
                         pStats.codeSize+", "+pStats.dataSize);
                 long total = getTotalSize(pStats);
@@ -1400,14 +1394,14 @@
             mHandler.sendMessage(msg);
         }
 
-        public void invokeGetSizeInfo(ApplicationInfo pAppInfo) {
-            if(pAppInfo == null || pAppInfo.packageName == null) {
+        public void invokeGetSizeInfo(String packageName) {
+            if (packageName == null) {
                 return;
             }
+            pkgName = packageName;
             if(localLOGV) Log.i(TAG, "Invoking getPackageSizeInfo for package:"+
-                    pAppInfo.packageName);
-            mAppInfo = pAppInfo;
-            mPm.getPackageSizeInfo(pAppInfo.packageName, this);
+                    packageName);
+            mPm.getPackageSizeInfo(packageName, this);
         }
     }
     
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index 63d88d3..5a5804e 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -42,6 +42,7 @@
 import android.text.Html;
 import android.text.TextUtils;
 import android.text.method.LinkMovementMethod;
+import android.util.Log;
 import android.view.View;
 import android.widget.TextView;
 import android.widget.Toast;
@@ -464,15 +465,26 @@
 
             if (ACTION_ADD_CREDENTIAL.equals(action)) {
                 mCstorAddCredentialHelper = new CstorAddCredentialHelper(intent);
-                showDialog(CSTOR_NAME_CREDENTIAL_DIALOG);
+                showCstorDialog(CSTOR_NAME_CREDENTIAL_DIALOG);
             } else if (ACTION_UNLOCK_CREDENTIAL_STORAGE.equals(action)) {
                 mSpecialIntent = intent;
-                showDialog(mCstorHelper.isCstorInitialized()
+                showCstorDialog(mCstorHelper.isCstorInitialized()
                         ? CSTOR_UNLOCK_DIALOG
                         : CSTOR_INIT_DIALOG);
             }
         }
 
+        private void showCstorDialog(int dialogId) {
+            mDialogId = dialogId;
+            showDialog(dialogId);
+
+            if (dialogId == CSTOR_NAME_CREDENTIAL_DIALOG) {
+                // set mView back as mView may be replaced by CSTOR_INIT_DIALOG
+                // or CSTOR_UNLOCK_DIALOG
+                mView = mCstorAddCredentialHelper.mView;
+            }
+        }
+
         private boolean isCstorUnlocked() {
             return (mKeystore.getState() == Keystore.UNLOCKED);
         }
@@ -514,15 +526,53 @@
             mKeystore.reset();
             enablePreferences(false);
             mAccessCheckBox.setChecked(false);
+            Toast.makeText(SecuritySettings.this, R.string.cstor_is_reset,
+                    Toast.LENGTH_LONG).show();
+        }
+
+        private boolean addCredential() {
+            if (mCstorAddCredentialHelper.saveToStorage() != 0) {
+                // set mView back as mView may be replaced by CSTOR_INIT_DIALOG
+                // or CSTOR_UNLOCK_DIALOG
+                mView = mCstorAddCredentialHelper.mView;
+                if (mCstorAddCredentialHelper.isPkcs12Keystore()) {
+                    showError(R.string.cstor_password_error);
+                } else {
+                    showError(R.string.cstor_storage_error);
+                }
+                Log.d("CSTOR", "failed to add credential");
+                return false;
+            }
+            Log.d("CSTOR", "credential is added: "
+                    + mCstorAddCredentialHelper.getName());
+            String formatString =
+                    getString(R.string.cstor_is_added);
+            String message = String.format(formatString,
+                    mCstorAddCredentialHelper.getName());
+            Toast.makeText(SecuritySettings.this, message,
+                    Toast.LENGTH_LONG).show();
+            return true;
         }
 
         public void onCancel(DialogInterface dialog) {
-            if (mCstorAddCredentialHelper != null) {
-                // release the object here so that it doesn't get triggerred in
-                // onDismiss()
-                mCstorAddCredentialHelper = null;
-                finish();
+            if (mCstorAddCredentialHelper == null) return;
+
+            switch (mDialogId) {
+                case CSTOR_INIT_DIALOG:
+                case CSTOR_UNLOCK_DIALOG:
+                    Toast.makeText(SecuritySettings.this,
+                            R.string.cstor_unable_to_save_cert,
+                            Toast.LENGTH_LONG).show();
+                    break;
+
+                case CSTOR_NAME_CREDENTIAL_DIALOG:
+                    Toast.makeText(SecuritySettings.this,
+                            R.string.cstor_cert_not_saved,
+                            Toast.LENGTH_LONG).show();
+                    break;
             }
+            mCstorAddCredentialHelper = null;
+            finish();
         }
 
         public void onClick(DialogInterface dialog, int which) {
@@ -554,31 +604,34 @@
         public void onDismiss(DialogInterface dialog) {
             if (!mConfirm) {
                 mConfirm = true;
-                showDialog(mDialogId);
+                showCstorDialog(mDialogId);
             } else {
-                removeDialog(mDialogId);
-
                 if (mDialogId == CSTOR_UNLOCK_DIALOG) {
                     mAccessCheckBox.setChecked(isCstorUnlocked());
                 }
 
                 if (mCstorAddCredentialHelper != null) {
                     if (!isCstorInitialized()) {
-                        showDialog(CSTOR_INIT_DIALOG);
+                        showCstorDialog(CSTOR_INIT_DIALOG);
                     } else if (!isCstorUnlocked()) {
-                        showDialog(CSTOR_UNLOCK_DIALOG);
+                        showCstorDialog(CSTOR_UNLOCK_DIALOG);
                     } else {
-                        String formatString =
-                                getString(R.string.cstor_is_added);
-                        String message = String.format(formatString,
-                                mCstorAddCredentialHelper.getName());
-                        Toast.makeText(SecuritySettings.this, message,
-                                Toast.LENGTH_SHORT).show();
-                        finish();
+                        if (addCredential()) {
+                            // succeeded
+                            finish();
+                        } else {
+                            // failed
+                            if (mDialogId != CSTOR_NAME_CREDENTIAL_DIALOG) {
+                                removeDialog(mDialogId);
+                            }
+                            showCstorDialog(CSTOR_NAME_CREDENTIAL_DIALOG);
+                        }
                     }
+                    return;
                 } else if (mSpecialIntent != null) {
                     finish();
                 }
+                removeDialog(mDialogId);
             }
         }
 
@@ -625,15 +678,6 @@
                 mCstorAddCredentialHelper.setPassword(password);
             }
 
-            if (mCstorAddCredentialHelper.saveToStorage() < 0) {
-                if (mCstorAddCredentialHelper.isPkcs12Keystore()) {
-                    showError(R.string.cstor_password_error);
-                } else {
-                    showError(R.string.cstor_storage_error);
-                }
-                return false;
-            }
-
             return true;
         }
 
@@ -760,7 +804,7 @@
                         public boolean onPreferenceChange(
                                 Preference pref, Object value) {
                             if (((Boolean) value)) {
-                                showDialog(isCstorInitialized()
+                                showCstorDialog(isCstorInitialized()
                                         ? CSTOR_UNLOCK_DIALOG
                                         : CSTOR_INIT_DIALOG);
                             } else {
@@ -781,7 +825,7 @@
             pref.setOnPreferenceClickListener(
                     new Preference.OnPreferenceClickListener() {
                         public boolean onPreferenceClick(Preference pref) {
-                            showDialog(isCstorInitialized()
+                            showCstorDialog(isCstorInitialized()
                                     ? CSTOR_CHANGE_PASSWORD_DIALOG
                                     : CSTOR_INIT_DIALOG);
                             return true;
@@ -797,7 +841,7 @@
             pref.setOnPreferenceClickListener(
                     new Preference.OnPreferenceClickListener() {
                         public boolean onPreferenceClick(Preference pref) {
-                            showDialog(CSTOR_RESET_DIALOG);
+                            showCstorDialog(CSTOR_RESET_DIALOG);
                             return true;
                         }
                     });
@@ -807,7 +851,6 @@
         }
 
         private Dialog createUnlockDialog() {
-            mDialogId = CSTOR_UNLOCK_DIALOG;
             mView = View.inflate(SecuritySettings.this,
                     R.layout.cstor_unlock_dialog_view, null);
             hideError();
@@ -830,7 +873,6 @@
         }
 
         private Dialog createSetPasswordDialog(int id) {
-            mDialogId = id;
             mView = View.inflate(SecuritySettings.this,
                     R.layout.cstor_set_password_dialog_view, null);
             hideError();
@@ -870,7 +912,6 @@
         }
 
         private Dialog createResetDialog() {
-            mDialogId = CSTOR_RESET_DIALOG;
             return new AlertDialog.Builder(SecuritySettings.this)
                     .setTitle(android.R.string.dialog_alert_title)
                     .setIcon(android.R.drawable.ic_dialog_alert)
@@ -881,9 +922,12 @@
         }
 
         private Dialog createNameCredentialDialog() {
-            mDialogId = CSTOR_NAME_CREDENTIAL_DIALOG;
             mView = View.inflate(SecuritySettings.this,
                     R.layout.cstor_name_credential_dialog_view, null);
+            if (mCstorAddCredentialHelper != null) {
+                mCstorAddCredentialHelper.mView = mView;
+            }
+
             hideError();
             if (!mCstorAddCredentialHelper.isPkcs12Keystore()) {
                 hide(R.id.cstor_credential_password_container);
@@ -915,6 +959,7 @@
         private String mDescription;
         private String mName;
         private String mPassword;
+        private View mView;
 
         CstorAddCredentialHelper(Intent intent) {
             parse(intent);
@@ -958,7 +1003,7 @@
                     byte[] blob = mItemList.get(i);
                     int ret = ks.put(mNamespaceList.get(i), mName,
                             new String(blob));
-                    if (ret < 0) return ret;
+                    if (ret != 0) return ret;
                 }
             }
             return 0;
diff --git a/src/com/android/settings/TextToSpeechSettings.java b/src/com/android/settings/TextToSpeechSettings.java
index 789368a..e17a6d6 100644
--- a/src/com/android/settings/TextToSpeechSettings.java
+++ b/src/com/android/settings/TextToSpeechSettings.java
@@ -59,7 +59,7 @@
     private static final String LOCALE_DELIMITER = "-";
 
     private static final String FALLBACK_TTS_DEFAULT_SYNTH =
-            TextToSpeech.Engine.FALLBACK_TTS_DEFAULT_SYNTH;
+            TextToSpeech.Engine.DEFAULT_SYNTH;
 
     private Preference         mPlayExample = null;
     private Preference         mInstallData = null;
@@ -141,7 +141,7 @@
             intVal = Settings.Secure.getInt(resolver, TTS_USE_DEFAULTS);
         } catch (SettingNotFoundException e) {
             // "use default" setting not found, initialize it
-            intVal = TextToSpeech.Engine.FALLBACK_TTS_USE_DEFAULTS;
+            intVal = TextToSpeech.Engine.USE_DEFAULTS;
             Settings.Secure.putInt(resolver, TTS_USE_DEFAULTS, intVal);
         }
         mUseDefaultPref.setChecked(intVal == 1);
@@ -162,7 +162,7 @@
             intVal = Settings.Secure.getInt(resolver, TTS_DEFAULT_RATE);
         } catch (SettingNotFoundException e) {
             // default rate setting not found, initialize it
-            intVal = TextToSpeech.Engine.FALLBACK_TTS_DEFAULT_RATE;
+            intVal = TextToSpeech.Engine.DEFAULT_RATE;
             Settings.Secure.putInt(resolver, TTS_DEFAULT_RATE, intVal);
         }
         mDefaultRatePref.setValue(String.valueOf(intVal));
@@ -223,7 +223,7 @@
     private void checkVoiceData() {
         PackageManager pm = getPackageManager();
         Intent intent = new Intent();
-        intent.setAction("android.intent.action.CHECK_TTS_DATA");
+        intent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
         List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0);
         // query only the package that matches that of the default engine
         for (int i = 0; i < resolveInfos.size(); i++) {
@@ -243,7 +243,7 @@
     private void installVoiceData() {
         PackageManager pm = getPackageManager();
         Intent intent = new Intent();
-        intent.setAction("android.intent.action.INSTALL_TTS_DATA");
+        intent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
         List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0);
         // query only the package that matches that of the default engine
         for (int i = 0; i < resolveInfos.size(); i++) {
@@ -260,7 +260,7 @@
      * Called when the TTS engine is initialized.
      */
     public void onInit(int status) {
-        if (status == TextToSpeech.TTS_SUCCESS) {
+        if (status == TextToSpeech.SUCCESS) {
             Log.v(TAG, "TTS engine for settings screen initialized.");
             mEnableDemo = true;
         } else {
@@ -337,7 +337,7 @@
             // Play example
             if (mTts != null) {
                 mTts.speak(getResources().getString(R.string.tts_demo),
-                        TextToSpeech.TTS_QUEUE_FLUSH, null);
+                        TextToSpeech.QUEUE_FLUSH, null);
             }
             return true;
         }
diff --git a/src/com/android/settings/deviceinfo/Status.java b/src/com/android/settings/deviceinfo/Status.java
index a165754..7d22d91 100644
--- a/src/com/android/settings/deviceinfo/Status.java
+++ b/src/com/android/settings/deviceinfo/Status.java
@@ -162,6 +162,7 @@
     @Override
     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
+        Preference removablePref;
 
         mHandler = new MyHandler(this);
         
@@ -188,8 +189,15 @@
             setSummaryText("prl_version", mPhone.getCdmaPrlVersion());
 
             // device is not GSM/UMTS, do not display GSM/UMTS features
-            getPreferenceScreen().removePreference(findPreference("imei"));
-            getPreferenceScreen().removePreference(findPreference("imei_sv"));
+            // check Null in case no specified preference in overlay xml
+            removablePref = findPreference("imei");
+            if (removablePref != null) {
+                getPreferenceScreen().removePreference(removablePref);
+            }
+            removablePref = findPreference("imei_sv");
+            if (removablePref != null) {
+                getPreferenceScreen().removePreference(removablePref);
+            }
         } else {
             setSummaryText("imei", mPhone.getDeviceId());
 
@@ -198,9 +206,19 @@
                         .getDeviceSoftwareVersion());
 
             // device is not CDMA, do not display CDMA features
-            getPreferenceScreen().removePreference(findPreference("prl_version"));
-            getPreferenceScreen().removePreference(findPreference("meid_number"));
-            getPreferenceScreen().removePreference(findPreference("min_number"));
+            // check Null in case no specified preference in overlay xml
+            removablePref = findPreference("prl_version");
+            if (removablePref != null) {
+                getPreferenceScreen().removePreference(removablePref);
+            }
+            removablePref = findPreference("meid_number");
+            if (removablePref != null) {
+                getPreferenceScreen().removePreference(removablePref);
+            }
+            removablePref = findPreference("min_number");
+            if (removablePref != null) {
+                getPreferenceScreen().removePreference(removablePref);
+            }
         }
 
         setSummaryText("number", mPhone.getLine1Number());
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 3dc9914..10c9a43 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -463,7 +463,7 @@
         btPower += (btPingCount
                 * mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_AT_CMD)) / 1000;
 
-        addEntry(getString(R.string.power_bluetooth), DrainType.IDLE, btOnTimeMs,
+        addEntry(getString(R.string.power_bluetooth), DrainType.BLUETOOTH, btOnTimeMs,
                 com.android.internal.R.drawable.ic_volume_bluetooth_in_call, btPower);
     }
 
diff --git a/src/com/android/settings/vpn/L2tpEditor.java b/src/com/android/settings/vpn/L2tpEditor.java
index 643ba3b..29036f2 100644
--- a/src/com/android/settings/vpn/L2tpEditor.java
+++ b/src/com/android/settings/vpn/L2tpEditor.java
@@ -30,9 +30,7 @@
  */
 class L2tpEditor extends VpnProfileEditor {
     private CheckBoxPreference mSecret;
-    private EditTextPreference mSecretString;
-    private String mOriginalSecret;
-    private boolean mOriginalSecretEnabled;
+    private SecretHandler mSecretHandler;
 
     public L2tpEditor(L2tpProfile p) {
         super(p);
@@ -43,11 +41,8 @@
         Context c = subpanel.getContext();
         subpanel.addPreference(createSecretPreference(c));
         subpanel.addPreference(createSecretStringPreference(c));
-        mSecretString.setEnabled(mSecret.isChecked());
 
         L2tpProfile profile = (L2tpProfile) getProfile();
-        mOriginalSecret = profile.getSecretString();
-        mOriginalSecretEnabled = profile.isSecretEnabled();
     }
 
     @Override
@@ -55,9 +50,7 @@
         String result = super.validate();
         if (!mSecret.isChecked()) return result;
 
-        return ((result != null)
-                ? result
-                : validate(mSecretString, R.string.vpn_a_l2tp_secret));
+        return ((result != null) ? result : mSecretHandler.validate());
     }
 
     private Preference createSecretPreference(Context c) {
@@ -73,7 +66,7 @@
                             Preference pref, Object newValue) {
                         boolean enabled = (Boolean) newValue;
                         profile.setSecretEnabled(enabled);
-                        mSecretString.setEnabled(enabled);
+                        mSecretHandler.getPreference().setEnabled(enabled);
                         setSecretTitle(mSecret, R.string.vpn_l2tp_secret,
                                 enabled);
                         setSecretSummary(mSecret, enabled);
@@ -84,22 +77,22 @@
     }
 
     private Preference createSecretStringPreference(Context c) {
-        final L2tpProfile profile = (L2tpProfile) getProfile();
-        mSecretString = createSecretPreference(c,
+        SecretHandler sHandler = mSecretHandler = new SecretHandler(c,
                 R.string.vpn_l2tp_secret_string_title,
-                R.string.vpn_l2tp_secret,
-                profile.getSecretString(),
-                new Preference.OnPreferenceChangeListener() {
-                    public boolean onPreferenceChange(
-                            Preference pref, Object newValue) {
-                        profile.setSecretString((String) newValue);
-                        setSecretSummary(mSecretString,
-                                R.string.vpn_l2tp_secret,
-                                (String) newValue);
-                        return true;
-                    }
-                });
-        return mSecretString;
+                R.string.vpn_l2tp_secret) {
+            @Override
+            protected String getSecretFromProfile() {
+                return ((L2tpProfile) getProfile()).getSecretString();
+            }
+
+            @Override
+            protected void saveSecretToProfile(String secret) {
+                ((L2tpProfile) getProfile()).setSecretString(secret);
+            }
+        };
+        Preference pref = sHandler.getPreference();
+        pref.setEnabled(mSecret.isChecked());
+        return pref;
     }
 
     private void setSecretSummary(CheckBoxPreference secret, boolean enabled) {
diff --git a/src/com/android/settings/vpn/L2tpIpsecPskEditor.java b/src/com/android/settings/vpn/L2tpIpsecPskEditor.java
index 11590da..1277c28 100644
--- a/src/com/android/settings/vpn/L2tpIpsecPskEditor.java
+++ b/src/com/android/settings/vpn/L2tpIpsecPskEditor.java
@@ -29,6 +29,7 @@
  */
 class L2tpIpsecPskEditor extends L2tpEditor {
     private EditTextPreference mPresharedKey;
+    private SecretHandler mPskHandler;
 
     public L2tpIpsecPskEditor(L2tpIpsecPskProfile p) {
         super(p);
@@ -45,27 +46,23 @@
     public String validate() {
         String result = super.validate();
 
-        return ((result != null)
-                ? result
-                : validate(mPresharedKey, R.string.vpn_a_ipsec_presharedkey));
+        return ((result != null) ? result : mPskHandler.validate());
     }
 
     private Preference createPresharedKeyPreference(Context c) {
-        final L2tpIpsecPskProfile profile = (L2tpIpsecPskProfile) getProfile();
-        mPresharedKey = createSecretPreference(c,
+        SecretHandler pskHandler = mPskHandler = new SecretHandler(c,
                 R.string.vpn_ipsec_presharedkey_title,
-                R.string.vpn_ipsec_presharedkey,
-                profile.getPresharedKey(),
-                new Preference.OnPreferenceChangeListener() {
-                    public boolean onPreferenceChange(
-                            Preference pref, Object newValue) {
-                        profile.setPresharedKey((String) newValue);
-                        setSecretSummary(mPresharedKey,
-                                R.string.vpn_ipsec_presharedkey,
-                                (String) newValue);
-                        return true;
-                    }
-                });
-        return mPresharedKey;
+                R.string.vpn_ipsec_presharedkey) {
+            @Override
+            protected String getSecretFromProfile() {
+                return ((L2tpIpsecPskProfile) getProfile()).getPresharedKey();
+            }
+
+            @Override
+            protected void saveSecretToProfile(String secret) {
+                ((L2tpIpsecPskProfile) getProfile()).setPresharedKey(secret);
+            }
+        };
+        return pskHandler.getPreference();
     }
 }
diff --git a/src/com/android/settings/vpn/PptpEditor.java b/src/com/android/settings/vpn/PptpEditor.java
new file mode 100644
index 0000000..fafe6a7
--- /dev/null
+++ b/src/com/android/settings/vpn/PptpEditor.java
@@ -0,0 +1,75 @@
+/* * 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.vpn;
+
+import com.android.settings.R;
+
+import android.content.Context;
+import android.net.vpn.PptpProfile;
+import android.preference.CheckBoxPreference;
+import android.preference.Preference;
+import android.preference.PreferenceGroup;
+
+/**
+ * The class for editing {@link PptpProfile}.
+ */
+class PptpEditor extends VpnProfileEditor {
+    private CheckBoxPreference mEncryption;
+
+    public PptpEditor(PptpProfile p) {
+        super(p);
+    }
+
+    @Override
+    protected void loadExtraPreferencesTo(PreferenceGroup subpanel) {
+        Context c = subpanel.getContext();
+        subpanel.addPreference(createEncryptionPreference(c));
+
+        PptpProfile profile = (PptpProfile) getProfile();
+    }
+
+    private Preference createEncryptionPreference(Context c) {
+        final PptpProfile profile = (PptpProfile) getProfile();
+        CheckBoxPreference encryption = mEncryption = new CheckBoxPreference(c);
+        boolean enabled = profile.isEncryptionEnabled();
+        setSecretTitle(encryption, R.string.vpn_pptp_encryption_title, enabled);
+        encryption.setChecked(enabled);
+        setEncryptionSummary(encryption, enabled);
+        encryption.setOnPreferenceChangeListener(
+                new Preference.OnPreferenceChangeListener() {
+                    public boolean onPreferenceChange(
+                            Preference pref, Object newValue) {
+                        boolean enabled = (Boolean) newValue;
+                        profile.setEncryptionEnabled(enabled);
+                        setSecretTitle(mEncryption,
+                                R.string.vpn_pptp_encryption_title, enabled);
+                        setEncryptionSummary(mEncryption, enabled);
+                        return true;
+                    }
+                });
+        return encryption;
+    }
+
+    private void setEncryptionSummary(CheckBoxPreference encryption,
+            boolean enabled) {
+        Context c = encryption.getContext();
+        String formatString = c.getString(enabled
+                ? R.string.vpn_is_enabled
+                : R.string.vpn_is_disabled);
+        encryption.setSummary(String.format(
+                formatString, c.getString(R.string.vpn_pptp_encryption)));
+    }
+}
diff --git a/src/com/android/settings/vpn/VpnEditor.java b/src/com/android/settings/vpn/VpnEditor.java
index b4dc2b6..497f4bf 100644
--- a/src/com/android/settings/vpn/VpnEditor.java
+++ b/src/com/android/settings/vpn/VpnEditor.java
@@ -24,9 +24,11 @@
 import android.net.vpn.L2tpIpsecProfile;
 import android.net.vpn.L2tpIpsecPskProfile;
 import android.net.vpn.L2tpProfile;
+import android.net.vpn.PptpProfile;
 import android.net.vpn.VpnProfile;
 import android.net.vpn.VpnType;
 import android.os.Bundle;
+import android.os.Parcel;
 import android.os.Parcelable;
 import android.preference.PreferenceActivity;
 import android.preference.PreferenceGroup;
@@ -47,6 +49,7 @@
 
     private VpnProfileEditor mProfileEditor;
     private boolean mAddingProfile;
+    private byte[] mOriginalProfileData;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -61,6 +64,10 @@
         addPreferencesFromResource(R.xml.vpn_edit);
 
         initViewFor(p);
+
+        Parcel parcel = Parcel.obtain();
+        p.writeToParcel(parcel, 0);
+        mOriginalProfileData = parcel.marshall();
     }
 
     @Override
@@ -90,7 +97,11 @@
                 return true;
 
             case MENU_CANCEL:
-                showCancellationConfirmDialog();
+                if (profileChanged()) {
+                    showCancellationConfirmDialog();
+                } else {
+                    finish();
+                }
                 return true;
         }
         return super.onOptionsItemSelected(item);
@@ -131,7 +142,7 @@
             return false;
         }
 
-        setResult(getProfile());
+        if (profileChanged()) setResult(getProfile());
         return true;
     }
 
@@ -152,6 +163,9 @@
             case L2TP:
                 return new L2tpEditor((L2tpProfile) p);
 
+            case PPTP:
+                return new PptpEditor((PptpProfile) p);
+
             default:
                 return new VpnProfileEditor(p);
         }
@@ -177,4 +191,17 @@
     private VpnProfile getProfile() {
         return mProfileEditor.getProfile();
     }
+
+    private boolean profileChanged() {
+        Parcel newParcel = Parcel.obtain();
+        getProfile().writeToParcel(newParcel, 0);
+        byte[] newData = newParcel.marshall();
+        if (mOriginalProfileData.length == newData.length) {
+            for (int i = 0, n = mOriginalProfileData.length; i < n; i++) {
+                if (mOriginalProfileData[i] != newData[i]) return true;
+            }
+            return false;
+        }
+        return true;
+    }
 }
diff --git a/src/com/android/settings/vpn/VpnProfileEditor.java b/src/com/android/settings/vpn/VpnProfileEditor.java
index bf2e57d..8dc3643 100644
--- a/src/com/android/settings/vpn/VpnProfileEditor.java
+++ b/src/com/android/settings/vpn/VpnProfileEditor.java
@@ -33,9 +33,6 @@
  * The common class for editing {@link VpnProfile}.
  */
 class VpnProfileEditor {
-    static final String SECRET_SET_INDICATOR =
-            new String(new byte[] {(byte) 1, (byte) 0});
-
     private static final String KEY_VPN_NAME = "vpn_name";
 
     private EditTextPreference mName;
@@ -69,6 +66,8 @@
                     }
                 });
         setName(getProfile().getName());
+        mName.getEditText().setInputType(InputType.TYPE_CLASS_TEXT
+                | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);
 
         subpanel.addPreference(createServerNamePreference(c));
         loadExtraPreferencesTo(subpanel);
@@ -147,22 +146,6 @@
         return pref;
     }
 
-    protected EditTextPreference createSecretPreference(Context c, int titleId,
-            int fieldNameId, String value,
-            Preference.OnPreferenceChangeListener listener) {
-        EditTextPreference pref = new EditTextPreference(c);
-        pref.setTitle(titleId);
-        pref.setDialogTitle(titleId);
-        pref.getEditText().setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
-        pref.getEditText().setTransformationMethod(
-                new PasswordTransformationMethod());
-        pref.setText(TextUtils.isEmpty(value) ? "" : SECRET_SET_INDICATOR);
-        setSecretSummary(pref, fieldNameId, value);
-        pref.setPersistent(true);
-        pref.setOnPreferenceChangeListener(listener);
-        return pref;
-    }
-
     protected String validate(Preference pref, int fieldNameId) {
         Context c = pref.getContext();
         String value = (pref instanceof EditTextPreference)
@@ -191,15 +174,6 @@
                 : v);
     }
 
-    protected void setSecretSummary(Preference pref, int fieldNameId,
-            String value) {
-        Context c = pref.getContext();
-        String formatString = TextUtils.isEmpty(value)
-                ? c.getString(R.string.vpn_field_not_set)
-                : c.getString(R.string.vpn_field_is_set);
-        pref.setSummary(String.format(formatString, c.getString(fieldNameId)));
-    }
-
     protected void setSecretTitle(
             CheckBoxPreference pref, int fieldNameId, boolean enabled) {
         Context c = pref.getContext();
@@ -215,4 +189,69 @@
         getProfile().setName(newName);
         setSummary(mName, R.string.vpn_name, newName);
     }
+
+    // Secret is tricky to handle because empty field may mean "not set" or
+    // "unchanged". This class hides that logic from callers.
+    protected static abstract class SecretHandler {
+        private EditTextPreference mPref;
+        private int mFieldNameId;
+        private boolean mHadSecret;
+
+        protected SecretHandler(Context c, int titleId, int fieldNameId) {
+            String value = getSecretFromProfile();
+            mHadSecret = !TextUtils.isEmpty(value);
+            mFieldNameId = fieldNameId;
+
+            EditTextPreference pref = mPref = new EditTextPreference(c);
+            pref.setTitle(titleId);
+            pref.setDialogTitle(titleId);
+            pref.getEditText().setInputType(
+                    InputType.TYPE_TEXT_VARIATION_PASSWORD);
+            pref.getEditText().setTransformationMethod(
+                    new PasswordTransformationMethod());
+            pref.setText("");
+            pref.getEditText().setHint(mHadSecret
+                    ? R.string.vpn_secret_unchanged
+                    : R.string.vpn_secret_not_set);
+            setSecretSummary(value);
+            pref.setPersistent(true);
+            saveSecretToProfile("");
+            pref.setOnPreferenceChangeListener(
+                    new Preference.OnPreferenceChangeListener() {
+                        public boolean onPreferenceChange(
+                                Preference pref, Object newValue) {
+                            saveSecretToProfile((String) newValue);
+                            setSecretSummary((String) newValue);
+                            return true;
+                        }
+                    });
+        }
+
+        protected EditTextPreference getPreference() {
+            return mPref;
+        }
+
+        protected String validate() {
+            Context c = mPref.getContext();
+            String value = mPref.getText();
+            return ((TextUtils.isEmpty(value) && !mHadSecret)
+                    ? String.format(
+                            c.getString(R.string.vpn_error_miss_entering),
+                            c.getString(mFieldNameId))
+                    : null);
+        }
+
+        private void setSecretSummary(String value) {
+            EditTextPreference pref = mPref;
+            Context c = pref.getContext();
+            String formatString = (TextUtils.isEmpty(value) && !mHadSecret)
+                    ? c.getString(R.string.vpn_field_not_set)
+                    : c.getString(R.string.vpn_field_is_set);
+            pref.setSummary(
+                    String.format(formatString, c.getString(mFieldNameId)));
+        }
+
+        protected abstract String getSecretFromProfile();
+        protected abstract void saveSecretToProfile(String secret);
+    }
 }
diff --git a/src/com/android/settings/vpn/VpnSettings.java b/src/com/android/settings/vpn/VpnSettings.java
index f0e71f7..4dda152 100644
--- a/src/com/android/settings/vpn/VpnSettings.java
+++ b/src/com/android/settings/vpn/VpnSettings.java
@@ -18,7 +18,6 @@
 
 import com.android.settings.R;
 import com.android.settings.SecuritySettings;
-import static com.android.settings.vpn.VpnProfileEditor.SECRET_SET_INDICATOR;
 
 import android.app.AlertDialog;
 import android.app.Dialog;
@@ -29,6 +28,7 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.net.vpn.IVpnService;
+import android.net.vpn.L2tpIpsecProfile;
 import android.net.vpn.L2tpIpsecPskProfile;
 import android.net.vpn.L2tpProfile;
 import android.net.vpn.VpnManager;
@@ -47,6 +47,7 @@
 import android.preference.PreferenceManager;
 import android.preference.PreferenceScreen;
 import android.preference.Preference.OnPreferenceClickListener;
+import android.security.CertTool;
 import android.security.Keystore;
 import android.text.TextUtils;
 import android.util.Log;
@@ -107,6 +108,9 @@
     private static final int DIALOG_RECONNECT = 2;
     private static final int DIALOG_AUTH_ERROR = 3;
     private static final int DIALOG_UNKNOWN_SERVER = 4;
+    private static final int DIALOG_SECRET_NOT_SET = 5;
+    private static final int DIALOG_CHALLENGE_ERROR = 6;
+    private static final int DIALOG_REMOTE_HUNG_UP_ERROR = 7;
 
     private static final int NO_ERROR = 0;
 
@@ -197,14 +201,23 @@
                 return createConnectDialog();
 
             case DIALOG_RECONNECT:
-                return createReconnectDialogBuilder().create();
+                return createReconnectDialog();
 
             case DIALOG_AUTH_ERROR:
                 return createAuthErrorDialog();
 
+            case DIALOG_REMOTE_HUNG_UP_ERROR:
+                return createRemoteHungUpErrorDialog();
+
+            case DIALOG_CHALLENGE_ERROR:
+                return createChallengeErrorDialog();
+
             case DIALOG_UNKNOWN_SERVER:
                 return createUnknownServerDialog();
 
+            case DIALOG_SECRET_NOT_SET:
+                return createSecretNotSetDialog();
+
             default:
                 return super.onCreateDialog(id);
         }
@@ -219,14 +232,74 @@
                         this)
                 .setNegativeButton(getString(android.R.string.cancel),
                         this)
+                .setOnCancelListener(new DialogInterface.OnCancelListener() {
+                            public void onCancel(DialogInterface dialog) {
+                                removeDialog(DIALOG_CONNECT);
+                                onIdle();
+                            }
+                        })
                 .create();
     }
 
-    private AlertDialog.Builder createReconnectDialogBuilder() {
+    private Dialog createReconnectDialog() {
+        return createCommonDialogBuilder()
+                .setMessage(R.string.vpn_confirm_reconnect)
+                .create();
+    }
+
+    private Dialog createAuthErrorDialog() {
+        return createCommonDialogBuilder()
+                .setMessage(R.string.vpn_auth_error_dialog_msg)
+                .create();
+    }
+
+    private Dialog createRemoteHungUpErrorDialog() {
+        return createCommonDialogBuilder()
+                .setMessage(R.string.vpn_remote_hung_up_error_dialog_msg)
+                .create();
+    }
+
+    private Dialog createChallengeErrorDialog() {
+        return createCommonEditDialogBuilder()
+                .setMessage(R.string.vpn_challenge_error_dialog_msg)
+                .create();
+    }
+
+    private Dialog createUnknownServerDialog() {
+        return createCommonEditDialogBuilder()
+                .setMessage(R.string.vpn_unknown_server_dialog_msg)
+                .create();
+    }
+
+    private Dialog createSecretNotSetDialog() {
+        return createCommonDialogBuilder()
+                .setMessage(R.string.vpn_secret_not_set_dialog_msg)
+                .setPositiveButton(R.string.vpn_yes_button,
+                        new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog, int w) {
+                                VpnProfile p = mConnectingActor.getProfile();
+                                startVpnEditor(p);
+                            }
+                        })
+                .create();
+    }
+
+    private AlertDialog.Builder createCommonEditDialogBuilder() {
+        return createCommonDialogBuilder()
+                .setPositiveButton(R.string.vpn_yes_button,
+                        new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog, int w) {
+                                VpnProfile p = mConnectingActor.getProfile();
+                                onIdle();
+                                startVpnEditor(p);
+                            }
+                        });
+    }
+
+    private AlertDialog.Builder createCommonDialogBuilder() {
         return new AlertDialog.Builder(this)
                 .setTitle(android.R.string.dialog_alert_title)
                 .setIcon(android.R.drawable.ic_dialog_alert)
-                .setMessage(R.string.vpn_confirm_reconnect)
                 .setPositiveButton(R.string.vpn_yes_button,
                         new DialogInterface.OnClickListener() {
                             public void onClick(DialogInterface dialog, int w) {
@@ -246,26 +319,6 @@
                         });
     }
 
-    private Dialog createAuthErrorDialog() {
-        return createReconnectDialogBuilder()
-                .setMessage(R.string.vpn_auth_error_dialog_msg)
-                .create();
-    }
-
-    private Dialog createUnknownServerDialog() {
-        return createReconnectDialogBuilder()
-                .setMessage(R.string.vpn_unknown_server_dialog_msg)
-                .setPositiveButton(R.string.vpn_yes_button,
-                        new DialogInterface.OnClickListener() {
-                            public void onClick(DialogInterface dialog, int w) {
-                                VpnProfile p = mConnectingActor.getProfile();
-                                onIdle();
-                                startVpnEditor(p);
-                            }
-                        })
-                .create();
-    }
-
     @Override
     public void onCreateContextMenu(ContextMenu menu, View v,
             ContextMenuInfo menuInfo) {
@@ -413,6 +466,7 @@
             }
         } else {
             removeDialog(DIALOG_CONNECT);
+            onIdle();
         }
     }
 
@@ -629,6 +683,7 @@
 
         mConnectingActor = getActor(p);
         mActiveProfile = p;
+        if (!checkSecrets(p)) return;
         if (mConnectingActor.isConnectDialogNeeded()) {
             showDialog(DIALOG_CONNECT);
         } else {
@@ -693,6 +748,14 @@
                     showDialog(DIALOG_AUTH_ERROR);
                     break;
 
+                case VpnManager.VPN_ERROR_REMOTE_HUNG_UP:
+                    showDialog(DIALOG_REMOTE_HUNG_UP_ERROR);
+                    break;
+
+                case VpnManager.VPN_ERROR_CHALLENGE:
+                    showDialog(DIALOG_CHALLENGE_ERROR);
+                    break;
+
                 case VpnManager.VPN_ERROR_UNKNOWN_SERVER:
                     showDialog(DIALOG_UNKNOWN_SERVER);
                     break;
@@ -707,6 +770,7 @@
     }
 
     private void onIdle() {
+        Log.d(TAG, "   onIdle()");
         mActiveProfile = null;
         mConnectingActor = null;
         enableProfilePreferences();
@@ -847,34 +911,93 @@
         return NAMESPACE_VPN + "_" + keyName;
     }
 
+    private boolean checkSecrets(VpnProfile p) {
+        Keystore ks = Keystore.getInstance();
+        HashSet<String> secretSet = new HashSet<String>();
+        boolean secretMissing = false;
+
+        if (p instanceof L2tpIpsecProfile) {
+            L2tpIpsecProfile certProfile = (L2tpIpsecProfile) p;
+            CertTool certTool = CertTool.getInstance();
+            Collections.addAll(secretSet, certTool.getAllCaCertificateKeys());
+            String cert = certProfile.getCaCertificate();
+            if (TextUtils.isEmpty(cert) || !secretSet.contains(cert)) {
+                certProfile.setCaCertificate(null);
+                secretMissing = true;
+            }
+
+            secretSet.clear();
+            Collections.addAll(secretSet, certTool.getAllUserCertificateKeys());
+            cert = certProfile.getUserCertificate();
+            if (TextUtils.isEmpty(cert) || !secretSet.contains(cert)) {
+                certProfile.setUserCertificate(null);
+                secretMissing = true;
+            }
+        }
+
+        secretSet.clear();
+        Collections.addAll(secretSet, ks.listKeys(NAMESPACE_VPN));
+
+        if (p instanceof L2tpIpsecPskProfile) {
+            L2tpIpsecPskProfile pskProfile = (L2tpIpsecPskProfile) p;
+            String presharedKey = pskProfile.getPresharedKey();
+            String keyName = KEY_PREFIX_IPSEC_PSK + p.getId();
+            if (TextUtils.isEmpty(presharedKey)
+                    || !secretSet.contains(keyName)) {
+                pskProfile.setPresharedKey(null);
+                secretMissing = true;
+            }
+        }
+
+        if (p instanceof L2tpProfile) {
+            L2tpProfile l2tpProfile = (L2tpProfile) p;
+            if (l2tpProfile.isSecretEnabled()) {
+                String secret = l2tpProfile.getSecretString();
+                String keyName = KEY_PREFIX_L2TP_SECRET + p.getId();
+                if (TextUtils.isEmpty(secret)
+                        || !secretSet.contains(keyName)) {
+                    l2tpProfile.setSecretString(null);
+                    secretMissing = true;
+                }
+            }
+        }
+
+        if (secretMissing) {
+            showDialog(DIALOG_SECRET_NOT_SET);
+            return false;
+        } else {
+            return true;
+        }
+    }
+
     private void processSecrets(VpnProfile p) {
         Keystore ks = Keystore.getInstance();
         switch (p.getType()) {
             case L2TP_IPSEC_PSK:
                 L2tpIpsecPskProfile pskProfile = (L2tpIpsecPskProfile) p;
                 String presharedKey = pskProfile.getPresharedKey();
-                if (!presharedKey.equals(SECRET_SET_INDICATOR)) {
-                    String keyName = KEY_PREFIX_IPSEC_PSK + p.getId();
+                String keyName = KEY_PREFIX_IPSEC_PSK + p.getId();
+                if (!TextUtils.isEmpty(presharedKey)) {
                     int ret = ks.put(NAMESPACE_VPN, keyName, presharedKey);
-                    if (ret < 0) {
+                    if (ret != 0) {
                         Log.e(TAG, "keystore write failed: key=" + keyName);
                     }
-                    pskProfile.setPresharedKey(keyNameForDaemon(keyName));
                 }
+                pskProfile.setPresharedKey(keyNameForDaemon(keyName));
                 // pass through
 
             case L2TP:
                 L2tpProfile l2tpProfile = (L2tpProfile) p;
-                String keyName = KEY_PREFIX_L2TP_SECRET + p.getId();
+                keyName = KEY_PREFIX_L2TP_SECRET + p.getId();
                 if (l2tpProfile.isSecretEnabled()) {
                     String secret = l2tpProfile.getSecretString();
-                    if (!secret.equals(SECRET_SET_INDICATOR)) {
+                    if (!TextUtils.isEmpty(secret)) {
                         int ret = ks.put(NAMESPACE_VPN, keyName, secret);
-                        if (ret < 0) {
+                        if (ret != 0) {
                             Log.e(TAG, "keystore write failed: key=" + keyName);
                         }
-                        l2tpProfile.setSecretString(keyNameForDaemon(keyName));
                     }
+                    l2tpProfile.setSecretString(keyNameForDaemon(keyName));
                 } else {
                     ks.remove(NAMESPACE_VPN, keyName);
                 }
diff --git a/src/com/android/settings/wifi/AccessPointDialog.java b/src/com/android/settings/wifi/AccessPointDialog.java
index c9f511b..5851a18 100644
--- a/src/com/android/settings/wifi/AccessPointDialog.java
+++ b/src/com/android/settings/wifi/AccessPointDialog.java
@@ -134,7 +134,7 @@
     private Spinner mSecuritySpinner;
     private Spinner mWepTypeSpinner;
     private CertTool mCertTool;
-    
+
     public AccessPointDialog(Context context, WifiLayer wifiLayer) {
         super(context);
 
@@ -217,6 +217,14 @@
         setTitle(getContext().getString(titleId));
     }
 
+    public void enableEnterpriseFields() {
+        setEnterpriseFieldsVisible(true);
+        updateCertificateSelection();
+        setGenericPasswordVisible(true);
+        // Both WPA and WPA2 show the same caption, so either is ok
+        updatePasswordCaption(AccessPointState.WPA);
+    }
+
     /** Called after flags are set, the dialog's layout/etc should be set up here */
     private void onLayout() {
         final Context context = getContext();
@@ -246,7 +254,6 @@
         } else if (mMode == MODE_INFO) {
             if (mState.isEnterprise() && !mState.configured) {
                 setLayout(R.layout.wifi_ap_configure);
-                defaultPasswordVisibility = false;
                 setEnterpriseFieldsVisible(true);
             } else {
                 setLayout(R.layout.wifi_ap_info);
@@ -319,17 +326,26 @@
         if (mMode == MODE_CONFIGURE ||
                 (mState.isEnterprise() && !mState.configured)) {
             setEnterpriseFields(view);
-            mEapSpinner.setSelection(getSelectionIndex(
-                    R.array.wifi_eap_entries, mState.getEap()));
-            mClientCertSpinner.setSelection(getSelectionIndex(
-                    getAllUserCertificateKeys(), mState.getEnterpriseField(
-                    AccessPointState.CLIENT_CERT)));
-            mCaCertSpinner.setSelection(getSelectionIndex(
-                    getAllCaCertificateKeys(), mState.getEnterpriseField(
-                    AccessPointState.CA_CERT)));
+            updateCertificateSelection();
         }
     }
 
+    private void updateCertificateSelection() {
+        setSpinnerAdapter(mClientCertSpinner, getAllUserCertificateKeys());
+        setSpinnerAdapter(mCaCertSpinner, getAllCaCertificateKeys());
+
+        mPhase2Spinner.setSelection(getSelectionIndex(
+                R.array.wifi_phase2_entries, mState.getPhase2()));
+        mEapSpinner.setSelection(getSelectionIndex(
+                R.array.wifi_eap_entries, mState.getEap()));
+        mClientCertSpinner.setSelection(getSelectionIndex(
+                getAllUserCertificateKeys(), mState.getEnterpriseField(
+                AccessPointState.CLIENT_CERT)));
+        mCaCertSpinner.setSelection(getSelectionIndex(
+                getAllCaCertificateKeys(), mState.getEnterpriseField(
+                AccessPointState.CA_CERT)));
+    }
+
     private String[] getAllCaCertificateKeys() {
         return appendEmptyInSelection(mCertTool.getAllCaCertificateKeys());
     }
@@ -663,14 +679,15 @@
             }
         }
         switch (securityType) {
+            case SECURITY_IEEE8021X: 
             case SECURITY_WPA_EAP: {
-                mState.setSecurity(AccessPointState.WPA_EAP);
+                if (securityType == SECURITY_WPA_EAP) {
+                    mState.setSecurity(AccessPointState.WPA_EAP);
+                } else {
+                    mState.setSecurity(AccessPointState.IEEE8021X);
+                }
                 mState.setEap(mEapSpinner.getSelectedItemPosition());
-                break;
-            }
-            case SECURITY_IEEE8021X: {
-                mState.setSecurity(AccessPointState.IEEE8021X);
-                mState.setEap(mEapSpinner.getSelectedItemPosition());
+                mState.setPhase2((String)mPhase2Spinner.getSelectedItem());
                 break;
             }
             default:
@@ -786,13 +803,9 @@
                 if (Keystore.getInstance().getState() != Keystore.UNLOCKED) {
                     getContext().startActivity(new Intent(
                             SecuritySettings.ACTION_UNLOCK_CREDENTIAL_STORAGE));
-                    mSecuritySpinner.setSelection(0);
                     return;
                 }
-                setEnterpriseFieldsVisible(true);
-                setGenericPasswordVisible(true);
-                // Both WPA and WPA2 show the same caption, so either is ok
-                updatePasswordCaption(AccessPointState.WPA);
+                enableEnterpriseFields();
                 break;
             }
         }
diff --git a/src/com/android/settings/wifi/AccessPointState.java b/src/com/android/settings/wifi/AccessPointState.java
index 8fb651b..899c304 100644
--- a/src/com/android/settings/wifi/AccessPointState.java
+++ b/src/com/android/settings/wifi/AccessPointState.java
@@ -375,12 +375,22 @@
 
     /* For Enterprise Fields */
     public void setEnterpriseField(int field, String value) {
-        if (value != null && field >= 0 && field < MAX_ENTRPRISE_FIELD) {
+        if ((value != null) && (field >= 0) && (field < MAX_ENTRPRISE_FIELD)) {
             this.mEnterpriseFields[field] = value;
             requestRefresh();
         }
     }
 
+    public void setPhase2(String phase2) {
+        if (!TextUtils.isEmpty(phase2) && (!phase2.equals("None"))) {
+            mPhase2 = phase2;
+        }
+    }
+
+    public String getPhase2() {
+        return mPhase2;
+    }
+
     public void setEap(int method) {
         mEap =  EAP_METHOD[method];
         requestRefresh();
@@ -495,6 +505,12 @@
         config.hiddenSSID = hiddenSsid;
         config.SSID = convertToQuotedString(ssid);
         config.eap = mEap;
+
+        if (!TextUtils.isEmpty(mPhase2)) {
+            config.phase2 = convertToQuotedString("auth=" + mPhase2);
+        } else {
+            config.phase2 = null;
+        }
         if (!TextUtils.isEmpty(mEnterpriseFields[IDENTITY])) {
             config.identity =
                     convertToQuotedString(mEnterpriseFields[IDENTITY]);
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index a015534..f18992a 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -86,6 +86,9 @@
     private Preference mAddOtherNetwork;
     
     private WeakHashMap<AccessPointState, AccessPointPreference> mAps;
+
+    private AccessPointState mResumeState = null;
+    private int mResumeMode;
     
     //============================
     // Wifi member variables
@@ -152,8 +155,22 @@
         super.onResume();
         mWifiLayer.onResume();
         mWifiEnabler.resume();
+        // do what we should have after keystore is unlocked.
+        if (mResumeState != null) {
+            if (Keystore.getInstance().getState() == Keystore.UNLOCKED) {
+                showAccessPointDialog(mResumeState, mResumeMode);
+            }
+            mResumeMode = -1;
+            mResumeState = null;
+        } else {
+            if (mResumeMode == AccessPointDialog.MODE_CONFIGURE) {
+                if (Keystore.getInstance().getState() == Keystore.UNLOCKED) {
+                    ((AccessPointDialog) mDialog).enableEnterpriseFields();
+                }
+            }
+        }
     }
-    
+
     @Override
     protected void onPause() {
         super.onPause();
@@ -231,6 +248,7 @@
     public void onDismiss(DialogInterface dialog) {
         if (dialog == mDialog) {
             mDialog = null;
+            mResumeMode = -1;
         }
     }
 
@@ -350,6 +368,7 @@
         dialog.setMode(AccessPointDialog.MODE_CONFIGURE);
         dialog.setTitle(R.string.wifi_add_other_network);
         dialog.setAutoSecurityAllowed(false);
+        mResumeMode = AccessPointDialog.MODE_CONFIGURE;
         showDialog(dialog);
     }
     
@@ -358,6 +377,8 @@
                 Keystore.getInstance().getState() != Keystore.UNLOCKED) {
             startActivity(new Intent(
                     SecuritySettings.ACTION_UNLOCK_CREDENTIAL_STORAGE));
+            mResumeState = state;
+            mResumeMode = mode;
             return;
         }
         AccessPointDialog dialog = new AccessPointDialog(this, mWifiLayer);