Prevent crash caused by dialog show when state saved.
Call dialog.show when state saved will cause IllegalStateException so we
should prevent this.
Fix: 139883603
Test: manual
Test: atest DocumentsUIGoogleTests
Change-Id: I7ada873a7573729744d039347f688d127c972d41
diff --git a/src/com/android/documentsui/CreateDirectoryFragment.java b/src/com/android/documentsui/CreateDirectoryFragment.java
index 0d4aa4f..1a35cbd 100644
--- a/src/com/android/documentsui/CreateDirectoryFragment.java
+++ b/src/com/android/documentsui/CreateDirectoryFragment.java
@@ -61,6 +61,11 @@
private static final String TAG_CREATE_DIRECTORY = "create_directory";
public static void show(FragmentManager fm) {
+ if (fm.isStateSaved()) {
+ Log.w(TAG, "Skip show create folder dialog because state saved");
+ return;
+ }
+
final CreateDirectoryFragment dialog = new CreateDirectoryFragment();
dialog.show(fm, TAG_CREATE_DIRECTORY);
}
diff --git a/src/com/android/documentsui/dirlist/RenameDocumentFragment.java b/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
index 0a25395..9bcfd56 100644
--- a/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
+++ b/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
@@ -60,6 +60,11 @@
private @Nullable DialogInterface mDialog;
public static void show(FragmentManager fm, DocumentInfo document) {
+ if (fm.isStateSaved()) {
+ Log.w(TAG, "Skip show rename dialog because state saved");
+ return;
+ }
+
final RenameDocumentFragment dialog = new RenameDocumentFragment();
dialog.mDocument = document;
dialog.show(fm, TAG_RENAME_DOCUMENT);
diff --git a/src/com/android/documentsui/files/DeleteDocumentFragment.java b/src/com/android/documentsui/files/DeleteDocumentFragment.java
index 12f7b3c..64393a3 100644
--- a/src/com/android/documentsui/files/DeleteDocumentFragment.java
+++ b/src/com/android/documentsui/files/DeleteDocumentFragment.java
@@ -15,9 +15,12 @@
*/
package com.android.documentsui.files;
+import static com.android.documentsui.base.SharedMinimal.TAG;
+
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
+import android.util.Log;
import android.view.LayoutInflater;
import android.widget.Button;
import android.widget.TextView;
@@ -54,6 +57,11 @@
* @param srcParent the parent document of the selection
*/
public static void show(FragmentManager fm, List<DocumentInfo> docs, DocumentInfo srcParent) {
+ if (fm.isStateSaved()) {
+ Log.w(TAG, "Skip show delete dialog because state saved");
+ return;
+ }
+
final DeleteDocumentFragment dialog = new DeleteDocumentFragment();
dialog.mDocuments = docs;
dialog.mSrcParent = srcParent;
diff --git a/src/com/android/documentsui/queries/SearchFragment.java b/src/com/android/documentsui/queries/SearchFragment.java
index 5eb7435..b98efe0 100644
--- a/src/com/android/documentsui/queries/SearchFragment.java
+++ b/src/com/android/documentsui/queries/SearchFragment.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -59,6 +60,11 @@
private List<String> mHistoryList;
public static void showFragment(FragmentManager fm, String initQuery) {
+ if (fm.isStateSaved()) {
+ Log.w(TAG, "Skip show because state saved");
+ return;
+ }
+
final SearchFragment fragment = new SearchFragment();
final Bundle args = new Bundle();
args.putString(KEY_QUERY, initQuery);
diff --git a/src/com/android/documentsui/sorting/SortListFragment.java b/src/com/android/documentsui/sorting/SortListFragment.java
index 7030f74..7c33c9d 100644
--- a/src/com/android/documentsui/sorting/SortListFragment.java
+++ b/src/com/android/documentsui/sorting/SortListFragment.java
@@ -1,8 +1,11 @@
package com.android.documentsui.sorting;
+import static com.android.documentsui.base.SharedMinimal.TAG;
+
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
+import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
@@ -34,6 +37,11 @@
private List<SortItem> mSortingList;
public static void show(FragmentManager fm, SortModel model) {
+ if (fm.isStateSaved()) {
+ Log.w(TAG, "Skip show sort dialog because state saved");
+ return;
+ }
+
if (fm.findFragmentByTag(TAG_SORTING_LIST) == null) {
SortListFragment fragment = new SortListFragment();
Bundle args = new Bundle();
diff --git a/tests/common/com/android/documentsui/DialogFragmentTest.java b/tests/common/com/android/documentsui/DialogFragmentTest.java
index 05ad5fb..4e373a9 100644
--- a/tests/common/com/android/documentsui/DialogFragmentTest.java
+++ b/tests/common/com/android/documentsui/DialogFragmentTest.java
@@ -36,7 +36,13 @@
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
+import com.android.documentsui.base.DocumentInfo;
+import com.android.documentsui.dirlist.RenameDocumentFragment;
+import com.android.documentsui.files.DeleteDocumentFragment;
import com.android.documentsui.files.FilesActivity;
+import com.android.documentsui.queries.SearchFragment;
+import com.android.documentsui.sorting.SortListFragment;
+import com.android.documentsui.sorting.SortModel;
import com.google.android.material.textfield.TextInputEditText;
@@ -45,6 +51,7 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mockito;
import java.io.FileInputStream;
import java.io.IOException;
@@ -202,6 +209,49 @@
switchOrientation(mActivityTestRule.getActivity());
}
+ @Test
+ public void testCreateDirectoryFragmentShows_skipWhenStateSaved() {
+ mFragmentManager = Mockito.mock(FragmentManager.class);
+ Mockito.when(mFragmentManager.isStateSaved()).thenReturn(true);
+
+ // Use mock FragmentManager will cause NPE then test fail when DialogFragment.show is
+ // called, so test pass means it skip.
+ CreateDirectoryFragment.show(mFragmentManager);
+ }
+
+ @Test
+ public void testDeleteDocumentFragmentShows_skipWhenStateSaved() {
+ mFragmentManager = Mockito.mock(FragmentManager.class);
+ Mockito.when(mFragmentManager.isStateSaved()).thenReturn(true);
+
+ DeleteDocumentFragment.show(mFragmentManager, null, null);
+ }
+
+ @Test
+ public void testRenameDocumentFragmentShows_skipWhenStateSaved() {
+ mFragmentManager = Mockito.mock(FragmentManager.class);
+ Mockito.when(mFragmentManager.isStateSaved()).thenReturn(true);
+
+ RenameDocumentFragment.show(mFragmentManager, new DocumentInfo());
+ }
+
+ @Test
+ public void testSearchFragmentShows_skipWhenStateSaved() {
+ mFragmentManager = Mockito.mock(FragmentManager.class);
+ Mockito.when(mFragmentManager.isStateSaved()).thenReturn(true);
+
+ SearchFragment.showFragment(mFragmentManager, "");
+ }
+
+ @Test
+ public void testSortListFragmentShows_skipWhenStateSaved() {
+ mFragmentManager = Mockito.mock(FragmentManager.class);
+ Mockito.when(mFragmentManager.isStateSaved()).thenReturn(true);
+ SortModel sortModel = Mockito.mock(SortModel.class);
+
+ SortListFragment.show(mFragmentManager, sortModel);
+ }
+
private static int getInputTextHeight(TextInputEditText v) {
Paint paint = v.getPaint();
final float textSize = paint.getTextSize();