Fix issue #3405957 com.android.settings: java.lang.NullPointerException...
...at android.app.DialogFragment.dismissInternal(DialogFragment.java:264)
Don't allow a DialogFragment to be dismissed twice.
Change-Id: Id2e9e3be1046b0d7862492c57c36001d8fd44a69
diff --git a/core/java/android/app/DialogFragment.java b/core/java/android/app/DialogFragment.java
index 50953d7..3d99055 100644
--- a/core/java/android/app/DialogFragment.java
+++ b/core/java/android/app/DialogFragment.java
@@ -25,6 +25,9 @@
import android.view.Window;
import android.view.WindowManager;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
/**
* A fragment that displays a dialog window, floating on top of its
* activity's window. This fragment contains a Dialog object, which it
@@ -177,8 +180,9 @@
int mBackStackId = -1;
Dialog mDialog;
- boolean mDestroyed;
- boolean mRemoved;
+ boolean mViewDestroyed;
+ boolean mDismissed;
+ boolean mShownByMe;
public DialogFragment() {
}
@@ -219,6 +223,8 @@
* {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}.
*/
public void show(FragmentManager manager, String tag) {
+ mDismissed = false;
+ mShownByMe = true;
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commit();
@@ -234,8 +240,10 @@
* {@link FragmentTransaction#commit() FragmentTransaction.commit()}.
*/
public int show(FragmentTransaction transaction, String tag) {
+ mDismissed = false;
+ mShownByMe = true;
transaction.add(this, tag);
- mRemoved = false;
+ mViewDestroyed = false;
mBackStackId = transaction.commit();
return mBackStackId;
}
@@ -251,11 +259,16 @@
}
void dismissInternal(boolean allowStateLoss) {
+ if (mDismissed) {
+ return;
+ }
+ mDismissed = true;
+ mShownByMe = false;
if (mDialog != null) {
mDialog.dismiss();
mDialog = null;
}
- mRemoved = true;
+ mViewDestroyed = true;
if (mBackStackId >= 0) {
getFragmentManager().popBackStack(mBackStackId,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
@@ -329,6 +342,27 @@
}
@Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ if (!mShownByMe) {
+ // If not explicitly shown through our API, take this as an
+ // indication that the dialog is no longer dismissed.
+ mDismissed = false;
+ }
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ if (!mShownByMe && !mDismissed) {
+ // The fragment was not shown by a direct call here, it is not
+ // dismissed, and now it is being detached... well, okay, thou
+ // art now dismissed. Have fun.
+ mDismissed = true;
+ }
+ }
+
+ @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -352,7 +386,6 @@
}
mDialog = onCreateDialog(savedInstanceState);
- mDestroyed = false;
switch (mStyle) {
case STYLE_NO_INPUT:
mDialog.getWindow().addFlags(
@@ -397,7 +430,7 @@
}
public void onDismiss(DialogInterface dialog) {
- if (!mRemoved) {
+ if (!mViewDestroyed) {
// Note: we need to use allowStateLoss, because the dialog
// dispatches this asynchronously so we can receive the call
// after the activity is paused. Worst case, when the user comes
@@ -439,7 +472,7 @@
public void onStart() {
super.onStart();
if (mDialog != null) {
- mRemoved = false;
+ mViewDestroyed = false;
mDialog.show();
}
}
@@ -484,14 +517,28 @@
@Override
public void onDestroyView() {
super.onDestroyView();
- mDestroyed = true;
if (mDialog != null) {
// Set removed here because this dismissal is just to hide
// the dialog -- we don't want this to cause the fragment to
// actually be removed.
- mRemoved = true;
+ mViewDestroyed = true;
mDialog.dismiss();
mDialog = null;
}
}
+
+ @Override
+ public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ super.dump(prefix, fd, writer, args);
+ writer.print(prefix); writer.println("DialogFragment:");
+ writer.print(prefix); writer.print(" mStyle="); writer.print(mStyle);
+ writer.print(" mTheme=0x"); writer.println(Integer.toHexString(mTheme));
+ writer.print(prefix); writer.print(" mCancelable="); writer.print(mCancelable);
+ writer.print(" mShowsDialog="); writer.print(mShowsDialog);
+ writer.print(" mBackStackId="); writer.println(mBackStackId);
+ writer.print(prefix); writer.print(" mDialog="); writer.println(mDialog);
+ writer.print(prefix); writer.print(" mViewDestroyed="); writer.print(mViewDestroyed);
+ writer.print(" mDismissed="); writer.print(mDismissed);
+ writer.print(" mShownByMe="); writer.println(mShownByMe);
+ }
}