diff --git a/core/java/android/credentials/CredentialManager.java b/core/java/android/credentials/CredentialManager.java index 54909aa53fc0d..07473d2db8546 100644 --- a/core/java/android/credentials/CredentialManager.java +++ b/core/java/android/credentials/CredentialManager.java @@ -21,6 +21,7 @@ import static android.Manifest.permission.CREDENTIAL_MANAGER_SET_ORIGIN; import static java.util.Objects.requireNonNull; import android.annotation.CallbackExecutor; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -30,6 +31,7 @@ import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; import android.content.IntentSender; +import android.content.pm.ServiceInfo; import android.os.CancellationSignal; import android.os.ICancellationSignal; import android.os.OutcomeReceiver; @@ -37,6 +39,8 @@ import android.os.RemoteException; import android.provider.DeviceConfig; import android.util.Log; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.List; import java.util.concurrent.Executor; @@ -54,6 +58,39 @@ import java.util.concurrent.Executor; public final class CredentialManager { private static final String TAG = "CredentialManager"; + /** @hide */ + @IntDef( + flag = true, + prefix = {"PROVIDER_FILTER_"}, + value = { + PROVIDER_FILTER_ALL_PROVIDERS, + PROVIDER_FILTER_SYSTEM_PROVIDERS_ONLY, + PROVIDER_FILTER_USER_PROVIDERS_ONLY, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ProviderFilter {} + + /** + * Returns both system and user credential providers. + * + * @hide + */ + public static final int PROVIDER_FILTER_ALL_PROVIDERS = 0; + + /** + * Returns system credential providers only. + * + * @hide + */ + public static final int PROVIDER_FILTER_SYSTEM_PROVIDERS_ONLY = 1; + + /** + * Returns user credential providers only. + * + * @hide + */ + public static final int PROVIDER_FILTER_USER_PROVIDERS_ONLY = 2; + private final Context mContext; private final ICredentialManager mService; @@ -404,6 +441,42 @@ public final class CredentialManager { } } + /** + * Returns the list of ServiceInfo for all discovered credential providers on this device. + * + * @hide + */ + @NonNull + @RequiresPermission(android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS) + public List getCredentialProviderServicesForTesting( + @ProviderFilter int providerFilter) { + try { + return mService.getCredentialProviderServices( + mContext.getUserId(), + /* disableSystemAppVerificationForTests= */ true, + providerFilter); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns the list of ServiceInfo for all discovered credential providers on this device. + * + * @hide + */ + @NonNull + @RequiresPermission(android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS) + public List getCredentialProviderServices( + int userId, @ProviderFilter int providerFilter) { + try { + return mService.getCredentialProviderServices( + userId, /* disableSystemAppVerificationForTests= */ false, providerFilter); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Returns whether the service is enabled. * diff --git a/core/java/android/credentials/ICredentialManager.aidl b/core/java/android/credentials/ICredentialManager.aidl index 604e56b1fdbd0..6d81d80d249c8 100644 --- a/core/java/android/credentials/ICredentialManager.aidl +++ b/core/java/android/credentials/ICredentialManager.aidl @@ -18,6 +18,7 @@ package android.credentials; import java.util.List; +import android.content.pm.ServiceInfo; import android.credentials.ClearCredentialStateRequest; import android.credentials.CreateCredentialRequest; import android.credentials.GetCredentialRequest; @@ -57,5 +58,7 @@ interface ICredentialManager { void unregisterCredentialDescription(in UnregisterCredentialDescriptionRequest request, String callingPackage); boolean isEnabledCredentialProviderService(in ComponentName componentName, String callingPackage); + + List getCredentialProviderServices(in int userId, in boolean disableSystemAppVerificationForTests, in int providerFilter); } diff --git a/core/java/android/service/credentials/CredentialProviderInfo.java b/core/java/android/service/credentials/CredentialProviderInfo.java index ce8bd0c6af0ef..75ba525f75eb3 100644 --- a/core/java/android/service/credentials/CredentialProviderInfo.java +++ b/core/java/android/service/credentials/CredentialProviderInfo.java @@ -21,6 +21,8 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.AppGlobals; +import android.app.admin.DevicePolicyManager; +import android.app.admin.PackagePolicy; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -29,6 +31,7 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.res.Resources; +import android.credentials.CredentialManager; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.RemoteException; @@ -38,7 +41,10 @@ import android.util.Slog; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; /** * {@link ServiceInfo} and meta-data about a credential provider. @@ -74,39 +80,124 @@ public final class CredentialProviderInfo { public CredentialProviderInfo(@NonNull Context context, @NonNull ComponentName serviceComponent, int userId, boolean isSystemProvider) throws PackageManager.NameNotFoundException { - this(context, getServiceInfoOrThrow(serviceComponent, userId), isSystemProvider); + this( + context, + getServiceInfoOrThrow(serviceComponent, userId), + isSystemProvider, + /* disableSystemAppVerificationForTests= */ false); } /** * Constructs an information instance of the credential provider. + * * @param context the context object * @param serviceInfo the service info for the provider app. This must be retrieved from the - * {@code PackageManager} - * @param isSystemProvider whether the provider is a system app or not + * {@code PackageManager} + * @param isSystemProvider whether the provider app is a system provider + * @param disableSystemAppVerificationForTests whether to disable system app permission + * verification so that tests can install system providers + * @throws SecurityException If provider does not require the relevant permission */ - public CredentialProviderInfo(@NonNull Context context, + public CredentialProviderInfo( + @NonNull Context context, @NonNull ServiceInfo serviceInfo, - boolean isSystemProvider) { - if (!Manifest.permission.BIND_CREDENTIAL_PROVIDER_SERVICE.equals(serviceInfo.permission)) { - Log.i(TAG, "Credential Provider Service from : " + serviceInfo.packageName - + "does not require permission" - + Manifest.permission.BIND_CREDENTIAL_PROVIDER_SERVICE); - throw new SecurityException("Service does not require the expected permission : " - + Manifest.permission.BIND_CREDENTIAL_PROVIDER_SERVICE); + boolean isSystemProvider, + boolean disableSystemAppVerificationForTests) { + verifyProviderPermission(serviceInfo); + if (isSystemProvider) { + if (!isValidSystemProvider( + context, serviceInfo, disableSystemAppVerificationForTests)) { + Slog.e(TAG, "Provider is not a valid system provider: " + serviceInfo); + throw new SecurityException( + "Provider is not a valid system provider: " + serviceInfo); + } } + + mIsSystemProvider = isSystemProvider; mContext = context; mServiceInfo = serviceInfo; mCapabilities = new ArrayList<>(); mIcon = mServiceInfo.loadIcon(mContext.getPackageManager()); - mLabel = mServiceInfo.loadSafeLabel( - mContext.getPackageManager(), 0 /* do not ellipsize */, - TextUtils.SAFE_STRING_FLAG_FIRST_LINE | TextUtils.SAFE_STRING_FLAG_TRIM); - mIsSystemProvider = isSystemProvider; - Log.i(TAG, "mLabel is : " + mLabel + ", for: " + mServiceInfo.getComponentName() - .flattenToString()); + mLabel = + mServiceInfo.loadSafeLabel( + mContext.getPackageManager(), + 0 /* do not ellipsize */, + TextUtils.SAFE_STRING_FLAG_FIRST_LINE | TextUtils.SAFE_STRING_FLAG_TRIM); + Log.i( + TAG, + "mLabel is : " + + mLabel + + ", for: " + + mServiceInfo.getComponentName().flattenToString()); populateProviderCapabilities(context, serviceInfo); } + private static void verifyProviderPermission(ServiceInfo serviceInfo) throws SecurityException { + final String permission = Manifest.permission.BIND_CREDENTIAL_PROVIDER_SERVICE; + if (permission.equals(serviceInfo.permission)) { + return; + } + + Slog.e( + TAG, + "Credential Provider Service from : " + + serviceInfo.packageName + + "does not require permission" + + permission); + throw new SecurityException( + "Service does not require the expected permission : " + permission); + } + + private static boolean isSystemProviderWithValidPermission( + ServiceInfo serviceInfo, Context context) { + final String permission = Manifest.permission.PROVIDE_DEFAULT_ENABLED_CREDENTIAL_SERVICE; + try { + ApplicationInfo appInfo = + context.getPackageManager() + .getApplicationInfo( + serviceInfo.packageName, + PackageManager.ApplicationInfoFlags.of( + PackageManager.MATCH_SYSTEM_ONLY)); + if (appInfo != null + && context.checkPermission(permission, /* pid= */ -1, appInfo.uid) + == PackageManager.PERMISSION_GRANTED) { + Slog.i(TAG, "SYS permission granted for: " + serviceInfo.packageName); + return true; + } else { + Slog.i(TAG, "SYS permission failed for: " + serviceInfo.packageName); + } + } catch (PackageManager.NameNotFoundException e) { + Slog.e(TAG, "Error getting info for " + serviceInfo + ": " + e); + } + return false; + } + + private static boolean isValidSystemProvider( + Context context, + ServiceInfo serviceInfo, + boolean disableSystemAppVerificationForTests) { + boolean isValidSystemTestProvider = + isTestSystemProvider(serviceInfo, disableSystemAppVerificationForTests); + if (isValidSystemTestProvider) { + return true; + } + return isSystemProviderWithValidPermission(serviceInfo, context); + } + + private static boolean isTestSystemProvider( + ServiceInfo serviceInfo, boolean disableSystemAppVerificationForTests) { + if (!disableSystemAppVerificationForTests) { + return false; + } + + Bundle metadata = serviceInfo.metaData; + if (metadata == null) { + Slog.e(TAG, "metadata is null: " + serviceInfo); + return false; + } + return metadata.getBoolean(CredentialProviderService.TEST_SYSTEM_PROVIDER_META_DATA_KEY); + } + private void populateProviderCapabilities(@NonNull Context context, ServiceInfo serviceInfo) { final PackageManager pm = context.getPackageManager(); try { @@ -133,7 +224,9 @@ public final class CredentialProviderInfo { mCapabilities.add(capability); } } catch (PackageManager.NameNotFoundException e) { - Slog.i(TAG, e.getMessage()); + Slog.e(TAG, e.getMessage()); + } catch (Resources.NotFoundException e) { + Slog.e(TAG, e.getMessage()); } } @@ -154,40 +247,80 @@ public final class CredentialProviderInfo { } /** - * Returns the valid credential provider services available for the user with the - * given {@code userId}. + * Returns the valid credential provider services available for the user with the given {@code + * userId}. + */ + @NonNull + private static List getAvailableSystemServiceInfos( + @NonNull Context context, + @UserIdInt int userId, + boolean disableSystemAppVerificationForTests) { + final List services = new ArrayList<>(); + final List resolveInfos = new ArrayList<>(); + + resolveInfos.addAll( + context.getPackageManager() + .queryIntentServicesAsUser( + new Intent(CredentialProviderService.SYSTEM_SERVICE_INTERFACE), + PackageManager.ResolveInfoFlags.of(PackageManager.GET_META_DATA), + userId)); + + for (ResolveInfo resolveInfo : resolveInfos) { + final ServiceInfo serviceInfo = resolveInfo.serviceInfo; + try { + PackageManager.ApplicationInfoFlags appInfoFlags = + disableSystemAppVerificationForTests + ? PackageManager.ApplicationInfoFlags.of(0) + : PackageManager.ApplicationInfoFlags.of( + PackageManager.MATCH_SYSTEM_ONLY); + ApplicationInfo appInfo = + context.getPackageManager() + .getApplicationInfo(serviceInfo.packageName, appInfoFlags); + + if (appInfo == null || serviceInfo == null) { + continue; + } + + services.add(serviceInfo); + } catch (SecurityException e) { + Slog.e(TAG, "Error getting info for " + serviceInfo + ": " + e); + } catch (PackageManager.NameNotFoundException e) { + Slog.e(TAG, "Error getting info for " + serviceInfo + ": " + e); + } + } + return services; + } + + /** + * Returns the valid credential provider services available for the user with the given {@code + * userId}. */ @NonNull public static List getAvailableSystemServices( @NonNull Context context, - @UserIdInt int userId) { - final List services = new ArrayList<>(); - - final List resolveInfos = - context.getPackageManager().queryIntentServicesAsUser( - new Intent(CredentialProviderService.SYSTEM_SERVICE_INTERFACE), - PackageManager.ResolveInfoFlags.of(PackageManager.GET_META_DATA), - userId); - for (ResolveInfo resolveInfo : resolveInfos) { - final ServiceInfo serviceInfo = resolveInfo.serviceInfo; + @UserIdInt int userId, + boolean disableSystemAppVerificationForTests) { + final List providerInfos = new ArrayList<>(); + for (ServiceInfo si : + getAvailableSystemServiceInfos( + context, userId, disableSystemAppVerificationForTests)) { try { - ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo( - serviceInfo.packageName, - PackageManager.ApplicationInfoFlags.of(PackageManager.MATCH_SYSTEM_ONLY)); - if (appInfo != null - && context.checkPermission( - Manifest.permission.PROVIDE_DEFAULT_ENABLED_CREDENTIAL_SERVICE, - /*pId=*/-1, appInfo.uid) == PackageManager.PERMISSION_GRANTED) { - services.add(new CredentialProviderInfo(context, serviceInfo, - /*isSystemProvider=*/true)); + CredentialProviderInfo cpi = + new CredentialProviderInfo( + context, + si, + /* isSystemProvider= */ true, + disableSystemAppVerificationForTests); + if (cpi.isSystemProvider()) { + providerInfos.add(cpi); + } else { + Slog.e(TAG, "Non system provider was in system provider list."); } } catch (SecurityException e) { - Log.i(TAG, "Error getting info for " + serviceInfo + ": " + e); - } catch (PackageManager.NameNotFoundException e) { - Log.i(TAG, "Error getting info for " + serviceInfo + ": " + e); + Slog.e(TAG, "Failed to create CredentialProviderInfo: " + e); } } - return services; + return providerInfos; } /** @@ -226,47 +359,153 @@ public final class CredentialProviderInfo { return Collections.unmodifiableList(mCapabilities); } + private static @Nullable PackagePolicy getDeviceManagerPolicy(@NonNull Context context) { + try { + DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); + return dpm.getCredentialManagerPolicy(); + } catch (SecurityException e) { + // If the current user is not enrolled in DPM then this can throw a security error. + Log.e(TAG, "Failed to get device policy: " + e); + } + + return null; + } + /** - * Returns the valid credential provider services available for the user with the - * given {@code userId}. + * Returns the valid credential provider services available for the user with the given {@code + * userId}. */ @NonNull - public static List getAvailableServices(@NonNull Context context, - @UserIdInt int userId) { - final List services = new ArrayList<>(); + public static List getCredentialProviderServices( + @NonNull Context context, + int userId, + boolean disableSystemAppVerificationForTests, + int providerFilter) { + // Get the device policy. + PackagePolicy pp = getDeviceManagerPolicy(context); + // Generate the provider list. + ProviderGenerator generator = + new ProviderGenerator( + context, pp, disableSystemAppVerificationForTests, providerFilter); + generator.addUserProviders( + getUserProviders(context, userId, disableSystemAppVerificationForTests)); + generator.addSystemProviders( + getAvailableSystemServices(context, userId, disableSystemAppVerificationForTests)); + return generator.getProviders(); + } + + private static class ProviderGenerator { + private final Context mContext; + private final PackagePolicy mPp; + private final boolean mDisableSystemAppVerificationForTests; + private final Map mServices = new HashMap(); + private final int mProviderFilter; + + ProviderGenerator( + Context context, + PackagePolicy pp, + boolean disableSystemAppVerificationForTests, + int providerFilter) { + this.mContext = context; + this.mPp = pp; + this.mDisableSystemAppVerificationForTests = disableSystemAppVerificationForTests; + this.mProviderFilter = providerFilter; + } + + private boolean isPackageAllowed(boolean isSystemProvider, String packageName) { + if (mPp == null) { + return true; + } + + if (isSystemProvider) { + return mPp.getPolicyType() == PackagePolicy.PACKAGE_POLICY_ALLOWLIST_AND_SYSTEM; + } + + return mPp.isPackageAllowed(packageName, new HashSet<>()); + } + + public List getProviders() { + return new ArrayList<>(mServices.values()); + } + + public void addUserProviders(List providers) { + for (CredentialProviderInfo cpi : providers) { + if (!cpi.isSystemProvider()) { + addProvider(cpi); + } + } + } + + public void addSystemProviders(List providers) { + for (CredentialProviderInfo cpi : providers) { + if (cpi.isSystemProvider()) { + addProvider(cpi); + } + } + } + + private boolean isProviderAllowedWithFilter(CredentialProviderInfo cpi) { + if (mProviderFilter == CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS) { + return true; + } + + if (cpi.isSystemProvider()) { + return mProviderFilter == CredentialManager.PROVIDER_FILTER_SYSTEM_PROVIDERS_ONLY; + } else { + return mProviderFilter == CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY; + } + } + + private void addProvider(CredentialProviderInfo cpi) { + final String componentNameString = + cpi.getServiceInfo().getComponentName().flattenToString(); + if (!isProviderAllowedWithFilter(cpi)) { + return; + } + + if (!isPackageAllowed(cpi.isSystemProvider(), cpi.getServiceInfo().packageName)) { + return; + } + + mServices.put(componentNameString, cpi); + } + } + + /** + * Returns the valid credential provider services available for the user with the given {@code + * userId}. + */ + @NonNull + private static List getUserProviders( + @NonNull Context context, + @UserIdInt int userId, + boolean disableSystemAppVerificationForTests) { + final List services = new ArrayList<>(); final List resolveInfos = - context.getPackageManager().queryIntentServicesAsUser( - new Intent(CredentialProviderService.SERVICE_INTERFACE), - PackageManager.ResolveInfoFlags.of(PackageManager.GET_META_DATA), - userId); + context.getPackageManager() + .queryIntentServicesAsUser( + new Intent(CredentialProviderService.SERVICE_INTERFACE), + PackageManager.ResolveInfoFlags.of(PackageManager.GET_META_DATA), + userId); for (ResolveInfo resolveInfo : resolveInfos) { final ServiceInfo serviceInfo = resolveInfo.serviceInfo; try { - services.add(new CredentialProviderInfo(context, - serviceInfo, false)); + CredentialProviderInfo cpi = + new CredentialProviderInfo( + context, + serviceInfo, + /* isSystemProvider= */ false, + disableSystemAppVerificationForTests); + if (!cpi.isSystemProvider()) { + services.add(cpi); + } } catch (SecurityException e) { - Log.w(TAG, "Error getting info for " + serviceInfo + ": " + e); + Slog.e(TAG, "Error getting info for " + serviceInfo + ": " + e); + } catch (Exception e) { + Slog.e(TAG, "Error getting info for " + serviceInfo + ": " + e); } } return services; } - - /** - * Returns the valid credential provider services available for the user, that can - * support the given {@code credentialType}. - */ - @NonNull - public static List getAvailableServicesForCapability( - @NonNull Context context, @UserIdInt int userId, @NonNull String credentialType) { - List servicesForCapability = new ArrayList<>(); - final List services = getAvailableServices(context, userId); - - for (CredentialProviderInfo service : services) { - if (service.hasCapability(credentialType)) { - servicesForCapability.add(service); - } - } - return servicesForCapability; - } } diff --git a/core/java/android/service/credentials/CredentialProviderService.java b/core/java/android/service/credentials/CredentialProviderService.java index dabf08e2a2fca..d737f6b6cdc8a 100644 --- a/core/java/android/service/credentials/CredentialProviderService.java +++ b/core/java/android/service/credentials/CredentialProviderService.java @@ -157,6 +157,10 @@ public abstract class CredentialProviderService extends Service { public static final String CAPABILITY_META_DATA_KEY = "android.credentials.capabilities"; + /** @hide */ + public static final String TEST_SYSTEM_PROVIDER_META_DATA_KEY = + "android.credentials.testsystemprovider"; + private Handler mHandler; /** diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java index 03340512fe56a..cce12a252e785 100644 --- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java +++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java @@ -28,10 +28,12 @@ import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.ServiceInfo; import android.credentials.ClearCredentialStateRequest; import android.credentials.CreateCredentialException; import android.credentials.CreateCredentialRequest; import android.credentials.CredentialDescription; +import android.credentials.CredentialManager; import android.credentials.CredentialOption; import android.credentials.GetCredentialException; import android.credentials.GetCredentialRequest; @@ -110,9 +112,12 @@ public final class CredentialManagerService private List constructSystemServiceListLocked( int resolvedUserId) { List services = new ArrayList<>(); - List credentialProviderInfos = - CredentialProviderInfo.getAvailableSystemServices(mContext, resolvedUserId); - credentialProviderInfos.forEach( + List serviceInfos = + CredentialProviderInfo.getAvailableSystemServices( + mContext, + resolvedUserId, + /* disableSystemAppVerificationForTests= */ false); + serviceInfos.forEach( info -> { services.add( new CredentialManagerServiceImpl(this, mLock, resolvedUserId, info)); @@ -209,11 +214,20 @@ public final class CredentialManagerService } private boolean hasWriteSecureSettingsPermission() { - final String permission = android.Manifest.permission.WRITE_SECURE_SETTINGS; + return hasPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS); + } + + private void verifyPermission(String permission) throws SecurityException { + if (!hasPermission(permission)) { + throw new SecurityException("Caller is missing permission: " + permission); + } + } + + private boolean hasPermission(String permission) { final boolean result = mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED; if (!result) { - Slog.e(TAG, "Caller does not have WRITE_SECURE_SETTINGS permission."); + Slog.e(TAG, "Caller does not have permission: " + permission); } return result; } @@ -224,7 +238,7 @@ public final class CredentialManagerService try { synchronized (mLock) { final List services = - getAllCredentialProviderServicesLocked(userId); + getCredentialProviderServicesLocked(userId); for (CredentialManagerServiceImpl s : services) { c.accept(s); } @@ -235,7 +249,7 @@ public final class CredentialManagerService } @GuardedBy("mLock") - private List getAllCredentialProviderServicesLocked(int userId) { + private List getCredentialProviderServicesLocked(int userId) { List concatenatedServices = new ArrayList<>(); List userConfigurableServices = getServiceListForUserLocked(userId); @@ -693,6 +707,23 @@ public final class CredentialManagerService return false; } + @Override + public List getCredentialProviderServices( + int userId, boolean disableSystemAppVerificationForTests, int providerFilter) { + Log.i(TAG, "getCredentialProviderServices"); + verifyPermission(android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS); + + List services = new ArrayList<>(); + List providers = + CredentialProviderInfo.getCredentialProviderServices( + mContext, userId, disableSystemAppVerificationForTests, providerFilter); + for (CredentialProviderInfo p : providers) { + services.add(p.getServiceInfo()); + } + + return services; + } + @Override public ICancellationSignal clearCredentialState( ClearCredentialStateRequest request, @@ -748,8 +779,7 @@ public final class CredentialManagerService enforceCallingPackage(callingPackage, Binder.getCallingUid()); List services = - CredentialProviderInfo.getAvailableServices( - mContext, UserHandle.getCallingUserId()); + getServicesForCredentialDescription(UserHandle.getCallingUserId()); List providers = services.stream() @@ -801,8 +831,7 @@ public final class CredentialManagerService enforceCallingPackage(callingPackage, Binder.getCallingUid()); List services = - CredentialProviderInfo.getAvailableServices( - mContext, UserHandle.getCallingUserId()); + getServicesForCredentialDescription(UserHandle.getCallingUserId()); List providers = services.stream() @@ -820,6 +849,14 @@ public final class CredentialManagerService session.executeUnregisterRequest(request, callingPackage); } + + private List getServicesForCredentialDescription(int userId) { + return CredentialProviderInfo.getCredentialProviderServices( + mContext, + userId, + /* disableSystemAppVerificationForTests= */ false, + CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS); + } } private void enforceCallingPackage(String callingPackage, int callingUid) { diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java b/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java index a6f6a830056f4..2c6c0d8b40187 100644 --- a/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java +++ b/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java @@ -21,6 +21,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ServiceInfo; +import android.credentials.CredentialManager; import android.credentials.ui.DisabledProviderData; import android.credentials.ui.IntentFactory; import android.credentials.ui.ProviderData; @@ -116,13 +117,17 @@ public class CredentialManagerUi { Set enabledProviders = providerDataList.stream() .map(ProviderData::getProviderFlattenedComponentName) .collect(Collectors.toUnmodifiableSet()); - // TODO("Filter out non user configurable providers") Set allProviders = - CredentialProviderInfo.getAvailableServices(mContext, mUserId).stream() - .map(CredentialProviderInfo::getServiceInfo) - .map(ServiceInfo::getComponentName) - .map(ComponentName::flattenToString) - .collect(Collectors.toUnmodifiableSet()); + CredentialProviderInfo.getCredentialProviderServices( + mContext, + mUserId, + /* disableSystemAppVerificationForTests= */ false, + CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY) + .stream() + .map(CredentialProviderInfo::getServiceInfo) + .map(ServiceInfo::getComponentName) + .map(ComponentName::flattenToString) + .collect(Collectors.toUnmodifiableSet()); for (String provider: allProviders) { if (!enabledProviders.contains(provider)) {