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;