Merge "Optionally remove calling app info from query phase"

This commit is contained in:
TreeHugger Robot
2023-02-07 20:18:28 +00:00
committed by Android (Google) Code Review
7 changed files with 192 additions and 46 deletions

View File

@@ -13470,7 +13470,9 @@ package android.credentials {
}
public final class CreateCredentialRequest implements android.os.Parcelable {
ctor public CreateCredentialRequest(@NonNull String, @NonNull android.os.Bundle, @NonNull android.os.Bundle, boolean, boolean);
ctor public CreateCredentialRequest(@NonNull String, @NonNull android.os.Bundle, @NonNull android.os.Bundle, boolean);
method public boolean alwaysSendAppInfoToProvider();
method public int describeContents();
method @NonNull public android.os.Bundle getCandidateQueryData();
method @NonNull public android.os.Bundle getCredentialData();
@@ -13542,6 +13544,7 @@ package android.credentials {
}
public final class GetCredentialRequest implements android.os.Parcelable {
method public boolean alwaysSendAppInfoToProvider();
method public int describeContents();
method @NonNull public java.util.List<android.credentials.CredentialOption> getCredentialOptions();
method @NonNull public android.os.Bundle getData();
@@ -13553,6 +13556,7 @@ package android.credentials {
ctor public GetCredentialRequest.Builder(@NonNull android.os.Bundle);
method @NonNull public android.credentials.GetCredentialRequest.Builder addCredentialOption(@NonNull android.credentials.CredentialOption);
method @NonNull public android.credentials.GetCredentialRequest build();
method @NonNull public android.credentials.GetCredentialRequest.Builder setAlwaysSendAppInfoToProvider(boolean);
method @NonNull public android.credentials.GetCredentialRequest.Builder setCredentialOptions(@NonNull java.util.List<android.credentials.CredentialOption>);
}
@@ -40225,9 +40229,10 @@ package android.service.credentials {
}
public class BeginCreateCredentialRequest implements android.os.Parcelable {
ctor public BeginCreateCredentialRequest(@NonNull android.service.credentials.CallingAppInfo, @NonNull String, @NonNull android.os.Bundle);
ctor public BeginCreateCredentialRequest(@NonNull String, @NonNull android.os.Bundle, @Nullable android.service.credentials.CallingAppInfo);
ctor public BeginCreateCredentialRequest(@NonNull String, @NonNull android.os.Bundle);
method public int describeContents();
method @NonNull public android.service.credentials.CallingAppInfo getCallingAppInfo();
method @Nullable public android.service.credentials.CallingAppInfo getCallingAppInfo();
method @NonNull public android.os.Bundle getData();
method @NonNull public String getType();
method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -40262,16 +40267,17 @@ package android.service.credentials {
public final class BeginGetCredentialRequest implements android.os.Parcelable {
method public int describeContents();
method @NonNull public java.util.List<android.service.credentials.BeginGetCredentialOption> getBeginGetCredentialOptions();
method @NonNull public android.service.credentials.CallingAppInfo getCallingAppInfo();
method @Nullable public android.service.credentials.CallingAppInfo getCallingAppInfo();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.BeginGetCredentialRequest> CREATOR;
}
public static final class BeginGetCredentialRequest.Builder {
ctor public BeginGetCredentialRequest.Builder(@NonNull android.service.credentials.CallingAppInfo);
ctor public BeginGetCredentialRequest.Builder();
method @NonNull public android.service.credentials.BeginGetCredentialRequest.Builder addBeginGetCredentialOption(@NonNull android.service.credentials.BeginGetCredentialOption);
method @NonNull public android.service.credentials.BeginGetCredentialRequest build();
method @NonNull public android.service.credentials.BeginGetCredentialRequest.Builder setBeginGetCredentialOptions(@NonNull java.util.List<android.service.credentials.BeginGetCredentialOption>);
method @NonNull public android.service.credentials.BeginGetCredentialRequest.Builder setCallingAppInfo(@Nullable android.service.credentials.CallingAppInfo);
}
public final class BeginGetCredentialResponse implements android.os.Parcelable {

View File

@@ -32,6 +32,18 @@ import com.android.internal.util.Preconditions;
*/
public final class CreateCredentialRequest implements Parcelable {
/**
* True/false value to determine if the calling app info should be
* sent to the provider at every stage.
*
* Developers must set this to false if they wish to remove the
* {@link android.service.credentials.CallingAppInfo} from the query phase request
* that providers receive. Note, that providers will still receive the app info in
* the final phase after the user has selected the entry.
*/
private final boolean mAlwaysSendAppInfoToProvider;
/**
* The requested credential type.
*/
@@ -103,12 +115,21 @@ public final class CreateCredentialRequest implements Parcelable {
return mIsSystemProviderRequired;
}
/**
* Return true/false value to determine if the calling app info should always be sent
* to providers (if true), or removed from the query phase (if false).
*/
public boolean alwaysSendAppInfoToProvider() {
return mAlwaysSendAppInfoToProvider;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString8(mType);
dest.writeBundle(mCredentialData);
dest.writeBundle(mCandidateQueryData);
dest.writeBoolean(mIsSystemProviderRequired);
dest.writeBoolean(mAlwaysSendAppInfoToProvider);
}
@Override
@@ -123,9 +144,44 @@ public final class CreateCredentialRequest implements Parcelable {
+ ", credentialData=" + mCredentialData
+ ", candidateQueryData=" + mCandidateQueryData
+ ", isSystemProviderRequired=" + mIsSystemProviderRequired
+ ", alwaysSendAppInfoToProvider="
+ mAlwaysSendAppInfoToProvider
+ "}";
}
/**
* Constructs a {@link CreateCredentialRequest}.
*
* @param type the requested credential type
* @param credentialData the full credential creation request data
* @param candidateQueryData the partial request data that will be sent to the provider
* during the initial creation candidate query stage
* @param isSystemProviderRequired whether the request must only be fulfilled by a system
* provider
* @param alwaysSendAppInfoToProvider whether the
* {@link android.service.credentials.CallingAppInfo} should be propagated to the provider
* at every stage of the request. If set to false,
* the calling app info will be removed from
* the query phase, and will only be sent along
* with the final request, after the user has selected
* an entry on the UI.
*
* @throws IllegalArgumentException If type is empty.
*/
public CreateCredentialRequest(
@NonNull String type,
@NonNull Bundle credentialData,
@NonNull Bundle candidateQueryData,
boolean isSystemProviderRequired,
boolean alwaysSendAppInfoToProvider) {
mType = Preconditions.checkStringNotEmpty(type, "type must not be empty");
mCredentialData = requireNonNull(credentialData, "credentialData must not be null");
mCandidateQueryData = requireNonNull(candidateQueryData,
"candidateQueryData must not be null");
mIsSystemProviderRequired = isSystemProviderRequired;
mAlwaysSendAppInfoToProvider = alwaysSendAppInfoToProvider;
}
/**
* Constructs a {@link CreateCredentialRequest}.
*
@@ -143,11 +199,8 @@ public final class CreateCredentialRequest implements Parcelable {
@NonNull Bundle credentialData,
@NonNull Bundle candidateQueryData,
boolean isSystemProviderRequired) {
mType = Preconditions.checkStringNotEmpty(type, "type must not be empty");
mCredentialData = requireNonNull(credentialData, "credentialData must not be null");
mCandidateQueryData = requireNonNull(candidateQueryData,
"candidateQueryData must not be null");
mIsSystemProviderRequired = isSystemProviderRequired;
this(type, credentialData, candidateQueryData, isSystemProviderRequired,
/*mAlwaysSendAppInfoToProvider=*/true);
}
private CreateCredentialRequest(@NonNull Parcel in) {
@@ -155,6 +208,7 @@ public final class CreateCredentialRequest implements Parcelable {
Bundle credentialData = in.readBundle();
Bundle candidateQueryData = in.readBundle();
boolean isSystemProviderRequired = in.readBoolean();
boolean alwaysSendAppInfoToProvider = in.readBoolean();
mType = type;
AnnotationValidations.validate(NonNull.class, null, mType);
@@ -163,6 +217,7 @@ public final class CreateCredentialRequest implements Parcelable {
mCandidateQueryData = candidateQueryData;
AnnotationValidations.validate(NonNull.class, null, mCandidateQueryData);
mIsSystemProviderRequired = isSystemProviderRequired;
mAlwaysSendAppInfoToProvider = alwaysSendAppInfoToProvider;
}
public static final @NonNull Parcelable.Creator<CreateCredentialRequest> CREATOR =

View File

@@ -19,6 +19,7 @@ package android.credentials;
import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -47,6 +48,17 @@ public final class GetCredentialRequest implements Parcelable {
@NonNull
private final Bundle mData;
/**
* True/False value to determine if the calling app info should be
* removed from the request that is sent to the providers.
* Developers must set this to false if they wish to remove the
* {@link android.service.credentials.CallingAppInfo} from the query phases requests that
* providers receive.
* If not set, the default value will be true and the calling app info will be
* propagated to the providers.
*/
private final boolean mAlwaysSendAppInfoToProvider;
/**
* Returns the list of credential options to be requested.
*/
@@ -63,10 +75,21 @@ public final class GetCredentialRequest implements Parcelable {
return mData;
}
/**
* Returns a value to determine if the calling app info should be always
* sent to the provider in every phase (if true), or should be removed
* from the query phase, and only sent as part of the request in the final phase,
* after the user has made a selection on the UI (if false).
*/
public boolean alwaysSendAppInfoToProvider() {
return mAlwaysSendAppInfoToProvider;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeTypedList(mCredentialOptions, flags);
dest.writeBundle(mData);
dest.writeBoolean(mAlwaysSendAppInfoToProvider);
}
@Override
@@ -78,11 +101,13 @@ public final class GetCredentialRequest implements Parcelable {
public String toString() {
return "GetCredentialRequest {credentialOption=" + mCredentialOptions
+ ", data=" + mData
+ ", alwaysSendAppInfoToProvider="
+ mAlwaysSendAppInfoToProvider
+ "}";
}
private GetCredentialRequest(@NonNull List<CredentialOption> credentialOptions,
@NonNull Bundle data) {
@NonNull Bundle data, @NonNull boolean alwaysSendAppInfoToProvider) {
Preconditions.checkCollectionNotEmpty(
credentialOptions,
/*valueName=*/ "credentialOptions");
@@ -92,6 +117,7 @@ public final class GetCredentialRequest implements Parcelable {
mCredentialOptions = credentialOptions;
mData = requireNonNull(data,
"data must not be null");
mAlwaysSendAppInfoToProvider = alwaysSendAppInfoToProvider;
}
private GetCredentialRequest(@NonNull Parcel in) {
@@ -104,6 +130,8 @@ public final class GetCredentialRequest implements Parcelable {
Bundle data = in.readBundle();
mData = data;
AnnotationValidations.validate(NonNull.class, null, mData);
mAlwaysSendAppInfoToProvider = in.readBoolean();
}
@NonNull public static final Parcelable.Creator<GetCredentialRequest> CREATOR =
@@ -128,6 +156,9 @@ public final class GetCredentialRequest implements Parcelable {
@NonNull
private final Bundle mData;
@NonNull
private boolean mAlwaysSendAppInfoToProvider = true;
/**
* @param data the top request level data
*/
@@ -145,6 +176,25 @@ public final class GetCredentialRequest implements Parcelable {
return this;
}
/**
* Sets a true/false value to determine if the calling app info should be
* removed from the request that is sent to the providers.
*
* Developers must set this to false if they wish to remove the
* {@link android.service.credentials.CallingAppInfo} from the query phases requests that
* providers receive. Note that the calling app info will still be sent in the
* final phase after the user has made a selection on the UI.
*
* If not set, the default value will be true and the calling app info will be
* propagated to the providers in every phase.
*/
@SuppressLint("MissingGetterMatchingBuilder")
@NonNull
public Builder setAlwaysSendAppInfoToProvider(boolean value) {
mAlwaysSendAppInfoToProvider = value;
return this;
}
/**
* Sets the list of {@link CredentialOption}.
*/
@@ -171,7 +221,8 @@ public final class GetCredentialRequest implements Parcelable {
Preconditions.checkCollectionElementsNotNull(
mCredentialOptions,
/*valueName=*/ "credentialOptions");
return new GetCredentialRequest(mCredentialOptions, mData);
return new GetCredentialRequest(mCredentialOptions, mData,
mAlwaysSendAppInfoToProvider);
}
}
}

View File

@@ -17,6 +17,7 @@
package android.service.credentials;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Parcel;
@@ -38,7 +39,7 @@ import java.util.Objects;
*/
@SuppressLint("ParcelNotFinal")
public class BeginCreateCredentialRequest implements Parcelable {
private final @NonNull CallingAppInfo mCallingAppInfo;
private final @Nullable CallingAppInfo mCallingAppInfo;
private final @NonNull String mType;
private final @NonNull Bundle mData;
@@ -49,13 +50,23 @@ public class BeginCreateCredentialRequest implements Parcelable {
* null or empty.
* @throws NullPointerException If {@code data} is null.
*/
public BeginCreateCredentialRequest(@NonNull CallingAppInfo callingAppInfo,
@NonNull String type, @NonNull Bundle data) {
mCallingAppInfo = Objects.requireNonNull(callingAppInfo,
"callingAppInfo must not be null");
public BeginCreateCredentialRequest(@NonNull String type, @NonNull Bundle data,
@Nullable CallingAppInfo callingAppInfo) {
mType = Preconditions.checkStringNotEmpty(type,
"type must not be null or empty");
mData = Objects.requireNonNull(data, "data must not be null");
mCallingAppInfo = callingAppInfo;
}
/**
* Constructs a new instance without {@link CallingAppInfo}.
*
* @throws IllegalArgumentException If {{@code type} string is
* null or empty.
* @throws NullPointerException If {@code data} is null.
*/
public BeginCreateCredentialRequest(@NonNull String type, @NonNull Bundle data) {
this(type, data, /*callingAppInfo=*/null);
}
private BeginCreateCredentialRequest(@NonNull Parcel in) {
@@ -90,7 +101,7 @@ public class BeginCreateCredentialRequest implements Parcelable {
}
/** Returns the info pertaining to the calling app. */
@NonNull
@Nullable
public CallingAppInfo getCallingAppInfo() {
return mCallingAppInfo;
}

View File

@@ -17,6 +17,7 @@
package android.service.credentials;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Parcel;
@@ -43,7 +44,7 @@ import java.util.Objects;
*/
public final class BeginGetCredentialRequest implements Parcelable {
/** Info pertaining to the app requesting for credentials. */
@NonNull private final CallingAppInfo mCallingAppInfo;
@Nullable private final CallingAppInfo mCallingAppInfo;
/**
* List of credential options. Each {@link BeginGetCredentialOption} object holds parameters to
@@ -56,7 +57,7 @@ public final class BeginGetCredentialRequest implements Parcelable {
*/
@NonNull private final List<BeginGetCredentialOption> mBeginGetCredentialOptions;
private BeginGetCredentialRequest(@NonNull CallingAppInfo callingAppInfo,
private BeginGetCredentialRequest(@Nullable CallingAppInfo callingAppInfo,
@NonNull List<BeginGetCredentialOption> getBeginCredentialOptions) {
this.mCallingAppInfo = callingAppInfo;
this.mBeginGetCredentialOptions = getBeginCredentialOptions;
@@ -98,7 +99,7 @@ public final class BeginGetCredentialRequest implements Parcelable {
/**
* Returns info pertaining to the app requesting credentials.
*/
public @NonNull CallingAppInfo getCallingAppInfo() {
public @Nullable CallingAppInfo getCallingAppInfo() {
return mCallingAppInfo;
}
@@ -114,17 +115,16 @@ public final class BeginGetCredentialRequest implements Parcelable {
* Builder for {@link BeginGetCredentialRequest}.
*/
public static final class Builder {
private CallingAppInfo mCallingAppInfo;
private CallingAppInfo mCallingAppInfo = null;
private List<BeginGetCredentialOption> mBeginGetCredentialOptions = new ArrayList<>();
/**
* Creates a new builder.
* @param callingAppInfo info pertaining to the app requesting credentials
*
* @throws IllegalArgumentException If {@code callingAppInfo} is null or empty.
* Sets information pertaining to the calling app.
* @param callingAppInfo the info object containing the package name, and app signatures
*/
public Builder(@NonNull CallingAppInfo callingAppInfo) {
mCallingAppInfo = Objects.requireNonNull(callingAppInfo);
public @NonNull Builder setCallingAppInfo(@Nullable CallingAppInfo callingAppInfo) {
mCallingAppInfo = callingAppInfo;
return this;
}
/**
@@ -165,7 +165,6 @@ public final class BeginGetCredentialRequest implements Parcelable {
* {@code callingAppInfo} is null or empty.
*/
public @NonNull BeginGetCredentialRequest build() {
Objects.requireNonNull(mCallingAppInfo, "callingAppInfo");
Preconditions.checkCollectionNotEmpty(mBeginGetCredentialOptions,
"beginGetCredentialOptions");
return new BeginGetCredentialRequest(mCallingAppInfo, mBeginGetCredentialOptions);

View File

@@ -26,6 +26,7 @@ import android.credentials.CreateCredentialResponse;
import android.credentials.ui.CreateCredentialProviderData;
import android.credentials.ui.Entry;
import android.credentials.ui.ProviderPendingIntentResponse;
import android.os.Bundle;
import android.service.credentials.BeginCreateCredentialRequest;
import android.service.credentials.BeginCreateCredentialResponse;
import android.service.credentials.CallingAppInfo;
@@ -74,10 +75,11 @@ public final class ProviderCreateSession extends ProviderSession<
createRequestSession.mClientAppInfo);
if (providerCreateRequest != null) {
BeginCreateCredentialRequest providerBeginCreateRequest =
new BeginCreateCredentialRequest(
providerCreateRequest.getCallingAppInfo(),
providerCreateRequest.getType(),
createRequestSession.mClientRequest.getCandidateQueryData());
constructQueryPhaseRequest(createRequestSession.mClientRequest.getType(),
createRequestSession.mClientRequest.getCandidateQueryData(),
createRequestSession.mClientAppInfo,
createRequestSession
.mClientRequest.alwaysSendAppInfoToProvider());
return new ProviderCreateSession(context, providerInfo, createRequestSession, userId,
remoteCredentialService, providerBeginCreateRequest, providerCreateRequest);
}
@@ -85,6 +87,21 @@ public final class ProviderCreateSession extends ProviderSession<
return null;
}
private static BeginCreateCredentialRequest constructQueryPhaseRequest(
String type, Bundle candidateQueryData, CallingAppInfo callingAppInfo,
boolean propagateToProvider) {
if (propagateToProvider) {
return new BeginCreateCredentialRequest(
type,
candidateQueryData
);
}
return new BeginCreateCredentialRequest(
type,
candidateQueryData,
callingAppInfo);
}
@Nullable
private static CreateCredentialRequest createProviderRequest(List<String> providerCapabilities,
android.credentials.CreateCredentialRequest clientRequest,

View File

@@ -92,9 +92,11 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
getRequestSession.mClientRequest);
if (filteredRequest != null) {
BeginGetCredentialRequest beginGetCredentialRequest = constructQueryPhaseRequest(
filteredRequest, getRequestSession.mClientAppInfo);
filteredRequest, getRequestSession.mClientAppInfo,
getRequestSession.mClientRequest.alwaysSendAppInfoToProvider());
return new ProviderGetSession(context, providerInfo, getRequestSession, userId,
remoteCredentialService, beginGetCredentialRequest, filteredRequest);
remoteCredentialService, beginGetCredentialRequest, filteredRequest,
getRequestSession.mClientAppInfo);
}
Log.i(TAG, "Unable to create provider session");
return null;
@@ -102,16 +104,20 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
private static BeginGetCredentialRequest constructQueryPhaseRequest(
android.credentials.GetCredentialRequest filteredRequest,
CallingAppInfo callingAppInfo
) {
return new BeginGetCredentialRequest.Builder(callingAppInfo)
.setBeginGetCredentialOptions(
filteredRequest.getCredentialOptions().stream().map(
option -> new BeginGetCredentialOption(
option.getType(),
option.getCandidateQueryData())).collect(Collectors
.toList()))
.build();
CallingAppInfo callingAppInfo,
boolean propagateToProvider) {
BeginGetCredentialRequest.Builder builder = new BeginGetCredentialRequest.Builder();
builder.setBeginGetCredentialOptions(
filteredRequest.getCredentialOptions().stream().map(
option -> {
return new BeginGetCredentialOption(
option.getType(),
option.getCandidateQueryData());
}).collect(Collectors.toList()));
if (propagateToProvider) {
builder.setCallingAppInfo(callingAppInfo);
}
return builder.build();
}
@Nullable
@@ -145,10 +151,11 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
ProviderInternalCallback<GetCredentialResponse> callbacks,
int userId, RemoteCredentialService remoteCredentialService,
BeginGetCredentialRequest beginGetRequest,
android.credentials.GetCredentialRequest completeGetRequest) {
android.credentials.GetCredentialRequest completeGetRequest,
CallingAppInfo callingAppInfo) {
super(context, info, beginGetRequest, callbacks, userId, remoteCredentialService);
mCompleteRequest = completeGetRequest;
mCallingAppInfo = beginGetRequest.getCallingAppInfo();
mCallingAppInfo = callingAppInfo;
setStatus(Status.PENDING);
}