Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5cc58ce7 authored by Reema Bajwa's avatar Reema Bajwa Committed by Android (Google) Code Review
Browse files

Merge "Skeleton for getCandidateCredentials API" into main

parents d66fa135 8ccd1ee3
Loading
Loading
Loading
Loading
+65 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.credentials;
import static java.util.Objects.requireNonNull;

import android.annotation.CallbackExecutor;
import android.annotation.Hide;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -116,6 +117,32 @@ public final class CredentialManager {
        mService = service;
    }

    /**
     * Returns a list of candidate credentials returned from credential manager providers
     *
     * @param request the request specifying type(s) of credentials to get from the
     *                credential providers
     * @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
     */
    @Hide
    public void getCandidateCredentials(
            @NonNull GetCredentialRequest request,
            @Nullable CancellationSignal cancellationSignal,
            @CallbackExecutor @NonNull Executor executor,
            @NonNull OutcomeReceiver<GetCredentialResponse, GetCredentialException> callback) {
        requireNonNull(request, "request must not be null");
        requireNonNull(executor, "executor must not be null");
        requireNonNull(callback, "callback must not be null");

        if (cancellationSignal != null && cancellationSignal.isCanceled()) {
            Log.w(TAG, "getCredential already canceled");
        }
    }

    /**
     * Launches the necessary flows to retrieve an app credential from the user.
     *
@@ -641,6 +668,44 @@ public final class CredentialManager {
        }
    }

    private static class GetCandidateCredentialsTransport
            extends IGetCandidateCredentialsCallback.Stub {

        private final Executor mExecutor;
        private final OutcomeReceiver<GetCandidateCredentialsResponse,
                GetCandidateCredentialsException> mCallback;

        private GetCandidateCredentialsTransport(
                Executor executor,
                OutcomeReceiver<GetCandidateCredentialsResponse,
                        GetCandidateCredentialsException> callback) {
            mExecutor = executor;
            mCallback = callback;
        }

        @Override
        public void onResponse(GetCandidateCredentialsResponse response) {
            final long identity = Binder.clearCallingIdentity();
            try {
                mExecutor.execute(() -> mCallback.onResult(response));
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }

        @Override
        public void onError(String errorType, String message) {
            final long identity = Binder.clearCallingIdentity();
            try {
                mExecutor.execute(
                        () -> mCallback.onError(new GetCandidateCredentialsException(
                                errorType, message)));
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    private static class GetCredentialTransport extends IGetCredentialCallback.Stub {
        // TODO: listen for cancellation to release callback.

+95 −0
Original line number Diff line number Diff line
/*
 * Copyright 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.credentials;

import android.annotation.Hide;
import android.annotation.NonNull;
import android.annotation.Nullable;

import com.android.internal.util.Preconditions;

/**
 * Represents an error encountered during the
 * {@link CredentialManager#getCandidateCredentials} operation.
 *
 * @hide
 */
@Hide
public class GetCandidateCredentialsException extends Exception {
    /**
     * The error type value for when the given operation failed due to an unknown reason.
     */
    @NonNull
    public static final String TYPE_UNKNOWN =
            "android.credentials.GetCandidateCredentialsException.TYPE_UNKNOWN";

    /**
     * The error type value for when no credential is found available for the given {@link
     * CredentialManager#getCandidateCredentials} request.
     */
    @NonNull
    public static final String TYPE_NO_CREDENTIAL =
            "android.credentials.GetCandidateCredentialsException.TYPE_NO_CREDENTIAL";

    @NonNull
    private final String mType;

    /** Returns the specific exception type. */
    @NonNull
    public String getType() {
        return mType;
    }

    /**
     * Constructs a {@link GetCandidateCredentialsException}.
     *
     * @throws IllegalArgumentException If type is empty.
     */
    public GetCandidateCredentialsException(@NonNull String type, @Nullable String message) {
        this(type, message, null);
    }

    /**
     * Constructs a {@link GetCandidateCredentialsException}.
     *
     * @throws IllegalArgumentException If type is empty.
     */
    public GetCandidateCredentialsException(
            @NonNull String type, @Nullable String message, @Nullable Throwable cause) {
        super(message, cause);
        this.mType = Preconditions.checkStringNotEmpty(type,
                "type must not be empty");
    }

    /**
     * Constructs a {@link GetCandidateCredentialsException}.
     *
     * @throws IllegalArgumentException If type is empty.
     */
    public GetCandidateCredentialsException(@NonNull String type, @Nullable Throwable cause) {
        this(type, null, cause);
    }

    /**
     * Constructs a {@link GetCandidateCredentialsException}.
     *
     * @throws IllegalArgumentException If type is empty.
     */
    public GetCandidateCredentialsException(@NonNull String type) {
        this(type, null, null);
    }
}
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright 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.credentials;

parcelable GetCandidateCredentialsRequest;
 No newline at end of file
+147 −0
Original line number Diff line number Diff line
/*
 * Copyright 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.credentials;

import static java.util.Objects.requireNonNull;

import android.annotation.Hide;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;

import com.android.internal.util.AnnotationValidations;
import com.android.internal.util.Preconditions;

import java.util.ArrayList;
import java.util.List;

/**
 * A request to retrieve a list of candidate credentials against the list of credential
 * options
 *
 * @hide
 */
@Hide
public final class GetCandidateCredentialsRequest implements Parcelable {

    /**
     * The list of credential requests.
     */
    @NonNull
    private final List<CredentialOption> mCredentialOptions;

    /**
     * The top request level data.
     */
    @NonNull
    private final Bundle mData;

    /**
     * The origin of the calling app. Callers of this special API (e.g. browsers)
     * can set this origin for an app different from their own, to be able to get credentials
     * on behalf of that app.
     */
    @Nullable
    private String mOrigin;

    /**
     * Returns the list of credential options to be requested.
     */
    @NonNull
    public List<CredentialOption> getCredentialOptions() {
        return mCredentialOptions;
    }

    /**
     * Returns the top request level data.
     */
    @NonNull
    public Bundle getData() {
        return mData;
    }

    /**
     * Returns the origin of the calling app if set otherwise returns null.
     */
    @Nullable
    public String getOrigin() {
        return mOrigin;
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeTypedList(mCredentialOptions, flags);
        dest.writeBundle(mData);
        dest.writeString8(mOrigin);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public String toString() {
        return "GetCandidateCredentialsRequest {credentialOption=" + mCredentialOptions
                + ", data=" + mData
                + ", origin=" + mOrigin
                + "}";
    }

    private GetCandidateCredentialsRequest(@NonNull List<CredentialOption> credentialOptions,
            @NonNull Bundle data, String origin) {
        Preconditions.checkCollectionNotEmpty(
                credentialOptions,
                /*valueName=*/ "credentialOptions");
        Preconditions.checkCollectionElementsNotNull(
                credentialOptions,
                /*valueName=*/ "credentialOptions");
        mCredentialOptions = credentialOptions;
        mData = requireNonNull(data,
                "data must not be null");
        mOrigin = origin;
    }

    private GetCandidateCredentialsRequest(@NonNull Parcel in) {
        List<CredentialOption> credentialOptions = new ArrayList<CredentialOption>();
        in.readTypedList(credentialOptions, CredentialOption.CREATOR);
        mCredentialOptions = credentialOptions;
        AnnotationValidations.validate(NonNull.class, null, mCredentialOptions);

        Bundle data = in.readBundle();
        mData = data;
        AnnotationValidations.validate(NonNull.class, null, mData);

        mOrigin = in.readString8();
    }

    @NonNull
    public static final Creator<GetCandidateCredentialsRequest> CREATOR =
            new Creator<>() {
                @Override
                public GetCandidateCredentialsRequest[] newArray(int size) {
                    return new GetCandidateCredentialsRequest[size];
                }

                @Override
                public GetCandidateCredentialsRequest createFromParcel(@NonNull Parcel in) {
                    return new GetCandidateCredentialsRequest(in);
                }
            };
}
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright 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.credentials;

parcelable GetCandidateCredentialsResponse;
 No newline at end of file
Loading