Align settings with new mocks

Test: ondevice
Bug: 278919696
Change-Id: I274126bce3616596c4a81dd3385f0844d8bdbf71
This commit is contained in:
Becca Hughes
2023-04-26 22:52:10 +00:00
parent 7dd5f5e156
commit b21df6c5fc
7 changed files with 287 additions and 211 deletions

View File

@@ -237,7 +237,10 @@ public final class CombinedProviderInfo {
List<CredentialProviderInfo> cpi = credmanServices.get(packageName); List<CredentialProviderInfo> cpi = credmanServices.get(packageName);
// If there are multiple autofill services then pick the first one. // If there are multiple autofill services then pick the first one.
AutofillServiceInfo selectedAsi = asi.isEmpty() ? null : asi.get(0); AutofillServiceInfo selectedAsi = null;
if (asi != null && !asi.isEmpty()) {
selectedAsi = asi.get(0);
}
// Check if we are the default autofill provider. // Check if we are the default autofill provider.
boolean isDefaultAutofillProvider = false; boolean isDefaultAutofillProvider = false;

View File

@@ -41,8 +41,8 @@ import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.OutcomeReceiver; import android.os.OutcomeReceiver;
import android.os.UserHandle; import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.provider.Settings; import android.provider.Settings;
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;
@@ -79,6 +79,15 @@ import java.util.concurrent.Executor;
public class CredentialManagerPreferenceController extends BasePreferenceController public class CredentialManagerPreferenceController extends BasePreferenceController
implements LifecycleObserver { implements LifecycleObserver {
public static final String ADD_SERVICE_DEVICE_CONFIG = "credential_manager_service_search_uri"; 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 TAG = "CredentialManagerPreferenceController";
private static final String ALTERNATE_INTENT = "android.settings.SYNC_SETTINGS"; private static final String ALTERNATE_INTENT = "android.settings.SYNC_SETTINGS";
private static final String PRIMARY_INTENT = "android.settings.CREDENTIAL_PROVIDER"; 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 String mFlagOverrideForTest = null;
private @Nullable PreferenceScreen mPreferenceScreen = null; private @Nullable PreferenceScreen mPreferenceScreen = null;
private boolean mVisibility = false;
public CredentialManagerPreferenceController(Context context, String preferenceKey) { public CredentialManagerPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey); super(context, preferenceKey);
mPm = context.getPackageManager(); mPm = context.getPackageManager();
@@ -131,7 +142,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
return UNSUPPORTED_ON_DEVICE; return UNSUPPORTED_ON_DEVICE;
} }
if (!isAutofillPrefSelected()) { if (!mVisibility) {
return CONDITIONALLY_UNAVAILABLE; return CONDITIONALLY_UNAVAILABLE;
} }
@@ -271,7 +282,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
setAvailableServices( setAvailableServices(
mCredentialManager.getCredentialProviderServices( mCredentialManager.getCredentialProviderServices(
getUser(), CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY), getUser(), CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS),
null); 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 @VisibleForTesting
void setAvailableServices( void setAvailableServices(
List<CredentialProviderInfo> availableServices, String flagOverrideForTest) { List<CredentialProviderInfo> availableServices, String flagOverrideForTest) {
@@ -320,48 +342,8 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
PreferenceGroup group = screen.findPreference(getPreferenceKey()); PreferenceGroup group = screen.findPreference(getPreferenceKey());
group.removeAll(); group.removeAll();
// Hide/show based on autofill pref.
boolean isVisible = isAutofillPrefSelected();
screen.setVisible(isVisible);
group.setVisible(isVisible);
if (!isVisible) {
return;
}
Context context = screen.getContext(); Context context = screen.getContext();
mPrefs.putAll(buildPreferenceList(context, group)); 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 @VisibleForTesting
public Map<String, SwitchPreference> buildPreferenceList( public Map<String, SwitchPreference> buildPreferenceList(
Context context, PreferenceGroup group) { Context context, PreferenceGroup group) {
// Group the services by package name. // Get the selected autofill provider. If it is the placeholder then replace it with an
Map<String, List<CredentialProviderInfo>> groupedInfos = new HashMap<>(); // empty string.
for (CredentialProviderInfo cpi : mServices) { String selectedAutofillProvider =
String packageName = cpi.getServiceInfo().packageName; DefaultCombinedPicker.getSelectedAutofillProvider(mContext, getUser());
if (isProviderHiddenBecauseOfAutofill(packageName)) { 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; continue;
} }
if (!groupedInfos.containsKey(packageName)) { // If this is an autofill provider then don't show it here.
groupedInfos.put(packageName, new ArrayList<>()); if (combinedInfo.getCredentialProviderInfos().isEmpty()) {
continue;
} }
groupedInfos.get(packageName).add(cpi); Drawable icon = combinedInfo.getAppIcon(context);
} CharSequence title = combinedInfo.getAppName(context);
// 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;
}
// Build the pref and add it to the output & group. // Build the pref and add it to the output & group.
SwitchPreference pref = SwitchPreference pref =
addProviderPreference( addProviderPreference(
context, title, icon, packageName, firstInfo.getSettingsSubtitle()); context, title, icon, packageName, combinedInfo.getSettingsSubtitle());
output.put(packageName, pref); output.put(packageName, pref);
group.addPreference(pref); group.addPreference(pref);
} }
// Set the visibility if we have services.
setVisibility(!output.isEmpty());
return output; return output;
} }
@@ -607,29 +596,6 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
return new NewProviderConfirmationDialogFragment(host, packageName, appName); 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 @VisibleForTesting
void completeEnableProviderDialogBox( void completeEnableProviderDialogBox(
int whichButton, String packageName, boolean setActivityResult) { int whichButton, String packageName, boolean setActivityResult) {

View File

@@ -16,21 +16,27 @@
package com.android.settings.applications.credentials; package com.android.settings.applications.credentials;
import android.annotation.Nullable;
import android.app.Activity; import android.app.Activity;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ServiceInfo;
import android.credentials.CredentialManager;
import android.credentials.CredentialProviderInfo;
import android.credentials.SetEnabledProvidersException;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.OutcomeReceiver;
import android.os.UserHandle; import android.os.UserHandle;
import android.provider.Settings; import android.provider.Settings;
import android.service.autofill.AutofillService;
import android.service.autofill.AutofillServiceInfo; import android.service.autofill.AutofillServiceInfo;
import android.text.Html; import android.text.Html;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import androidx.core.content.ContextCompat;
import androidx.preference.Preference; import androidx.preference.Preference;
import com.android.internal.content.PackageMonitor; import com.android.internal.content.PackageMonitor;
@@ -47,8 +53,8 @@ public class DefaultCombinedPicker extends DefaultAppPickerFragment {
private static final String TAG = "DefaultCombinedPicker"; private static final String TAG = "DefaultCombinedPicker";
public static final String SETTING = Settings.Secure.AUTOFILL_SERVICE; public static final String AUTOFILL_SETTING = Settings.Secure.AUTOFILL_SERVICE;
public static final Intent AUTOFILL_PROBE = new Intent(AutofillService.SERVICE_INTERFACE); public static final String CREDENTIAL_SETTING = Settings.Secure.CREDENTIAL_SERVICE;
/** Extra set when the fragment is implementing ACTION_REQUEST_SET_AUTOFILL_SERVICE. */ /** Extra set when the fragment is implementing ACTION_REQUEST_SET_AUTOFILL_SERVICE. */
public static final String EXTRA_PACKAGE_NAME = "package_name"; public static final String EXTRA_PACKAGE_NAME = "package_name";
@@ -56,6 +62,8 @@ public class DefaultCombinedPicker extends DefaultAppPickerFragment {
/** Set when the fragment is implementing ACTION_REQUEST_SET_AUTOFILL_SERVICE. */ /** Set when the fragment is implementing ACTION_REQUEST_SET_AUTOFILL_SERVICE. */
private DialogInterface.OnClickListener mCancelListener; private DialogInterface.OnClickListener mCancelListener;
private CredentialManager mCredentialManager;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@@ -71,6 +79,7 @@ public class DefaultCombinedPicker extends DefaultAppPickerFragment {
// ACTION_REQUEST_SET_AUTOFILL_SERVICE and we should always use the calling uid. // ACTION_REQUEST_SET_AUTOFILL_SERVICE and we should always use the calling uid.
mUserId = UserHandle.myUserId(); mUserId = UserHandle.myUserId();
} }
mSettingsPackageMonitor.register(activity, activity.getMainLooper(), false); mSettingsPackageMonitor.register(activity, activity.getMainLooper(), false);
update(); update();
} }
@@ -187,35 +196,76 @@ public class DefaultCombinedPicker extends DefaultAppPickerFragment {
} }
} }
@Override /**
* Get the Credential Manager service if we haven't already got it. We need to get the service
* later because if we do it in onCreate it will fail.
*/
private @Nullable CredentialManager getCredentialProviderService() {
if (mCredentialManager == null) {
mCredentialManager = getContext().getSystemService(CredentialManager.class);
}
return mCredentialManager;
}
private List<CombinedProviderInfo> getAllProviders() {
final Context context = getContext();
final List<AutofillServiceInfo> autofillProviders =
AutofillServiceInfo.getAvailableServices(context, mUserId);
final CredentialManager service = getCredentialProviderService();
final List<CredentialProviderInfo> credManProviders = new ArrayList<>();
if (service != null) {
credManProviders.addAll(
service.getCredentialProviderServices(
mUserId, CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY));
}
final String selectedAutofillProvider = getSelectedAutofillProvider(context, mUserId);
return CombinedProviderInfo.buildMergedList(
autofillProviders, credManProviders, selectedAutofillProvider);
}
public static String getSelectedAutofillProvider(Context context, int userId) {
return Settings.Secure.getStringForUser(
context.getContentResolver(), AUTOFILL_SETTING, userId);
}
protected List<DefaultAppInfo> getCandidates() { protected List<DefaultAppInfo> getCandidates() {
final Context context = getContext();
final List<CombinedProviderInfo> allProviders = getAllProviders();
final List<DefaultAppInfo> candidates = new ArrayList<>(); final List<DefaultAppInfo> candidates = new ArrayList<>();
final List<AutofillServiceInfo> services =
AutofillServiceInfo.getAvailableServices(getContext(), mUserId); for (CombinedProviderInfo cpi : allProviders) {
for (AutofillServiceInfo asi : services) { ServiceInfo brandingService = cpi.getBrandingService();
candidates.add( if (brandingService == null) {
new DefaultAppInfo( candidates.add(
getContext(), mPm, mUserId, asi.getServiceInfo().getComponentName())); new DefaultAppInfo(
context,
mPm,
mUserId,
cpi.getApplicationInfo(),
cpi.getSettingsSubtitle(),
true));
} else {
candidates.add(
new DefaultAppInfo(
context,
mPm,
mUserId,
brandingService,
cpi.getSettingsSubtitle(),
true));
}
} }
return candidates; return candidates;
} }
public static String getDefaultKey(Context context, int userId) {
String setting =
Settings.Secure.getStringForUser(context.getContentResolver(), SETTING, userId);
if (setting != null) {
ComponentName componentName = ComponentName.unflattenFromString(setting);
if (componentName != null) {
return componentName.flattenToString();
}
}
return null;
}
@Override @Override
protected String getDefaultKey() { protected String getDefaultKey() {
return getDefaultKey(getContext(), mUserId); final CombinedProviderInfo topProvider =
CombinedProviderInfo.getTopProvider(getAllProviders());
return topProvider == null ? "" : topProvider.getApplicationInfo().packageName;
} }
@Override @Override
@@ -234,7 +284,39 @@ public class DefaultCombinedPicker extends DefaultAppPickerFragment {
@Override @Override
protected boolean setDefaultKey(String key) { protected boolean setDefaultKey(String key) {
Settings.Secure.putStringForUser(getContext().getContentResolver(), SETTING, key, mUserId); // Get the list of providers and see if any match the key (package name).
final List<CombinedProviderInfo> allProviders = getAllProviders();
CombinedProviderInfo matchedProvider = null;
for (CombinedProviderInfo cpi : allProviders) {
if (cpi.getApplicationInfo().packageName.equals(key)) {
matchedProvider = cpi;
break;
}
}
// If there were none then clear the stored providers.
if (matchedProvider == null) {
setProviders(null, new ArrayList<>());
return true;
}
// Get the component names and save them.
final List<String> credManComponents = new ArrayList<>();
for (CredentialProviderInfo pi : matchedProvider.getCredentialProviderInfos()) {
credManComponents.add(pi.getServiceInfo().getComponentName().flattenToString());
}
String autofillValue = null;
if (matchedProvider.getAutofillServiceInfo() != null) {
autofillValue =
matchedProvider
.getAutofillServiceInfo()
.getServiceInfo()
.getComponentName()
.flattenToString();
}
setProviders(autofillValue, credManComponents);
// Check if activity was launched from Settings.ACTION_REQUEST_SET_AUTOFILL_SERVICE // Check if activity was launched from Settings.ACTION_REQUEST_SET_AUTOFILL_SERVICE
// intent, and set proper result if so... // intent, and set proper result if so...
@@ -255,4 +337,38 @@ public class DefaultCombinedPicker extends DefaultAppPickerFragment {
return true; return true;
} }
private void setProviders(String autofillProvider, List<String> credManProviders) {
if (TextUtils.isEmpty(autofillProvider)) {
if (credManProviders.size() > 0) {
autofillProvider =
CredentialManagerPreferenceController
.AUTOFILL_CREDMAN_ONLY_PROVIDER_PLACEHOLDER;
}
}
Settings.Secure.putStringForUser(
getContext().getContentResolver(), AUTOFILL_SETTING, autofillProvider, mUserId);
CredentialManager service = getCredentialProviderService();
if (service == null) {
return;
}
service.setEnabledProviders(
credManProviders,
mUserId,
ContextCompat.getMainExecutor(getContext()),
new OutcomeReceiver<Void, SetEnabledProvidersException>() {
@Override
public void onResult(Void result) {
Log.i(TAG, "setEnabledProviders success");
}
@Override
public void onError(SetEnabledProvidersException e) {
Log.e(TAG, "setEnabledProviders error: " + e.toString());
}
});
}
} }

View File

@@ -23,7 +23,9 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo; import android.content.pm.ServiceInfo;
import android.credentials.CredentialManager; import android.credentials.CredentialManager;
import android.credentials.CredentialProviderInfo;
import android.provider.Settings; import android.provider.Settings;
import android.service.autofill.AutofillService;
import android.service.autofill.AutofillServiceInfo; import android.service.autofill.AutofillServiceInfo;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
@@ -36,6 +38,9 @@ import java.util.List;
public class DefaultCombinedPreferenceController extends DefaultAppPreferenceController { public class DefaultCombinedPreferenceController extends DefaultAppPreferenceController {
private static final Intent AUTOFILL_PROBE = new Intent(AutofillService.SERVICE_INTERFACE);
private static final String TAG = "DefaultCombinedPreferenceController";
private final AutofillManager mAutofillManager; private final AutofillManager mAutofillManager;
private final CredentialManager mCredentialManager; private final CredentialManager mCredentialManager;
@@ -76,26 +81,57 @@ public class DefaultCombinedPreferenceController extends DefaultAppPreferenceCon
@Override @Override
protected DefaultAppInfo getDefaultAppInfo() { protected DefaultAppInfo getDefaultAppInfo() {
final String flattenComponent = List<CombinedProviderInfo> providers = getAllProviders(mUserId);
Settings.Secure.getString( CombinedProviderInfo topProvider = CombinedProviderInfo.getTopProvider(providers);
mContext.getContentResolver(), DefaultCombinedPicker.SETTING); if (topProvider != null) {
if (!TextUtils.isEmpty(flattenComponent)) { ServiceInfo brandingService = topProvider.getBrandingService();
DefaultAppInfo appInfo = if (brandingService == null) {
new DefaultAppInfo( return new DefaultAppInfo(
mContext, mContext,
mPackageManager, mPackageManager,
mUserId, mUserId,
ComponentName.unflattenFromString(flattenComponent)); topProvider.getApplicationInfo(),
return appInfo; topProvider.getSettingsSubtitle(),
true);
} else {
return new DefaultAppInfo(
mContext,
mPackageManager,
mUserId,
brandingService,
topProvider.getSettingsSubtitle(),
true);
}
} }
return null; return null;
} }
private List<CombinedProviderInfo> getAllProviders(int userId) {
final List<AutofillServiceInfo> autofillProviders =
AutofillServiceInfo.getAvailableServices(mContext, userId);
final List<CredentialProviderInfo> credManProviders =
mCredentialManager.getCredentialProviderServices(
userId, CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY);
final String selectedAutofillProvider =
Settings.Secure.getStringForUser(
mContext.getContentResolver(),
DefaultCombinedPicker.AUTOFILL_SETTING,
userId);
return CombinedProviderInfo.buildMergedList(
autofillProviders, credManProviders, selectedAutofillProvider);
}
@Override @Override
protected boolean showLabelAsTitle() { protected boolean showLabelAsTitle() {
return true; return true;
} }
@Override
protected boolean showAppSummary() {
return true;
}
/** Provides Intent to setting activity for the specified autofill service. */ /** Provides Intent to setting activity for the specified autofill service. */
static final class AutofillSettingIntentProvider { static final class AutofillSettingIntentProvider {
@@ -113,9 +149,7 @@ public class DefaultCombinedPreferenceController extends DefaultAppPreferenceCon
final List<ResolveInfo> resolveInfos = final List<ResolveInfo> resolveInfos =
mContext.getPackageManager() mContext.getPackageManager()
.queryIntentServicesAsUser( .queryIntentServicesAsUser(
DefaultCombinedPicker.AUTOFILL_PROBE, AUTOFILL_PROBE, PackageManager.GET_META_DATA, mUserId);
PackageManager.GET_META_DATA,
mUserId);
for (ResolveInfo resolveInfo : resolveInfos) { for (ResolveInfo resolveInfo : resolveInfos) {
final ServiceInfo serviceInfo = resolveInfo.serviceInfo; final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
@@ -130,9 +164,7 @@ public class DefaultCombinedPreferenceController extends DefaultAppPreferenceCon
.getSettingsActivity(); .getSettingsActivity();
} catch (SecurityException e) { } catch (SecurityException e) {
// Service does not declare the proper permission, ignore it. // Service does not declare the proper permission, ignore it.
Log.w( Log.w(TAG, "Error getting info for " + serviceInfo + ": " + e);
"AutofillSettingIntentProvider",
"Error getting info for " + serviceInfo + ": " + e);
return null; return null;
} }
if (TextUtils.isEmpty(settingsActivity)) { if (TextUtils.isEmpty(settingsActivity)) {

View File

@@ -52,7 +52,7 @@ public class DefaultWorkCombinedPreferenceController extends DefaultCombinedPref
final String flattenComponent = final String flattenComponent =
Settings.Secure.getStringForUser( Settings.Secure.getStringForUser(
mContext.getContentResolver(), mContext.getContentResolver(),
DefaultCombinedPicker.SETTING, DefaultCombinedPicker.AUTOFILL_SETTING,
mUserHandle.getIdentifier()); mUserHandle.getIdentifier());
if (!TextUtils.isEmpty(flattenComponent)) { if (!TextUtils.isEmpty(flattenComponent)) {
DefaultAppInfo appInfo = DefaultAppInfo appInfo =

View File

@@ -18,6 +18,7 @@ package com.android.settings.applications.defaultapps;
import static com.android.settingslib.widget.TwoTargetPreference.ICON_SIZE_MEDIUM; import static com.android.settingslib.widget.TwoTargetPreference.ICON_SIZE_MEDIUM;
import android.annotation.Nullable;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
@@ -65,16 +66,21 @@ public abstract class DefaultAppPreferenceController extends AbstractPreferenceC
((TwoTargetPreference) preference).setIconSize(ICON_SIZE_MEDIUM); ((TwoTargetPreference) preference).setIconSize(ICON_SIZE_MEDIUM);
} }
if (!TextUtils.isEmpty(defaultAppLabel)) { if (!TextUtils.isEmpty(defaultAppLabel)) {
if (showLabelAsTitle()) { if (showLabelAsTitle() && showAppSummary()) {
preference.setTitle(defaultAppLabel);
preference.setSummary(getDefaultAppSummary());
} else if (showLabelAsTitle()) {
preference.setTitle(defaultAppLabel); preference.setTitle(defaultAppLabel);
} else { } else {
preference.setSummary(defaultAppLabel); preference.setSummary(defaultAppLabel);
} }
preference.setIcon(Utils.getSafeIcon(getDefaultAppIcon())); preference.setIcon(Utils.getSafeIcon(getDefaultAppIcon()));
} else { } else {
Log.d(TAG, "No default app"); Log.d(TAG, "No default app");
if (showLabelAsTitle()) { if (showLabelAsTitle()) {
preference.setTitle(R.string.app_list_preference_none); preference.setTitle(R.string.app_list_preference_none);
preference.setSummary(null);
} else { } else {
preference.setSummary(R.string.app_list_preference_none); preference.setSummary(R.string.app_list_preference_none);
} }
@@ -89,8 +95,7 @@ public abstract class DefaultAppPreferenceController extends AbstractPreferenceC
} }
final Intent settingIntent = getSettingIntent(app); final Intent settingIntent = getSettingIntent(app);
if (settingIntent != null) { if (settingIntent != null) {
((GearPreference) preference).setOnGearClickListener( ((GearPreference) preference).setOnGearClickListener(p -> startActivity(settingIntent));
p -> startActivity(settingIntent));
} else { } else {
((GearPreference) preference).setOnGearClickListener(null); ((GearPreference) preference).setOnGearClickListener(null);
} }
@@ -102,21 +107,22 @@ public abstract class DefaultAppPreferenceController extends AbstractPreferenceC
protected abstract DefaultAppInfo getDefaultAppInfo(); protected abstract DefaultAppInfo getDefaultAppInfo();
/** /** Returns an optional intent that will be launched when clicking "gear" icon. */
* Returns an optional intent that will be launched when clicking "gear" icon.
*/
protected Intent getSettingIntent(DefaultAppInfo info) { protected Intent getSettingIntent(DefaultAppInfo info) {
//By default return null. It's up to subclasses to provide logic. // By default return null. It's up to subclasses to provide logic.
return null; return null;
} }
/** /** Whether to show the default app label as the title, instead of as the summary. */
* Whether to show the default app label as the title, instead of as the summary.
*/
protected boolean showLabelAsTitle() { protected boolean showLabelAsTitle() {
return false; return false;
} }
/** Whether to show the app summary. */
protected boolean showAppSummary() {
return false;
}
public Drawable getDefaultAppIcon() { public Drawable getDefaultAppIcon() {
if (!isAvailable()) { if (!isAvailable()) {
return null; return null;
@@ -138,4 +144,15 @@ public abstract class DefaultAppPreferenceController extends AbstractPreferenceC
} }
return null; return null;
} }
private @Nullable CharSequence getDefaultAppSummary() {
if (!isAvailable()) {
return null;
}
final DefaultAppInfo app = getDefaultAppInfo();
if (app != null) {
return app.getSummary();
}
return null;
}
} }

View File

@@ -121,64 +121,6 @@ public class CredentialManagerPreferenceControllerTest {
assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE); assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE);
} }
@Test
public void verifyHiddenIfAutofillSelectedProvider() {
CredentialManagerPreferenceController controller =
createControllerWithServices(Collections.emptyList());
// Set the autofill provider.
Settings.Secure.putStringForUser(mContext.getContentResolver(),
Settings.Secure.AUTOFILL_SERVICE, "com.example.test/AutofillClass",
UserHandle.myUserId());
// Verify the error cases
assertThat(controller.isProviderHiddenBecauseOfAutofill(null)).isFalse();
assertThat(controller.isProviderHiddenBecauseOfAutofill("")).isFalse();
assertThat(controller.isProviderHiddenBecauseOfAutofill("test")).isFalse();
// Verify the example.
assertThat(controller.isProviderHiddenBecauseOfAutofill("com.example.test")).isTrue();
}
@Test
public void displayPreference_noServices_noPreferencesAdded_useAutofillUri() {
Settings.Secure.putStringForUser(
mContext.getContentResolver(),
Settings.Secure.AUTOFILL_SERVICE_SEARCH_URI,
"test",
UserHandle.myUserId());
CredentialManagerPreferenceController controller =
createControllerWithServices(Collections.emptyList());
controller.displayPreference(mScreen);
assertThat(mCredentialsPreferenceCategory.getPreferenceCount()).isEqualTo(1);
Preference pref = mCredentialsPreferenceCategory.getPreference(0);
assertThat(pref.getTitle()).isEqualTo("Add service");
assertThat(controller.getAddServiceUri(mContext)).isEqualTo("test");
}
@Test
public void displayPreference_noServices_noPreferencesAdded_useCredManUri() {
Settings.Secure.putStringForUser(
mContext.getContentResolver(),
Settings.Secure.AUTOFILL_SERVICE_SEARCH_URI,
"test",
UserHandle.myUserId());
CredentialManagerPreferenceController controller =
createControllerWithServicesAndAddServiceOverride(
Collections.emptyList(), "credman");
controller.displayPreference(mScreen);
assertThat(mCredentialsPreferenceCategory.getPreferenceCount()).isEqualTo(1);
Preference pref = mCredentialsPreferenceCategory.getPreference(0);
assertThat(pref.getTitle()).isEqualTo("Add service");
assertThat(controller.getAddServiceUri(mContext)).isEqualTo("credman");
}
@Test @Test
public void displayPreference_withServices_preferencesAdded() { public void displayPreference_withServices_preferencesAdded() {
CredentialManagerPreferenceController controller = CredentialManagerPreferenceController controller =