Fix settings crash
Fix settings crash when dialog is shown
becuase the wrong fragment manager is
used.
Bug: 264939770
Test: unit test and test on device
Change-Id: I5f4c04740058baaa1c96a7108dc4b08b3e467fb8
diff --git a/src/com/android/settings/accounts/AccountDashboardFragment.java b/src/com/android/settings/accounts/AccountDashboardFragment.java
index e252688..16351e8 100644
--- a/src/com/android/settings/accounts/AccountDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountDashboardFragment.java
@@ -75,7 +75,7 @@
if (CredentialManager.isServiceEnabled(context)) {
CredentialManagerPreferenceController cmpp =
use(CredentialManagerPreferenceController.class);
- cmpp.setParentFragment(this);
+ cmpp.init(this, getFragmentManager());
}
getSettingsLifecycle().addObserver(use(PasswordsPreferenceController.class));
@@ -127,8 +127,8 @@
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
- public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
- boolean enabled) {
+ public List<SearchIndexableResource> getXmlResourcesToIndex(
+ Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = getPreferenceLayoutResId(context);
return List.of(sir);
diff --git a/src/com/android/settings/accounts/AccountPersonalDashboardFragment.java b/src/com/android/settings/accounts/AccountPersonalDashboardFragment.java
index 5f9a288..30fb1a1 100644
--- a/src/com/android/settings/accounts/AccountPersonalDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountPersonalDashboardFragment.java
@@ -69,7 +69,7 @@
if (CredentialManager.isServiceEnabled(context)) {
CredentialManagerPreferenceController cmpp =
use(CredentialManagerPreferenceController.class);
- cmpp.setParentFragment(this);
+ cmpp.init(this, getFragmentManager());
}
getSettingsLifecycle().addObserver(use(PasswordsPreferenceController.class));
diff --git a/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java b/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java
index 4835b17..5a89457 100644
--- a/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java
@@ -69,7 +69,7 @@
if (CredentialManager.isServiceEnabled(context)) {
CredentialManagerPreferenceController cmpp =
use(CredentialManagerPreferenceController.class);
- cmpp.setParentFragment(this);
+ cmpp.init(this, getFragmentManager());
}
getSettingsLifecycle().addObserver(use(PasswordsPreferenceController.class));
diff --git a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
index c6e545e..865f173 100644
--- a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
+++ b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
@@ -21,7 +21,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Dialog;
-import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
@@ -43,6 +42,7 @@
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.DialogFragment;
+import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.OnLifecycleEvent;
@@ -54,7 +54,6 @@
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.BasePreferenceController;
-import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.dashboard.DashboardFragment;
import java.util.ArrayList;
@@ -80,7 +79,7 @@
private final Executor mExecutor;
private final Map<String, SwitchPreference> mPrefs = new HashMap<>(); // key is package name
- private @Nullable DashboardFragment mParentFragment = null;
+ private @Nullable FragmentManager mFragmentManager = null;
public CredentialManagerPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
@@ -113,13 +112,15 @@
}
/**
- * Sets the parent fragment and attaches this controller to the settings lifecycle.
+ * Initializes the controller with the parent fragment and adds the controller to observe its
+ * lifecycle. Also stores the fragment manager which is used to open dialogs.
*
* @param fragment the fragment to use as the parent
+ * @param fragmentManager the fragment manager to use
*/
- public void setParentFragment(DashboardFragment fragment) {
- mParentFragment = fragment;
+ public void init(DashboardFragment fragment, FragmentManager fragmentManager) {
fragment.getSettingsLifecycle().addObserver(this);
+ mFragmentManager = fragmentManager;
}
@OnLifecycleEvent(ON_CREATE)
@@ -133,7 +134,7 @@
CredentialProviderInfo.getAvailableServices(mContext, getUser())) {
services.add(cpi.getServiceInfo());
}
- init(lifecycleOwner, services);
+ setAvailableServices(lifecycleOwner, services);
mCredentialManager.listEnabledProviders(
mCancellationSignal,
@@ -161,7 +162,7 @@
}
@VisibleForTesting
- void init(LifecycleOwner lifecycleOwner, List<ServiceInfo> availableServices) {
+ void setAvailableServices(LifecycleOwner lifecycleOwner, List<ServiceInfo> availableServices) {
mServices.clear();
mServices.addAll(availableServices);
}
@@ -280,13 +281,11 @@
if (!togglePackageNameEnabled(packageName)) {
final DialogFragment fragment = newErrorDialogFragment();
- if (fragment == null || mParentFragment == null) {
+ if (fragment == null || mFragmentManager == null) {
return true;
}
- fragment.show(
- mParentFragment.getActivity().getSupportFragmentManager(),
- ErrorDialogFragment.TAG);
+ fragment.show(mFragmentManager, ErrorDialogFragment.TAG);
// The user set the check to true so we need to set it back.
pref.setChecked(false);
@@ -298,13 +297,11 @@
final DialogFragment fragment =
newConfirmationDialogFragment(packageName, title, pref);
- if (fragment == null || mParentFragment == null) {
+ if (fragment == null || mFragmentManager == null) {
return true;
}
- fragment.show(
- mParentFragment.getActivity().getSupportFragmentManager(),
- ConfirmationDialogFragment.TAG);
+ fragment.show(mFragmentManager, ConfirmationDialogFragment.TAG);
}
return true;
@@ -344,11 +341,6 @@
DialogHost host =
new DialogHost() {
@Override
- public DashboardFragment getParentFragment() {
- return mParentFragment;
- }
-
- @Override
public void onDialogClick(int whichButton) {
if (whichButton == DialogInterface.BUTTON_POSITIVE) {
// Since the package is now enabled then we
@@ -362,10 +354,6 @@
}
};
- if (host.getParentFragment() == null) {
- return null;
- }
-
return new ConfirmationDialogFragment(host, packageName, appName);
}
@@ -373,18 +361,9 @@
DialogHost host =
new DialogHost() {
@Override
- public DashboardFragment getParentFragment() {
- return mParentFragment;
- }
-
- @Override
public void onDialogClick(int whichButton) {}
};
- if (host.getParentFragment() == null) {
- return null;
- }
-
return new ErrorDialogFragment(host);
}
@@ -396,12 +375,10 @@
/** Called when the dialog button is clicked. */
private interface DialogHost {
void onDialogClick(int whichButton);
-
- DashboardFragment getParentFragment();
}
/** Dialog fragment parent class. */
- private abstract static class CredentialManagerDialogFragment extends InstrumentedDialogFragment
+ private abstract static class CredentialManagerDialogFragment extends DialogFragment
implements DialogInterface.OnClickListener {
public static final String TAG = "CredentialManagerDialogFragment";
@@ -412,18 +389,12 @@
CredentialManagerDialogFragment(DialogHost dialogHost) {
super();
- setTargetFragment(dialogHost.getParentFragment(), 0);
mDialogHost = dialogHost;
}
public DialogHost getDialogHost() {
return mDialogHost;
}
-
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.ACCOUNT;
- }
}
/** Dialog showing error when too many providers are selected. */
diff --git a/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java
index 035b4e5..ff7e71a 100644
--- a/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java
@@ -182,7 +182,7 @@
CredentialManagerPreferenceController controller =
new CredentialManagerPreferenceController(
mContext, mCredentialsPreferenceCategory.getKey());
- controller.init(() -> mock(Lifecycle.class), availableServices);
+ controller.setAvailableServices(() -> mock(Lifecycle.class), availableServices);
return controller;
}