Fix dialog handling.

* Changes
  + VpnSettings:
    + Add reconnect dialog to showDialog() framework for handling screen
      rotation.
    + Dismiss other alert dialogs in onDestroy()
    + Remove onPrepareDialog() from VpnSettings.
    + Remove updateConnectDialog() from VpnProfileActor.
    + Add authentication error dialog.
    + Add unknown server dialog.
  + SecuritySettings:
    + Make cstor dialogs cancelable.
    + Add cancelable listener.
  Patch Set 6:
  + VpnSettings:
    + Disable preferences when connecting/disconnecting.
    + Fix state broadcast when binding a VpnService goes wrong.
This commit is contained in:
Hung-ying Tyan
2009-07-11 22:28:00 +08:00
parent a5cead2cf7
commit 1ddccd07f7
5 changed files with 166 additions and 111 deletions

View File

@@ -1850,6 +1850,8 @@ found in the list of installed applications.</string>
<string name="vpn_confirm_add_profile_cancellation">Are you sure you don\'t want to create this profile?</string> <string name="vpn_confirm_add_profile_cancellation">Are you sure you don\'t want to create this profile?</string>
<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_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_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_auth_error_dialog_msg">The username or password you entered is incorrect. Do you want to try again?</string>
<!-- VPN type selection activity title --> <!-- VPN type selection activity title -->
<string name="vpn_type_title">Add VPN</string> <string name="vpn_type_title">Add VPN</string>
@@ -1870,8 +1872,6 @@ found in the list of installed applications.</string>
<!-- Preference summary text when VPN is not connected --> <!-- Preference summary text when VPN is not connected -->
<string name="vpn_connect_hint">Connect to network</string> <string name="vpn_connect_hint">Connect to network</string>
<string name="vpn_default_profile_name">nowhere</string>
<!-- Name of a VPN profile --> <!-- Name of a VPN profile -->
<string name="vpn_name">VPN name</string> <string name="vpn_name">VPN name</string>
<string name="vpn_a_name">a VPN name</string> <string name="vpn_a_name">a VPN name</string>

View File

@@ -442,8 +442,9 @@ public class SecuritySettings extends PreferenceActivity implements
} }
} }
private class CstorHelper implements private class CstorHelper implements DialogInterface.OnClickListener,
DialogInterface.OnClickListener, DialogInterface.OnDismissListener { DialogInterface.OnDismissListener,
DialogInterface.OnCancelListener {
private Keystore mKeystore = Keystore.getInstance(); private Keystore mKeystore = Keystore.getInstance();
private View mView; private View mView;
private int mDialogId; private int mDialogId;
@@ -523,14 +524,18 @@ public class SecuritySettings extends PreferenceActivity implements
.show(); .show();
} }
public void onCancel(DialogInterface dialog) {
if (mCstorAddCredentialHelper != null) {
// release the object here so that it doesn't get triggerred in
// onDismiss()
mCstorAddCredentialHelper = null;
finish();
}
}
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_NEGATIVE) { if (which == DialogInterface.BUTTON_NEGATIVE) {
if (mCstorAddCredentialHelper != null) { onCancel(dialog);
// release the object here so that it doesn't get triggerred in
// onDismiss()
mCstorAddCredentialHelper = null;
finish();
}
return; return;
} }
@@ -797,7 +802,7 @@ public class SecuritySettings extends PreferenceActivity implements
.setTitle(R.string.cstor_access_dialog_title) .setTitle(R.string.cstor_access_dialog_title)
.setPositiveButton(android.R.string.ok, this) .setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, this) .setNegativeButton(android.R.string.cancel, this)
.setCancelable(false) .setOnCancelListener(this)
.create(); .create();
d.setOnDismissListener(this); d.setOnDismissListener(this);
return d; return d;
@@ -837,7 +842,7 @@ public class SecuritySettings extends PreferenceActivity implements
.setTitle(R.string.cstor_set_passwd_dialog_title) .setTitle(R.string.cstor_set_passwd_dialog_title)
.setPositiveButton(android.R.string.ok, this) .setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, this) .setNegativeButton(android.R.string.cancel, this)
.setCancelable(false) .setOnCancelListener(this)
.create(); .create();
d.setOnDismissListener(this); d.setOnDismissListener(this);
return d; return d;
@@ -872,7 +877,7 @@ public class SecuritySettings extends PreferenceActivity implements
.setTitle(R.string.cstor_name_credential_dialog_title) .setTitle(R.string.cstor_name_credential_dialog_title)
.setPositiveButton(android.R.string.ok, this) .setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, this) .setNegativeButton(android.R.string.cancel, this)
.setCancelable(false) .setOnCancelListener(this)
.create(); .create();
d.setOnDismissListener(this); d.setOnDismissListener(this);
return d; return d;

View File

@@ -99,14 +99,18 @@ public class AuthenticationActor implements VpnProfileActor {
//@Override //@Override
public View createConnectView() { public View createConnectView() {
return View.inflate(mContext, R.layout.vpn_connect_dialog_view, null); View v = View.inflate(mContext, R.layout.vpn_connect_dialog_view, null);
} TextView usernameView = (TextView) v.findViewById(R.id.username_value);
TextView passwordView = (TextView) v.findViewById(R.id.password_value);
CheckBox saveUsername = (CheckBox) v.findViewById(R.id.save_username);
//@Override
public void updateConnectView(Dialog d) {
String username = mProfile.getSavedUsername(); String username = mProfile.getSavedUsername();
if (username == null) username = ""; if (!TextUtils.isEmpty(username)) {
updateConnectView(d, username, "", !TextUtils.isEmpty(username)); usernameView.setText(username);
saveUsername.setChecked(true);
passwordView.requestFocus();
}
return v;
} }
protected Context getContext() { protected Context getContext() {
@@ -118,22 +122,20 @@ public class AuthenticationActor implements VpnProfileActor {
ServiceConnection c = new ServiceConnection() { ServiceConnection c = new ServiceConnection() {
public void onServiceConnected(ComponentName className, public void onServiceConnected(ComponentName className,
IBinder service) { IBinder service) {
boolean success = false;
try { try {
success = IVpnService.Stub.asInterface(service) boolean success = IVpnService.Stub.asInterface(service)
.connect(mProfile, username, password); .connect(mProfile, username, password);
} catch (Throwable e) {
Log.e(TAG, "connect()", e);
checkStatus();
} finally {
mContext.unbindService(this);
if (!success) { if (!success) {
Log.d(TAG, "~~~~~~ connect() failed!"); Log.d(TAG, "~~~~~~ connect() failed!");
broadcastConnectivity(VpnState.IDLE);
} else { } else {
Log.d(TAG, "~~~~~~ connect() succeeded!"); Log.d(TAG, "~~~~~~ connect() succeeded!");
} }
} catch (Throwable e) {
Log.e(TAG, "connect()", e);
broadcastConnectivity(VpnState.IDLE,
VpnManager.VPN_ERROR_CONNECTION_FAILED);
} finally {
mContext.unbindService(this);
} }
} }
@@ -141,7 +143,10 @@ public class AuthenticationActor implements VpnProfileActor {
checkStatus(); checkStatus();
} }
}; };
if (!bindService(c)) broadcastConnectivity(VpnState.IDLE); if (!bindService(c)) {
broadcastConnectivity(VpnState.IDLE,
VpnManager.VPN_ERROR_CONNECTION_FAILED);
}
} }
//@Override //@Override
@@ -156,7 +161,6 @@ public class AuthenticationActor implements VpnProfileActor {
checkStatus(); checkStatus();
} finally { } finally {
mContext.unbindService(this); mContext.unbindService(this);
broadcastConnectivity(VpnState.IDLE);
} }
} }
@@ -164,7 +168,9 @@ public class AuthenticationActor implements VpnProfileActor {
checkStatus(); checkStatus();
} }
}; };
bindService(c); if (!bindService(c)) {
checkStatus();
}
} }
//@Override //@Override
@@ -174,8 +180,9 @@ public class AuthenticationActor implements VpnProfileActor {
IBinder service) { IBinder service) {
try { try {
IVpnService.Stub.asInterface(service).checkStatus(mProfile); IVpnService.Stub.asInterface(service).checkStatus(mProfile);
} catch (Throwable e) { } catch (RemoteException e) {
Log.e(TAG, "checkStatus()", e); Log.e(TAG, "checkStatus()", e);
broadcastConnectivity(VpnState.IDLE);
} finally { } finally {
notify(); notify();
} }
@@ -196,21 +203,14 @@ public class AuthenticationActor implements VpnProfileActor {
return mVpnManager.bindVpnService(c); return mVpnManager.bindVpnService(c);
} }
private void updateConnectView(Dialog d, String username,
String password, boolean toSaveUsername) {
TextView usernameView = (TextView) d.findViewById(R.id.username_value);
TextView passwordView = (TextView) d.findViewById(R.id.password_value);
CheckBox saveUsername = (CheckBox) d.findViewById(R.id.save_username);
usernameView.setText(username);
passwordView.setText(password);
saveUsername.setChecked(toSaveUsername);
if (toSaveUsername) passwordView.requestFocus();
}
private void broadcastConnectivity(VpnState s) { private void broadcastConnectivity(VpnState s) {
mVpnManager.broadcastConnectivity(mProfile.getName(), s); mVpnManager.broadcastConnectivity(mProfile.getName(), s);
} }
private void broadcastConnectivity(VpnState s, int errorCode) {
mVpnManager.broadcastConnectivity(mProfile.getName(), s, errorCode);
}
private void wait(Object o, int ms) { private void wait(Object o, int ms) {
synchronized (o) { synchronized (o) {
try { try {

View File

@@ -37,12 +37,6 @@ public interface VpnProfileActor {
*/ */
View createConnectView(); View createConnectView();
/**
* Updates the view in the connect dialog.
* @param dialog the recycled connect dialog.
*/
void updateConnectView(Dialog dialog);
/** /**
* Validates the inputs in the dialog. * Validates the inputs in the dialog.
* @param dialog the connect dialog * @param dialog the connect dialog

View File

@@ -99,7 +99,12 @@ public class VpnSettings extends PreferenceActivity implements
private static final int CONNECT_BUTTON = DialogInterface.BUTTON1; private static final int CONNECT_BUTTON = DialogInterface.BUTTON1;
private static final int OK_BUTTON = DialogInterface.BUTTON1; private static final int OK_BUTTON = DialogInterface.BUTTON1;
private static final int DIALOG_CONNECT = 0; private static final int DIALOG_CONNECT = 1;
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 NO_ERROR = 0;
private PreferenceScreen mAddVpn; private PreferenceScreen mAddVpn;
private PreferenceCategory mVpnListContainer; private PreferenceCategory mVpnListContainer;
@@ -115,7 +120,6 @@ public class VpnSettings extends PreferenceActivity implements
// actor engaged in connecting // actor engaged in connecting
private VpnProfileActor mConnectingActor; private VpnProfileActor mConnectingActor;
private boolean mStateSaved = false;
// states saved for unlocking keystore // states saved for unlocking keystore
private Runnable mUnlockAction; private Runnable mUnlockAction;
@@ -125,7 +129,9 @@ public class VpnSettings extends PreferenceActivity implements
private ConnectivityReceiver mConnectivityReceiver = private ConnectivityReceiver mConnectivityReceiver =
new ConnectivityReceiver(); new ConnectivityReceiver();
private boolean mConnectingError; private int mConnectingErrorCode = NO_ERROR;
private Dialog mShowingDialog;
private StatusChecker mStatusChecker = new StatusChecker(); private StatusChecker mStatusChecker = new StatusChecker();
@@ -156,11 +162,10 @@ public class VpnSettings extends PreferenceActivity implements
String profileName = (savedInstanceState == null) String profileName = (savedInstanceState == null)
? null ? null
: savedInstanceState.getString(STATE_ACTIVE_ACTOR); : savedInstanceState.getString(STATE_ACTIVE_ACTOR);
mStateSaved = !TextUtils.isEmpty(profileName);
retrieveVpnListFromStorage(); retrieveVpnListFromStorage();
if (mStateSaved) { if (!TextUtils.isEmpty(profileName)) {
mConnectingActor = mActiveProfile = mVpnPreferenceMap.get(profileName).mProfile;
getActor(mVpnPreferenceMap.get(profileName).mProfile); mConnectingActor = getActor(mActiveProfile);
} else { } else {
checkVpnConnectionStatusInBackground(); checkVpnConnectionStatusInBackground();
} }
@@ -188,6 +193,7 @@ public class VpnSettings extends PreferenceActivity implements
protected synchronized void onSaveInstanceState(Bundle outState) { protected synchronized void onSaveInstanceState(Bundle outState) {
if (mConnectingActor == null) return; if (mConnectingActor == null) return;
Log.d(TAG, " ~~~~~ save connecting actor");
outState.putString(STATE_ACTIVE_ACTOR, outState.putString(STATE_ACTIVE_ACTOR,
mConnectingActor.getProfile().getName()); mConnectingActor.getProfile().getName());
} }
@@ -197,6 +203,9 @@ public class VpnSettings extends PreferenceActivity implements
super.onDestroy(); super.onDestroy();
unregisterForContextMenu(getListView()); unregisterForContextMenu(getListView());
mVpnManager.unregisterConnectivityReceiver(mConnectivityReceiver); mVpnManager.unregisterConnectivityReceiver(mConnectivityReceiver);
if ((mShowingDialog != null) && mShowingDialog.isShowing()) {
mShowingDialog.dismiss();
}
} }
@Override @Override
@@ -205,39 +214,76 @@ public class VpnSettings extends PreferenceActivity implements
case DIALOG_CONNECT: case DIALOG_CONNECT:
return createConnectDialog(); return createConnectDialog();
case DIALOG_RECONNECT:
return createReconnectDialogBuilder().create();
case DIALOG_AUTH_ERROR:
return createAuthErrorDialog();
case DIALOG_UNKNOWN_SERVER:
return createUnknownServerDialog();
default: default:
return null; return super.onCreateDialog(id);
} }
} }
private Dialog createConnectDialog() { private Dialog createConnectDialog() {
if (mConnectingActor == null) { return new AlertDialog.Builder(this)
Log.e(TAG, "no connecting actor to create the dialog");
return null;
}
String name = (mConnectingActor == null)
? getString(R.string.vpn_default_profile_name)
: mConnectingActor.getProfile().getName();
Dialog d = new AlertDialog.Builder(this)
.setView(mConnectingActor.createConnectView()) .setView(mConnectingActor.createConnectView())
.setTitle(String.format(getString(R.string.vpn_connect_to), .setTitle(String.format(getString(R.string.vpn_connect_to),
name)) mConnectingActor.getProfile().getName()))
.setPositiveButton(getString(R.string.vpn_connect_button), .setPositiveButton(getString(R.string.vpn_connect_button),
this) this)
.setNegativeButton(getString(android.R.string.cancel), .setNegativeButton(getString(android.R.string.cancel),
this) this)
.create(); .create();
return d;
} }
@Override private AlertDialog.Builder createReconnectDialogBuilder() {
protected void onPrepareDialog (int id, Dialog dialog) { return new AlertDialog.Builder(this)
if (mStateSaved) { .setTitle(android.R.string.dialog_alert_title)
mStateSaved = false; .setIcon(android.R.drawable.ic_dialog_alert)
super.onPrepareDialog(id, dialog); .setMessage(R.string.vpn_confirm_reconnect)
} else if (mConnectingActor != null) { .setPositiveButton(R.string.vpn_yes_button,
mConnectingActor.updateConnectView(dialog); new DialogInterface.OnClickListener() {
} public void onClick(DialogInterface dialog, int w) {
connectOrDisconnect(mConnectingActor.getProfile());
}
})
.setNegativeButton(R.string.vpn_no_button,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int w) {
onIdle();
}
})
.setOnCancelListener(new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
onIdle();
}
});
}
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();
mIndexOfEditedProfile =
mVpnProfileList.indexOf(p);
startVpnEditor(p);
}
})
.create();
} }
@Override @Override
@@ -252,8 +298,8 @@ public class VpnSettings extends PreferenceActivity implements
menu.setHeaderTitle(p.getName()); menu.setHeaderTitle(p.getName());
boolean isIdle = (state == VpnState.IDLE); boolean isIdle = (state == VpnState.IDLE);
boolean isNotConnect = boolean isNotConnect = (isIdle || (state == VpnState.DISCONNECTING)
(isIdle || (state == VpnState.DISCONNECTING)); || (state == VpnState.CANCELLED));
menu.add(0, CONTEXT_MENU_CONNECT_ID, 0, R.string.vpn_menu_connect) menu.add(0, CONTEXT_MENU_CONNECT_ID, 0, R.string.vpn_menu_connect)
.setEnabled(isIdle && (mActiveProfile == null)); .setEnabled(isIdle && (mActiveProfile == null));
menu.add(0, CONTEXT_MENU_DISCONNECT_ID, 0, menu.add(0, CONTEXT_MENU_DISCONNECT_ID, 0,
@@ -363,17 +409,18 @@ public class VpnSettings extends PreferenceActivity implements
// Called when the buttons on the connect dialog are clicked. // Called when the buttons on the connect dialog are clicked.
//@Override //@Override
public synchronized void onClick(DialogInterface dialog, int which) { public synchronized void onClick(DialogInterface dialog, int which) {
dismissDialog(DIALOG_CONNECT);
if (which == CONNECT_BUTTON) { if (which == CONNECT_BUTTON) {
Dialog d = (Dialog) dialog; Dialog d = (Dialog) dialog;
String error = mConnectingActor.validateInputs(d); String error = mConnectingActor.validateInputs(d);
if (error == null) { if (error == null) {
changeState(mConnectingActor.getProfile(), VpnState.CONNECTING); changeState(mConnectingActor.getProfile(), VpnState.CONNECTING);
mConnectingActor.connect(d); mConnectingActor.connect(d);
removeDialog(DIALOG_CONNECT);
return; return;
} else { } else {
dismissDialog(DIALOG_CONNECT);
// show error dialog // show error dialog
new AlertDialog.Builder(this) mShowingDialog = new AlertDialog.Builder(this)
.setTitle(android.R.string.dialog_alert_title) .setTitle(android.R.string.dialog_alert_title)
.setIcon(android.R.drawable.ic_dialog_alert) .setIcon(android.R.drawable.ic_dialog_alert)
.setMessage(String.format(getString( .setMessage(String.format(getString(
@@ -385,8 +432,11 @@ public class VpnSettings extends PreferenceActivity implements
showDialog(DIALOG_CONNECT); showDialog(DIALOG_CONNECT);
} }
}) })
.show(); .create();
mShowingDialog.show();
} }
} else {
removeDialog(DIALOG_CONNECT);
} }
} }
@@ -428,13 +478,14 @@ public class VpnSettings extends PreferenceActivity implements
} }
} }
}; };
new AlertDialog.Builder(this) mShowingDialog = new AlertDialog.Builder(this)
.setTitle(android.R.string.dialog_alert_title) .setTitle(android.R.string.dialog_alert_title)
.setIcon(android.R.drawable.ic_dialog_alert) .setIcon(android.R.drawable.ic_dialog_alert)
.setMessage(R.string.vpn_confirm_profile_deletion) .setMessage(R.string.vpn_confirm_profile_deletion)
.setPositiveButton(android.R.string.ok, onClickListener) .setPositiveButton(android.R.string.ok, onClickListener)
.setNegativeButton(R.string.vpn_no_button, onClickListener) .setNegativeButton(R.string.vpn_no_button, onClickListener)
.show(); .create();
mShowingDialog.show();
} }
// Randomly generates an ID for the profile. // Randomly generates an ID for the profile.
@@ -583,8 +634,8 @@ public class VpnSettings extends PreferenceActivity implements
} }
mConnectingActor = getActor(p); mConnectingActor = getActor(p);
mActiveProfile = p;
if (mConnectingActor.isConnectDialogNeeded()) { if (mConnectingActor.isConnectDialogNeeded()) {
removeDialog(DIALOG_CONNECT);
showDialog(DIALOG_CONNECT); showDialog(DIALOG_CONNECT);
} else { } else {
changeState(p, VpnState.CONNECTING); changeState(p, VpnState.CONNECTING);
@@ -605,8 +656,6 @@ public class VpnSettings extends PreferenceActivity implements
break; break;
case CONNECTED: case CONNECTED:
mConnectingError = false;
// pass through
case DISCONNECTING: case DISCONNECTING:
changeState(p, VpnState.DISCONNECTING); changeState(p, VpnState.DISCONNECTING);
getActor(p).disconnect(); getActor(p).disconnect();
@@ -625,16 +674,13 @@ public class VpnSettings extends PreferenceActivity implements
switch (state) { switch (state) {
case CONNECTED: case CONNECTED:
mConnectingActor = null; mConnectingActor = null;
// pass through
case CONNECTING:
mActiveProfile = p; mActiveProfile = p;
disableProfilePreferencesIfOneActive(); disableProfilePreferencesIfOneActive();
break; break;
case CONNECTING:
case DISCONNECTING: case DISCONNECTING:
if (oldState == VpnState.CONNECTING) { disableProfilePreferencesIfOneActive();
mConnectingError = true;
}
break; break;
case CANCELLED: case CANCELLED:
@@ -642,31 +688,34 @@ public class VpnSettings extends PreferenceActivity implements
break; break;
case IDLE: case IDLE:
assert(mActiveProfile != p); assert(mActiveProfile == p);
mActiveProfile = null;
mConnectingActor = null;
enableProfilePreferences();
if (oldState == VpnState.CONNECTING) mConnectingError = true; switch (mConnectingErrorCode) {
if (mConnectingError) showReconnectDialog(p); case NO_ERROR:
onIdle();
break;
case VpnManager.VPN_ERROR_AUTH:
showDialog(DIALOG_AUTH_ERROR);
break;
case VpnManager.VPN_ERROR_UNKNOWN_SERVER:
showDialog(DIALOG_UNKNOWN_SERVER);
break;
default:
showDialog(DIALOG_RECONNECT);
break;
}
mConnectingErrorCode = NO_ERROR;
break; break;
} }
} }
private void showReconnectDialog(final VpnProfile p) { private void onIdle() {
new AlertDialog.Builder(this) mActiveProfile = null;
.setTitle(android.R.string.dialog_alert_title) mConnectingActor = null;
.setIcon(android.R.drawable.ic_dialog_alert) enableProfilePreferences();
.setMessage(R.string.vpn_confirm_reconnect)
.setPositiveButton(R.string.vpn_yes_button,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int w) {
dialog.dismiss();
connectOrDisconnect(p);
}
})
.setNegativeButton(R.string.vpn_no_button, null)
.show();
} }
private void disableProfilePreferencesIfOneActive() { private void disableProfilePreferencesIfOneActive() {
@@ -674,6 +723,7 @@ public class VpnSettings extends PreferenceActivity implements
for (VpnProfile p : mVpnProfileList) { for (VpnProfile p : mVpnProfileList) {
switch (p.getState()) { switch (p.getState()) {
case CONNECTING:
case DISCONNECTING: case DISCONNECTING:
case IDLE: case IDLE:
mVpnPreferenceMap.get(p.getName()).setEnabled(false); mVpnPreferenceMap.get(p.getName()).setEnabled(false);
@@ -856,14 +906,20 @@ public class VpnSettings extends PreferenceActivity implements
VpnState s = (VpnState) intent.getSerializableExtra( VpnState s = (VpnState) intent.getSerializableExtra(
VpnManager.BROADCAST_CONNECTION_STATE); VpnManager.BROADCAST_CONNECTION_STATE);
if (s == null) { if (s == null) {
Log.e(TAG, "received null connectivity state"); Log.e(TAG, "received null connectivity state");
return; return;
} }
mConnectingErrorCode = intent.getIntExtra(
VpnManager.BROADCAST_ERROR_CODE, NO_ERROR);
VpnPreference pref = mVpnPreferenceMap.get(profileName); VpnPreference pref = mVpnPreferenceMap.get(profileName);
if (pref != null) { if (pref != null) {
Log.d(TAG, "received connectivity: " + profileName Log.d(TAG, "received connectivity: " + profileName
+ ": connected? " + s); + ": connected? " + s
+ " err=" + mConnectingErrorCode);
changeState(pref.mProfile, s); changeState(pref.mProfile, s);
} else { } else {
Log.e(TAG, "received connectivity: " + profileName Log.e(TAG, "received connectivity: " + profileName