Move CredentialProviderInfo for test/settings (framework)
This is a precusor CL to adding a subtitle for settings
to use so we need to move CPI where it can be used
by settings, atest and CTS.
Test: ondevice & atest & cts
Bug: 253157366
Change-Id: I2ffb1f89caf3f2c5bbf7d4dd693ad9a1bbc93fbb
(cherry picked from commit on googleplex-android-review.googlesource.com host: 496d3a3aae0f83f2456f92f09e0800276f1a0dc0)
Merged-In: I2ffb1f89caf3f2c5bbf7d4dd693ad9a1bbc93fbb
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 85163ed..17c3d33 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1072,6 +1072,40 @@
}
+package android.credentials {
+
+ public final class CredentialManager {
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.QUERY_ALL_PACKAGES, "android.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS"}) public java.util.List<android.credentials.CredentialProviderInfo> getCredentialProviderServicesForTesting(int);
+ method public static boolean isServiceEnabled(@NonNull android.content.Context);
+ field public static final int PROVIDER_FILTER_ALL_PROVIDERS = 0; // 0x0
+ field public static final int PROVIDER_FILTER_SYSTEM_PROVIDERS_ONLY = 1; // 0x1
+ field public static final int PROVIDER_FILTER_USER_PROVIDERS_ONLY = 2; // 0x2
+ }
+
+ public final class CredentialProviderInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<java.lang.String> getCapabilities();
+ method @NonNull public android.content.ComponentName getComponentName();
+ method @Nullable public CharSequence getLabel(@NonNull android.content.Context);
+ method @Nullable public android.graphics.drawable.Drawable getServiceIcon(@NonNull android.content.Context);
+ method @NonNull public android.content.pm.ServiceInfo getServiceInfo();
+ method @NonNull public boolean hasCapability(@NonNull String);
+ method public boolean isEnabled();
+ method public boolean isSystemProvider();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.credentials.CredentialProviderInfo> CREATOR;
+ }
+
+ public static final class CredentialProviderInfo.Builder {
+ ctor public CredentialProviderInfo.Builder(@NonNull android.content.pm.ServiceInfo);
+ method @NonNull public android.credentials.CredentialProviderInfo.Builder addCapabilities(@NonNull java.util.List<java.lang.String>);
+ method @NonNull public android.credentials.CredentialProviderInfo build();
+ method @NonNull public android.credentials.CredentialProviderInfo.Builder setEnabled(boolean);
+ method @NonNull public android.credentials.CredentialProviderInfo.Builder setSystemProvider(boolean);
+ }
+
+}
+
package android.credentials.ui {
public final class AuthenticationEntry implements android.os.Parcelable {
diff --git a/core/java/android/credentials/CredentialManager.java b/core/java/android/credentials/CredentialManager.java
index f0230e7..0806f1d 100644
--- a/core/java/android/credentials/CredentialManager.java
+++ b/core/java/android/credentials/CredentialManager.java
@@ -26,12 +26,12 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.app.Activity;
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;
@@ -75,21 +75,21 @@
*
* @hide
*/
- public static final int PROVIDER_FILTER_ALL_PROVIDERS = 0;
+ @TestApi 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;
+ @TestApi 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;
+ @TestApi public static final int PROVIDER_FILTER_USER_PROVIDERS_ONLY = 2;
private final Context mContext;
private final ICredentialManager mService;
@@ -263,44 +263,6 @@
}
/**
- * Gets a list of all user configurable credential providers registered on the system. This API
- * is intended for browsers and settings apps.
- *
- * @param cancellationSignal an optional signal that allows for cancelling this call
- * @param executor the callback will take place on this {@link Executor}
- * @param callback the callback invoked when the request succeeds or fails
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
- public void listEnabledProviders(
- @Nullable CancellationSignal cancellationSignal,
- @CallbackExecutor @NonNull Executor executor,
- @NonNull
- OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException>
- callback) {
- requireNonNull(executor, "executor must not be null");
- requireNonNull(callback, "callback must not be null");
-
- if (cancellationSignal != null && cancellationSignal.isCanceled()) {
- Log.w(TAG, "listEnabledProviders already canceled");
- return;
- }
-
- ICancellationSignal cancelRemote = null;
- try {
- cancelRemote =
- mService.listEnabledProviders(
- new ListEnabledProvidersTransport(executor, callback));
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
-
- if (cancellationSignal != null && cancelRemote != null) {
- cancellationSignal.setRemote(cancelRemote);
- }
- }
-
- /**
* Sets a list of all user configurable credential providers registered on the system. This API
* is intended for settings apps.
*
@@ -348,36 +310,43 @@
}
/**
- * Returns the list of ServiceInfo for all discovered credential providers on this device.
+ * Returns the list of CredentialProviderInfo for all discovered credential providers on this
+ * device but will include test system providers as well.
*
* @hide
*/
@NonNull
- @RequiresPermission(android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS)
- public List<ServiceInfo> getCredentialProviderServicesForTesting(
- @ProviderFilter int providerFilter) {
+ @TestApi
+ @RequiresPermission(
+ anyOf = {
+ android.Manifest.permission.QUERY_ALL_PACKAGES,
+ android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS
+ })
+ public List<CredentialProviderInfo> getCredentialProviderServicesForTesting(
+ @ProviderFilter int providerFilter) {
try {
- return mService.getCredentialProviderServices(
- mContext.getUserId(),
- /* disableSystemAppVerificationForTests= */ true,
- providerFilter);
+ return mService.getCredentialProviderServicesForTesting(providerFilter);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
- * Returns the list of ServiceInfo for all discovered credential providers on this device.
+ * Returns the list of CredentialProviderInfo for all discovered credential providers on this
+ * device.
*
* @hide
*/
@NonNull
- @RequiresPermission(android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS)
- public List<ServiceInfo> getCredentialProviderServices(
+ @RequiresPermission(
+ anyOf = {
+ android.Manifest.permission.QUERY_ALL_PACKAGES,
+ android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS
+ })
+ public List<CredentialProviderInfo> getCredentialProviderServices(
int userId, @ProviderFilter int providerFilter) {
try {
- return mService.getCredentialProviderServices(
- userId, /* disableSystemAppVerificationForTests= */ false, providerFilter);
+ return mService.getCredentialProviderServices(userId, providerFilter);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -388,7 +357,9 @@
*
* @hide
*/
- public static boolean isServiceEnabled(Context context) {
+ @TestApi
+ public static boolean isServiceEnabled(@NonNull Context context) {
+ requireNonNull(context, "context must not be null");
if (context == null) {
return false;
}
@@ -578,33 +549,6 @@
}
}
- private static class ListEnabledProvidersTransport extends IListEnabledProvidersCallback.Stub {
- // TODO: listen for cancellation to release callback.
-
- private final Executor mExecutor;
- private final OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException>
- mCallback;
-
- private ListEnabledProvidersTransport(
- Executor executor,
- OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException>
- callback) {
- mExecutor = executor;
- mCallback = callback;
- }
-
- @Override
- public void onResponse(ListEnabledProvidersResponse response) {
- mExecutor.execute(() -> mCallback.onResult(response));
- }
-
- @Override
- public void onError(String errorType, String message) {
- mExecutor.execute(
- () -> mCallback.onError(new ListEnabledProvidersException(errorType, message)));
- }
- }
-
private static class SetEnabledProvidersTransport extends ISetEnabledProvidersCallback.Stub {
// TODO: listen for cancellation to release callback.
diff --git a/core/java/android/credentials/IListEnabledProvidersCallback.aidl b/core/java/android/credentials/CredentialProviderInfo.aidl
similarity index 63%
rename from core/java/android/credentials/IListEnabledProvidersCallback.aidl
rename to core/java/android/credentials/CredentialProviderInfo.aidl
index 3a8e25ed..30b7742 100644
--- a/core/java/android/credentials/IListEnabledProvidersCallback.aidl
+++ b/core/java/android/credentials/CredentialProviderInfo.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 The Android Open Source Project
+ * Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,14 +16,4 @@
package android.credentials;
-import android.credentials.ListEnabledProvidersResponse;
-
-/**
- * Listener for an listEnabledProviders request.
- *
- * @hide
- */
-interface IListEnabledProvidersCallback {
- oneway void onResponse(in ListEnabledProvidersResponse response);
- oneway void onError(String errorType, String message);
-}
\ No newline at end of file
+parcelable CredentialProviderInfo;
\ No newline at end of file
diff --git a/core/java/android/credentials/CredentialProviderInfo.java b/core/java/android/credentials/CredentialProviderInfo.java
new file mode 100644
index 0000000..7276770
--- /dev/null
+++ b/core/java/android/credentials/CredentialProviderInfo.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.credentials;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.ServiceInfo;
+import android.graphics.drawable.Drawable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * {@link ServiceInfo} and meta-data about a credential provider.
+ *
+ * @hide
+ */
+@TestApi
+public final class CredentialProviderInfo implements Parcelable {
+ @NonNull private final ServiceInfo mServiceInfo;
+ @NonNull private final List<String> mCapabilities = new ArrayList<>();
+ @Nullable private final CharSequence mOverrideLabel;
+ private final boolean mIsSystemProvider;
+ private final boolean mIsEnabled;
+
+ /**
+ * Constructs an information instance of the credential provider.
+ *
+ * @param builder the builder object.
+ */
+ private CredentialProviderInfo(@NonNull Builder builder) {
+ mServiceInfo = builder.mServiceInfo;
+ mCapabilities.addAll(builder.mCapabilities);
+ mIsSystemProvider = builder.mIsSystemProvider;
+ mIsEnabled = builder.mIsEnabled;
+ mOverrideLabel = builder.mOverrideLabel;
+ }
+
+ /** Returns true if the service supports the given {@code credentialType}, false otherwise. */
+ @NonNull
+ public boolean hasCapability(@NonNull String credentialType) {
+ return mCapabilities.contains(credentialType);
+ }
+
+ /** Returns the service info. */
+ @NonNull
+ public ServiceInfo getServiceInfo() {
+ return mServiceInfo;
+ }
+
+ /** Returns whether it is a system provider. */
+ public boolean isSystemProvider() {
+ return mIsSystemProvider;
+ }
+
+ /** Returns the service icon. */
+ @Nullable
+ public Drawable getServiceIcon(@NonNull Context context) {
+ return mServiceInfo.loadIcon(context.getPackageManager());
+ }
+
+ /** Returns the service label. */
+ @Nullable
+ public CharSequence getLabel(@NonNull Context context) {
+ if (mOverrideLabel != null) {
+ return mOverrideLabel;
+ }
+ return mServiceInfo.loadSafeLabel(context.getPackageManager());
+ }
+
+ /** Returns a list of capabilities this provider service can support. */
+ @NonNull
+ public List<String> getCapabilities() {
+ return Collections.unmodifiableList(mCapabilities);
+ }
+
+ /** Returns whether the provider is enabled by the user. */
+ public boolean isEnabled() {
+ return mIsEnabled;
+ }
+
+ /** Returns the component name for the service. */
+ @NonNull
+ public ComponentName getComponentName() {
+ return mServiceInfo.getComponentName();
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeTypedObject(mServiceInfo, flags);
+ dest.writeBoolean(mIsSystemProvider);
+ dest.writeStringList(mCapabilities);
+ dest.writeBoolean(mIsEnabled);
+ TextUtils.writeToParcel(mOverrideLabel, dest, flags);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return "CredentialProviderInfo {"
+ + "serviceInfo="
+ + mServiceInfo
+ + ", "
+ + "isSystemProvider="
+ + mIsSystemProvider
+ + ", "
+ + "isEnabled="
+ + mIsEnabled
+ + ", "
+ + "overrideLabel="
+ + mOverrideLabel
+ + ", "
+ + "capabilities="
+ + String.join(",", mCapabilities)
+ + "}";
+ }
+
+ private CredentialProviderInfo(@NonNull Parcel in) {
+ mServiceInfo = in.readTypedObject(ServiceInfo.CREATOR);
+ mIsSystemProvider = in.readBoolean();
+ in.readStringList(mCapabilities);
+ mIsEnabled = in.readBoolean();
+ mOverrideLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ }
+
+ public static final @NonNull Parcelable.Creator<CredentialProviderInfo> CREATOR =
+ new Parcelable.Creator<CredentialProviderInfo>() {
+ @Override
+ public CredentialProviderInfo[] newArray(int size) {
+ return new CredentialProviderInfo[size];
+ }
+
+ @Override
+ public CredentialProviderInfo createFromParcel(@NonNull Parcel in) {
+ return new CredentialProviderInfo(in);
+ }
+ };
+
+ /** A builder for {@link CredentialProviderInfo} objects. */
+ public static final class Builder {
+
+ @NonNull private ServiceInfo mServiceInfo;
+ @NonNull private List<String> mCapabilities = new ArrayList<>();
+ private boolean mIsSystemProvider = false;
+ private boolean mIsEnabled = false;
+ @Nullable private CharSequence mOverrideLabel = null;
+
+ /**
+ * Creates a new builder.
+ *
+ * @param serviceInfo the service info of the credential provider service.
+ */
+ public Builder(@NonNull ServiceInfo serviceInfo) {
+ mServiceInfo = serviceInfo;
+ }
+
+ /** Sets whether it is a system provider. */
+ public @NonNull Builder setSystemProvider(boolean isSystemProvider) {
+ mIsSystemProvider = isSystemProvider;
+ return this;
+ }
+
+ /**
+ * Sets the label to be used instead of getting from the system (for unit tests).
+ *
+ * @hide
+ */
+ public @NonNull Builder setOverrideLabel(@NonNull CharSequence overrideLabel) {
+ mOverrideLabel = overrideLabel;
+ return this;
+ }
+
+ /** Sets a list of capabilities this provider service can support. */
+ public @NonNull Builder addCapabilities(@NonNull List<String> capabilities) {
+ mCapabilities.addAll(capabilities);
+ return this;
+ }
+
+ /** Sets whether it is enabled by the user. */
+ public @NonNull Builder setEnabled(boolean isEnabled) {
+ mIsEnabled = isEnabled;
+ return this;
+ }
+
+ /** Builds a new {@link CredentialProviderInfo} instance. */
+ public @NonNull CredentialProviderInfo build() {
+ return new CredentialProviderInfo(this);
+ }
+ }
+}
diff --git a/core/java/android/credentials/ICredentialManager.aidl b/core/java/android/credentials/ICredentialManager.aidl
index 625fc8a..8c2cb5a 100644
--- a/core/java/android/credentials/ICredentialManager.aidl
+++ b/core/java/android/credentials/ICredentialManager.aidl
@@ -18,7 +18,7 @@
import java.util.List;
-import android.content.pm.ServiceInfo;
+import android.credentials.CredentialProviderInfo;
import android.credentials.ClearCredentialStateRequest;
import android.credentials.CreateCredentialRequest;
import android.credentials.GetCredentialRequest;
@@ -27,7 +27,6 @@
import android.credentials.IClearCredentialStateCallback;
import android.credentials.ICreateCredentialCallback;
import android.credentials.IGetCredentialCallback;
-import android.credentials.IListEnabledProvidersCallback;
import android.credentials.ISetEnabledProvidersCallback;
import android.content.ComponentName;
import android.os.ICancellationSignal;
@@ -45,8 +44,6 @@
@nullable ICancellationSignal clearCredentialState(in ClearCredentialStateRequest request, in IClearCredentialStateCallback callback, String callingPackage);
- @nullable ICancellationSignal listEnabledProviders(in IListEnabledProvidersCallback callback);
-
void setEnabledProviders(in List<String> providers, in int userId, in ISetEnabledProvidersCallback callback);
void registerCredentialDescription(in RegisterCredentialDescriptionRequest request, String callingPackage);
@@ -55,6 +52,8 @@
boolean isEnabledCredentialProviderService(in ComponentName componentName, String callingPackage);
- List<ServiceInfo> getCredentialProviderServices(in int userId, in boolean disableSystemAppVerificationForTests, in int providerFilter);
+ List<CredentialProviderInfo> getCredentialProviderServices(in int userId, in int providerFilter);
+
+ List<CredentialProviderInfo> getCredentialProviderServicesForTesting(in int providerFilter);
}
diff --git a/core/java/android/service/credentials/CredentialProviderInfo.java b/core/java/android/service/credentials/CredentialProviderInfoFactory.java
similarity index 69%
rename from core/java/android/service/credentials/CredentialProviderInfo.java
rename to core/java/android/service/credentials/CredentialProviderInfoFactory.java
index b5464db..fd9360f 100644
--- a/core/java/android/service/credentials/CredentialProviderInfo.java
+++ b/core/java/android/service/credentials/CredentialProviderInfoFactory.java
@@ -34,40 +34,27 @@
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.credentials.CredentialManager;
-import android.graphics.drawable.Drawable;
+import android.credentials.CredentialProviderInfo;
import android.os.Bundle;
import android.os.RemoteException;
-import android.text.TextUtils;
+import android.os.UserHandle;
import android.util.Log;
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;
+import java.util.Set;
/**
- * {@link ServiceInfo} and meta-data about a credential provider.
+ * {@link CredentialProviderInfo} generator.
*
* @hide
*/
-public final class CredentialProviderInfo {
- private static final String TAG = "CredentialProviderInfo";
-
- @NonNull
- private final ServiceInfo mServiceInfo;
- @NonNull
- private final List<String> mCapabilities;
-
- @NonNull
- private final Context mContext;
- @Nullable
- private final Drawable mIcon;
- @Nullable
- private final CharSequence mLabel;
- private final boolean mIsSystemProvider;
+public final class CredentialProviderInfoFactory {
+ private static final String TAG = "CredentialProviderInfoFactory";
/**
* Constructs an information instance of the credential provider.
@@ -79,14 +66,18 @@
* @throws PackageManager.NameNotFoundException If provider service is not found
* @throws SecurityException If provider does not require the relevant permission
*/
- public CredentialProviderInfo(@NonNull Context context,
- @NonNull ComponentName serviceComponent, int userId, boolean isSystemProvider)
+ public static CredentialProviderInfo create(
+ @NonNull Context context,
+ @NonNull ComponentName serviceComponent,
+ int userId,
+ boolean isSystemProvider)
throws PackageManager.NameNotFoundException {
- this(
+ return create(
context,
getServiceInfoOrThrow(serviceComponent, userId),
isSystemProvider,
- /* disableSystemAppVerificationForTests= */ false);
+ /* disableSystemAppVerificationForTests= */ false,
+ /* isEnabled= */ false);
}
/**
@@ -98,13 +89,16 @@
* @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
+ * @param isEnabled whether the user enabled this provider
* @throws SecurityException If provider does not require the relevant permission
*/
- public CredentialProviderInfo(
+ public static CredentialProviderInfo create(
@NonNull Context context,
@NonNull ServiceInfo serviceInfo,
boolean isSystemProvider,
- boolean disableSystemAppVerificationForTests) {
+ boolean disableSystemAppVerificationForTests,
+ boolean isEnabled)
+ throws SecurityException {
verifyProviderPermission(serviceInfo);
if (isSystemProvider) {
if (!isValidSystemProvider(
@@ -114,23 +108,11 @@
"Provider is not a valid system provider: " + serviceInfo);
}
}
- mIsSystemProvider = isSystemProvider;
- mContext = requireNonNull(context, "context must not be null");
- mServiceInfo = requireNonNull(serviceInfo, "serviceInfo must not be null");
- 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);
- Log.i(
- TAG,
- "mLabel is : "
- + mLabel
- + ", for: "
- + mServiceInfo.getComponentName().flattenToString());
- populateProviderCapabilities(context, serviceInfo);
+
+ return populateMetadata(context, serviceInfo)
+ .setSystemProvider(isSystemProvider)
+ .setEnabled(isEnabled)
+ .build();
}
private static void verifyProviderPermission(ServiceInfo serviceInfo) throws SecurityException {
@@ -138,19 +120,14 @@
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) {
+ requireNonNull(context, "context must not be null");
+
final String permission = Manifest.permission.PROVIDE_DEFAULT_ENABLED_CREDENTIAL_SERVICE;
try {
ApplicationInfo appInfo =
@@ -177,67 +154,88 @@
Context context,
ServiceInfo serviceInfo,
boolean disableSystemAppVerificationForTests) {
- boolean isValidSystemTestProvider =
- isTestSystemProvider(serviceInfo, disableSystemAppVerificationForTests);
- if (isValidSystemTestProvider) {
- return true;
+ requireNonNull(context, "context must not be null");
+
+ if (disableSystemAppVerificationForTests) {
+ Bundle metadata = serviceInfo.metaData;
+ if (metadata == null) {
+ Slog.e(TAG, "isValidSystemProvider - metadata is null: " + serviceInfo);
+ return false;
+ }
+ return metadata.getBoolean(
+ CredentialProviderService.TEST_SYSTEM_PROVIDER_META_DATA_KEY);
}
+
return isSystemProviderWithValidPermission(serviceInfo, context);
}
- private static boolean isTestSystemProvider(
- ServiceInfo serviceInfo, boolean disableSystemAppVerificationForTests) {
- if (!disableSystemAppVerificationForTests) {
- return false;
- }
+ private static CredentialProviderInfo.Builder populateMetadata(
+ @NonNull Context context, ServiceInfo serviceInfo) {
+ requireNonNull(context, "context must not be null");
- 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 CredentialProviderInfo.Builder builder =
+ new CredentialProviderInfo.Builder(serviceInfo);
final PackageManager pm = context.getPackageManager();
+
+ // 1. Get the metadata for the service.
+ final Bundle metadata = serviceInfo.metaData;
+ if (metadata == null) {
+ Log.i(TAG, "populateMetadata - metadata is null");
+ return builder;
+ }
+
+ // 2. Extract the capabilities from the bundle.
try {
- Bundle metadata = serviceInfo.metaData;
Resources resources = pm.getResourcesForApplication(serviceInfo.applicationInfo);
if (metadata == null || resources == null) {
- Log.i(TAG, "populateProviderCapabilities - metadata or resources is null");
- return;
+ Log.i(TAG, "populateMetadata - resources is null");
+ return builder;
}
- String[] capabilities = resources.getStringArray(metadata.getInt(
- CredentialProviderService.CAPABILITY_META_DATA_KEY));
- if (capabilities == null || capabilities.length == 0) {
- Slog.i(TAG, "No capabilities found for provider:" + serviceInfo.packageName);
- return;
- }
-
- for (String capability : capabilities) {
- if (capability.isEmpty()) {
- Slog.i(TAG, "Skipping empty capability");
- continue;
- }
- Slog.i(TAG, "Capabilities found for provider: " + capability);
- mCapabilities.add(capability);
- }
+ builder.addCapabilities(populateProviderCapabilities(resources, metadata, serviceInfo));
} catch (PackageManager.NameNotFoundException e) {
Slog.e(TAG, e.getMessage());
- } catch (Resources.NotFoundException e) {
- Slog.e(TAG, e.getMessage());
}
+
+ return builder;
}
- private static ServiceInfo getServiceInfoOrThrow(@NonNull ComponentName serviceComponent,
- int userId) throws PackageManager.NameNotFoundException {
+ private static List<String> populateProviderCapabilities(
+ Resources resources, Bundle metadata, ServiceInfo serviceInfo) {
+ List<String> output = new ArrayList<>();
+ String[] capabilities = new String[0];
+
try {
- ServiceInfo si = AppGlobals.getPackageManager().getServiceInfo(
- serviceComponent,
- PackageManager.GET_META_DATA,
- userId);
+ capabilities =
+ resources.getStringArray(
+ metadata.getInt(CredentialProviderService.CAPABILITY_META_DATA_KEY));
+ } catch (Resources.NotFoundException e) {
+ Slog.e(TAG, "Failed to get capabilities: " + e.getMessage());
+ }
+
+ if (capabilities == null || capabilities.length == 0) {
+ Slog.e(TAG, "No capabilities found for provider:" + serviceInfo.packageName);
+ return output;
+ }
+
+ for (String capability : capabilities) {
+ if (capability.isEmpty()) {
+ Slog.e(TAG, "Skipping empty capability");
+ continue;
+ }
+ Slog.e(TAG, "Capabilities found for provider: " + capability);
+ output.add(capability);
+ }
+ return output;
+ }
+
+ private static ServiceInfo getServiceInfoOrThrow(
+ @NonNull ComponentName serviceComponent, int userId)
+ throws PackageManager.NameNotFoundException {
+ try {
+ ServiceInfo si =
+ AppGlobals.getPackageManager()
+ .getServiceInfo(serviceComponent, PackageManager.GET_META_DATA, userId);
if (si != null) {
return si;
}
@@ -256,6 +254,8 @@
@NonNull Context context,
@UserIdInt int userId,
boolean disableSystemAppVerificationForTests) {
+ requireNonNull(context, "context must not be null");
+
final List<ServiceInfo> services = new ArrayList<>();
final List<ResolveInfo> resolveInfos = new ArrayList<>();
@@ -268,15 +268,20 @@
for (ResolveInfo resolveInfo : resolveInfos) {
final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
+ if (disableSystemAppVerificationForTests) {
+ if (serviceInfo != null) {
+ services.add(serviceInfo);
+ }
+ continue;
+ }
+
try {
- PackageManager.ApplicationInfoFlags appInfoFlags =
- disableSystemAppVerificationForTests
- ? PackageManager.ApplicationInfoFlags.of(0)
- : PackageManager.ApplicationInfoFlags.of(
- PackageManager.MATCH_SYSTEM_ONLY);
ApplicationInfo appInfo =
context.getPackageManager()
- .getApplicationInfo(serviceInfo.packageName, appInfoFlags);
+ .getApplicationInfo(
+ serviceInfo.packageName,
+ PackageManager.ApplicationInfoFlags.of(
+ PackageManager.MATCH_SYSTEM_ONLY));
if (appInfo == null || serviceInfo == null) {
continue;
@@ -300,19 +305,22 @@
public static List<CredentialProviderInfo> getAvailableSystemServices(
@NonNull Context context,
@UserIdInt int userId,
- boolean disableSystemAppVerificationForTests) {
+ boolean disableSystemAppVerificationForTests,
+ Set<ServiceInfo> enabledServices) {
requireNonNull(context, "context must not be null");
+
final List<CredentialProviderInfo> providerInfos = new ArrayList<>();
for (ServiceInfo si :
getAvailableSystemServiceInfos(
context, userId, disableSystemAppVerificationForTests)) {
try {
CredentialProviderInfo cpi =
- new CredentialProviderInfo(
+ CredentialProviderInfoFactory.create(
context,
si,
/* isSystemProvider= */ true,
- disableSystemAppVerificationForTests);
+ disableSystemAppVerificationForTests,
+ enabledServices.contains(si));
if (cpi.isSystemProvider()) {
providerInfos.add(cpi);
} else {
@@ -325,45 +333,12 @@
return providerInfos;
}
- /**
- * Returns true if the service supports the given {@code credentialType}, false otherwise.
- */
- @NonNull
- public boolean hasCapability(@NonNull String credentialType) {
- return mCapabilities.contains(credentialType);
- }
+ private static @Nullable PackagePolicy getDeviceManagerPolicy(
+ @NonNull Context context, int userId) {
+ Context newContext = context.createContextAsUser(UserHandle.of(userId), 0);
- /** Returns the service info. */
- @NonNull
- public ServiceInfo getServiceInfo() {
- return mServiceInfo;
- }
-
- public boolean isSystemProvider() {
- return mIsSystemProvider;
- }
-
- /** Returns the service icon. */
- @Nullable
- public Drawable getServiceIcon() {
- return mIcon;
- }
-
- /** Returns the service label. */
- @Nullable
- public CharSequence getServiceLabel() {
- return mLabel;
- }
-
- /** Returns an immutable list of capabilities this provider service can support. */
- @NonNull
- public List<String> getCapabilities() {
- return Collections.unmodifiableList(mCapabilities);
- }
-
- private static @Nullable PackagePolicy getDeviceManagerPolicy(@NonNull Context context) {
try {
- DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+ DevicePolicyManager dpm = newContext.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.
@@ -381,21 +356,53 @@
public static List<CredentialProviderInfo> getCredentialProviderServices(
@NonNull Context context,
int userId,
- boolean disableSystemAppVerificationForTests,
- int providerFilter) {
+ int providerFilter,
+ Set<ServiceInfo> enabledServices) {
requireNonNull(context, "context must not be null");
// Get the device policy.
- PackagePolicy pp = getDeviceManagerPolicy(context);
+ PackagePolicy pp = getDeviceManagerPolicy(context, userId);
// Generate the provider list.
+ final boolean disableSystemAppVerificationForTests = false;
ProviderGenerator generator =
new ProviderGenerator(
context, pp, disableSystemAppVerificationForTests, providerFilter);
generator.addUserProviders(
- getUserProviders(context, userId, disableSystemAppVerificationForTests));
+ getUserProviders(
+ context, userId, disableSystemAppVerificationForTests, enabledServices));
generator.addSystemProviders(
- getAvailableSystemServices(context, userId, disableSystemAppVerificationForTests));
+ getAvailableSystemServices(
+ context, userId, disableSystemAppVerificationForTests, enabledServices));
+ return generator.getProviders();
+ }
+
+ /**
+ * Returns the valid credential provider services available for the user with the given {@code
+ * userId}. Includes test providers.
+ */
+ @NonNull
+ public static List<CredentialProviderInfo> getCredentialProviderServicesForTesting(
+ @NonNull Context context,
+ int userId,
+ int providerFilter,
+ Set<ServiceInfo> enabledServices) {
+ requireNonNull(context, "context must not be null");
+
+ // Get the device policy.
+ PackagePolicy pp = getDeviceManagerPolicy(context, userId);
+
+ // Generate the provider list.
+ final boolean disableSystemAppVerificationForTests = true;
+ ProviderGenerator generator =
+ new ProviderGenerator(
+ context, pp, disableSystemAppVerificationForTests, providerFilter);
+ generator.addUserProviders(
+ getUserProviders(
+ context, userId, disableSystemAppVerificationForTests, enabledServices));
+ generator.addSystemProviders(
+ getAvailableSystemServices(
+ context, userId, disableSystemAppVerificationForTests, enabledServices));
return generator.getProviders();
}
@@ -484,7 +491,8 @@
private static List<CredentialProviderInfo> getUserProviders(
@NonNull Context context,
@UserIdInt int userId,
- boolean disableSystemAppVerificationForTests) {
+ boolean disableSystemAppVerificationForTests,
+ Set<ServiceInfo> enabledServices) {
final List<CredentialProviderInfo> services = new ArrayList<>();
final List<ResolveInfo> resolveInfos =
context.getPackageManager()
@@ -496,11 +504,12 @@
final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
try {
CredentialProviderInfo cpi =
- new CredentialProviderInfo(
+ CredentialProviderInfoFactory.create(
context,
serviceInfo,
/* isSystemProvider= */ false,
- disableSystemAppVerificationForTests);
+ disableSystemAppVerificationForTests,
+ enabledServices.contains(serviceInfo));
if (!cpi.isSystemProvider()) {
services.add(cpi);
}
diff --git a/core/tests/coretests/src/android/credentials/CredentialManagerTest.java b/core/tests/coretests/src/android/credentials/CredentialManagerTest.java
index 43334ab..e31d5ae 100644
--- a/core/tests/coretests/src/android/credentials/CredentialManagerTest.java
+++ b/core/tests/coretests/src/android/credentials/CredentialManagerTest.java
@@ -30,6 +30,7 @@
import android.app.Activity;
import android.app.slice.Slice;
import android.content.Context;
+import android.content.pm.ServiceInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
@@ -47,6 +48,7 @@
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
+import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
@@ -59,6 +61,17 @@
@Mock
private Activity mMockActivity;
+ private static final int TEST_USER_ID = 1;
+ private static final CredentialProviderInfo TEST_CREDENTIAL_PROVIDER_INFO =
+ new CredentialProviderInfo.Builder(new ServiceInfo())
+ .setSystemProvider(true)
+ .setOverrideLabel("test")
+ .addCapabilities(Arrays.asList("passkey"))
+ .setEnabled(true)
+ .build();
+ private static final List<CredentialProviderInfo> TEST_CREDENTIAL_PROVIDER_INFO_LIST =
+ Arrays.asList(TEST_CREDENTIAL_PROVIDER_INFO);
+
private GetCredentialRequest mGetRequest;
private CreateCredentialRequest mCreateRequest;
@@ -438,95 +451,53 @@
}
@Test
- public void testListEnabledProviders_nullExecutor() {
- assertThrows(NullPointerException.class,
- () -> mCredentialManager.listEnabledProviders(null, null, result -> {
- }));
-
+ public void testGetCredentialProviderServices_allProviders() throws RemoteException {
+ verifyGetCredentialProviderServices(CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS);
}
@Test
- public void testListEnabledProviders_nullCallback() {
- assertThrows(NullPointerException.class,
- () -> mCredentialManager.listEnabledProviders(null, mExecutor, null));
-
+ public void testGetCredentialProviderServices_userProviders() throws RemoteException {
+ verifyGetCredentialProviderServices(CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY);
}
@Test
- public void testListEnabledProviders_alreadyCancelled() throws RemoteException {
- final CancellationSignal cancellation = new CancellationSignal();
- cancellation.cancel();
-
- mCredentialManager.listEnabledProviders(cancellation, mExecutor, result -> {
- });
-
- verify(mMockCredentialManagerService, never()).listEnabledProviders(any());
+ public void testGetCredentialProviderServices_systemProviders() throws RemoteException {
+ verifyGetCredentialProviderServices(CredentialManager.PROVIDER_FILTER_SYSTEM_PROVIDERS_ONLY);
}
@Test
- public void testListEnabledProviders_cancel() throws RemoteException {
- final ICancellationSignal serviceSignal = mock(ICancellationSignal.class);
- final CancellationSignal cancellation = new CancellationSignal();
-
- OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException> callback =
- mock(OutcomeReceiver.class);
-
- when(mMockCredentialManagerService.listEnabledProviders(any())).thenReturn(serviceSignal);
-
- mCredentialManager.listEnabledProviders(cancellation, mExecutor, callback);
-
- verify(mMockCredentialManagerService).listEnabledProviders(any());
-
- cancellation.cancel();
- verify(serviceSignal).cancel();
+ public void testGetCredentialProviderServicesForTesting_allProviders() throws RemoteException {
+ verifyGetCredentialProviderServicesForTesting(CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS);
}
@Test
- public void testListEnabledProviders_failed() throws RemoteException {
- ArgumentCaptor<IListEnabledProvidersCallback> callbackCaptor = ArgumentCaptor.forClass(
- IListEnabledProvidersCallback.class);
- ArgumentCaptor<ListEnabledProvidersException> errorCaptor = ArgumentCaptor.forClass(
- ListEnabledProvidersException.class);
-
- OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException> callback =
- mock(OutcomeReceiver.class);
-
- when(mMockCredentialManagerService.listEnabledProviders(
- callbackCaptor.capture())).thenReturn(mock(ICancellationSignal.class));
- mCredentialManager.listEnabledProviders(null, mExecutor, callback);
- verify(mMockCredentialManagerService).listEnabledProviders(any());
-
- final String errorType = "type";
- callbackCaptor.getValue().onError("type", "unknown error");
- verify(callback).onError(errorCaptor.capture());
-
- assertThat(errorCaptor.getValue().getType()).isEqualTo(errorType);
+ public void testGetCredentialProviderServicesForTesting_userProviders() throws RemoteException {
+ verifyGetCredentialProviderServicesForTesting(CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY);
}
@Test
- public void testListEnabledProviders_success() throws RemoteException {
- ListEnabledProvidersResponse response = ListEnabledProvidersResponse.create(
- List.of("foo", "bar", "baz"));
+ public void testGetCredentialProviderServicesForTesting_systemProviders() throws RemoteException {
+ verifyGetCredentialProviderServicesForTesting(CredentialManager.PROVIDER_FILTER_SYSTEM_PROVIDERS_ONLY);
+ }
- OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException> callback =
- mock(OutcomeReceiver.class);
+ private void verifyGetCredentialProviderServices(int testFilter) throws RemoteException {
+ when(mMockCredentialManagerService.getCredentialProviderServices(
+ TEST_USER_ID, testFilter)).thenReturn(TEST_CREDENTIAL_PROVIDER_INFO_LIST);
- ArgumentCaptor<IListEnabledProvidersCallback> callbackCaptor = ArgumentCaptor.forClass(
- IListEnabledProvidersCallback.class);
- ArgumentCaptor<ListEnabledProvidersResponse> responseCaptor = ArgumentCaptor.forClass(
- ListEnabledProvidersResponse.class);
+ List<CredentialProviderInfo> output =
+ mCredentialManager.getCredentialProviderServices(TEST_USER_ID, testFilter);
- when(mMockCredentialManagerService.listEnabledProviders(
- callbackCaptor.capture())).thenReturn(mock(ICancellationSignal.class));
- mCredentialManager.listEnabledProviders(null, mExecutor, callback);
+ assertThat(output).containsExactlyElementsIn(TEST_CREDENTIAL_PROVIDER_INFO_LIST);
+ }
- verify(mMockCredentialManagerService).listEnabledProviders(any());
+ private void verifyGetCredentialProviderServicesForTesting(int testFilter) throws RemoteException {
+ when(mMockCredentialManagerService.getCredentialProviderServicesForTesting(
+ testFilter)).thenReturn(TEST_CREDENTIAL_PROVIDER_INFO_LIST);
- callbackCaptor.getValue().onResponse(response);
+ List<CredentialProviderInfo> output =
+ mCredentialManager.getCredentialProviderServicesForTesting(testFilter);
- verify(callback).onResult(responseCaptor.capture());
- assertThat(responseCaptor.getValue().getProviderComponentNames()).containsExactlyElementsIn(
- response.getProviderComponentNames());
+ assertThat(output).containsExactlyElementsIn(TEST_CREDENTIAL_PROVIDER_INFO_LIST);
}
@Test
diff --git a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
index c8ec7c2..49db5f7 100644
--- a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
@@ -20,13 +20,13 @@
import android.content.ComponentName;
import android.content.Context;
import android.credentials.ClearCredentialStateRequest;
+import android.credentials.CredentialProviderInfo;
import android.credentials.IClearCredentialStateCallback;
import android.credentials.ui.ProviderData;
import android.credentials.ui.RequestInfo;
import android.os.CancellationSignal;
import android.os.RemoteException;
import android.service.credentials.CallingAppInfo;
-import android.service.credentials.CredentialProviderInfo;
import android.util.Log;
import com.android.server.credentials.metrics.ApiName;
diff --git a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
index 0c1133c..90e1067 100644
--- a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
@@ -27,13 +27,13 @@
import android.credentials.CreateCredentialRequest;
import android.credentials.CreateCredentialResponse;
import android.credentials.CredentialManager;
+import android.credentials.CredentialProviderInfo;
import android.credentials.ICreateCredentialCallback;
import android.credentials.ui.ProviderData;
import android.credentials.ui.RequestInfo;
import android.os.CancellationSignal;
import android.os.RemoteException;
import android.service.credentials.CallingAppInfo;
-import android.service.credentials.CredentialProviderInfo;
import android.util.Log;
import com.android.server.credentials.metrics.ApiName;
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index 41ae911..8170dc3 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -36,15 +36,14 @@
import android.credentials.CredentialDescription;
import android.credentials.CredentialManager;
import android.credentials.CredentialOption;
+import android.credentials.CredentialProviderInfo;
import android.credentials.GetCredentialException;
import android.credentials.GetCredentialRequest;
import android.credentials.IClearCredentialStateCallback;
import android.credentials.ICreateCredentialCallback;
import android.credentials.ICredentialManager;
import android.credentials.IGetCredentialCallback;
-import android.credentials.IListEnabledProvidersCallback;
import android.credentials.ISetEnabledProvidersCallback;
-import android.credentials.ListEnabledProvidersResponse;
import android.credentials.RegisterCredentialDescriptionRequest;
import android.credentials.UnregisterCredentialDescriptionRequest;
import android.credentials.ui.IntentFactory;
@@ -56,7 +55,7 @@
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.service.credentials.CallingAppInfo;
-import android.service.credentials.CredentialProviderInfo;
+import android.service.credentials.CredentialProviderInfoFactory;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
@@ -118,10 +117,11 @@
int resolvedUserId) {
List<CredentialManagerServiceImpl> services = new ArrayList<>();
List<CredentialProviderInfo> serviceInfos =
- CredentialProviderInfo.getAvailableSystemServices(
+ CredentialProviderInfoFactory.getAvailableSystemServices(
mContext,
resolvedUserId,
- /* disableSystemAppVerificationForTests= */ false);
+ /* disableSystemAppVerificationForTests= */ false,
+ new HashSet<>());
serviceInfos.forEach(
info -> {
services.add(
@@ -222,10 +222,16 @@
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 void verifyGetProvidersPermission() throws SecurityException {
+ if (hasPermission(android.Manifest.permission.QUERY_ALL_PACKAGES)) {
+ return;
}
+
+ if (hasPermission(android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS)) {
+ return;
+ }
+
+ throw new SecurityException("Caller is missing permission: QUERY_ALL_PACKAGES or LIST_ENABLED_CREDENTIAL_PROVIDERS");
}
private boolean hasPermission(String permission) {
@@ -550,40 +556,6 @@
providerSessions.forEach(ProviderSession::invokeSession);
}
- @SuppressWarnings("GuardedBy") // ErrorProne requires listEnabledProviders
- // to be guarded by 'service.mLock', which is the same as mLock.
- @Override
- public ICancellationSignal listEnabledProviders(IListEnabledProvidersCallback callback) {
- Log.i(TAG, "listEnabledProviders");
- ICancellationSignal cancelTransport = CancellationSignal.createTransport();
-
- if (!hasWriteSecureSettingsPermission()) {
- try {
- callback.onError(
- PERMISSION_DENIED_ERROR, PERMISSION_DENIED_WRITE_SECURE_SETTINGS_ERROR);
- } catch (RemoteException e) {
- Log.e(TAG, "Issue with invoking response: " + e.getMessage());
- }
- return cancelTransport;
- }
-
- List<String> enabledProviders = new ArrayList<>();
- runForUser(
- (service) -> {
- enabledProviders.add(service.getComponentName().flattenToString());
- });
-
- // Call the callback.
- try {
- callback.onResponse(ListEnabledProvidersResponse.create(enabledProviders));
- } catch (RemoteException e) {
- Log.i(TAG, "Issue with invoking response: " + e.getMessage());
- // TODO: Propagate failure
- }
-
- return cancelTransport;
- }
-
@Override
public void setEnabledProviders(
List<String> providers, int userId, ISetEnabledProvidersCallback callback) {
@@ -677,20 +649,35 @@
}
@Override
- public List<ServiceInfo> getCredentialProviderServices(
- int userId, boolean disableSystemAppVerificationForTests, int providerFilter) {
+ public List<CredentialProviderInfo> getCredentialProviderServices(
+ int userId, int providerFilter) {
Log.i(TAG, "getCredentialProviderServices");
- verifyPermission(android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS);
+ verifyGetProvidersPermission();
- List<ServiceInfo> services = new ArrayList<>();
- List<CredentialProviderInfo> providers =
- CredentialProviderInfo.getCredentialProviderServices(
- mContext, userId, disableSystemAppVerificationForTests, providerFilter);
- for (CredentialProviderInfo p : providers) {
- services.add(p.getServiceInfo());
+ return CredentialProviderInfoFactory.getCredentialProviderServices(
+ mContext, userId, providerFilter, getEnabledProviders());
+ }
+
+ @Override
+ public List<CredentialProviderInfo> getCredentialProviderServicesForTesting(
+ int providerFilter) {
+ Log.i(TAG, "getCredentialProviderServicesForTesting");
+ verifyGetProvidersPermission();
+
+ final int userId = UserHandle.getCallingUserId();
+ return CredentialProviderInfoFactory.getCredentialProviderServicesForTesting(
+ mContext, userId, providerFilter, getEnabledProviders());
+ }
+
+ private Set<ServiceInfo> getEnabledProviders() {
+ Set<ServiceInfo> enabledProviders = new HashSet<>();
+ synchronized (mLock) {
+ runForUser(
+ (service) -> {
+ enabledProviders.add(service.getCredentialProviderInfo().getServiceInfo());
+ });
}
-
- return services;
+ return enabledProviders;
}
@Override
@@ -828,11 +815,11 @@
}
private List<CredentialProviderInfo> getServicesForCredentialDescription(int userId) {
- return CredentialProviderInfo.getCredentialProviderServices(
+ return CredentialProviderInfoFactory.getCredentialProviderServices(
mContext,
userId,
- /* disableSystemAppVerificationForTests= */ false,
- CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS);
+ CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS,
+ new HashSet<>());
}
}
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java b/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java
index 546c48f..ee55a1c 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerServiceImpl.java
@@ -21,7 +21,8 @@
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
-import android.service.credentials.CredentialProviderInfo;
+import android.credentials.CredentialProviderInfo;
+import android.service.credentials.CredentialProviderInfoFactory;
import android.util.Log;
import android.util.Slog;
@@ -82,7 +83,7 @@
Log.i(TAG, "newServiceInfoLocked with null mInfo , "
+ serviceComponent.getPackageName());
}
- mInfo = new CredentialProviderInfo(
+ mInfo = CredentialProviderInfoFactory.create(
getContext(), serviceComponent,
mUserId, /*isSystemProvider=*/false);
return mInfo.getServiceInfo();
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java b/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java
index 2c6c0d8..546c37f 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java
@@ -22,6 +22,7 @@
import android.content.Intent;
import android.content.pm.ServiceInfo;
import android.credentials.CredentialManager;
+import android.credentials.CredentialProviderInfo;
import android.credentials.ui.DisabledProviderData;
import android.credentials.ui.IntentFactory;
import android.credentials.ui.ProviderData;
@@ -31,11 +32,12 @@
import android.os.Handler;
import android.os.Looper;
import android.os.ResultReceiver;
-import android.service.credentials.CredentialProviderInfo;
+import android.service.credentials.CredentialProviderInfoFactory;
import android.util.Log;
import android.util.Slog;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
@@ -118,11 +120,11 @@
.map(ProviderData::getProviderFlattenedComponentName)
.collect(Collectors.toUnmodifiableSet());
Set<String> allProviders =
- CredentialProviderInfo.getCredentialProviderServices(
+ CredentialProviderInfoFactory.getCredentialProviderServices(
mContext,
mUserId,
- /* disableSystemAppVerificationForTests= */ false,
- CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY)
+ CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY,
+ new HashSet<>())
.stream()
.map(CredentialProviderInfo::getServiceInfo)
.map(ServiceInfo::getComponentName)
diff --git a/services/credentials/java/com/android/server/credentials/GetRequestSession.java b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
index 13f4b54..4af2713 100644
--- a/services/credentials/java/com/android/server/credentials/GetRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
@@ -22,6 +22,7 @@
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
+import android.credentials.CredentialProviderInfo;
import android.credentials.GetCredentialException;
import android.credentials.GetCredentialRequest;
import android.credentials.GetCredentialResponse;
@@ -31,7 +32,6 @@
import android.os.CancellationSignal;
import android.os.RemoteException;
import android.service.credentials.CallingAppInfo;
-import android.service.credentials.CredentialProviderInfo;
import android.util.Log;
import com.android.server.credentials.metrics.ApiName;
diff --git a/services/credentials/java/com/android/server/credentials/ProviderClearSession.java b/services/credentials/java/com/android/server/credentials/ProviderClearSession.java
index 941d9ad..b7a4cd5 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderClearSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderClearSession.java
@@ -20,11 +20,11 @@
import android.annotation.UserIdInt;
import android.content.Context;
import android.credentials.ClearCredentialStateException;
+import android.credentials.CredentialProviderInfo;
import android.credentials.ui.ProviderData;
import android.credentials.ui.ProviderPendingIntentResponse;
import android.service.credentials.CallingAppInfo;
import android.service.credentials.ClearCredentialStateRequest;
-import android.service.credentials.CredentialProviderInfo;
import android.util.Log;
import android.util.Slog;
diff --git a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
index 17caba5..640cc33 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
@@ -24,6 +24,7 @@
import android.content.Intent;
import android.credentials.CreateCredentialException;
import android.credentials.CreateCredentialResponse;
+import android.credentials.CredentialProviderInfo;
import android.credentials.ui.CreateCredentialProviderData;
import android.credentials.ui.Entry;
import android.credentials.ui.ProviderPendingIntentResponse;
@@ -33,7 +34,6 @@
import android.service.credentials.CallingAppInfo;
import android.service.credentials.CreateCredentialRequest;
import android.service.credentials.CreateEntry;
-import android.service.credentials.CredentialProviderInfo;
import android.service.credentials.CredentialProviderService;
import android.service.credentials.RemoteEntry;
import android.util.Log;
diff --git a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
index b8b11eb..07e2f87 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.content.Intent;
import android.credentials.CredentialOption;
+import android.credentials.CredentialProviderInfo;
import android.credentials.GetCredentialException;
import android.credentials.GetCredentialResponse;
import android.credentials.ui.AuthenticationEntry;
@@ -35,7 +36,6 @@
import android.service.credentials.BeginGetCredentialResponse;
import android.service.credentials.CallingAppInfo;
import android.service.credentials.CredentialEntry;
-import android.service.credentials.CredentialProviderInfo;
import android.service.credentials.CredentialProviderService;
import android.service.credentials.GetCredentialRequest;
import android.service.credentials.RemoteEntry;
diff --git a/services/credentials/java/com/android/server/credentials/ProviderSession.java b/services/credentials/java/com/android/server/credentials/ProviderSession.java
index 53ed070..fc179e4 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderSession.java
@@ -27,11 +27,11 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.credentials.Credential;
+import android.credentials.CredentialProviderInfo;
import android.credentials.ui.ProviderData;
import android.credentials.ui.ProviderPendingIntentResponse;
import android.os.ICancellationSignal;
import android.os.RemoteException;
-import android.service.credentials.CredentialProviderInfo;
import android.util.Log;
import com.android.server.credentials.metrics.CandidateProviderMetric;
diff --git a/services/credentials/java/com/android/server/credentials/RequestSession.java b/services/credentials/java/com/android/server/credentials/RequestSession.java
index abfb210..c1f35d0 100644
--- a/services/credentials/java/com/android/server/credentials/RequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/RequestSession.java
@@ -22,6 +22,7 @@
import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Context;
+import android.credentials.CredentialProviderInfo;
import android.credentials.ui.ProviderData;
import android.credentials.ui.UserSelectionDialogResult;
import android.os.Binder;
@@ -30,7 +31,6 @@
import android.os.IBinder;
import android.os.Looper;
import android.service.credentials.CallingAppInfo;
-import android.service.credentials.CredentialProviderInfo;
import android.util.Log;
import com.android.internal.R;