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
This commit is contained in:
@@ -75,7 +75,7 @@ public class AccountDashboardFragment extends DashboardFragment {
|
|||||||
if (CredentialManager.isServiceEnabled(context)) {
|
if (CredentialManager.isServiceEnabled(context)) {
|
||||||
CredentialManagerPreferenceController cmpp =
|
CredentialManagerPreferenceController cmpp =
|
||||||
use(CredentialManagerPreferenceController.class);
|
use(CredentialManagerPreferenceController.class);
|
||||||
cmpp.setParentFragment(this);
|
cmpp.init(this, getFragmentManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
getSettingsLifecycle().addObserver(use(PasswordsPreferenceController.class));
|
getSettingsLifecycle().addObserver(use(PasswordsPreferenceController.class));
|
||||||
@@ -127,8 +127,8 @@ public class AccountDashboardFragment extends DashboardFragment {
|
|||||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||||
new BaseSearchIndexProvider() {
|
new BaseSearchIndexProvider() {
|
||||||
@Override
|
@Override
|
||||||
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
|
public List<SearchIndexableResource> getXmlResourcesToIndex(
|
||||||
boolean enabled) {
|
Context context, boolean enabled) {
|
||||||
final SearchIndexableResource sir = new SearchIndexableResource(context);
|
final SearchIndexableResource sir = new SearchIndexableResource(context);
|
||||||
sir.xmlResId = getPreferenceLayoutResId(context);
|
sir.xmlResId = getPreferenceLayoutResId(context);
|
||||||
return List.of(sir);
|
return List.of(sir);
|
||||||
|
@@ -69,7 +69,7 @@ public class AccountPersonalDashboardFragment extends DashboardFragment {
|
|||||||
if (CredentialManager.isServiceEnabled(context)) {
|
if (CredentialManager.isServiceEnabled(context)) {
|
||||||
CredentialManagerPreferenceController cmpp =
|
CredentialManagerPreferenceController cmpp =
|
||||||
use(CredentialManagerPreferenceController.class);
|
use(CredentialManagerPreferenceController.class);
|
||||||
cmpp.setParentFragment(this);
|
cmpp.init(this, getFragmentManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
getSettingsLifecycle().addObserver(use(PasswordsPreferenceController.class));
|
getSettingsLifecycle().addObserver(use(PasswordsPreferenceController.class));
|
||||||
|
@@ -69,7 +69,7 @@ public class AccountWorkProfileDashboardFragment extends DashboardFragment {
|
|||||||
if (CredentialManager.isServiceEnabled(context)) {
|
if (CredentialManager.isServiceEnabled(context)) {
|
||||||
CredentialManagerPreferenceController cmpp =
|
CredentialManagerPreferenceController cmpp =
|
||||||
use(CredentialManagerPreferenceController.class);
|
use(CredentialManagerPreferenceController.class);
|
||||||
cmpp.setParentFragment(this);
|
cmpp.init(this, getFragmentManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
getSettingsLifecycle().addObserver(use(PasswordsPreferenceController.class));
|
getSettingsLifecycle().addObserver(use(PasswordsPreferenceController.class));
|
||||||
|
@@ -21,7 +21,6 @@ import static androidx.lifecycle.Lifecycle.Event.ON_CREATE;
|
|||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.app.settings.SettingsEnums;
|
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
@@ -43,6 +42,7 @@ import android.util.Log;
|
|||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.fragment.app.DialogFragment;
|
import androidx.fragment.app.DialogFragment;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.lifecycle.LifecycleObserver;
|
import androidx.lifecycle.LifecycleObserver;
|
||||||
import androidx.lifecycle.LifecycleOwner;
|
import androidx.lifecycle.LifecycleOwner;
|
||||||
import androidx.lifecycle.OnLifecycleEvent;
|
import androidx.lifecycle.OnLifecycleEvent;
|
||||||
@@ -54,7 +54,6 @@ import com.android.internal.annotations.VisibleForTesting;
|
|||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.Utils;
|
import com.android.settings.Utils;
|
||||||
import com.android.settings.core.BasePreferenceController;
|
import com.android.settings.core.BasePreferenceController;
|
||||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
|
||||||
import com.android.settings.dashboard.DashboardFragment;
|
import com.android.settings.dashboard.DashboardFragment;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -80,7 +79,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
|
|||||||
private final Executor mExecutor;
|
private final Executor mExecutor;
|
||||||
private final Map<String, SwitchPreference> mPrefs = new HashMap<>(); // key is package name
|
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) {
|
public CredentialManagerPreferenceController(Context context, String preferenceKey) {
|
||||||
super(context, 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 fragment the fragment to use as the parent
|
||||||
|
* @param fragmentManager the fragment manager to use
|
||||||
*/
|
*/
|
||||||
public void setParentFragment(DashboardFragment fragment) {
|
public void init(DashboardFragment fragment, FragmentManager fragmentManager) {
|
||||||
mParentFragment = fragment;
|
|
||||||
fragment.getSettingsLifecycle().addObserver(this);
|
fragment.getSettingsLifecycle().addObserver(this);
|
||||||
|
mFragmentManager = fragmentManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnLifecycleEvent(ON_CREATE)
|
@OnLifecycleEvent(ON_CREATE)
|
||||||
@@ -133,7 +134,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
|
|||||||
CredentialProviderInfo.getAvailableServices(mContext, getUser())) {
|
CredentialProviderInfo.getAvailableServices(mContext, getUser())) {
|
||||||
services.add(cpi.getServiceInfo());
|
services.add(cpi.getServiceInfo());
|
||||||
}
|
}
|
||||||
init(lifecycleOwner, services);
|
setAvailableServices(lifecycleOwner, services);
|
||||||
|
|
||||||
mCredentialManager.listEnabledProviders(
|
mCredentialManager.listEnabledProviders(
|
||||||
mCancellationSignal,
|
mCancellationSignal,
|
||||||
@@ -161,7 +162,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void init(LifecycleOwner lifecycleOwner, List<ServiceInfo> availableServices) {
|
void setAvailableServices(LifecycleOwner lifecycleOwner, List<ServiceInfo> availableServices) {
|
||||||
mServices.clear();
|
mServices.clear();
|
||||||
mServices.addAll(availableServices);
|
mServices.addAll(availableServices);
|
||||||
}
|
}
|
||||||
@@ -280,13 +281,11 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
|
|||||||
if (!togglePackageNameEnabled(packageName)) {
|
if (!togglePackageNameEnabled(packageName)) {
|
||||||
final DialogFragment fragment = newErrorDialogFragment();
|
final DialogFragment fragment = newErrorDialogFragment();
|
||||||
|
|
||||||
if (fragment == null || mParentFragment == null) {
|
if (fragment == null || mFragmentManager == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fragment.show(
|
fragment.show(mFragmentManager, ErrorDialogFragment.TAG);
|
||||||
mParentFragment.getActivity().getSupportFragmentManager(),
|
|
||||||
ErrorDialogFragment.TAG);
|
|
||||||
|
|
||||||
// The user set the check to true so we need to set it back.
|
// The user set the check to true so we need to set it back.
|
||||||
pref.setChecked(false);
|
pref.setChecked(false);
|
||||||
@@ -298,13 +297,11 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
|
|||||||
final DialogFragment fragment =
|
final DialogFragment fragment =
|
||||||
newConfirmationDialogFragment(packageName, title, pref);
|
newConfirmationDialogFragment(packageName, title, pref);
|
||||||
|
|
||||||
if (fragment == null || mParentFragment == null) {
|
if (fragment == null || mFragmentManager == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fragment.show(
|
fragment.show(mFragmentManager, ConfirmationDialogFragment.TAG);
|
||||||
mParentFragment.getActivity().getSupportFragmentManager(),
|
|
||||||
ConfirmationDialogFragment.TAG);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -343,11 +340,6 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
|
|||||||
@NonNull SwitchPreference pref) {
|
@NonNull SwitchPreference pref) {
|
||||||
DialogHost host =
|
DialogHost host =
|
||||||
new DialogHost() {
|
new DialogHost() {
|
||||||
@Override
|
|
||||||
public DashboardFragment getParentFragment() {
|
|
||||||
return mParentFragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDialogClick(int whichButton) {
|
public void onDialogClick(int whichButton) {
|
||||||
if (whichButton == DialogInterface.BUTTON_POSITIVE) {
|
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);
|
return new ConfirmationDialogFragment(host, packageName, appName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @Nullable ErrorDialogFragment newErrorDialogFragment() {
|
private @Nullable ErrorDialogFragment newErrorDialogFragment() {
|
||||||
DialogHost host =
|
DialogHost host =
|
||||||
new DialogHost() {
|
new DialogHost() {
|
||||||
@Override
|
|
||||||
public DashboardFragment getParentFragment() {
|
|
||||||
return mParentFragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDialogClick(int whichButton) {}
|
public void onDialogClick(int whichButton) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (host.getParentFragment() == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ErrorDialogFragment(host);
|
return new ErrorDialogFragment(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,12 +375,10 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
|
|||||||
/** Called when the dialog button is clicked. */
|
/** Called when the dialog button is clicked. */
|
||||||
private interface DialogHost {
|
private interface DialogHost {
|
||||||
void onDialogClick(int whichButton);
|
void onDialogClick(int whichButton);
|
||||||
|
|
||||||
DashboardFragment getParentFragment();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Dialog fragment parent class. */
|
/** Dialog fragment parent class. */
|
||||||
private abstract static class CredentialManagerDialogFragment extends InstrumentedDialogFragment
|
private abstract static class CredentialManagerDialogFragment extends DialogFragment
|
||||||
implements DialogInterface.OnClickListener {
|
implements DialogInterface.OnClickListener {
|
||||||
|
|
||||||
public static final String TAG = "CredentialManagerDialogFragment";
|
public static final String TAG = "CredentialManagerDialogFragment";
|
||||||
@@ -412,18 +389,12 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
|
|||||||
|
|
||||||
CredentialManagerDialogFragment(DialogHost dialogHost) {
|
CredentialManagerDialogFragment(DialogHost dialogHost) {
|
||||||
super();
|
super();
|
||||||
setTargetFragment(dialogHost.getParentFragment(), 0);
|
|
||||||
mDialogHost = dialogHost;
|
mDialogHost = dialogHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DialogHost getDialogHost() {
|
public DialogHost getDialogHost() {
|
||||||
return mDialogHost;
|
return mDialogHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMetricsCategory() {
|
|
||||||
return SettingsEnums.ACCOUNT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Dialog showing error when too many providers are selected. */
|
/** Dialog showing error when too many providers are selected. */
|
||||||
|
@@ -182,7 +182,7 @@ public class CredentialManagerPreferenceControllerTest {
|
|||||||
CredentialManagerPreferenceController controller =
|
CredentialManagerPreferenceController controller =
|
||||||
new CredentialManagerPreferenceController(
|
new CredentialManagerPreferenceController(
|
||||||
mContext, mCredentialsPreferenceCategory.getKey());
|
mContext, mCredentialsPreferenceCategory.getKey());
|
||||||
controller.init(() -> mock(Lifecycle.class), availableServices);
|
controller.setAvailableServices(() -> mock(Lifecycle.class), availableServices);
|
||||||
return controller;
|
return controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user