Add provider facing GET APIs for Credential Manager.

Credential Manager is a set of APIs that allows developers to get and
create credentials. These credentials are sourced from providers that
are registered with the android framework.

Test: Built and Deployed on device locally.
Bug: 247545196
CTS-Coverage-Bug: 247549381
Change-Id: If5b6569810be30ec6f7997e9161fe9b85d286cfc
diff --git a/core/java/android/service/credentials/Action.java b/core/java/android/service/credentials/Action.java
new file mode 100644
index 0000000..186b2a6
--- /dev/null
+++ b/core/java/android/service/credentials/Action.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2022 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.service.credentials;
+
+import android.app.PendingIntent;
+import android.app.slice.Slice;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.NonNull;
+
+import java.util.Objects;
+
+/**
+ * An action defined by the provider that intents into the provider's app for specific
+ * user actions.
+ *
+ * @hide
+ */
+public final class Action implements Parcelable {
+    /** Info to be displayed with this action on the UI. */
+    private final @NonNull Slice mInfo;
+    /**
+     * The pending intent to be invoked when the user selects this action.
+     */
+    private final @NonNull PendingIntent mPendingIntent;
+
+    /**
+     * Constructs an action to be displayed on the UI.
+     *
+     * @param actionInfo The info to be displayed along with this action.
+     * @param pendingIntent The intent to be invoked when the user selects this action.
+     * @throws NullPointerException If {@code actionInfo}, or {@code pendingIntent} is null.
+     */
+    public Action(@NonNull Slice actionInfo, @NonNull PendingIntent pendingIntent) {
+        Objects.requireNonNull(actionInfo, "actionInfo must not be null");
+        Objects.requireNonNull(pendingIntent, "pendingIntent must not be null");
+        mInfo = actionInfo;
+        mPendingIntent = pendingIntent;
+    }
+
+    private Action(@NonNull Parcel in) {
+        mInfo = in.readParcelable(Slice.class.getClassLoader(), Slice.class);
+        mPendingIntent = in.readParcelable(PendingIntent.class.getClassLoader(),
+                PendingIntent.class);
+    }
+
+    public static final @NonNull Creator<Action> CREATOR = new Creator<Action>() {
+        @Override
+        public Action createFromParcel(@NonNull Parcel in) {
+            return new Action(in);
+        }
+
+        @Override
+        public Action[] newArray(int size) {
+            return new Action[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        mInfo.writeToParcel(dest, flags);
+        mPendingIntent.writeToParcel(dest, flags);
+    }
+
+    /**
+     * Returns the action info as a {@link Slice} object, to be displayed on the UI.
+     */
+    public @NonNull Slice getActionInfo() {
+        return mInfo;
+    }
+
+    /**
+     * Returns the {@link PendingIntent} to be invoked when the action is selected.
+     */
+    public @NonNull PendingIntent getPendingIntent() {
+        return mPendingIntent;
+    }
+}
diff --git a/core/java/android/service/credentials/Credential.java b/core/java/android/service/credentials/Credential.java
new file mode 100644
index 0000000..7d5da8a
--- /dev/null
+++ b/core/java/android/service/credentials/Credential.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2022 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.service.credentials;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.NonNull;
+
+import static java.util.Objects.requireNonNull;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * A Credential object that contains type specific data that is returned from the credential
+ * provider to the framework. Framework then converts it to an app facing representation and
+ * returns to the calling app.
+ *
+ * @hide
+ */
+public final class Credential implements Parcelable {
+    /** The type of this credential. */
+    private final @NonNull String mType;
+
+    /** The data associated with this credential. */
+    private final @NonNull Bundle mData;
+
+    /**
+     * Constructs a credential object.
+     *
+     * @param type The type of the credential.
+     * @param data The data of the credential that is passed back to the framework, and eventually
+     *             to the calling app.
+     * @throws NullPointerException If {@code data} is null.
+     * @throws IllegalArgumentException If {@code type} is null or empty.
+     */
+    public Credential(@NonNull String type, @NonNull Bundle data) {
+        Preconditions.checkStringNotEmpty(type, "type must not be null, or empty");
+        requireNonNull(data, "data must not be null");
+        this.mType = type;
+        this.mData = data;
+    }
+
+    private Credential(@NonNull Parcel in) {
+        mType = in.readString16NoHelper();
+        mData = in.readBundle();
+    }
+
+    /**
+     * Returns the type of the credential.
+     */
+    public @NonNull String getType() {
+        return mType;
+    }
+
+    /**
+     * Returns the data associated with the credential.
+     */
+    public @NonNull Bundle getData() {
+        return mData;
+    }
+
+    public static final @NonNull Creator<Credential> CREATOR = new Creator<Credential>() {
+        @Override
+        public Credential createFromParcel(@NonNull Parcel in) {
+            return new Credential(in);
+        }
+
+        @Override
+        public Credential[] newArray(int size) {
+            return new Credential[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString8(mType);
+        dest.writeBundle(mData);
+    }
+}
diff --git a/core/java/android/service/credentials/CredentialEntry.java b/core/java/android/service/credentials/CredentialEntry.java
new file mode 100644
index 0000000..b49215a
--- /dev/null
+++ b/core/java/android/service/credentials/CredentialEntry.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2022 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.service.credentials;
+
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.app.slice.Slice;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.NonNull;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.Objects;
+
+/**
+ * A credential entry that is displayed on the account selector UI. Each entry corresponds to
+ * something that the user can select.
+ *
+ * @hide
+ */
+public final class CredentialEntry implements Parcelable {
+    /** The type of the credential entry to be shown on the UI. */
+    private final @NonNull String mType;
+
+    /** The info to be displayed along with this credential entry on the UI. */
+    private final @NonNull Slice mInfo;
+
+    /** The pending intent to be invoked when this credential entry is selected. */
+    private final @Nullable PendingIntent mPendingIntent;
+
+    /**
+     * The underlying credential to be returned to the app when the user selects
+     * this credential entry.
+     */
+    private final @Nullable Credential mCredential;
+
+    /** A flag denoting whether auto-select is enabled for this entry. */
+    private final @NonNull boolean mAutoSelectAllowed;
+
+    private CredentialEntry(@NonNull String type, @NonNull Slice entryInfo,
+            @Nullable PendingIntent pendingIntent, @Nullable Credential credential,
+            @NonNull boolean autoSeletAllowed) {
+        mType = type;
+        mInfo = entryInfo;
+        mPendingIntent = pendingIntent;
+        mCredential = credential;
+        mAutoSelectAllowed = autoSeletAllowed;
+    }
+
+    private CredentialEntry(@NonNull Parcel in) {
+        mType = in.readString();
+        mInfo = in.readParcelable(Slice.class.getClassLoader(), Slice.class);
+        mPendingIntent = in.readParcelable(PendingIntent.class.getClassLoader(),
+                PendingIntent.class);
+        mCredential = in.readParcelable(Credential.class.getClassLoader(),
+                Credential.class);
+        mAutoSelectAllowed = in.readBoolean();
+    }
+
+    public static final @NonNull Creator<CredentialEntry> CREATOR =
+            new Creator<CredentialEntry>() {
+        @Override
+        public CredentialEntry createFromParcel(@NonNull Parcel in) {
+            return new CredentialEntry(in);
+        }
+
+        @Override
+        public CredentialEntry[] newArray(int size) {
+            return new CredentialEntry[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString8(mType);
+        mInfo.writeToParcel(dest, flags);
+        mPendingIntent.writeToParcel(dest, flags);
+        mCredential.writeToParcel(dest, flags);
+        dest.writeBoolean(mAutoSelectAllowed);
+    }
+
+    /**
+     * Returns the specific credential type of the entry.
+     */
+    public @NonNull String getType() {
+        return mType;
+    }
+
+    /**
+     * Returns the UI info to be displayed for this entry.
+     */
+    public @NonNull Slice getInfo() {
+        return mInfo;
+    }
+
+    /**
+     * Returns the pending intent to be invoked if the user selects this entry.
+     */
+    public @Nullable PendingIntent getPendingIntent() {
+        return mPendingIntent;
+    }
+
+    /**
+     * Returns the credential associated with this entry.
+     */
+    public @Nullable Credential getCredential() {
+        return mCredential;
+    }
+
+    /**
+     * Returns whether this entry can be auto selected if it is the only option for the user.
+     */
+    public @NonNull boolean isAutoSelectAllowed() {
+        return mAutoSelectAllowed;
+    }
+
+    /**
+     * Builder for {@link CredentialEntry}.
+     */
+    public static final class Builder {
+        private String mType;
+        private Slice mInfo;
+        private PendingIntent mPendingIntent;
+        private Credential mCredential;
+        private boolean mAutoSelectAllowed = false;
+
+        /**
+         * Builds the instance.
+         * @param type The type of credential underlying this credential entry.
+         * @param info The info to be displayed with this entry on the UI.
+         *
+         * @throws IllegalArgumentException If {@code type} is null or empty.
+         * @throws NullPointerException If {@code info} is null.
+         */
+        public Builder(@NonNull String type, @NonNull Slice info) {
+            mType = Preconditions.checkStringNotEmpty(type, "type must not be "
+                    + "null, or empty");
+            mInfo = Objects.requireNonNull(info, "info must not be null");
+        }
+
+        /**
+         * Sets the pendingIntent to be invoked if the user selects this entry.
+         *
+         * @throws IllegalStateException If {@code credential} is already set. Must either set the
+         * {@code credential}, or the {@code pendingIntent}.
+         */
+        public @NonNull Builder setPendingIntent(@Nullable PendingIntent pendingIntent) {
+            Preconditions.checkState(pendingIntent != null && mCredential != null,
+                    "credential is already set. Cannot set both the pendingIntent "
+                            + "and the credential");
+            mPendingIntent = pendingIntent;
+            return this;
+        }
+
+        /**
+         * Sets the credential to be used, if the user selects this entry.
+         *
+         * @throws IllegalStateException If {@code pendingIntent} is already set. Must either set
+         * the {@code pendingIntent}, or the {@code credential}.
+         */
+        public @NonNull Builder setCredential(@Nullable Credential credential) {
+            Preconditions.checkState(credential != null && mPendingIntent != null,
+                    "pendingIntent is already set. Cannot set both the "
+                            + "pendingIntent and the credential");
+            mCredential = credential;
+            return this;
+        }
+
+        /**
+         * Sets whether the entry is allowed to be auto selected by the framework.
+         * The default value is set to false.
+         */
+        public @NonNull Builder setAutoSelectAllowed(@NonNull boolean autoSelectAllowed) {
+            mAutoSelectAllowed = autoSelectAllowed;
+            return this;
+        }
+
+        /**
+         * Creates a new {@link CredentialEntry} instance.
+         *
+         * @throws NullPointerException If {@code info} is null.
+         * @throws IllegalArgumentException If {@code type} is null, or empty.
+         * @throws IllegalStateException If neither {@code pendingIntent} nor {@code credential}
+         * is set, or if both are set.
+         */
+        public @NonNull CredentialEntry build() {
+            Preconditions.checkState(mPendingIntent == null && mCredential == null,
+                    "Either pendingIntent or credential must be set");
+            Preconditions.checkState(mPendingIntent != null && mCredential != null,
+                    "Cannot set both the pendingIntent and credential");
+            return new CredentialEntry(mType, mInfo, mPendingIntent,
+                    mCredential, mAutoSelectAllowed);
+        }
+    }
+}
diff --git a/core/java/android/service/credentials/CredentialProviderService.java b/core/java/android/service/credentials/CredentialProviderService.java
new file mode 100644
index 0000000..e2a495d
--- /dev/null
+++ b/core/java/android/service/credentials/CredentialProviderService.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2022 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.service.credentials;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
+import android.annotation.CallSuper;
+import android.annotation.NonNull;
+import android.app.Service;
+import android.content.Intent;
+import android.os.CancellationSignal;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.ICancellationSignal;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.Objects;
+
+/**
+ * Main service to be extended by credential providers, in order to return user credentials
+ * to the framework.
+ *
+ * @hide
+ */
+public abstract class CredentialProviderService extends Service {
+    private static final String TAG = "CredProviderService";
+    private Handler mHandler;
+
+    public static final String SERVICE_INTERFACE =
+            "android.service.credentials.CredentialProviderService";
+
+    @CallSuper
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mHandler = new Handler(Looper.getMainLooper(), null, true);
+    }
+
+    @Override
+    public final @NonNull IBinder onBind(@NonNull Intent intent) {
+        if (SERVICE_INTERFACE.equals(intent.getAction())) {
+            return mInterface.asBinder();
+        }
+        Log.i(TAG, "Failed to bind with intent: " + intent);
+        return null;
+    }
+
+    private final ICredentialProviderService mInterface = new ICredentialProviderService.Stub() {
+        @Override
+        public void onGetCredentials(GetCredentialsRequest request, ICancellationSignal transport,
+                IGetCredentialsCallback callback) throws RemoteException {
+            Objects.requireNonNull(request);
+            Objects.requireNonNull(callback);
+
+            mHandler.sendMessage(obtainMessage(
+                    CredentialProviderService::onGetCredentials,
+                    CredentialProviderService.this, request,
+                    CancellationSignal.fromTransport(transport),
+                    new GetCredentialsCallback(callback)
+            ));
+        }
+    };
+
+    /**
+     * Called by the android system to retrieve user credentials from the connected provider
+     * service.
+     * @param request The credential request for the provider to handle.
+     * @param cancellationSignal Signal for providers to listen to any cancellation requests from
+     *                           the android system.
+     * @param callback Object used to relay the response of the credentials request.
+     */
+    public abstract void onGetCredentials(@NonNull GetCredentialsRequest request,
+            @NonNull CancellationSignal cancellationSignal,
+            @NonNull GetCredentialsCallback callback);
+}
diff --git a/core/java/android/service/credentials/CredentialsDisplayContent.java b/core/java/android/service/credentials/CredentialsDisplayContent.java
new file mode 100644
index 0000000..106f322
--- /dev/null
+++ b/core/java/android/service/credentials/CredentialsDisplayContent.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2022 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.service.credentials;
+
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.NonNull;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Content to be displayed on the account selector UI, including credential entries,
+ * actions etc.
+ *
+ * @hide
+ */
+public final class CredentialsDisplayContent implements Parcelable {
+    /** Header to be displayed on the UI. */
+    private final @Nullable CharSequence mHeader;
+
+    /** List of credential entries to be displayed on the UI. */
+    private final @NonNull List<CredentialEntry> mCredentialEntries;
+
+    /** List of provider actions to be displayed on the UI. */
+    private final @NonNull List<Action> mActions;
+
+    private CredentialsDisplayContent(@Nullable CharSequence header,
+            @NonNull List<CredentialEntry> credentialEntries,
+            @NonNull List<Action> actions) {
+        mHeader = header;
+        mCredentialEntries = credentialEntries;
+        mActions = actions;
+    }
+
+    private CredentialsDisplayContent(@NonNull Parcel in) {
+        mHeader = in.readCharSequence();
+        mCredentialEntries = in.createTypedArrayList(CredentialEntry.CREATOR);
+        mActions = in.createTypedArrayList(Action.CREATOR);
+    }
+
+    public static final @NonNull Creator<CredentialsDisplayContent> CREATOR =
+            new Creator<CredentialsDisplayContent>() {
+                @Override
+                public CredentialsDisplayContent createFromParcel(@NonNull Parcel in) {
+                    return new CredentialsDisplayContent(in);
+                }
+
+                @Override
+                public CredentialsDisplayContent[] newArray(int size) {
+                    return new CredentialsDisplayContent[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeCharSequence(mHeader);
+        dest.writeTypedList(mCredentialEntries);
+        dest.writeTypedList(mActions);
+    }
+
+    /**
+     * Returns the header to be displayed on the UI.
+     */
+    public @Nullable CharSequence getHeader() {
+        return mHeader;
+    }
+
+    /**
+     * Returns the list of credential entries to be displayed on the UI.
+     */
+    public @NonNull List<CredentialEntry> getCredentialEntries() {
+        return mCredentialEntries;
+    }
+
+    /**
+     * Returns the list of actions to be displayed on the UI.
+     */
+    public @NonNull List<Action> getActions() {
+        return mActions;
+    }
+
+    /**
+     * Builds an instance of {@link CredentialsDisplayContent}.
+     */
+    public static final class Builder {
+        private CharSequence mHeader = null;
+        private List<CredentialEntry> mCredentialEntries = new ArrayList<>();
+        private List<Action> mActions = new ArrayList<>();
+
+        /**
+         * Sets the header to be displayed on the UI.
+         */
+        public @NonNull Builder setHeader(@Nullable CharSequence header) {
+            mHeader = header;
+            return this;
+        }
+
+        /**
+         * Adds a {@link CredentialEntry} to the list of entries to be displayed on
+         * the UI.
+         *
+         * @throws NullPointerException If the {@code credentialEntry} is null.
+         */
+        public @NonNull Builder addCredentialEntry(@NonNull CredentialEntry credentialEntry) {
+            mCredentialEntries.add(Objects.requireNonNull(credentialEntry));
+            return this;
+        }
+
+        /**
+         * Adds an {@link Action} to the list of actions to be displayed on
+         * the UI.
+         *
+         * @throws NullPointerException If {@code action} is null.
+         */
+        public @NonNull Builder addAction(@NonNull Action action) {
+            mActions.add(Objects.requireNonNull(action, "action must not be null"));
+            return this;
+        }
+
+        /**
+         * Sets the list of actions to be displayed on the UI.
+         *
+         * @throws NullPointerException If {@code actions} is null, or any of its elements
+         * is null.
+         */
+        public @NonNull Builder setActions(@NonNull List<Action> actions) {
+            mActions = Preconditions.checkCollectionElementsNotNull(actions,
+                    "actions");
+            return this;
+        }
+
+        /**
+         * Sets the list of credential entries to be displayed on the
+         * account selector UI.
+         *
+         * @throws NullPointerException If {@code credentialEntries} is null, or any of its
+         * elements is null.
+         */
+        public @NonNull Builder setCredentialEntries(
+                @NonNull List<CredentialEntry> credentialEntries) {
+            mCredentialEntries = Preconditions.checkCollectionElementsNotNull(
+                    credentialEntries,
+                    "credentialEntries");
+            return this;
+        }
+
+        /**
+         * Builds a {@link GetCredentialsResponse} instance.
+         *
+         * @throws NullPointerException If {@code credentialEntries} is null.
+         * @throws IllegalStateException if both {@code credentialEntries} and
+         * {@code actions} are empty.
+         */
+        public @NonNull CredentialsDisplayContent build() {
+            if (mCredentialEntries != null && mCredentialEntries.isEmpty()
+                    && mActions != null && mActions.isEmpty()) {
+                throw new IllegalStateException("credentialEntries and actions must not both "
+                        + "be empty");
+            }
+            return new CredentialsDisplayContent(mHeader, mCredentialEntries, mActions);
+        }
+    }
+}
diff --git a/core/java/android/service/credentials/GetCredentialOption.java b/core/java/android/service/credentials/GetCredentialOption.java
new file mode 100644
index 0000000..c6cda1d
--- /dev/null
+++ b/core/java/android/service/credentials/GetCredentialOption.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2022 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.service.credentials;
+
+import android.annotation.NonNull;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A type specific credential request, containing the associated data to be used for
+ * retrieving credentials.
+ *
+ * @hide
+ */
+public final class GetCredentialOption implements Parcelable {
+    /** The type of credential requested. */
+    private final @NonNull String mType;
+
+    /** The data associated with the request. */
+    private final @NonNull Bundle mData;
+
+    /**
+     * Constructs a new instance of {@link GetCredentialOption}
+     *
+     * @throws IllegalArgumentException If {@code type} string is null or empty.
+     * @throws NullPointerException If {@code data} is null.
+     */
+    public GetCredentialOption(@NonNull String type, @NonNull Bundle data) {
+        Preconditions.checkStringNotEmpty(type, "type must not be null, or empty");
+        requireNonNull(data, "data must not be null");
+        mType = type;
+        mData = data;
+    }
+
+    /**
+     * Returns the data associated with this credential request option.
+     */
+    public @NonNull Bundle getData() {
+        return mData;
+    }
+
+    /**
+     * Returns the type associated with this credential request option.
+     */
+    public @NonNull String getType() {
+        return mType;
+    }
+
+    private GetCredentialOption(@NonNull Parcel in) {
+        mType = in.readString16NoHelper();
+        mData = in.readBundle();
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString16NoHelper(mType);
+        dest.writeBundle(mData);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final @NonNull Creator<GetCredentialOption> CREATOR =
+            new Creator<GetCredentialOption>() {
+        @Override
+        public GetCredentialOption createFromParcel(@NonNull Parcel in) {
+            return new GetCredentialOption(in);
+        }
+
+        @Override
+        public GetCredentialOption[] newArray(int size) {
+            return new GetCredentialOption[size];
+        }
+    };
+}
diff --git a/core/java/android/service/credentials/GetCredentialsCallback.java b/core/java/android/service/credentials/GetCredentialsCallback.java
new file mode 100644
index 0000000..0e81b8f
--- /dev/null
+++ b/core/java/android/service/credentials/GetCredentialsCallback.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2022 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.service.credentials;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * Callback to be invoked as a response to {@link GetCredentialsRequest}.
+ *
+ * @hide
+ */
+public final class GetCredentialsCallback {
+
+    private static final String TAG = "GetCredentialsCallback";
+
+    private final IGetCredentialsCallback mCallback;
+
+    /** @hide */
+    public GetCredentialsCallback(@NonNull IGetCredentialsCallback callback) {
+        mCallback = callback;
+    }
+
+    /**
+     * Invoked on a successful response for {@link GetCredentialsRequest}
+     * @param response The response from the credential provider.
+     */
+    public void onSuccess(@Nullable GetCredentialsResponse response) {
+        try {
+            mCallback.onSuccess(response);
+        } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Invoked on a failure response for {@link GetCredentialsRequest}
+     * @param errorCode The code defining the kind of error.
+     * @param message The message corresponding to the failure.
+     */
+    public void onFailure(int errorCode, @Nullable CharSequence message) {
+        Log.w(TAG, "onFailure: " + message);
+        try {
+            mCallback.onFailure(errorCode, message);
+        } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
+        }
+    }
+}
diff --git a/core/java/android/service/credentials/GetCredentialsRequest.aidl b/core/java/android/service/credentials/GetCredentialsRequest.aidl
new file mode 100644
index 0000000..b309d69
--- /dev/null
+++ b/core/java/android/service/credentials/GetCredentialsRequest.aidl
@@ -0,0 +1,3 @@
+package android.service.credentials;
+
+parcelable GetCredentialsRequest;
\ No newline at end of file
diff --git a/core/java/android/service/credentials/GetCredentialsRequest.java b/core/java/android/service/credentials/GetCredentialsRequest.java
new file mode 100644
index 0000000..cf7c283
--- /dev/null
+++ b/core/java/android/service/credentials/GetCredentialsRequest.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2022 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.service.credentials;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.NonNull;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Request for getting user's credentials from a given credential provider.
+ *
+ * @hide
+ */
+public final class GetCredentialsRequest implements Parcelable {
+    /** Calling package of the app requesting for credentials. */
+    private final @NonNull String mCallingPackage;
+
+    /**
+     * List of credential options. Each {@link GetCredentialOption} object holds parameters to
+     * be used for retrieving specific type of credentials.
+     */
+    private final @NonNull List<GetCredentialOption> mGetCredentialOptions;
+
+    private GetCredentialsRequest(@NonNull String callingPackage,
+            @NonNull List<GetCredentialOption> getCredentialOptions) {
+        this.mCallingPackage = callingPackage;
+        this.mGetCredentialOptions = getCredentialOptions;
+    }
+
+    private GetCredentialsRequest(@NonNull Parcel in) {
+        mCallingPackage = in.readString16NoHelper();
+        mGetCredentialOptions = in.createTypedArrayList(GetCredentialOption.CREATOR);
+    }
+
+    public static final @NonNull Creator<GetCredentialsRequest> CREATOR =
+            new Creator<GetCredentialsRequest>() {
+                @Override
+                public GetCredentialsRequest createFromParcel(Parcel in) {
+                    return new GetCredentialsRequest(in);
+                }
+
+                @Override
+                public GetCredentialsRequest[] newArray(int size) {
+                    return new GetCredentialsRequest[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString16NoHelper(mCallingPackage);
+        dest.writeTypedList(mGetCredentialOptions);
+    }
+
+    /**
+     * Returns the calling package of the app requesting credentials.
+     */
+    public @NonNull String getCallingPackage() {
+        return mCallingPackage;
+    }
+
+    /**
+     * Returns the list of type specific credential options to return credentials for.
+     */
+    public @NonNull List<GetCredentialOption> getGetCredentialOptions() {
+        return mGetCredentialOptions;
+    }
+
+    /**
+     * Builder for {@link GetCredentialsRequest}.
+     */
+    public static final class Builder {
+        private String mCallingPackage;
+        private List<GetCredentialOption> mGetCredentialOptions = new ArrayList<>();
+
+        /**
+         * Creates a new builder.
+         * @param callingPackage The calling package of the app requesting credentials.
+         *
+         * @throws IllegalArgumentException If {@code callingPackag}e is null or empty.
+         */
+        public Builder(@NonNull String callingPackage) {
+            mCallingPackage = Preconditions.checkStringNotEmpty(callingPackage);
+        }
+
+        /**
+         * Sets the list of credential options.
+         *
+         * @throws NullPointerException If {@code getCredentialOptions} itself or any of its
+         * elements is null.
+         * @throws IllegalArgumentException If {@code getCredentialOptions} is empty.
+         */
+        public @NonNull Builder setGetCredentialOptions(
+                @NonNull List<GetCredentialOption> getCredentialOptions) {
+            Preconditions.checkCollectionNotEmpty(mGetCredentialOptions,
+                    "getCredentialOptions");
+            Preconditions.checkCollectionElementsNotNull(mGetCredentialOptions,
+                    "getCredentialOptions");
+            mGetCredentialOptions = getCredentialOptions;
+            return this;
+        }
+
+        /**
+         * Adds a single {@link GetCredentialOption} object to the list of credential options.
+         *
+         * @throws NullPointerException If {@code getCredentialOption} is null.
+         */
+        public @NonNull Builder addGetCredentialOption(
+                @NonNull GetCredentialOption getCredentialOption) {
+            Objects.requireNonNull(getCredentialOption,
+                    "getCredentialOption must not be null");
+            mGetCredentialOptions.add(getCredentialOption);
+            return this;
+        }
+
+        /**
+         * Builds a new {@link GetCredentialsRequest} instance.
+         *
+         * @throws NullPointerException If {@code getCredentialOptions} is null.
+         * @throws IllegalArgumentException If {@code getCredentialOptions} is empty, or if
+         * {@code callingPackage} is null or empty.
+         */
+        public @NonNull GetCredentialsRequest build() {
+            Preconditions.checkStringNotEmpty(mCallingPackage,
+                    "Must set the calling package");
+            Preconditions.checkCollectionNotEmpty(mGetCredentialOptions,
+                    "getCredentialOptions");
+            return new GetCredentialsRequest(mCallingPackage, mGetCredentialOptions);
+        }
+    }
+}
diff --git a/core/java/android/service/credentials/GetCredentialsResponse.aidl b/core/java/android/service/credentials/GetCredentialsResponse.aidl
new file mode 100644
index 0000000..0d8c635
--- /dev/null
+++ b/core/java/android/service/credentials/GetCredentialsResponse.aidl
@@ -0,0 +1,3 @@
+package android.service.credentials;
+
+parcelable GetCredentialsResponse;
\ No newline at end of file
diff --git a/core/java/android/service/credentials/GetCredentialsResponse.java b/core/java/android/service/credentials/GetCredentialsResponse.java
new file mode 100644
index 0000000..293867b
--- /dev/null
+++ b/core/java/android/service/credentials/GetCredentialsResponse.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2022 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.service.credentials;
+
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.NonNull;
+
+import java.util.Objects;
+
+/**
+ * Response from a credential provider, containing credential entries and other associated
+ * data to be shown on the account selector UI.
+ *
+ * @hide
+ */
+public final class GetCredentialsResponse implements Parcelable {
+    /** Content to be used for the UI. */
+    private final @Nullable CredentialsDisplayContent mCredentialsDisplayContent;
+
+    /**
+     * Authentication action that must be launched and completed before showing any content
+     * from the provider.
+     */
+    private final @Nullable Action mAuthenticationAction;
+
+    /**
+     * Creates a {@link GetCredentialsRequest} instance with an authentication action set.
+     * Providers must use this method when no content can be shown before authentication.
+     *
+     * @throws NullPointerException If {@code authenticationAction} is null.
+     */
+    public static @NonNull GetCredentialsResponse createWithAuthentication(
+            @NonNull Action authenticationAction) {
+        Objects.requireNonNull(authenticationAction,
+                "authenticationAction must not be null");
+        return new GetCredentialsResponse(null, authenticationAction);
+    }
+
+    /**
+     * Creates a {@link GetCredentialsRequest} instance with display content to be shown on the UI.
+     * Providers must use this method when there is content to be shown without top level
+     * authentication required.
+     *
+     * @throws NullPointerException If {@code credentialsDisplayContent} is null.
+     */
+    public static @NonNull GetCredentialsResponse createWithDisplayContent(
+            @NonNull CredentialsDisplayContent credentialsDisplayContent) {
+        Objects.requireNonNull(credentialsDisplayContent,
+                "credentialsDisplayContent must not be null");
+        return new GetCredentialsResponse(credentialsDisplayContent, null);
+    }
+
+    private GetCredentialsResponse(@Nullable CredentialsDisplayContent credentialsDisplayContent,
+            @Nullable Action authenticationAction) {
+        mCredentialsDisplayContent = credentialsDisplayContent;
+        mAuthenticationAction = authenticationAction;
+    }
+
+    private GetCredentialsResponse(@NonNull Parcel in) {
+        mCredentialsDisplayContent = in.readParcelable(CredentialsDisplayContent.class
+                .getClassLoader(), CredentialsDisplayContent.class);
+        mAuthenticationAction = in.readParcelable(Action.class.getClassLoader(), Action.class);
+    }
+
+    public static final @NonNull Creator<GetCredentialsResponse> CREATOR =
+            new Creator<GetCredentialsResponse>() {
+                @Override
+                public GetCredentialsResponse createFromParcel(Parcel in) {
+                    return new GetCredentialsResponse(in);
+                }
+
+                @Override
+                public GetCredentialsResponse[] newArray(int size) {
+                    return new GetCredentialsResponse[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeParcelable(mCredentialsDisplayContent, flags);
+        dest.writeParcelable(mAuthenticationAction, flags);
+    }
+
+    /**
+     * Returns whether the response contains a top level authentication action.
+     */
+    public @NonNull boolean isAuthenticationActionSet() {
+        return mAuthenticationAction != null;
+    }
+
+    /**
+     * Returns the authentication action to be invoked before any other content
+     * can be shown to the user.
+     */
+    public @NonNull Action getAuthenticationAction() {
+        return mAuthenticationAction;
+    }
+
+    /**
+     * Returns the credentialDisplayContent that does not require authentication, and
+     * can be shown to the user on the account selector UI.
+     */
+    public @NonNull CredentialsDisplayContent getCredentialsDisplayContent() {
+        return mCredentialsDisplayContent;
+    }
+}
diff --git a/core/java/android/service/credentials/ICredentialProviderService.aidl b/core/java/android/service/credentials/ICredentialProviderService.aidl
new file mode 100644
index 0000000..0b2a9d6
--- /dev/null
+++ b/core/java/android/service/credentials/ICredentialProviderService.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 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.service.credentials;
+
+import android.os.ICancellationSignal;
+import android.service.credentials.GetCredentialsRequest;
+import android.service.credentials.IGetCredentialsCallback;
+
+/**
+ * Interface from the system to a credential provider service.
+ *
+ * @hide
+ */
+oneway interface ICredentialProviderService {
+    void onGetCredentials(in GetCredentialsRequest request, in ICancellationSignal transport, in IGetCredentialsCallback callback);
+}
\ No newline at end of file
diff --git a/core/java/android/service/credentials/IGetCredentialsCallback.aidl b/core/java/android/service/credentials/IGetCredentialsCallback.aidl
new file mode 100644
index 0000000..6e20c55
--- /dev/null
+++ b/core/java/android/service/credentials/IGetCredentialsCallback.aidl
@@ -0,0 +1,13 @@
+package android.service.credentials;
+
+import android.service.credentials.GetCredentialsResponse;
+
+/**
+ * Interface from the system to a credential provider service.
+ *
+ * @hide
+ */
+oneway interface IGetCredentialsCallback {
+    void onSuccess(in GetCredentialsResponse response);
+    void onFailure(int errorCode, in CharSequence message);
+}
\ No newline at end of file