From e1608b369f809dca9888fa05bb4296b1619fa334 Mon Sep 17 00:00:00 2001 From: Becca Hughes Date: Tue, 10 Jan 2023 18:41:14 +0000 Subject: [PATCH] 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 --- .../accounts/AccountDashboardFragment.java | 6 +- .../AccountPersonalDashboardFragment.java | 2 +- .../AccountWorkProfileDashboardFragment.java | 2 +- ...CredentialManagerPreferenceController.java | 57 +++++-------------- ...entialManagerPreferenceControllerTest.java | 2 +- 5 files changed, 20 insertions(+), 49 deletions(-) diff --git a/src/com/android/settings/accounts/AccountDashboardFragment.java b/src/com/android/settings/accounts/AccountDashboardFragment.java index e252688fd18..16351e834f3 100644 --- a/src/com/android/settings/accounts/AccountDashboardFragment.java +++ b/src/com/android/settings/accounts/AccountDashboardFragment.java @@ -75,7 +75,7 @@ public class AccountDashboardFragment extends DashboardFragment { 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 class AccountDashboardFragment extends DashboardFragment { public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider() { @Override - public List getXmlResourcesToIndex(Context context, - boolean enabled) { + public List 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 5f9a288034d..30fb1a1c5af 100644 --- a/src/com/android/settings/accounts/AccountPersonalDashboardFragment.java +++ b/src/com/android/settings/accounts/AccountPersonalDashboardFragment.java @@ -69,7 +69,7 @@ public class AccountPersonalDashboardFragment extends DashboardFragment { 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 4835b173355..5a894575aeb 100644 --- a/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java +++ b/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java @@ -69,7 +69,7 @@ public class AccountWorkProfileDashboardFragment extends DashboardFragment { 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 c6e545e2226..865f1733b51 100644 --- a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java +++ b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java @@ -21,7 +21,6 @@ import static androidx.lifecycle.Lifecycle.Event.ON_CREATE; 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 android.util.Log; 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.internal.annotations.VisibleForTesting; 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 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl private final Executor mExecutor; private final Map 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 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl } /** - * 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 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl CredentialProviderInfo.getAvailableServices(mContext, getUser())) { services.add(cpi.getServiceInfo()); } - init(lifecycleOwner, services); + setAvailableServices(lifecycleOwner, services); mCredentialManager.listEnabledProviders( mCancellationSignal, @@ -161,7 +162,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl } @VisibleForTesting - void init(LifecycleOwner lifecycleOwner, List availableServices) { + void setAvailableServices(LifecycleOwner lifecycleOwner, List availableServices) { mServices.clear(); mServices.addAll(availableServices); } @@ -280,13 +281,11 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl 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 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl 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; @@ -343,11 +340,6 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl @NonNull SwitchPreference pref) { DialogHost host = new DialogHost() { - @Override - public DashboardFragment getParentFragment() { - return mParentFragment; - } - @Override public void onDialogClick(int whichButton) { if (whichButton == DialogInterface.BUTTON_POSITIVE) { @@ -362,29 +354,16 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl } }; - if (host.getParentFragment() == null) { - return null; - } - return new ConfirmationDialogFragment(host, packageName, appName); } private @Nullable ErrorDialogFragment newErrorDialogFragment() { 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 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl /** 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 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl 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 035b4e5485d..ff7e71a948f 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 @@ public class CredentialManagerPreferenceControllerTest { CredentialManagerPreferenceController controller = new CredentialManagerPreferenceController( mContext, mCredentialsPreferenceCategory.getKey()); - controller.init(() -> mock(Lifecycle.class), availableServices); + controller.setAvailableServices(() -> mock(Lifecycle.class), availableServices); return controller; }