From d7c780aac7a47d1316a03947bc33cb624f5fd77d Mon Sep 17 00:00:00 2001 From: Becca Hughes Date: Fri, 1 Sep 2023 07:47:03 -0700 Subject: [PATCH] Add missing divider to credman settings Test: ondevice Bug: 274126440 Change-Id: I3ba68a749899840c6ed646793e1d65725f10cce8 --- ...CredentialManagerPreferenceController.java | 112 +++++++++++++++--- ...entialManagerPreferenceControllerTest.java | 44 +++---- 2 files changed, 116 insertions(+), 40 deletions(-) diff --git a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java index f704ca81a7e..4ba634c56c8 100644 --- a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java +++ b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java @@ -47,6 +47,8 @@ import android.service.autofill.AutofillServiceInfo; import android.text.TextUtils; import android.util.IconDrawableFactory; import android.util.Log; +import android.view.View; +import android.widget.Switch; import androidx.appcompat.app.AlertDialog; import androidx.core.content.ContextCompat; @@ -58,7 +60,7 @@ import androidx.lifecycle.OnLifecycleEvent; import androidx.preference.Preference; import androidx.preference.PreferenceGroup; import androidx.preference.PreferenceScreen; -import androidx.preference.SwitchPreference; +import androidx.preference.PreferenceViewHolder; import com.android.internal.annotations.VisibleForTesting; 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.dashboard.DashboardFragment; import com.android.settingslib.utils.ThreadUtils; +import com.android.settingslib.widget.TwoTargetPreference; import java.util.ArrayList; import java.util.HashMap; @@ -100,7 +103,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl private final Set mEnabledPackageNames; private final @Nullable CredentialManager mCredentialManager; private final Executor mExecutor; - private final Map mPrefs = new HashMap<>(); // key is package name + private final Map mPrefs = new HashMap<>(); // key is package name private final List mPendingServiceInfos = new ArrayList<>(); private final Handler mHandler = new Handler(); 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. */ @VisibleForTesting - public Map buildPreferenceList( + public Map buildPreferenceList( Context context, PreferenceGroup group) { // Get the selected autofill provider. If it is the placeholder then replace it with an // empty string. @@ -415,7 +418,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl return new HashMap<>(); } - Map output = new HashMap<>(); + Map output = new HashMap<>(); for (CombinedProviderInfo combinedInfo : providers) { final String packageName = combinedInfo.getApplicationInfo().packageName; @@ -434,7 +437,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl CharSequence title = combinedInfo.getAppName(context); // Build the pref and add it to the output & group. - SwitchPreference pref = + CombiPreference pref = addProviderPreference( context, title, icon, packageName, combinedInfo.getSettingsSubtitle()); output.put(packageName, pref); @@ -449,7 +452,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl /** Creates a preference object based on the provider info. */ @VisibleForTesting - public SwitchPreference createPreference(Context context, CredentialProviderInfo service) { + public CombiPreference createPreference(Context context, CredentialProviderInfo service) { CharSequence label = service.getLabel(context); return addProviderPreference( context, @@ -510,15 +513,15 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl return enabledServices; } - private SwitchPreference addProviderPreference( + private CombiPreference addProviderPreference( @NonNull Context prefContext, @NonNull CharSequence title, @Nullable Drawable icon, @NonNull String packageName, @Nullable CharSequence subtitle) { - final SwitchPreference pref = new SwitchPreference(prefContext); + final CombiPreference pref = + new CombiPreference(prefContext, mEnabledPackageNames.contains(packageName)); pref.setTitle(title); - pref.setChecked(mEnabledPackageNames.contains(packageName)); if (icon != null) { pref.setIcon(Utils.getSafeIcon(icon)); @@ -528,10 +531,8 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl pref.setSummary(subtitle); } - pref.setOnPreferenceClickListener( - p -> { - boolean isChecked = pref.isChecked(); - + pref.setPreferenceListener( + (p, isChecked) -> { if (isChecked) { if (mEnabledPackageNames.size() >= MAX_SELECTABLE_PROVIDERS) { // Show the error if too many enabled. @@ -539,11 +540,11 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl final DialogFragment fragment = newErrorDialogFragment(); if (fragment == null || mFragmentManager == null) { - return true; + return; } fragment.show(mFragmentManager, ErrorDialogFragment.TAG); - return true; + return; } togglePackageNameEnabled(packageName); @@ -552,12 +553,9 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl if (mPrefs.containsKey(packageName)) { mPrefs.get(packageName).setChecked(true); } - return true; } else { togglePackageNameDisabled(packageName); } - - return true; }); return pref; @@ -836,4 +834,80 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl updateFromExternal(); } } -} \ No newline at end of file + + /** 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; + } + } + } +} 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 d5203647375..7d400ad7405 100644 --- a/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java @@ -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.CONDITIONALLY_UNAVAILABLE; - import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import android.app.Activity; @@ -33,15 +30,12 @@ import android.content.pm.ServiceInfo; import android.credentials.CredentialProviderInfo; import android.net.Uri; import android.os.Looper; -import android.os.UserHandle; import android.provider.Settings; -import androidx.lifecycle.Lifecycle; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; -import androidx.preference.SwitchPreference; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -86,12 +80,14 @@ public class CredentialManagerPreferenceControllerTest { mCredentialsPreferenceCategory.setKey("credentials_test"); mScreen.addPreference(mCredentialsPreferenceCategory); mReceivedResultCode = Optional.empty(); - mDelegate = new CredentialManagerPreferenceController.Delegate() { - public void setActivityResult(int resultCode) { - mReceivedResultCode = Optional.of(resultCode); - } - public void forceDelegateRefresh() {} - }; + mDelegate = + new CredentialManagerPreferenceController.Delegate() { + public void setActivityResult(int resultCode) { + mReceivedResultCode = Optional.of(resultCode); + } + + public void forceDelegateRefresh() {} + }; } @Test @@ -134,7 +130,7 @@ public class CredentialManagerPreferenceControllerTest { } @Test - public void buildSwitchPreference() { + public void buildPreference() { CredentialProviderInfo providerInfo1 = createCredentialProviderInfoWithSubtitle( "com.android.provider1", "ClassA", "Service Title", null); @@ -158,13 +154,15 @@ public class CredentialManagerPreferenceControllerTest { assertThat(enabledProviders.contains("com.android.provider1")).isTrue(); // 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.isChecked()).isTrue(); assertThat(pref.getSummary()).isNull(); // 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.isChecked()).isFalse(); assertThat(pref2.getSummary().toString()).isEqualTo("Summary Text"); @@ -311,7 +309,7 @@ public class CredentialManagerPreferenceControllerTest { assertThat(controller.isConnected()).isFalse(); assertThat(mCredentialsPreferenceCategory.getPreferenceCount()).isEqualTo(3); - Map prefs = + Map prefs = controller.buildPreferenceList(mContext, mCredentialsPreferenceCategory); assertThat(prefs.keySet()) .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.setData(Uri.parse("package:" + packageName)); 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); } @@ -364,7 +363,8 @@ public class CredentialManagerPreferenceControllerTest { Intent intent = new Intent(PRIMARY_INTENT); intent.setData(Uri.parse("package:" + packageName)); 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); } @@ -390,7 +390,8 @@ public class CredentialManagerPreferenceControllerTest { Intent intent = new Intent(ALTERNATE_INTENT); intent.setData(Uri.parse("package:" + packageName)); 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); } @@ -405,7 +406,8 @@ public class CredentialManagerPreferenceControllerTest { Intent intent = new Intent(ALTERNATE_INTENT); intent.setData(Uri.parse("package:" + packageName)); 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); } @@ -502,4 +504,4 @@ public class CredentialManagerPreferenceControllerTest { return new CredentialProviderInfo.Builder(si).setOverrideLabel(serviceLabel); } -} \ No newline at end of file +}