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

Commit 48c0a642 authored by Reema Bajwa's avatar Reema Bajwa
Browse files

Make RemoteEntry flow independent

Based on API feedback from DP1 testers, we need to make RemoteEntry a standalone feature
irrespective of the type of the credential, or a particular option from the GetCredentialRequest.
With this change, remote entry can be created with just some UI metadata (defined on jetpack side).
When user selects this entry, we send all CredentialOptions to this provider and the entire list can be
serviced on a remote device.
Consequently, this change includes modifying android.service.GetCredentialRequest to take in a list of
CredentialOption's as opposed to a single CredentialOption. When a CredentialEntry is selected, that list
will always contain a single option. When a RemoteEntry is selected, that list may conttain >1 options.
A RemoteEntry is  not tied to a type and hence we need a dedicated type for it that only contains Slice (holding the UI metadata). Earlier we were using a CredentialEntry to represent a remote entry in the get flow. However a CredentialEntry requires a type and hence is not applicable. In the create flow, we were using a CreateEntry which does not require a type but in order to keep the flows symmetric, we decide to use RemoteEntry as a separate entry type in both flows.

Test: built locally & CTS tests
Bug: 270186121

Change-Id: Ibfe76d88bde727cb8eed3227ae0dc26ae7fe6834
parent 031692c5
Loading
Loading
Loading
Loading
+14 −6
Original line number Diff line number Diff line
@@ -40508,7 +40508,7 @@ package android.service.credentials {
    ctor public BeginCreateCredentialResponse();
    method public int describeContents();
    method @NonNull public java.util.List<android.service.credentials.CreateEntry> getCreateEntries();
    method @Nullable public android.service.credentials.CreateEntry getRemoteCreateEntry();
    method @Nullable public android.service.credentials.RemoteEntry getRemoteCreateEntry();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.BeginCreateCredentialResponse> CREATOR;
  }
@@ -40518,7 +40518,7 @@ package android.service.credentials {
    method @NonNull public android.service.credentials.BeginCreateCredentialResponse.Builder addCreateEntry(@NonNull android.service.credentials.CreateEntry);
    method @NonNull public android.service.credentials.BeginCreateCredentialResponse build();
    method @NonNull public android.service.credentials.BeginCreateCredentialResponse.Builder setCreateEntries(@NonNull java.util.List<android.service.credentials.CreateEntry>);
    method @NonNull public android.service.credentials.BeginCreateCredentialResponse.Builder setRemoteCreateEntry(@Nullable android.service.credentials.CreateEntry);
    method @NonNull public android.service.credentials.BeginCreateCredentialResponse.Builder setRemoteCreateEntry(@Nullable android.service.credentials.RemoteEntry);
  }
  public class BeginGetCredentialOption implements android.os.Parcelable {
@@ -40553,7 +40553,7 @@ package android.service.credentials {
    method @NonNull public java.util.List<android.service.credentials.Action> getActions();
    method @NonNull public java.util.List<android.service.credentials.Action> getAuthenticationActions();
    method @NonNull public java.util.List<android.service.credentials.CredentialEntry> getCredentialEntries();
    method @Nullable public android.service.credentials.CredentialEntry getRemoteCredentialEntry();
    method @Nullable public android.service.credentials.RemoteEntry getRemoteCredentialEntry();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.BeginGetCredentialResponse> CREATOR;
  }
@@ -40567,7 +40567,7 @@ package android.service.credentials {
    method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setActions(@NonNull java.util.List<android.service.credentials.Action>);
    method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setAuthenticationActions(@NonNull java.util.List<android.service.credentials.Action>);
    method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setCredentialEntries(@NonNull java.util.List<android.service.credentials.CredentialEntry>);
    method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setRemoteCredentialEntry(@Nullable android.service.credentials.CredentialEntry);
    method @NonNull public android.service.credentials.BeginGetCredentialResponse.Builder setRemoteCredentialEntry(@Nullable android.service.credentials.RemoteEntry);
  }
  public final class CallingAppInfo implements android.os.Parcelable {
@@ -40637,14 +40637,22 @@ package android.service.credentials {
  }
  public final class GetCredentialRequest implements android.os.Parcelable {
    ctor public GetCredentialRequest(@NonNull android.service.credentials.CallingAppInfo, @NonNull android.credentials.CredentialOption);
    ctor public GetCredentialRequest(@NonNull android.service.credentials.CallingAppInfo, @NonNull java.util.List<android.credentials.CredentialOption>);
    method public int describeContents();
    method @NonNull public android.service.credentials.CallingAppInfo getCallingAppInfo();
    method @NonNull public android.credentials.CredentialOption getCredentialOption();
    method @NonNull public java.util.List<android.credentials.CredentialOption> getCredentialOptions();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.GetCredentialRequest> CREATOR;
  }
  public class RemoteEntry implements android.os.Parcelable {
    ctor public RemoteEntry(@NonNull android.app.slice.Slice);
    method public int describeContents();
    method @NonNull public android.app.slice.Slice getSlice();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.RemoteEntry> CREATOR;
  }
}
package android.service.dreams {
+0 −1
Original line number Diff line number Diff line
@@ -149,7 +149,6 @@ public final class GetCredentialRequest implements Parcelable {
        mCredentialOptions = credentialOptions;
        AnnotationValidations.validate(NonNull.class, null, mCredentialOptions);


        Bundle data = in.readBundle();
        mData = data;
        AnnotationValidations.validate(NonNull.class, null, mData);
+6 −6
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ import java.util.Objects;
 */
public final class BeginCreateCredentialResponse implements Parcelable {
    private final @NonNull List<CreateEntry> mCreateEntries;
    private final @Nullable CreateEntry mRemoteCreateEntry;
    private final @Nullable RemoteEntry mRemoteCreateEntry;

    /**
     * Creates an empty response instance, to be used when there are no {@link CreateEntry}
@@ -46,7 +46,7 @@ public final class BeginCreateCredentialResponse implements Parcelable {
        List<CreateEntry> createEntries = new ArrayList<>();
        in.readTypedList(createEntries, CreateEntry.CREATOR);
        mCreateEntries = createEntries;
        mRemoteCreateEntry = in.readTypedObject(CreateEntry.CREATOR);
        mRemoteCreateEntry = in.readTypedObject(RemoteEntry.CREATOR);
    }

    @Override
@@ -75,7 +75,7 @@ public final class BeginCreateCredentialResponse implements Parcelable {

    /* package-private */ BeginCreateCredentialResponse(
            @NonNull List<CreateEntry> createEntries,
            @Nullable CreateEntry remoteCreateEntry) {
            @Nullable RemoteEntry remoteCreateEntry) {
        this.mCreateEntries = createEntries;
        com.android.internal.util.AnnotationValidations.validate(
                NonNull.class, null, mCreateEntries);
@@ -88,7 +88,7 @@ public final class BeginCreateCredentialResponse implements Parcelable {
    }

    /** Returns the remote create entry to be displayed on the UI. */
    public @Nullable CreateEntry getRemoteCreateEntry() {
    public @Nullable RemoteEntry getRemoteCreateEntry() {
        return mRemoteCreateEntry;
    }

@@ -98,7 +98,7 @@ public final class BeginCreateCredentialResponse implements Parcelable {
    @SuppressWarnings("WeakerAccess") /* synthetic access */
    public static final class Builder {
        private @NonNull List<CreateEntry> mCreateEntries = new ArrayList<>();
        private @Nullable CreateEntry mRemoteCreateEntry;
        private @Nullable RemoteEntry mRemoteCreateEntry;

        /**
         * Sets the list of create entries to be shown on the UI.
@@ -138,7 +138,7 @@ public final class BeginCreateCredentialResponse implements Parcelable {
         * {@link CredentialProviderService#EXTRA_CREATE_CREDENTIAL_RESPONSE} key should be populated
         * with a {@link android.credentials.CreateCredentialResponse} object.
         */
        public @NonNull Builder setRemoteCreateEntry(@Nullable CreateEntry remoteCreateEntry) {
        public @NonNull Builder setRemoteCreateEntry(@Nullable RemoteEntry remoteCreateEntry) {
            mRemoteCreateEntry = remoteCreateEntry;
            return this;
        }
+6 −6
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ public final class BeginGetCredentialResponse implements Parcelable {
    private final @NonNull List<Action> mActions;

    /** Remote credential entry to get the response from a different device. */
    private final @Nullable CredentialEntry mRemoteCredentialEntry;
    private final @Nullable RemoteEntry mRemoteCredentialEntry;

    /**
     * Creates an empty response instance, to be used when there are no {@link CredentialEntry},
@@ -57,7 +57,7 @@ public final class BeginGetCredentialResponse implements Parcelable {

    private BeginGetCredentialResponse(@NonNull List<CredentialEntry> credentialEntries,
            @NonNull List<Action> authenticationEntries, @NonNull List<Action> actions,
            @Nullable CredentialEntry remoteCredentialEntry) {
            @Nullable RemoteEntry remoteCredentialEntry) {
        mCredentialEntries = new ArrayList<>(credentialEntries);
        mAuthenticationEntries = new ArrayList<>(authenticationEntries);
        mActions = new ArrayList<>(actions);
@@ -74,7 +74,7 @@ public final class BeginGetCredentialResponse implements Parcelable {
        List<Action> actions = new ArrayList<>();
        in.readTypedList(actions, Action.CREATOR);
        mActions = actions;
        mRemoteCredentialEntry = in.readTypedObject(CredentialEntry.CREATOR);
        mRemoteCredentialEntry = in.readTypedObject(RemoteEntry.CREATOR);
    }

    public static final @NonNull Creator<BeginGetCredentialResponse> CREATOR =
@@ -127,7 +127,7 @@ public final class BeginGetCredentialResponse implements Parcelable {
    /**
     * Returns the remote credential entry to be displayed on the UI.
     */
    public @Nullable CredentialEntry getRemoteCredentialEntry() {
    public @Nullable RemoteEntry getRemoteCredentialEntry() {
        return mRemoteCredentialEntry;
    }

@@ -139,7 +139,7 @@ public final class BeginGetCredentialResponse implements Parcelable {

        private List<Action> mAuthenticationEntries = new ArrayList<>();
        private List<Action> mActions = new ArrayList<>();
        private CredentialEntry mRemoteCredentialEntry;
        private RemoteEntry mRemoteCredentialEntry;

        /**
         * Sets a remote credential entry to be shown on the UI. Provider must set this if they
@@ -155,7 +155,7 @@ public final class BeginGetCredentialResponse implements Parcelable {
         * {@link CredentialProviderService#EXTRA_GET_CREDENTIAL_RESPONSE} key should be populated
         * with a {@link android.credentials.Credential} object.
         */
        public @NonNull Builder setRemoteCredentialEntry(@Nullable CredentialEntry
        public @NonNull Builder setRemoteCredentialEntry(@Nullable RemoteEntry
                remoteCredentialEntry) {
            mRemoteCredentialEntry = remoteCredentialEntry;
            return this;
+35 −14
Original line number Diff line number Diff line
@@ -23,14 +23,16 @@ import android.os.Parcelable;

import com.android.internal.util.AnnotationValidations;

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

/**
 * Request for getting user's credential from a given credential provider.
 *
 * <p>Provider will receive this request once the user selects a given {@link CredentialEntry}
 * on the selector, that was sourced from provider's result to
 * {@link CredentialProviderService#onBeginGetCredential}.
 * <p>A credential provider will receive this request once the user selects a
 * given {@link CredentialEntry}, or {@link RemoteEntry} on the selector, that was sourced
 * from provider's initial response to {@link CredentialProviderService#onBeginGetCredential}.
 */
public final class GetCredentialRequest implements Parcelable {
    /** Calling package of the app requesting for credentials. */
@@ -38,24 +40,27 @@ public final class GetCredentialRequest implements Parcelable {
    private final CallingAppInfo mCallingAppInfo;

    /**
     * Holds parameters to be used for retrieving a specific type of credential.
     * Holds a list of options (parameters) to be used for retrieving a specific type of credential.
     */
    @NonNull
    private final CredentialOption mCredentialOption;
    private final List<CredentialOption> mCredentialOptions;

    public GetCredentialRequest(@NonNull CallingAppInfo callingAppInfo,
            @NonNull CredentialOption credentialOption) {
            @NonNull List<CredentialOption> credentialOptions) {
        this.mCallingAppInfo = Objects.requireNonNull(callingAppInfo,
                "callingAppInfo must not be null");
        this.mCredentialOption = Objects.requireNonNull(credentialOption,
                "credentialOption must not be null");
        this.mCredentialOptions = Objects.requireNonNull(credentialOptions,
                "credentialOptions must not be null");
    }

    private GetCredentialRequest(@NonNull Parcel in) {
        mCallingAppInfo = in.readTypedObject(CallingAppInfo.CREATOR);
        AnnotationValidations.validate(NonNull.class, null, mCallingAppInfo);
        mCredentialOption = in.readTypedObject(CredentialOption.CREATOR);
        AnnotationValidations.validate(NonNull.class, null, mCredentialOption);

        List<CredentialOption> credentialOptions = new ArrayList<>();
        in.readTypedList(credentialOptions, CredentialOption.CREATOR);
        mCredentialOptions = credentialOptions;
        AnnotationValidations.validate(NonNull.class, null, mCredentialOptions);
    }

    @NonNull public static final  Creator<GetCredentialRequest> CREATOR =
@@ -79,7 +84,7 @@ public final class GetCredentialRequest implements Parcelable {
    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeTypedObject(mCallingAppInfo, flags);
        dest.writeTypedObject(mCredentialOption, flags);
        dest.writeTypedList(mCredentialOptions, flags);
    }

    /**
@@ -91,10 +96,26 @@ public final class GetCredentialRequest implements Parcelable {
    }

    /**
     * Returns the parameters needed to return a given type of credential.
     * Returns a list of options containing parameters needed to return a given type of credential.
     * This is part of the request that the credential provider receives after the user has
     * selected an entry on a selector UI.
     *
     * When the user selects a {@link CredentialEntry} and the credential provider receives a
     * {@link GetCredentialRequest}, this list is expected to contain a single
     * {@link CredentialOption} only. A {@link CredentialEntry} is always created for a given
     * {@link BeginGetCredentialOption}, and hence when the user selects it, the provider
     * receives a corresponding {@link CredentialOption} that contains all the required parameters
     * to actually retrieve the credential.
     *
     * When the user selects a {@link RemoteEntry} and the credential provider receives a
     * {@link GetCredentialRequest}, this list may contain greater than a single
     * {@link CredentialOption}, representing the number of options specified by the developer
     * in the original {@link android.credentials.GetCredentialRequest}. This is because a
     * {@link RemoteEntry} indicates that the entire request will be processed on a different
     * device and is not tied to a particular option.
     */
    @NonNull
    public CredentialOption getCredentialOption() {
        return mCredentialOption;
    public List<CredentialOption> getCredentialOptions() {
        return mCredentialOptions;
    }
}
Loading