Add missing divider to credman settings

Test: ondevice
Bug: 274126440
Change-Id: I3ba68a749899840c6ed646793e1d65725f10cce8
This commit is contained in:
Becca Hughes
2023-09-01 07:47:03 -07:00
parent 56556078ad
commit d7c780aac7
2 changed files with 116 additions and 40 deletions

View File

@@ -47,6 +47,8 @@ import android.service.autofill.AutofillServiceInfo;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.IconDrawableFactory; import android.util.IconDrawableFactory;
import android.util.Log; import android.util.Log;
import android.view.View;
import android.widget.Switch;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
@@ -58,7 +60,7 @@ import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceGroup; import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference; import androidx.preference.PreferenceViewHolder;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor; import com.android.internal.content.PackageMonitor;
@@ -67,6 +69,7 @@ import com.android.settings.Utils;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;
import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.utils.ThreadUtils; import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.widget.TwoTargetPreference;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@@ -100,7 +103,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
private final Set<String> mEnabledPackageNames; private final Set<String> mEnabledPackageNames;
private final @Nullable CredentialManager mCredentialManager; private final @Nullable CredentialManager mCredentialManager;
private final Executor mExecutor; private final Executor mExecutor;
private final Map<String, SwitchPreference> mPrefs = new HashMap<>(); // key is package name private final Map<String, CombiPreference> mPrefs = new HashMap<>(); // key is package name
private final List<ServiceInfo> mPendingServiceInfos = new ArrayList<>(); private final List<ServiceInfo> mPendingServiceInfos = new ArrayList<>();
private final Handler mHandler = new Handler(); private final Handler mHandler = new Handler();
private final SettingContentObserver mSettingsContentObserver; private final SettingContentObserver mSettingsContentObserver;
@@ -389,7 +392,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
/** Aggregates the list of services and builds a list of UI prefs to show. */ /** Aggregates the list of services and builds a list of UI prefs to show. */
@VisibleForTesting @VisibleForTesting
public Map<String, SwitchPreference> buildPreferenceList( public Map<String, CombiPreference> buildPreferenceList(
Context context, PreferenceGroup group) { Context context, PreferenceGroup group) {
// Get the selected autofill provider. If it is the placeholder then replace it with an // Get the selected autofill provider. If it is the placeholder then replace it with an
// empty string. // empty string.
@@ -415,7 +418,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
return new HashMap<>(); return new HashMap<>();
} }
Map<String, SwitchPreference> output = new HashMap<>(); Map<String, CombiPreference> output = new HashMap<>();
for (CombinedProviderInfo combinedInfo : providers) { for (CombinedProviderInfo combinedInfo : providers) {
final String packageName = combinedInfo.getApplicationInfo().packageName; final String packageName = combinedInfo.getApplicationInfo().packageName;
@@ -434,7 +437,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
CharSequence title = combinedInfo.getAppName(context); CharSequence title = combinedInfo.getAppName(context);
// Build the pref and add it to the output & group. // Build the pref and add it to the output & group.
SwitchPreference pref = CombiPreference pref =
addProviderPreference( addProviderPreference(
context, title, icon, packageName, combinedInfo.getSettingsSubtitle()); context, title, icon, packageName, combinedInfo.getSettingsSubtitle());
output.put(packageName, pref); output.put(packageName, pref);
@@ -449,7 +452,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
/** Creates a preference object based on the provider info. */ /** Creates a preference object based on the provider info. */
@VisibleForTesting @VisibleForTesting
public SwitchPreference createPreference(Context context, CredentialProviderInfo service) { public CombiPreference createPreference(Context context, CredentialProviderInfo service) {
CharSequence label = service.getLabel(context); CharSequence label = service.getLabel(context);
return addProviderPreference( return addProviderPreference(
context, context,
@@ -510,15 +513,15 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
return enabledServices; return enabledServices;
} }
private SwitchPreference addProviderPreference( private CombiPreference addProviderPreference(
@NonNull Context prefContext, @NonNull Context prefContext,
@NonNull CharSequence title, @NonNull CharSequence title,
@Nullable Drawable icon, @Nullable Drawable icon,
@NonNull String packageName, @NonNull String packageName,
@Nullable CharSequence subtitle) { @Nullable CharSequence subtitle) {
final SwitchPreference pref = new SwitchPreference(prefContext); final CombiPreference pref =
new CombiPreference(prefContext, mEnabledPackageNames.contains(packageName));
pref.setTitle(title); pref.setTitle(title);
pref.setChecked(mEnabledPackageNames.contains(packageName));
if (icon != null) { if (icon != null) {
pref.setIcon(Utils.getSafeIcon(icon)); pref.setIcon(Utils.getSafeIcon(icon));
@@ -528,10 +531,8 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
pref.setSummary(subtitle); pref.setSummary(subtitle);
} }
pref.setOnPreferenceClickListener( pref.setPreferenceListener(
p -> { (p, isChecked) -> {
boolean isChecked = pref.isChecked();
if (isChecked) { if (isChecked) {
if (mEnabledPackageNames.size() >= MAX_SELECTABLE_PROVIDERS) { if (mEnabledPackageNames.size() >= MAX_SELECTABLE_PROVIDERS) {
// Show the error if too many enabled. // Show the error if too many enabled.
@@ -539,11 +540,11 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
final DialogFragment fragment = newErrorDialogFragment(); final DialogFragment fragment = newErrorDialogFragment();
if (fragment == null || mFragmentManager == null) { if (fragment == null || mFragmentManager == null) {
return true; return;
} }
fragment.show(mFragmentManager, ErrorDialogFragment.TAG); fragment.show(mFragmentManager, ErrorDialogFragment.TAG);
return true; return;
} }
togglePackageNameEnabled(packageName); togglePackageNameEnabled(packageName);
@@ -552,12 +553,9 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
if (mPrefs.containsKey(packageName)) { if (mPrefs.containsKey(packageName)) {
mPrefs.get(packageName).setChecked(true); mPrefs.get(packageName).setChecked(true);
} }
return true;
} else { } else {
togglePackageNameDisabled(packageName); togglePackageNameDisabled(packageName);
} }
return true;
}); });
return pref; return pref;
@@ -836,4 +834,80 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
updateFromExternal(); updateFromExternal();
} }
} }
/** CombiPreference is a combination of TwoTargetPreference and SwitchPreference. */
public static class CombiPreference extends TwoTargetPreference {
private final Listener mListener = new Listener();
private class Listener implements View.OnClickListener {
@Override
public void onClick(View buttonView) {
// Forward the event.
if (mSwitch != null) {
mOnClickListener.onCheckChanged(CombiPreference.this, mSwitch.isChecked());
}
}
}
// Stores a reference to the switch view.
private @Nullable Switch mSwitch;
// Switch text for on and off states
private @NonNull boolean mChecked = false;
private @Nullable OnCombiPreferenceClickListener mOnClickListener = null;
public interface OnCombiPreferenceClickListener {
/** Called when the check is updated */
void onCheckChanged(CombiPreference p, boolean isChecked);
}
public CombiPreference(Context context, boolean initialValue) {
super(context);
mChecked = initialValue;
}
/** Set the new checked value */
public void setChecked(boolean isChecked) {
// Don't update if we don't need too.
if (mChecked == isChecked) {
return;
}
mChecked = isChecked;
if (mSwitch != null) {
mSwitch.setChecked(isChecked);
}
}
public boolean isChecked() {
return mChecked;
}
public void setPreferenceListener(OnCombiPreferenceClickListener onClickListener) {
mOnClickListener = onClickListener;
}
@Override
protected int getSecondTargetResId() {
return R.layout.preference_widget_primary_switch;
}
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
// Setup the switch.
View checkableView = view.itemView.findViewById(R.id.switchWidget);
if (checkableView != null && checkableView instanceof Switch) {
final Switch switchView = (Switch) checkableView;
switchView.setChecked(mChecked);
switchView.setOnClickListener(mListener);
// Store this for later.
mSwitch = switchView;
}
}
}
} }

View File

@@ -18,10 +18,7 @@ package com.android.settings.applications.credentials;
import static com.android.settings.core.BasePreferenceController.AVAILABLE; import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE; import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import android.app.Activity; import android.app.Activity;
@@ -33,15 +30,12 @@ import android.content.pm.ServiceInfo;
import android.credentials.CredentialProviderInfo; import android.credentials.CredentialProviderInfo;
import android.net.Uri; import android.net.Uri;
import android.os.Looper; import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings; import android.provider.Settings;
import androidx.lifecycle.Lifecycle;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -86,10 +80,12 @@ public class CredentialManagerPreferenceControllerTest {
mCredentialsPreferenceCategory.setKey("credentials_test"); mCredentialsPreferenceCategory.setKey("credentials_test");
mScreen.addPreference(mCredentialsPreferenceCategory); mScreen.addPreference(mCredentialsPreferenceCategory);
mReceivedResultCode = Optional.empty(); mReceivedResultCode = Optional.empty();
mDelegate = new CredentialManagerPreferenceController.Delegate() { mDelegate =
new CredentialManagerPreferenceController.Delegate() {
public void setActivityResult(int resultCode) { public void setActivityResult(int resultCode) {
mReceivedResultCode = Optional.of(resultCode); mReceivedResultCode = Optional.of(resultCode);
} }
public void forceDelegateRefresh() {} public void forceDelegateRefresh() {}
}; };
} }
@@ -134,7 +130,7 @@ public class CredentialManagerPreferenceControllerTest {
} }
@Test @Test
public void buildSwitchPreference() { public void buildPreference() {
CredentialProviderInfo providerInfo1 = CredentialProviderInfo providerInfo1 =
createCredentialProviderInfoWithSubtitle( createCredentialProviderInfoWithSubtitle(
"com.android.provider1", "ClassA", "Service Title", null); "com.android.provider1", "ClassA", "Service Title", null);
@@ -158,13 +154,15 @@ public class CredentialManagerPreferenceControllerTest {
assertThat(enabledProviders.contains("com.android.provider1")).isTrue(); assertThat(enabledProviders.contains("com.android.provider1")).isTrue();
// Create the pref (checked). // Create the pref (checked).
SwitchPreference pref = controller.createPreference(mContext, providerInfo1); CredentialManagerPreferenceController.CombiPreference pref =
controller.createPreference(mContext, providerInfo1);
assertThat(pref.getTitle().toString()).isEqualTo("Service Title"); assertThat(pref.getTitle().toString()).isEqualTo("Service Title");
assertThat(pref.isChecked()).isTrue(); assertThat(pref.isChecked()).isTrue();
assertThat(pref.getSummary()).isNull(); assertThat(pref.getSummary()).isNull();
// Create the pref (not checked). // Create the pref (not checked).
SwitchPreference pref2 = controller.createPreference(mContext, providerInfo2); CredentialManagerPreferenceController.CombiPreference pref2 =
controller.createPreference(mContext, providerInfo2);
assertThat(pref2.getTitle().toString()).isEqualTo("Service Title"); assertThat(pref2.getTitle().toString()).isEqualTo("Service Title");
assertThat(pref2.isChecked()).isFalse(); assertThat(pref2.isChecked()).isFalse();
assertThat(pref2.getSummary().toString()).isEqualTo("Summary Text"); assertThat(pref2.getSummary().toString()).isEqualTo("Summary Text");
@@ -311,7 +309,7 @@ public class CredentialManagerPreferenceControllerTest {
assertThat(controller.isConnected()).isFalse(); assertThat(controller.isConnected()).isFalse();
assertThat(mCredentialsPreferenceCategory.getPreferenceCount()).isEqualTo(3); assertThat(mCredentialsPreferenceCategory.getPreferenceCount()).isEqualTo(3);
Map<String, SwitchPreference> prefs = Map<String, CredentialManagerPreferenceController.CombiPreference> prefs =
controller.buildPreferenceList(mContext, mCredentialsPreferenceCategory); controller.buildPreferenceList(mContext, mCredentialsPreferenceCategory);
assertThat(prefs.keySet()) assertThat(prefs.keySet())
.containsExactly(TEST_PACKAGE_NAME_A, TEST_PACKAGE_NAME_B, TEST_PACKAGE_NAME_C); .containsExactly(TEST_PACKAGE_NAME_A, TEST_PACKAGE_NAME_B, TEST_PACKAGE_NAME_C);
@@ -349,7 +347,8 @@ public class CredentialManagerPreferenceControllerTest {
Intent intent = new Intent(PRIMARY_INTENT); Intent intent = new Intent(PRIMARY_INTENT);
intent.setData(Uri.parse("package:" + packageName)); intent.setData(Uri.parse("package:" + packageName));
assertThat(controller.verifyReceivedIntent(intent)).isTrue(); assertThat(controller.verifyReceivedIntent(intent)).isTrue();
controller.completeEnableProviderDialogBox(DialogInterface.BUTTON_POSITIVE, packageName, true); controller.completeEnableProviderDialogBox(
DialogInterface.BUTTON_POSITIVE, packageName, true);
assertThat(mReceivedResultCode.get()).isEqualTo(Activity.RESULT_OK); assertThat(mReceivedResultCode.get()).isEqualTo(Activity.RESULT_OK);
} }
@@ -364,7 +363,8 @@ public class CredentialManagerPreferenceControllerTest {
Intent intent = new Intent(PRIMARY_INTENT); Intent intent = new Intent(PRIMARY_INTENT);
intent.setData(Uri.parse("package:" + packageName)); intent.setData(Uri.parse("package:" + packageName));
assertThat(controller.verifyReceivedIntent(intent)).isTrue(); assertThat(controller.verifyReceivedIntent(intent)).isTrue();
controller.completeEnableProviderDialogBox(DialogInterface.BUTTON_NEGATIVE, packageName, true); controller.completeEnableProviderDialogBox(
DialogInterface.BUTTON_NEGATIVE, packageName, true);
assertThat(mReceivedResultCode.get()).isEqualTo(Activity.RESULT_CANCELED); assertThat(mReceivedResultCode.get()).isEqualTo(Activity.RESULT_CANCELED);
} }
@@ -390,7 +390,8 @@ public class CredentialManagerPreferenceControllerTest {
Intent intent = new Intent(ALTERNATE_INTENT); Intent intent = new Intent(ALTERNATE_INTENT);
intent.setData(Uri.parse("package:" + packageName)); intent.setData(Uri.parse("package:" + packageName));
assertThat(controller.verifyReceivedIntent(intent)).isTrue(); assertThat(controller.verifyReceivedIntent(intent)).isTrue();
controller.completeEnableProviderDialogBox(DialogInterface.BUTTON_POSITIVE, packageName, true); controller.completeEnableProviderDialogBox(
DialogInterface.BUTTON_POSITIVE, packageName, true);
assertThat(mReceivedResultCode.get()).isEqualTo(Activity.RESULT_OK); assertThat(mReceivedResultCode.get()).isEqualTo(Activity.RESULT_OK);
} }
@@ -405,7 +406,8 @@ public class CredentialManagerPreferenceControllerTest {
Intent intent = new Intent(ALTERNATE_INTENT); Intent intent = new Intent(ALTERNATE_INTENT);
intent.setData(Uri.parse("package:" + packageName)); intent.setData(Uri.parse("package:" + packageName));
assertThat(controller.verifyReceivedIntent(intent)).isTrue(); assertThat(controller.verifyReceivedIntent(intent)).isTrue();
controller.completeEnableProviderDialogBox(DialogInterface.BUTTON_NEGATIVE, packageName, true); controller.completeEnableProviderDialogBox(
DialogInterface.BUTTON_NEGATIVE, packageName, true);
assertThat(mReceivedResultCode.get()).isEqualTo(Activity.RESULT_CANCELED); assertThat(mReceivedResultCode.get()).isEqualTo(Activity.RESULT_CANCELED);
} }