Merge "Align settings with new mocks" into udc-dev am: 21733fa106 am: 1022918da5

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/22912923

Change-Id: Ica4092467ac4a290b5f1a5ec0f7c7905e3928755
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Becca Hughes
2023-05-03 17:36:09 +00:00
committed by Automerger Merge Worker
7 changed files with 287 additions and 211 deletions

View File

@@ -41,8 +41,8 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.OutcomeReceiver;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.service.autofill.AutofillServiceInfo;
import android.text.TextUtils;
import android.util.IconDrawableFactory;
import android.util.Log;
@@ -79,6 +79,15 @@ import java.util.concurrent.Executor;
public class CredentialManagerPreferenceController extends BasePreferenceController
implements LifecycleObserver {
public static final String ADD_SERVICE_DEVICE_CONFIG = "credential_manager_service_search_uri";
/**
* In the settings logic we should hide the list of additional credman providers if there is no
* provider selected at the top. The current logic relies on checking whether the autofill
* provider is set which won't work for cred-man only providers. Therefore when a CM only
* provider is set we will set the autofill setting to be this placeholder.
*/
public static final String AUTOFILL_CREDMAN_ONLY_PROVIDER_PLACEHOLDER = "credential-provider";
private static final String TAG = "CredentialManagerPreferenceController";
private static final String ALTERNATE_INTENT = "android.settings.SYNC_SETTINGS";
private static final String PRIMARY_INTENT = "android.settings.CREDENTIAL_PROVIDER";
@@ -99,6 +108,8 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
private @Nullable String mFlagOverrideForTest = null;
private @Nullable PreferenceScreen mPreferenceScreen = null;
private boolean mVisibility = false;
public CredentialManagerPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mPm = context.getPackageManager();
@@ -131,7 +142,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
return UNSUPPORTED_ON_DEVICE;
}
if (!isAutofillPrefSelected()) {
if (!mVisibility) {
return CONDITIONALLY_UNAVAILABLE;
}
@@ -271,7 +282,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
setAvailableServices(
mCredentialManager.getCredentialProviderServices(
getUser(), CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY),
getUser(), CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS),
null);
}
@@ -287,6 +298,17 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
}
}
private void setVisibility(boolean newVisibility) {
if (newVisibility == mVisibility) {
return;
}
mVisibility = newVisibility;
if (mDelegate != null) {
mDelegate.forceDelegateRefresh();
}
}
@VisibleForTesting
void setAvailableServices(
List<CredentialProviderInfo> availableServices, String flagOverrideForTest) {
@@ -320,48 +342,8 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
PreferenceGroup group = screen.findPreference(getPreferenceKey());
group.removeAll();
// Hide/show based on autofill pref.
boolean isVisible = isAutofillPrefSelected();
screen.setVisible(isVisible);
group.setVisible(isVisible);
if (!isVisible) {
return;
}
Context context = screen.getContext();
mPrefs.putAll(buildPreferenceList(context, group));
// Add the "add service" button only when there are no providers.
if (mPrefs.isEmpty()) {
String searchUri = getAddServiceUri(context);
if (!TextUtils.isEmpty(searchUri)) {
group.addPreference(newAddServicePreference(searchUri, context));
}
}
}
/**
* Returns the "add service" URI to show the play store. It will first try and use the
* credential manager specific search URI and if that is null it will fallback to the autofill
* one.
*/
public @NonNull String getAddServiceUri(@NonNull Context context) {
// Check the credential manager gflag for a link.
String searchUri =
DeviceConfig.getString(
DeviceConfig.NAMESPACE_CREDENTIAL,
ADD_SERVICE_DEVICE_CONFIG,
mFlagOverrideForTest);
if (!TextUtils.isEmpty(searchUri)) {
return searchUri;
}
// If not fall back on autofill.
return Settings.Secure.getStringForUser(
context.getContentResolver(),
Settings.Secure.AUTOFILL_SERVICE_SEARCH_URI,
getUser());
}
/**
@@ -396,52 +378,59 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
@VisibleForTesting
public Map<String, SwitchPreference> buildPreferenceList(
Context context, PreferenceGroup group) {
// Group the services by package name.
Map<String, List<CredentialProviderInfo>> groupedInfos = new HashMap<>();
for (CredentialProviderInfo cpi : mServices) {
String packageName = cpi.getServiceInfo().packageName;
if (isProviderHiddenBecauseOfAutofill(packageName)) {
// Get the selected autofill provider. If it is the placeholder then replace it with an
// empty string.
String selectedAutofillProvider =
DefaultCombinedPicker.getSelectedAutofillProvider(mContext, getUser());
if (TextUtils.equals(
selectedAutofillProvider, AUTOFILL_CREDMAN_ONLY_PROVIDER_PLACEHOLDER)) {
selectedAutofillProvider = "";
}
// Get the list of combined providers.
List<CombinedProviderInfo> providers =
CombinedProviderInfo.buildMergedList(
AutofillServiceInfo.getAvailableServices(context, getUser()),
mServices,
selectedAutofillProvider);
// Get the provider that is displayed at the top. If there is none then hide
// everything.
CombinedProviderInfo topProvider = CombinedProviderInfo.getTopProvider(providers);
if (topProvider == null) {
setVisibility(false);
return new HashMap<>();
}
Map<String, SwitchPreference> output = new HashMap<>();
for (CombinedProviderInfo combinedInfo : providers) {
final String packageName = combinedInfo.getApplicationInfo().packageName;
// If this provider is displayed at the top then we should not show it.
if (topProvider != null
&& topProvider.getApplicationInfo().packageName.equals(packageName)) {
continue;
}
if (!groupedInfos.containsKey(packageName)) {
groupedInfos.put(packageName, new ArrayList<>());
// If this is an autofill provider then don't show it here.
if (combinedInfo.getCredentialProviderInfos().isEmpty()) {
continue;
}
groupedInfos.get(packageName).add(cpi);
}
// Build the pref list.
Map<String, SwitchPreference> output = new HashMap<>();
for (String packageName : groupedInfos.keySet()) {
List<CredentialProviderInfo> infos = groupedInfos.get(packageName);
CredentialProviderInfo firstInfo = infos.get(0);
ServiceInfo firstServiceInfo = firstInfo.getServiceInfo();
CharSequence title = firstInfo.getLabel(context);
Drawable icon = firstInfo.getServiceIcon(context);
if (infos.size() > 1) {
// If there is more than one then group them under the package.
ApplicationInfo appInfo = firstServiceInfo.applicationInfo;
if (appInfo.nonLocalizedLabel != null) {
title = appInfo.loadLabel(mPm);
}
icon = mIconFactory.getBadgedIcon(appInfo, getUser());
}
// If there is no title then show the package manager.
if (TextUtils.isEmpty(title)) {
title = firstServiceInfo.packageName;
}
Drawable icon = combinedInfo.getAppIcon(context);
CharSequence title = combinedInfo.getAppName(context);
// Build the pref and add it to the output & group.
SwitchPreference pref =
addProviderPreference(
context, title, icon, packageName, firstInfo.getSettingsSubtitle());
context, title, icon, packageName, combinedInfo.getSettingsSubtitle());
output.put(packageName, pref);
group.addPreference(pref);
}
// Set the visibility if we have services.
setVisibility(!output.isEmpty());
return output;
}
@@ -607,29 +596,6 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
return new NewProviderConfirmationDialogFragment(host, packageName, appName);
}
/** If the provider is also the autofill provider then hide it. */
@VisibleForTesting
public boolean isProviderHiddenBecauseOfAutofill(String packageName) {
final String autofillService =
Settings.Secure.getStringForUser(
mContext.getContentResolver(), Settings.Secure.AUTOFILL_SERVICE, getUser());
if (autofillService == null || TextUtils.isEmpty(autofillService)) {
return false;
}
if (packageName == null || TextUtils.isEmpty(packageName)) {
return false;
}
return autofillService.startsWith(packageName);
}
private boolean isAutofillPrefSelected() {
final String autofillService =
Settings.Secure.getStringForUser(
mContext.getContentResolver(), Settings.Secure.AUTOFILL_SERVICE, getUser());
return !TextUtils.isEmpty(autofillService);
}
@VisibleForTesting
void completeEnableProviderDialogBox(
int whichButton, String packageName, boolean setActivityResult) {