From b2295174dcb27efa0bf2fb58bb31a517413d9c86 Mon Sep 17 00:00:00 2001 From: Chung-yih Wang Date: Wed, 22 Jul 2009 11:48:33 +0800 Subject: [PATCH 01/14] Add the missing phase2 field in EAP configuration. + Enable the password field for configuring the EAP-APs scanned. --- .../settings/wifi/AccessPointDialog.java | 16 +++++++++------- .../settings/wifi/AccessPointState.java | 18 +++++++++++++++++- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/com/android/settings/wifi/AccessPointDialog.java b/src/com/android/settings/wifi/AccessPointDialog.java index c9f511bc4ca..3e44961b624 100644 --- a/src/com/android/settings/wifi/AccessPointDialog.java +++ b/src/com/android/settings/wifi/AccessPointDialog.java @@ -246,7 +246,6 @@ public class AccessPointDialog extends AlertDialog implements DialogInterface.On } 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,6 +318,8 @@ public class AccessPointDialog extends AlertDialog implements DialogInterface.On if (mMode == MODE_CONFIGURE || (mState.isEnterprise() && !mState.configured)) { setEnterpriseFields(view); + mPhase2Spinner.setSelection(getSelectionIndex( + R.array.wifi_phase2_entries, mState.getPhase2())); mEapSpinner.setSelection(getSelectionIndex( R.array.wifi_eap_entries, mState.getEap())); mClientCertSpinner.setSelection(getSelectionIndex( @@ -663,14 +664,15 @@ public class AccessPointDialog extends AlertDialog implements DialogInterface.On } } switch (securityType) { + case SECURITY_IEEE8021X: case SECURITY_WPA_EAP: { - mState.setSecurity(AccessPointState.WPA_EAP); - mState.setEap(mEapSpinner.getSelectedItemPosition()); - break; - } - case SECURITY_IEEE8021X: { - mState.setSecurity(AccessPointState.IEEE8021X); + if (securityType == SECURITY_WPA_EAP) { + mState.setSecurity(AccessPointState.WPA_EAP); + } else { + mState.setSecurity(AccessPointState.IEEE8021X); + } mState.setEap(mEapSpinner.getSelectedItemPosition()); + mState.setPhase2(mPhase2Spinner.getSelectedItem()); break; } default: diff --git a/src/com/android/settings/wifi/AccessPointState.java b/src/com/android/settings/wifi/AccessPointState.java index 8fb651bc012..899c3047a5f 100644 --- a/src/com/android/settings/wifi/AccessPointState.java +++ b/src/com/android/settings/wifi/AccessPointState.java @@ -375,12 +375,22 @@ public final class AccessPointState implements Comparable, Par /* 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 @@ public final class AccessPointState implements Comparable, Par 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]); From c78e0b01e6c4da1d8fecd5b6017a76f159066ea1 Mon Sep 17 00:00:00 2001 From: Chung-yih Wang Date: Thu, 23 Jul 2009 01:56:57 +0800 Subject: [PATCH 02/14] Fix the broken build --- src/com/android/settings/wifi/AccessPointDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/settings/wifi/AccessPointDialog.java b/src/com/android/settings/wifi/AccessPointDialog.java index 3e44961b624..41520563908 100644 --- a/src/com/android/settings/wifi/AccessPointDialog.java +++ b/src/com/android/settings/wifi/AccessPointDialog.java @@ -672,7 +672,7 @@ public class AccessPointDialog extends AlertDialog implements DialogInterface.On mState.setSecurity(AccessPointState.IEEE8021X); } mState.setEap(mEapSpinner.getSelectedItemPosition()); - mState.setPhase2(mPhase2Spinner.getSelectedItem()); + mState.setPhase2((String)mPhase2Spinner.getSelectedItem()); break; } default: From d8858c3ee12bfdde1bde60dfe7cdf8bc497cf254 Mon Sep 17 00:00:00 2001 From: Hung-ying Tyan Date: Wed, 22 Jul 2009 21:31:28 +0800 Subject: [PATCH 03/14] Improve UX of adding credential... with more toast messages and fix dialog handling when needs another dialog to initialize or enable the credential storage. --- res/values/strings.xml | 3 + .../android/settings/SecuritySettings.java | 117 ++++++++++++------ 2 files changed, 84 insertions(+), 36 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index c8919799cea..a92e3abaecf 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1991,6 +1991,9 @@ found in the list of installed applications. Please enter a name. Please enter a name that contains only letters and numbers. Unable to save the certificate. Click OK to retry. + Unable to save the certificate. The credential storage is not enabled or properly initialized. + The certificate is not saved. + The credential storage is erased. Credential storage is enabled. diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java index 63d88d378b4..5a5804e6c46 100644 --- a/src/com/android/settings/SecuritySettings.java +++ b/src/com/android/settings/SecuritySettings.java @@ -42,6 +42,7 @@ import android.security.Keystore; 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 @@ public class SecuritySettings extends PreferenceActivity implements 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 @@ public class SecuritySettings extends PreferenceActivity implements 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 class SecuritySettings extends PreferenceActivity implements 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 @@ public class SecuritySettings extends PreferenceActivity implements 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 class SecuritySettings extends PreferenceActivity implements 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 @@ public class SecuritySettings extends PreferenceActivity implements 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 @@ public class SecuritySettings extends PreferenceActivity implements pref.setOnPreferenceClickListener( new Preference.OnPreferenceClickListener() { public boolean onPreferenceClick(Preference pref) { - showDialog(CSTOR_RESET_DIALOG); + showCstorDialog(CSTOR_RESET_DIALOG); return true; } }); @@ -807,7 +851,6 @@ public class SecuritySettings extends PreferenceActivity implements } private Dialog createUnlockDialog() { - mDialogId = CSTOR_UNLOCK_DIALOG; mView = View.inflate(SecuritySettings.this, R.layout.cstor_unlock_dialog_view, null); hideError(); @@ -830,7 +873,6 @@ public class SecuritySettings extends PreferenceActivity implements } 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 @@ public class SecuritySettings extends PreferenceActivity implements } 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 @@ public class SecuritySettings extends PreferenceActivity implements } 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 @@ public class SecuritySettings extends PreferenceActivity implements private String mDescription; private String mName; private String mPassword; + private View mView; CstorAddCredentialHelper(Intent intent) { parse(intent); @@ -958,7 +1003,7 @@ public class SecuritySettings extends PreferenceActivity implements 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; From c25f8955bee14a26520457fca2ab79c013f6196e Mon Sep 17 00:00:00 2001 From: Amith Yamasani Date: Wed, 22 Jul 2009 16:19:18 -0700 Subject: [PATCH 04/14] Link to bluetooth settings. WiFi -> Wi-Fi --- res/values/strings.xml | 2 +- src/com/android/settings/fuelgauge/PowerUsageSummary.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index a92e3abaecf..f63a0a6e513 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1737,7 +1737,7 @@ found in the list of installed applications. Battery used by Wi-Fi - Turn off WiFi when not using it or where it is not available + Turn off Wi-Fi when not using it or where it is not available Battery used by bluetooth diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java index 3dc991439f7..10c9a43054e 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java +++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java @@ -463,7 +463,7 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable { 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); } From 38a9daffa5d3c5cd478bf5a81334cdbc02d4727c Mon Sep 17 00:00:00 2001 From: Hung-ying Tyan Date: Thu, 23 Jul 2009 07:36:23 +0800 Subject: [PATCH 05/14] Fix secret EditText display and other fixes. + Now it shows shadowed "(unchanged)" (as in wifi settings) and "(not set)" instead of two dots. Patch Set 2: + Show cancellation confirmation dialog only when there's change in profile. Patch Set 3: + Re-enable profile preferences when the reconnect dialog is cancelled. --- res/values/strings.xml | 6 +- src/com/android/settings/vpn/L2tpEditor.java | 43 ++++----- .../settings/vpn/L2tpIpsecPskEditor.java | 33 +++---- src/com/android/settings/vpn/VpnEditor.java | 27 +++++- .../settings/vpn/VpnProfileEditor.java | 93 +++++++++++++------ src/com/android/settings/vpn/VpnSettings.java | 75 ++++++++------- 6 files changed, 171 insertions(+), 106 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index f63a0a6e513..b96f3ee1479 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1829,7 +1829,7 @@ found in the list of installed applications. Yes No Back - No, it's a mistake + No Save Cancel @@ -1935,6 +1935,10 @@ found in the list of installed applications. VPN settings Set up & manage Virtual Private Networks (VPNs) + + (unchanged) + + (not set) Credential storage diff --git a/src/com/android/settings/vpn/L2tpEditor.java b/src/com/android/settings/vpn/L2tpEditor.java index 643ba3b61f2..29036f23b88 100644 --- a/src/com/android/settings/vpn/L2tpEditor.java +++ b/src/com/android/settings/vpn/L2tpEditor.java @@ -30,9 +30,7 @@ import android.preference.PreferenceGroup; */ 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 @@ class L2tpEditor extends VpnProfileEditor { 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 @@ class L2tpEditor extends VpnProfileEditor { 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 @@ class L2tpEditor extends VpnProfileEditor { 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 @@ class L2tpEditor extends VpnProfileEditor { } 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 11590daaa5b..1277c282b6e 100644 --- a/src/com/android/settings/vpn/L2tpIpsecPskEditor.java +++ b/src/com/android/settings/vpn/L2tpIpsecPskEditor.java @@ -29,6 +29,7 @@ import android.preference.PreferenceGroup; */ class L2tpIpsecPskEditor extends L2tpEditor { private EditTextPreference mPresharedKey; + private SecretHandler mPskHandler; public L2tpIpsecPskEditor(L2tpIpsecPskProfile p) { super(p); @@ -45,27 +46,23 @@ class L2tpIpsecPskEditor extends L2tpEditor { 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/VpnEditor.java b/src/com/android/settings/vpn/VpnEditor.java index b4dc2b688a8..162c129956e 100644 --- a/src/com/android/settings/vpn/VpnEditor.java +++ b/src/com/android/settings/vpn/VpnEditor.java @@ -27,6 +27,7 @@ import android.net.vpn.L2tpProfile; 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 +48,7 @@ public class VpnEditor extends PreferenceActivity { private VpnProfileEditor mProfileEditor; private boolean mAddingProfile; + private byte[] mOriginalProfileData; @Override public void onCreate(Bundle savedInstanceState) { @@ -61,6 +63,10 @@ public class VpnEditor extends PreferenceActivity { addPreferencesFromResource(R.xml.vpn_edit); initViewFor(p); + + Parcel parcel = Parcel.obtain(); + p.writeToParcel(parcel, 0); + mOriginalProfileData = parcel.marshall(); } @Override @@ -90,7 +96,11 @@ public class VpnEditor extends PreferenceActivity { return true; case MENU_CANCEL: - showCancellationConfirmDialog(); + if (profileChanged()) { + showCancellationConfirmDialog(); + } else { + finish(); + } return true; } return super.onOptionsItemSelected(item); @@ -131,7 +141,7 @@ public class VpnEditor extends PreferenceActivity { return false; } - setResult(getProfile()); + if (profileChanged()) setResult(getProfile()); return true; } @@ -177,4 +187,17 @@ public class VpnEditor extends PreferenceActivity { 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 bf2e57dba8a..bf51749d89c 100644 --- a/src/com/android/settings/vpn/VpnProfileEditor.java +++ b/src/com/android/settings/vpn/VpnProfileEditor.java @@ -33,9 +33,6 @@ import android.text.method.PasswordTransformationMethod; * 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; @@ -147,22 +144,6 @@ class VpnProfileEditor { 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 +172,6 @@ class VpnProfileEditor { : 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 +187,69 @@ class VpnProfileEditor { 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 f0e71f782eb..137e42049ca 100644 --- a/src/com/android/settings/vpn/VpnSettings.java +++ b/src/com/android/settings/vpn/VpnSettings.java @@ -18,7 +18,6 @@ package com.android.settings.vpn; 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; @@ -197,7 +196,7 @@ public class VpnSettings extends PreferenceActivity implements return createConnectDialog(); case DIALOG_RECONNECT: - return createReconnectDialogBuilder().create(); + return createReconnectDialog(); case DIALOG_AUTH_ERROR: return createAuthErrorDialog(); @@ -219,14 +218,44 @@ public class VpnSettings extends PreferenceActivity implements 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 createUnknownServerDialog() { + return createCommonDialogBuilder() + .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(); + } + + 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 +275,6 @@ public class VpnSettings extends PreferenceActivity implements }); } - 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 +422,7 @@ public class VpnSettings extends PreferenceActivity implements } } else { removeDialog(DIALOG_CONNECT); + onIdle(); } } @@ -707,6 +717,7 @@ public class VpnSettings extends PreferenceActivity implements } private void onIdle() { + Log.d(TAG, " onIdle()"); mActiveProfile = null; mConnectingActor = null; enableProfilePreferences(); @@ -853,28 +864,28 @@ public class VpnSettings extends PreferenceActivity implements 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); } From 6120ddd7863d1240a535bc111b62e068c8736058 Mon Sep 17 00:00:00 2001 From: Hung-ying Tyan Date: Sun, 26 Jul 2009 00:05:21 +0800 Subject: [PATCH 06/14] Capitalize the first letter of a VPN name. --- src/com/android/settings/vpn/VpnProfileEditor.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/com/android/settings/vpn/VpnProfileEditor.java b/src/com/android/settings/vpn/VpnProfileEditor.java index bf51749d89c..8dc36431769 100644 --- a/src/com/android/settings/vpn/VpnProfileEditor.java +++ b/src/com/android/settings/vpn/VpnProfileEditor.java @@ -66,6 +66,8 @@ class VpnProfileEditor { } }); setName(getProfile().getName()); + mName.getEditText().setInputType(InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES); subpanel.addPreference(createServerNamePreference(c)); loadExtraPreferencesTo(subpanel); From c09326318334904f65d63c485c6fa1a7cb146bd8 Mon Sep 17 00:00:00 2001 From: Suchi Amalapurapu Date: Tue, 28 Jul 2009 10:28:23 -0700 Subject: [PATCH 07/14] Remove debug statement --- src/com/android/settings/ManageApplications.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/ManageApplications.java b/src/com/android/settings/ManageApplications.java index 642a48ef929..7da4eae7c8e 100644 --- a/src/com/android/settings/ManageApplications.java +++ b/src/com/android/settings/ManageApplications.java @@ -1300,7 +1300,7 @@ public class ManageApplications extends ListActivity implements 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])) { @@ -1318,7 +1318,7 @@ public class ManageApplications extends ListActivity implements } AppInfo entry = mCache.getEntry(pkgName); if (entry == null) { - Log.w(TAG, "Entry for package:"+pkgName+"doesnt exist in map"); + if (localLOGV) Log.w(TAG, "Entry for package:"+pkgName+"doesnt exist in map"); return; } // Copy the index into the newly updated entry From c157aadf5682e417ace8e4cf3fba498e6953cad3 Mon Sep 17 00:00:00 2001 From: Hung-ying Tyan Date: Wed, 29 Jul 2009 12:05:27 +0800 Subject: [PATCH 08/14] Add error dialog when secrets are missing. --- res/values/strings.xml | 1 + src/com/android/settings/vpn/VpnSettings.java | 79 +++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/res/values/strings.xml b/res/values/strings.xml index b96f3ee1479..108bd5f9aed 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1848,6 +1848,7 @@ found in the list of installed applications. Are you sure you want to discard the changes made to this profile? Unable to connect to the network. Do you want to try again? Server name cannot be resolved. Do you want to check your server name setting? + One or more secrets are missing in this VPN configuration. Do you want to check your secret setting? The username or password you entered is incorrect. Do you want to try again? diff --git a/src/com/android/settings/vpn/VpnSettings.java b/src/com/android/settings/vpn/VpnSettings.java index 137e42049ca..0dc171971e0 100644 --- a/src/com/android/settings/vpn/VpnSettings.java +++ b/src/com/android/settings/vpn/VpnSettings.java @@ -28,6 +28,7 @@ import android.content.DialogInterface; 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; @@ -46,6 +47,7 @@ import android.preference.PreferenceCategory; 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; @@ -106,6 +108,7 @@ public class VpnSettings extends PreferenceActivity implements 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 NO_ERROR = 0; @@ -204,6 +207,9 @@ public class VpnSettings extends PreferenceActivity implements case DIALOG_UNKNOWN_SERVER: return createUnknownServerDialog(); + case DIALOG_SECRET_NOT_SET: + return createSecretNotSetDialog(); + default: return super.onCreateDialog(id); } @@ -252,6 +258,19 @@ public class VpnSettings extends PreferenceActivity implements .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 createCommonDialogBuilder() { return new AlertDialog.Builder(this) .setTitle(android.R.string.dialog_alert_title) @@ -639,6 +658,7 @@ public class VpnSettings extends PreferenceActivity implements mConnectingActor = getActor(p); mActiveProfile = p; + if (!checkSecrets(p)) return; if (mConnectingActor.isConnectDialogNeeded()) { showDialog(DIALOG_CONNECT); } else { @@ -858,6 +878,65 @@ public class VpnSettings extends PreferenceActivity implements return NAMESPACE_VPN + "_" + keyName; } + private boolean checkSecrets(VpnProfile p) { + Keystore ks = Keystore.getInstance(); + HashSet secretSet = new HashSet(); + 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()) { From 387dc0ca9c990511a71bd71c77d34ee33bc3f1aa Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Tue, 28 Jul 2009 15:13:35 -0700 Subject: [PATCH 09/14] Fix bug 2017664. Use the new constant names in TextToSpeech. --- src/com/android/settings/TextToSpeechSettings.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/com/android/settings/TextToSpeechSettings.java b/src/com/android/settings/TextToSpeechSettings.java index 789368a0b3f..e17a6d6ec85 100644 --- a/src/com/android/settings/TextToSpeechSettings.java +++ b/src/com/android/settings/TextToSpeechSettings.java @@ -59,7 +59,7 @@ public class TextToSpeechSettings extends PreferenceActivity implements 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 @@ public class TextToSpeechSettings extends PreferenceActivity implements 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 @@ public class TextToSpeechSettings extends PreferenceActivity implements 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 @@ public class TextToSpeechSettings extends PreferenceActivity implements 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 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 @@ public class TextToSpeechSettings extends PreferenceActivity implements 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 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 @@ public class TextToSpeechSettings extends PreferenceActivity implements * 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 @@ public class TextToSpeechSettings extends PreferenceActivity implements // Play example if (mTts != null) { mTts.speak(getResources().getString(R.string.tts_demo), - TextToSpeech.TTS_QUEUE_FLUSH, null); + TextToSpeech.QUEUE_FLUSH, null); } return true; } From 489eaccb98c726408d0024376f637b81d8b0314b Mon Sep 17 00:00:00 2001 From: Suchi Amalapurapu Date: Wed, 29 Jul 2009 10:44:21 -0700 Subject: [PATCH 10/14] Fix duplicate entries being added when application is in active use --- .../android/settings/ManageApplications.java | 74 +++++++++---------- 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/src/com/android/settings/ManageApplications.java b/src/com/android/settings/ManageApplications.java index 7da4eae7c8e..0d4895e8c85 100644 --- a/src/com/android/settings/ManageApplications.java +++ b/src/com/android/settings/ManageApplications.java @@ -355,7 +355,7 @@ public class ManageApplications extends ListActivity implements 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 @@ public class ManageApplications extends ListActivity implements 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 @@ public class ManageApplications extends ListActivity implements } return mSizeComparator; } - + public void bulkUpdateIcons(Map icons) { if (icons == null) { return; @@ -1162,19 +1167,6 @@ public class ManageApplications extends ListActivity implements } } - 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 class ManageApplications extends ListActivity implements } } + 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++) { @@ -1311,21 +1321,6 @@ public class ManageApplications extends ListActivity implements notifyDataSetChanged(); } } - - public void updateAppSize(String pkgName, long size, String formattedSize) { - if(pkgName == null) { - return; - } - AppInfo entry = mCache.getEntry(pkgName); - if (entry == null) { - if (localLOGV) 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 @@ public class ManageApplications extends ListActivity implements * 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 @@ public class ManageApplications extends ListActivity implements } 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 @@ public class ManageApplications extends ListActivity implements 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); } } From 03f46bf48e41b0b2e43fd4c2d6dc0eb213d55fdb Mon Sep 17 00:00:00 2001 From: Amith Yamasani Date: Wed, 29 Jul 2009 21:03:02 -0700 Subject: [PATCH 11/14] Remove link to Contributors. Fix for #2022496 --- res/xml/device_info_settings.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/res/xml/device_info_settings.xml b/res/xml/device_info_settings.xml index 80370e2e7ff..56810b47c4f 100644 --- a/res/xml/device_info_settings.xml +++ b/res/xml/device_info_settings.xml @@ -76,12 +76,13 @@ + Date: Thu, 30 Jul 2009 19:54:13 +0800 Subject: [PATCH 12/14] Add encryption option to PPTP UI. Also add new error dialogs for L2TP challenge error and remote server hanging up error. --- res/values/strings.xml | 4 + src/com/android/settings/vpn/PptpEditor.java | 75 +++++++++++++++++++ src/com/android/settings/vpn/VpnEditor.java | 4 + src/com/android/settings/vpn/VpnSettings.java | 51 ++++++++++--- 4 files changed, 125 insertions(+), 9 deletions(-) create mode 100644 src/com/android/settings/vpn/PptpEditor.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 108bd5f9aed..5d89800df50 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1848,8 +1848,10 @@ found in the list of installed applications. Are you sure you want to discard the changes made to this profile? Unable to connect to the network. Do you want to try again? Server name cannot be resolved. Do you want to check your server name setting? + Challenge error. Do you want to check your secret setting? One or more secrets are missing in this VPN configuration. Do you want to check your secret setting? The username or password you entered is incorrect. Do you want to try again? + Server hung up. The username or password you entered could be incorrect. Do you want to try again? Add VPN @@ -1895,6 +1897,8 @@ found in the list of installed applications. L2TP secret an L2TP secret + encryption + PPTP encryption Set IPSec pre-shared key diff --git a/src/com/android/settings/vpn/PptpEditor.java b/src/com/android/settings/vpn/PptpEditor.java new file mode 100644 index 00000000000..fafe6a76bb7 --- /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 162c129956e..497f4bfa42b 100644 --- a/src/com/android/settings/vpn/VpnEditor.java +++ b/src/com/android/settings/vpn/VpnEditor.java @@ -24,6 +24,7 @@ import android.content.Intent; 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; @@ -162,6 +163,9 @@ public class VpnEditor extends PreferenceActivity { case L2TP: return new L2tpEditor((L2tpProfile) p); + case PPTP: + return new PptpEditor((PptpProfile) p); + default: return new VpnProfileEditor(p); } diff --git a/src/com/android/settings/vpn/VpnSettings.java b/src/com/android/settings/vpn/VpnSettings.java index 0dc171971e0..4dda152793f 100644 --- a/src/com/android/settings/vpn/VpnSettings.java +++ b/src/com/android/settings/vpn/VpnSettings.java @@ -109,6 +109,8 @@ public class VpnSettings extends PreferenceActivity implements 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; @@ -204,6 +206,12 @@ public class VpnSettings extends PreferenceActivity implements 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(); @@ -244,17 +252,22 @@ public class VpnSettings extends PreferenceActivity implements .setMessage(R.string.vpn_auth_error_dialog_msg) .create(); } - private Dialog createUnknownServerDialog() { + + 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) - .setPositiveButton(R.string.vpn_yes_button, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int w) { - VpnProfile p = mConnectingActor.getProfile(); - onIdle(); - startVpnEditor(p); - } - }) .create(); } @@ -271,6 +284,18 @@ public class VpnSettings extends PreferenceActivity implements .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) @@ -723,6 +748,14 @@ public class VpnSettings extends PreferenceActivity implements 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; From c538b651a23287ab25584995c6c4b7a68ece027c Mon Sep 17 00:00:00 2001 From: Chung-yih Wang Date: Thu, 30 Jul 2009 19:04:31 +0800 Subject: [PATCH 13/14] Fix some UI flow issues when the keystore is locked in WiFi setting. To make it more user friendly, we need to continue on what users intend to do after unlocking the credential storage. --- .../settings/wifi/AccessPointDialog.java | 43 ++++++++++++------- .../android/settings/wifi/WifiSettings.java | 23 +++++++++- 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/src/com/android/settings/wifi/AccessPointDialog.java b/src/com/android/settings/wifi/AccessPointDialog.java index 41520563908..5851a184d01 100644 --- a/src/com/android/settings/wifi/AccessPointDialog.java +++ b/src/com/android/settings/wifi/AccessPointDialog.java @@ -134,7 +134,7 @@ public class AccessPointDialog extends AlertDialog implements DialogInterface.On private Spinner mSecuritySpinner; private Spinner mWepTypeSpinner; private CertTool mCertTool; - + public AccessPointDialog(Context context, WifiLayer wifiLayer) { super(context); @@ -217,6 +217,14 @@ public class AccessPointDialog extends AlertDialog implements DialogInterface.On 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(); @@ -318,19 +326,26 @@ public class AccessPointDialog extends AlertDialog implements DialogInterface.On if (mMode == MODE_CONFIGURE || (mState.isEnterprise() && !mState.configured)) { setEnterpriseFields(view); - 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))); + 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()); } @@ -788,13 +803,9 @@ public class AccessPointDialog extends AlertDialog implements DialogInterface.On 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/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java index a0155343a20..f18992a578a 100644 --- a/src/com/android/settings/wifi/WifiSettings.java +++ b/src/com/android/settings/wifi/WifiSettings.java @@ -86,6 +86,9 @@ public class WifiSettings extends PreferenceActivity implements WifiLayer.Callba private Preference mAddOtherNetwork; private WeakHashMap mAps; + + private AccessPointState mResumeState = null; + private int mResumeMode; //============================ // Wifi member variables @@ -152,8 +155,22 @@ public class WifiSettings extends PreferenceActivity implements WifiLayer.Callba 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 class WifiSettings extends PreferenceActivity implements WifiLayer.Callba public void onDismiss(DialogInterface dialog) { if (dialog == mDialog) { mDialog = null; + mResumeMode = -1; } } @@ -350,6 +368,7 @@ public class WifiSettings extends PreferenceActivity implements WifiLayer.Callba 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 @@ public class WifiSettings extends PreferenceActivity implements WifiLayer.Callba Keystore.getInstance().getState() != Keystore.UNLOCKED) { startActivity(new Intent( SecuritySettings.ACTION_UNLOCK_CREDENTIAL_STORAGE)); + mResumeState = state; + mResumeMode = mode; return; } AccessPointDialog dialog = new AccessPointDialog(this, mWifiLayer); From ed47f1e497abf5ad31b1c7035ae04478e9932986 Mon Sep 17 00:00:00 2001 From: John Wang Date: Thu, 30 Jul 2009 18:22:58 -0700 Subject: [PATCH 14/14] Fix the NullPointerException in Status Info. Fix bug 1964037 Phone states activity fail. It only happens in Zaku build. Zaku build overlay the device_info_status.xml under vendor/docomo and don't have CDMA related preference. Status.java will hit the NullPointerException when trying to remove the non-exist preferences. modified: src/com/android/settings/deviceinfo/Status.java --- .../android/settings/deviceinfo/Status.java | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/com/android/settings/deviceinfo/Status.java b/src/com/android/settings/deviceinfo/Status.java index a165754104b..7d22d913a85 100644 --- a/src/com/android/settings/deviceinfo/Status.java +++ b/src/com/android/settings/deviceinfo/Status.java @@ -162,6 +162,7 @@ public class Status extends PreferenceActivity { @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); + Preference removablePref; mHandler = new MyHandler(this); @@ -188,8 +189,15 @@ public class Status extends PreferenceActivity { 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 @@ public class Status extends PreferenceActivity { .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());