Merge "Make RemoteEntry flow independent" into udc-dev am: 572d61cf3b

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21533944

Change-Id: I54c5d327ef037483668702e939c76a707dff7761
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Reema Bajwa
2023-03-03 19:28:09 +00:00
committed by Automerger Merge Worker
9 changed files with 177 additions and 45 deletions

View File

@@ -40539,7 +40539,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;
}
@@ -40549,7 +40549,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 {
@@ -40584,7 +40584,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;
}
@@ -40598,7 +40598,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 {
@@ -40668,14 +40668,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 {

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -0,0 +1,97 @@
/*
* 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.SuppressLint;
import android.app.PendingIntent;
import android.app.slice.Slice;
import android.os.Parcel;
import android.os.Parcelable;
/**
* An entry to be shown on the UI. This entry represents remote execution of a get/create flow
* whereby credentials are retrieved from, or stored to a remote device.
*
* <p>If user selects this entry, the corresponding {@link PendingIntent} set on the
* {@code slice} as a {@link androidx.slice.core.SliceAction} will get invoked.
* Once the resulting activity fulfills the required user engagement,
* the {@link android.app.Activity} result should be set to {@link android.app.Activity#RESULT_OK},
* and the result of the operation must be set as the activity result.
*
* For a get flow, invoked through {@link CredentialProviderService#onBeginGetCredential},
* providers must set a {@link android.credentials.GetCredentialResponse} on the activity result,
* against the key {@link CredentialProviderService#EXTRA_GET_CREDENTIAL_RESPONSE}.
*
* For a creates flow, invoked through {@link CredentialProviderService#onBeginCreateCredential},
* providers must set a {@link android.credentials.CreateCredentialResponse} on the activity
* result against the ket {@link CredentialProviderService#EXTRA_CREATE_CREDENTIAL_RESPONSE}.
*
* <p>Any class that extends this class must only add extra field values to the {@code slice}
* object passed into the constructor. Any other field will not be parceled through. If the
* derived class has custom parceling implementation, this class will not be able to unpack
* the parcel without having access to that implementation.
*/
@SuppressLint("ParcelNotFinal")
public class RemoteEntry implements Parcelable {
private final @NonNull Slice mSlice;
private RemoteEntry(@NonNull Parcel in) {
mSlice = in.readTypedObject(Slice.CREATOR);
}
@NonNull
public static final Creator<RemoteEntry> CREATOR = new Creator<RemoteEntry>() {
@Override
public RemoteEntry createFromParcel(@NonNull Parcel in) {
return new RemoteEntry(in);
}
@Override
public RemoteEntry[] newArray(int size) {
return new RemoteEntry[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeTypedObject(mSlice, flags);
}
/**
* Constructs a RemoteEntry to be displayed on the UI.
*
* @param slice the display content to be displayed on the UI, along with this entry
*/
public RemoteEntry(
@NonNull Slice slice) {
this.mSlice = slice;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mSlice);
}
/** Returns the content to be displayed with this remote entry on the UI. */
@NonNull
public Slice getSlice() {
return mSlice;
}
}

View File

@@ -35,6 +35,7 @@ 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;
import android.util.Pair;
import android.util.Slog;
@@ -301,14 +302,14 @@ public final class ProviderCreateSession extends ProviderSession<
@NonNull
private final Map<String, Pair<CreateEntry, Entry>> mUiCreateEntries = new HashMap<>();
@Nullable private Pair<String, Pair<CreateEntry, Entry>> mUiRemoteEntry = null;
@Nullable private Pair<String, Pair<RemoteEntry, Entry>> mUiRemoteEntry = null;
ProviderResponseDataHandler(String hybridService) {
mExpectedRemoteEntryProviderService = ComponentName.unflattenFromString(hybridService);
}
public void addResponseContent(List<CreateEntry> createEntries,
CreateEntry remoteEntry) {
RemoteEntry remoteEntry) {
createEntries.forEach(this::addCreateEntry);
setRemoteEntry(remoteEntry);
}
@@ -319,7 +320,7 @@ public final class ProviderCreateSession extends ProviderSession<
mUiCreateEntries.put(id, new Pair<>(createEntry, entry));
}
public void setRemoteEntry(@Nullable CreateEntry remoteEntry) {
public void setRemoteEntry(@Nullable RemoteEntry remoteEntry) {
if (remoteEntry == null) {
mUiRemoteEntry = null;
return;
@@ -363,7 +364,7 @@ public final class ProviderCreateSession extends ProviderSession<
return mUiCreateEntries.isEmpty() && mUiRemoteEntry == null;
}
@Nullable
public CreateEntry getRemoteEntry(String entryKey) {
public RemoteEntry getRemoteEntry(String entryKey) {
return mUiRemoteEntry == null || mUiRemoteEntry
.first == null || !mUiRemoteEntry.first.equals(entryKey)
|| mUiRemoteEntry.second == null

View File

@@ -38,6 +38,7 @@ 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;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
@@ -299,7 +300,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
}
return new Intent().putExtra(CredentialProviderService.EXTRA_GET_CREDENTIAL_REQUEST,
new GetCredentialRequest(
mCallingAppInfo, mBeginGetOptionToCredentialOptionMap.get(id)));
mCallingAppInfo, List.of(mBeginGetOptionToCredentialOptionMap.get(id))));
}
private Intent setUpFillInIntentWithQueryRequest() {
@@ -472,7 +473,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
private final Map<String, Pair<Action, AuthenticationEntry>> mUiAuthenticationEntries =
new HashMap<>();
@Nullable private Pair<String, Pair<CredentialEntry, Entry>> mUiRemoteEntry = null;
@Nullable private Pair<String, Pair<RemoteEntry, Entry>> mUiRemoteEntry = null;
ProviderResponseDataHandler(ComponentName expectedRemoteEntryProviderService) {
mExpectedRemoteEntryProviderService = expectedRemoteEntryProviderService;
@@ -480,7 +481,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
public void addResponseContent(List<CredentialEntry> credentialEntries,
List<Action> actions, List<Action> authenticationActions,
CredentialEntry remoteEntry) {
RemoteEntry remoteEntry) {
credentialEntries.forEach(this::addCredentialEntry);
actions.forEach(this::addAction);
authenticationActions.forEach(
@@ -522,7 +523,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
mUiAuthenticationEntries.remove(id);
}
public void setRemoteEntry(@Nullable CredentialEntry remoteEntry) {
public void setRemoteEntry(@Nullable RemoteEntry remoteEntry) {
if (remoteEntry == null) {
return;
}
@@ -533,8 +534,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
}
String id = generateUniqueId();
Entry entry = new Entry(REMOTE_ENTRY_KEY,
id, remoteEntry.getSlice(), setUpFillInIntent(
remoteEntry.getBeginGetCredentialOption().getId()));
id, remoteEntry.getSlice(), setUpFillInIntentForRemoteEntry());
mUiRemoteEntry = new Pair<>(generateUniqueId(), new Pair<>(remoteEntry, entry));
}
@@ -604,7 +604,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
}
@Nullable
public CredentialEntry getRemoteEntry(String entryKey) {
public RemoteEntry getRemoteEntry(String entryKey) {
return mUiRemoteEntry.first.equals(entryKey) && mUiRemoteEntry.second != null
? mUiRemoteEntry.second.first : null;
}
@@ -662,4 +662,10 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
from.getFrameworkExtrasIntent());
}
}
private Intent setUpFillInIntentForRemoteEntry() {
return new Intent().putExtra(CredentialProviderService.EXTRA_GET_CREDENTIAL_REQUEST,
new GetCredentialRequest(
mCallingAppInfo, mCompleteRequest.getCredentialOptions()));
}
}

View File

@@ -121,7 +121,7 @@ public class ProviderRegistryGetSession extends ProviderSession<CredentialOption
CredentialProviderService
.EXTRA_GET_CREDENTIAL_REQUEST,
new android.service.credentials.GetCredentialRequest(
mCallingAppInfo, mProviderRequest));
mCallingAppInfo, List.of(mProviderRequest)));
return intent;
}