Fix alert dialogs in VpnSettings.

+ Don't check mDialogFragment.isVisible() in SettingsPreferenceFragment.removeDialog()
  as mDialogFragment may not be visible in parent fragment's onResume().
+ Replace mConnectDialog with mConnectDialogShowing and remove
  removeConnectDialog().
+ Dismiss alert dialogs in onPause() so that we don't need to maintain extra
  states during pause-resume cycle.

In addition, fix a NPE when startVpnTypeSelection().

Bug: 3381434
Bug: 3289365

Change-Id: Ic4aa87c7a618d95e86e45d6617f2ad7dab35f019
This commit is contained in:
Hung-ying Tyan
2011-01-24 15:05:27 +08:00
parent 0ee51e04fb
commit adc83d8312
2 changed files with 46 additions and 28 deletions

View File

@@ -105,8 +105,10 @@ public class SettingsPreferenceFragment extends PreferenceFragment
} }
protected void removeDialog(int dialogId) { protected void removeDialog(int dialogId) {
if (mDialogFragment != null && mDialogFragment.getDialogId() == dialogId // mDialogFragment may not be visible yet in parent fragment's onResume().
&& mDialogFragment.isVisible()) { // To be able to dismiss dialog at that time, don't check
// mDialogFragment.isVisible().
if (mDialogFragment != null && mDialogFragment.getDialogId() == dialogId) {
mDialogFragment.dismiss(); mDialogFragment.dismiss();
} }
mDialogFragment = null; mDialogFragment = null;

View File

@@ -131,7 +131,9 @@ public class VpnSettings extends SettingsPreferenceFragment
private int mConnectingErrorCode = NO_ERROR; private int mConnectingErrorCode = NO_ERROR;
private Dialog mShowingDialog, mConnectDialog; private Dialog mShowingDialog;
private boolean mConnectDialogShowing = false;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
@@ -190,14 +192,17 @@ public class VpnSettings extends SettingsPreferenceFragment
public void onPause() { public void onPause() {
// ignore vpn connectivity event // ignore vpn connectivity event
mVpnManager.unregisterConnectivityReceiver(mConnectivityReceiver); mVpnManager.unregisterConnectivityReceiver(mConnectivityReceiver);
if ((mShowingDialog != null) && mShowingDialog.isShowing()) {
mShowingDialog.dismiss();
mShowingDialog = null;
}
super.onPause(); super.onPause();
} }
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
if (DEBUG) if (DEBUG) Log.d(TAG, "onResume");
Log.d(TAG, "onResume");
// listen to vpn connectivity event // listen to vpn connectivity event
mVpnManager.registerConnectivityReceiver(mConnectivityReceiver); mVpnManager.registerConnectivityReceiver(mConnectivityReceiver);
@@ -207,21 +212,22 @@ public class VpnSettings extends SettingsPreferenceFragment
mUnlockAction = null; mUnlockAction = null;
getActivity().runOnUiThread(action); getActivity().runOnUiThread(action);
} }
if (mConnectDialog == null || !mConnectDialog.isShowing()) {
if (!mConnectDialogShowing) {
checkVpnConnectionStatus(); checkVpnConnectionStatus();
} else { } else {
// Dismiss the connect dialog in case there is another instance // Dismiss the connect dialog in case there is another instance
// trying to operate a vpn connection. // trying to operate a vpn connection.
if (!mVpnManager.isIdle()) removeConnectDialog(); if (!mVpnManager.isIdle()) {
removeDialog(DIALOG_CONNECT);
checkVpnConnectionStatus();
}
} }
} }
@Override @Override
public void onDestroyView() { public void onDestroyView() {
unregisterForContextMenu(getListView()); unregisterForContextMenu(getListView());
if ((mShowingDialog != null) && mShowingDialog.isShowing()) {
mShowingDialog.dismiss();
}
// This should be called after the procedure above as ListView inside this Fragment // This should be called after the procedure above as ListView inside this Fragment
// will be deleted here. // will be deleted here.
super.onDestroyView(); super.onDestroyView();
@@ -242,8 +248,23 @@ public class VpnSettings extends SettingsPreferenceFragment
protected void showDialog(int dialogId) { protected void showDialog(int dialogId) {
super.showDialog(dialogId); super.showDialog(dialogId);
if (dialogId == DIALOG_CONNECT) {
mConnectDialogShowing = true;
setOnDismissListener(new DialogInterface.OnDismissListener() {
public void onDismiss(DialogInterface dialog) {
mConnectDialogShowing = false;
}
});
}
setOnCancelListener(new DialogInterface.OnCancelListener() { setOnCancelListener(new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) { public void onCancel(DialogInterface dialog) {
if (mActiveProfile != null) {
changeState(mActiveProfile, VpnState.IDLE);
}
// Make sure onIdle() is called as the above changeState()
// may not be effective if the state is already IDLE.
// XXX: VpnService should broadcast non-IDLE state, say UNUSABLE,
// when an error occurs.
onIdle(); onIdle();
} }
}); });
@@ -253,8 +274,7 @@ public class VpnSettings extends SettingsPreferenceFragment
public Dialog onCreateDialog (int id) { public Dialog onCreateDialog (int id) {
switch (id) { switch (id) {
case DIALOG_CONNECT: case DIALOG_CONNECT:
mConnectDialog = createConnectDialog(); return createConnectDialog();
return mConnectDialog;
case DIALOG_SECRET_NOT_SET: case DIALOG_SECRET_NOT_SET:
return createSecretNotSetDialog(); return createSecretNotSetDialog();
@@ -270,14 +290,6 @@ public class VpnSettings extends SettingsPreferenceFragment
} }
} }
private void removeConnectDialog() {
if (mConnectDialog != null) {
mConnectDialog.dismiss();
mConnectDialog = null;
checkVpnConnectionStatus();
}
}
private Dialog createConnectDialog() { private Dialog createConnectDialog() {
final Activity activity = getActivity(); final Activity activity = getActivity();
return new AlertDialog.Builder(activity) return new AlertDialog.Builder(activity)
@@ -508,14 +520,10 @@ public class VpnSettings extends SettingsPreferenceFragment
String error = mConnectingActor.validateInputs(d); String error = mConnectingActor.validateInputs(d);
if (error == null) { if (error == null) {
mConnectingActor.connect(d); mConnectingActor.connect(d);
removeConnectDialog();
return; return;
} else { } else {
// dismissDialog(DIALOG_CONNECT);
removeConnectDialog();
final Activity activity = getActivity();
// show error dialog // show error dialog
final Activity activity = getActivity();
mShowingDialog = new AlertDialog.Builder(activity) mShowingDialog = new AlertDialog.Builder(activity)
.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)
@@ -529,10 +537,14 @@ public class VpnSettings extends SettingsPreferenceFragment
} }
}) })
.create(); .create();
// The profile state is "connecting". If we allow the dialog to
// be cancelable, then we need to clear the state in the
// onCancel handler.
mShowingDialog.setCancelable(false);
mShowingDialog.show(); mShowingDialog.show();
} }
} else { } else {
removeConnectDialog(); changeState(mActiveProfile, VpnState.IDLE);
} }
} }
@@ -668,7 +680,9 @@ public class VpnSettings extends SettingsPreferenceFragment
} }
private void startVpnTypeSelection() { private void startVpnTypeSelection() {
((PreferenceActivity)getActivity()).startPreferencePanel( if (getActivity() == null) return;
((PreferenceActivity) getActivity()).startPreferencePanel(
VpnTypeSelection.class.getCanonicalName(), null, R.string.vpn_type_title, null, VpnTypeSelection.class.getCanonicalName(), null, R.string.vpn_type_title, null,
this, REQUEST_SELECT_VPN_TYPE); this, REQUEST_SELECT_VPN_TYPE);
} }
@@ -812,7 +826,7 @@ public class VpnSettings extends SettingsPreferenceFragment
} }
private void onIdle() { private void onIdle() {
Log.d(TAG, " onIdle()"); if (DEBUG) Log.d(TAG, " onIdle()");
mActiveProfile = null; mActiveProfile = null;
mConnectingActor = null; mConnectingActor = null;
enableProfilePreferences(); enableProfilePreferences();
@@ -1070,6 +1084,8 @@ public class VpnSettings extends SettingsPreferenceFragment
Log.d(TAG, "received connectivity: " + profileName Log.d(TAG, "received connectivity: " + profileName
+ ": connected? " + s + ": connected? " + s
+ " err=" + mConnectingErrorCode); + " err=" + mConnectingErrorCode);
// XXX: VpnService should broadcast non-IDLE state, say UNUSABLE,
// when an error occurs.
changeState(pref.mProfile, s); changeState(pref.mProfile, s);
} else { } else {
Log.e(TAG, "received connectivity: " + profileName Log.e(TAG, "received connectivity: " + profileName