Merge "Unhide Credential Manager provider APIs Test: Built & deployed locally Bug: 253155222 CTS-Coverage-Bug:247549381"
This commit is contained in:
@@ -39328,6 +39328,149 @@ package android.service.controls.templates {
|
||||
|
||||
}
|
||||
|
||||
package android.service.credentials {
|
||||
|
||||
public final class Action implements android.os.Parcelable {
|
||||
ctor public Action(@NonNull android.app.slice.Slice, @NonNull android.app.PendingIntent);
|
||||
method public int describeContents();
|
||||
method @NonNull public android.app.PendingIntent getPendingIntent();
|
||||
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.Action> CREATOR;
|
||||
}
|
||||
|
||||
public final class BeginCreateCredentialRequest implements android.os.Parcelable {
|
||||
ctor public BeginCreateCredentialRequest(@NonNull String, @NonNull String, @NonNull android.os.Bundle);
|
||||
method public int describeContents();
|
||||
method @NonNull public String getCallingPackage();
|
||||
method @NonNull public android.os.Bundle getData();
|
||||
method @NonNull public String getType();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.BeginCreateCredentialRequest> CREATOR;
|
||||
}
|
||||
|
||||
public final class BeginCreateCredentialResponse implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method @NonNull public java.util.List<android.service.credentials.CreateEntry> getCreateEntries();
|
||||
method @Nullable public android.service.credentials.CreateEntry getRemoteCreateEntry();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.BeginCreateCredentialResponse> CREATOR;
|
||||
}
|
||||
|
||||
public static final class BeginCreateCredentialResponse.Builder {
|
||||
ctor public BeginCreateCredentialResponse.Builder();
|
||||
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);
|
||||
}
|
||||
|
||||
public final class CreateCredentialRequest implements android.os.Parcelable {
|
||||
ctor public CreateCredentialRequest(@NonNull String, @NonNull String, @NonNull android.os.Bundle);
|
||||
method public int describeContents();
|
||||
method @NonNull public String getCallingPackage();
|
||||
method @NonNull public android.os.Bundle getData();
|
||||
method @NonNull public String getType();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.CreateCredentialRequest> CREATOR;
|
||||
}
|
||||
|
||||
public final class CreateEntry implements android.os.Parcelable {
|
||||
ctor public CreateEntry(@NonNull android.app.slice.Slice, @NonNull android.app.PendingIntent);
|
||||
method public int describeContents();
|
||||
method @NonNull public android.app.PendingIntent getPendingIntent();
|
||||
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.CreateEntry> CREATOR;
|
||||
}
|
||||
|
||||
public final class CredentialEntry implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method @Nullable public android.credentials.Credential getCredential();
|
||||
method @Nullable public android.app.PendingIntent getPendingIntent();
|
||||
method @NonNull public android.app.slice.Slice getSlice();
|
||||
method @NonNull public String getType();
|
||||
method public boolean isAutoSelectAllowed();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.CredentialEntry> CREATOR;
|
||||
}
|
||||
|
||||
public static final class CredentialEntry.Builder {
|
||||
ctor public CredentialEntry.Builder(@NonNull String, @NonNull android.app.slice.Slice, @NonNull android.app.PendingIntent);
|
||||
ctor public CredentialEntry.Builder(@NonNull String, @NonNull android.app.slice.Slice, @NonNull android.credentials.Credential);
|
||||
method @NonNull public android.service.credentials.CredentialEntry build();
|
||||
method @NonNull public android.service.credentials.CredentialEntry.Builder setAutoSelectAllowed(@NonNull boolean);
|
||||
}
|
||||
|
||||
public class CredentialProviderException extends java.lang.Exception {
|
||||
ctor public CredentialProviderException(int, @NonNull String, @NonNull Throwable);
|
||||
ctor public CredentialProviderException(int, @NonNull String);
|
||||
ctor public CredentialProviderException(int, @NonNull Throwable);
|
||||
ctor public CredentialProviderException(int);
|
||||
method public int getErrorCode();
|
||||
field public static final int ERROR_UNKNOWN = 0; // 0x0
|
||||
}
|
||||
|
||||
public abstract class CredentialProviderService extends android.app.Service {
|
||||
ctor public CredentialProviderService();
|
||||
method public abstract void onBeginCreateCredential(@NonNull android.service.credentials.BeginCreateCredentialRequest, @NonNull android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<android.service.credentials.BeginCreateCredentialResponse,android.service.credentials.CredentialProviderException>);
|
||||
method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
|
||||
method public abstract void onGetCredentials(@NonNull android.service.credentials.GetCredentialsRequest, @NonNull android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<android.service.credentials.GetCredentialsResponse,android.service.credentials.CredentialProviderException>);
|
||||
field public static final String CAPABILITY_META_DATA_KEY = "android.credentials.capabilities";
|
||||
field public static final String EXTRA_CREATE_CREDENTIAL_REQUEST = "android.service.credentials.extra.CREATE_CREDENTIAL_REQUEST";
|
||||
field public static final String EXTRA_CREATE_CREDENTIAL_RESULT = "android.service.credentials.extra.CREATE_CREDENTIAL_RESULT";
|
||||
field public static final String EXTRA_CREDENTIAL_RESULT = "android.service.credentials.extra.CREDENTIAL_RESULT";
|
||||
field public static final String EXTRA_ERROR = "android.service.credentials.extra.ERROR";
|
||||
field public static final String EXTRA_GET_CREDENTIALS_CONTENT_RESULT = "android.service.credentials.extra.GET_CREDENTIALS_CONTENT_RESULT";
|
||||
field public static final String SERVICE_INTERFACE = "android.service.credentials.CredentialProviderService";
|
||||
}
|
||||
|
||||
public final class CredentialsResponseContent implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method @NonNull public java.util.List<android.service.credentials.Action> getActions();
|
||||
method @NonNull public java.util.List<android.service.credentials.CredentialEntry> getCredentialEntries();
|
||||
method @Nullable public android.service.credentials.CredentialEntry getRemoteCredentialEntry();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.CredentialsResponseContent> CREATOR;
|
||||
}
|
||||
|
||||
public static final class CredentialsResponseContent.Builder {
|
||||
ctor public CredentialsResponseContent.Builder();
|
||||
method @NonNull public android.service.credentials.CredentialsResponseContent.Builder addAction(@NonNull android.service.credentials.Action);
|
||||
method @NonNull public android.service.credentials.CredentialsResponseContent.Builder addCredentialEntry(@NonNull android.service.credentials.CredentialEntry);
|
||||
method @NonNull public android.service.credentials.CredentialsResponseContent build();
|
||||
method @NonNull public android.service.credentials.CredentialsResponseContent.Builder setActions(@NonNull java.util.List<android.service.credentials.Action>);
|
||||
method @NonNull public android.service.credentials.CredentialsResponseContent.Builder setCredentialEntries(@NonNull java.util.List<android.service.credentials.CredentialEntry>);
|
||||
method @NonNull public android.service.credentials.CredentialsResponseContent.Builder setRemoteCredentialEntry(@Nullable android.service.credentials.CredentialEntry);
|
||||
}
|
||||
|
||||
public final class GetCredentialsRequest implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method @NonNull public String getCallingPackage();
|
||||
method @NonNull public java.util.List<android.credentials.GetCredentialOption> getGetCredentialOptions();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.GetCredentialsRequest> CREATOR;
|
||||
}
|
||||
|
||||
public static final class GetCredentialsRequest.Builder {
|
||||
ctor public GetCredentialsRequest.Builder(@NonNull String);
|
||||
method @NonNull public android.service.credentials.GetCredentialsRequest.Builder addGetCredentialOption(@NonNull android.credentials.GetCredentialOption);
|
||||
method @NonNull public android.service.credentials.GetCredentialsRequest build();
|
||||
method @NonNull public android.service.credentials.GetCredentialsRequest.Builder setGetCredentialOptions(@NonNull java.util.List<android.credentials.GetCredentialOption>);
|
||||
}
|
||||
|
||||
public final class GetCredentialsResponse implements android.os.Parcelable {
|
||||
method @NonNull public static android.service.credentials.GetCredentialsResponse createWithAuthentication(@NonNull android.service.credentials.Action);
|
||||
method @NonNull public static android.service.credentials.GetCredentialsResponse createWithResponseContent(@NonNull android.service.credentials.CredentialsResponseContent);
|
||||
method public int describeContents();
|
||||
method @Nullable public android.service.credentials.Action getAuthenticationAction();
|
||||
method @Nullable public android.service.credentials.CredentialsResponseContent getCredentialsResponseContent();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.service.credentials.GetCredentialsResponse> CREATOR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
package android.service.dreams {
|
||||
|
||||
public class DreamService extends android.app.Service implements android.view.Window.Callback {
|
||||
|
||||
@@ -27,8 +27,6 @@ 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 {
|
||||
/** Slice object containing display content to be displayed with this action on the UI. */
|
||||
@@ -39,6 +37,13 @@ public final class Action implements Parcelable {
|
||||
/**
|
||||
* Constructs an action to be displayed on the UI.
|
||||
*
|
||||
* <p> Actions must be used for any provider related operations, such as opening the provider
|
||||
* app, intenting straight into certain app activities like 'manage credentials', top
|
||||
* level authentication before displaying any content etc.
|
||||
*
|
||||
* <p> See details on usage of {@code Action} for various actionable entries in
|
||||
* {@link BeginCreateCredentialResponse} and {@link GetCredentialsResponse}.
|
||||
*
|
||||
* @param slice the display content to be displayed on the UI, along with this action
|
||||
* @param pendingIntent the intent to be invoked when the user selects this action
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
package android.service.credentials;
|
||||
|
||||
parcelable BeginCreateCredentialRequest;
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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 java.util.Objects;
|
||||
|
||||
/**
|
||||
* Request for beginning a create credential request.
|
||||
*
|
||||
* See {@link BeginCreateCredentialResponse} for the counterpart response
|
||||
*/
|
||||
public final class BeginCreateCredentialRequest implements Parcelable {
|
||||
private final @NonNull String mCallingPackage;
|
||||
private final @NonNull String mType;
|
||||
private final @NonNull Bundle mData;
|
||||
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
*
|
||||
* @throws IllegalArgumentException If {@code callingPackage}, or {@code type} string is
|
||||
* null or empty.
|
||||
* @throws NullPointerException If {@code data} is null.
|
||||
*/
|
||||
public BeginCreateCredentialRequest(@NonNull String callingPackage,
|
||||
@NonNull String type, @NonNull Bundle data) {
|
||||
mCallingPackage = Preconditions.checkStringNotEmpty(callingPackage,
|
||||
"callingPackage must not be null or empty");
|
||||
mType = Preconditions.checkStringNotEmpty(type,
|
||||
"type must not be null or empty");
|
||||
mData = Objects.requireNonNull(data, "data must not be null");
|
||||
}
|
||||
|
||||
private BeginCreateCredentialRequest(@NonNull Parcel in) {
|
||||
mCallingPackage = in.readString8();
|
||||
mType = in.readString8();
|
||||
mData = in.readBundle(Bundle.class.getClassLoader());
|
||||
}
|
||||
|
||||
public static final @NonNull Creator<BeginCreateCredentialRequest> CREATOR =
|
||||
new Creator<BeginCreateCredentialRequest>() {
|
||||
@Override
|
||||
public BeginCreateCredentialRequest createFromParcel(@NonNull Parcel in) {
|
||||
return new BeginCreateCredentialRequest(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeginCreateCredentialRequest[] newArray(int size) {
|
||||
return new BeginCreateCredentialRequest[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeString8(mCallingPackage);
|
||||
dest.writeString8(mType);
|
||||
dest.writeBundle(mData);
|
||||
}
|
||||
|
||||
/** Returns the calling package of the calling app. */
|
||||
@NonNull
|
||||
public String getCallingPackage() {
|
||||
return mCallingPackage;
|
||||
}
|
||||
|
||||
/** Returns the type of the credential to be created. */
|
||||
@NonNull
|
||||
public String getType() {
|
||||
return mType;
|
||||
}
|
||||
|
||||
/** Returns the data to be used while resolving the credential to create. */
|
||||
@NonNull
|
||||
public Bundle getData() {
|
||||
return mData;
|
||||
}
|
||||
}
|
||||
@@ -16,4 +16,4 @@
|
||||
|
||||
package android.service.credentials;
|
||||
|
||||
parcelable CreateCredentialResponse;
|
||||
parcelable BeginCreateCredentialResponse;
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Response to a {@link BeginCreateCredentialRequest}.
|
||||
*/
|
||||
public final class BeginCreateCredentialResponse implements Parcelable {
|
||||
private final @NonNull List<CreateEntry> mCreateEntries;
|
||||
private final @Nullable CreateEntry mRemoteCreateEntry;
|
||||
|
||||
private BeginCreateCredentialResponse(@NonNull Parcel in) {
|
||||
List<CreateEntry> createEntries = new ArrayList<>();
|
||||
in.readTypedList(createEntries, CreateEntry.CREATOR);
|
||||
mCreateEntries = createEntries;
|
||||
mRemoteCreateEntry = in.readTypedObject(CreateEntry.CREATOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeTypedList(mCreateEntries);
|
||||
dest.writeTypedObject(mRemoteCreateEntry, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static final @NonNull Creator<BeginCreateCredentialResponse> CREATOR =
|
||||
new Creator<BeginCreateCredentialResponse>() {
|
||||
@Override
|
||||
public BeginCreateCredentialResponse createFromParcel(@NonNull Parcel in) {
|
||||
return new BeginCreateCredentialResponse(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeginCreateCredentialResponse[] newArray(int size) {
|
||||
return new BeginCreateCredentialResponse[size];
|
||||
}
|
||||
};
|
||||
|
||||
/* package-private */ BeginCreateCredentialResponse(
|
||||
@NonNull List<CreateEntry> createEntries,
|
||||
@Nullable CreateEntry remoteCreateEntry) {
|
||||
this.mCreateEntries = createEntries;
|
||||
com.android.internal.util.AnnotationValidations.validate(
|
||||
NonNull.class, null, mCreateEntries);
|
||||
this.mRemoteCreateEntry = remoteCreateEntry;
|
||||
}
|
||||
|
||||
/** Returns the list of create entries to be displayed on the UI. */
|
||||
public @NonNull List<CreateEntry> getCreateEntries() {
|
||||
return mCreateEntries;
|
||||
}
|
||||
|
||||
/** Returns the remote create entry to be displayed on the UI. */
|
||||
public @Nullable CreateEntry getRemoteCreateEntry() {
|
||||
return mRemoteCreateEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder for {@link BeginCreateCredentialResponse}
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess") /* synthetic access */
|
||||
public static final class Builder {
|
||||
private @NonNull List<CreateEntry> mCreateEntries = new ArrayList<>();
|
||||
private @Nullable CreateEntry mRemoteCreateEntry;
|
||||
|
||||
/**
|
||||
* Sets the list of create entries to be shown on the UI.
|
||||
*
|
||||
* @throws IllegalArgumentException If {@code createEntries} is empty.
|
||||
* @throws NullPointerException If {@code createEntries} is null, or any of its elements
|
||||
* are null.
|
||||
*/
|
||||
public @NonNull Builder setCreateEntries(@NonNull List<CreateEntry> createEntries) {
|
||||
Preconditions.checkCollectionNotEmpty(createEntries, "createEntries");
|
||||
mCreateEntries = Preconditions.checkCollectionElementsNotNull(
|
||||
createEntries, "createEntries");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an entry to the list of create entries to be shown on the UI.
|
||||
*
|
||||
* @throws NullPointerException If {@code createEntry} is null.
|
||||
*/
|
||||
public @NonNull Builder addCreateEntry(@NonNull CreateEntry createEntry) {
|
||||
mCreateEntries.add(Objects.requireNonNull(createEntry));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a remote create entry to be shown on the UI. Provider must set this entry if they
|
||||
* wish to create the credential on a different device.
|
||||
*
|
||||
* <p> When constructing the {@link CreateEntry} object, the {@code pendingIntent} must be
|
||||
* set such that it leads to an activity that can provide UI to fulfill the request on
|
||||
* a remote device. When user selects this {@code remoteCreateEntry}, the system will
|
||||
* invoke the {@code pendingIntent} set on the {@link CreateEntry}.
|
||||
*
|
||||
* <p> Once the remote credential flow is complete, the {@link android.app.Activity}
|
||||
* result should be set to {@link android.app.Activity#RESULT_OK} and an extra with the
|
||||
* {@link CredentialProviderService#EXTRA_CREATE_CREDENTIAL_RESULT} key should be populated
|
||||
* with a {@link android.credentials.CreateCredentialResponse} object.
|
||||
*/
|
||||
public @NonNull Builder setRemoteCreateEntry(@Nullable CreateEntry remoteCreateEntry) {
|
||||
mRemoteCreateEntry = remoteCreateEntry;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a new instance of {@link BeginCreateCredentialResponse}.
|
||||
*
|
||||
* @throws NullPointerException If {@code createEntries} is null.
|
||||
* @throws IllegalArgumentException If {@code createEntries} is empty.
|
||||
*/
|
||||
public @NonNull BeginCreateCredentialResponse build() {
|
||||
Preconditions.checkCollectionNotEmpty(mCreateEntries, "createEntries must "
|
||||
+ "not be null, or empty");
|
||||
return new BeginCreateCredentialResponse(mCreateEntries, mRemoteCreateEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
package android.service.credentials;
|
||||
|
||||
parcelable CreateCredentialRequest;
|
||||
@@ -27,8 +27,6 @@ import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Request for creating a credential.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class CreateCredentialRequest implements Parcelable {
|
||||
private final @NonNull String mCallingPackage;
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* 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.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Response to a {@link CreateCredentialRequest}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class CreateCredentialResponse implements Parcelable {
|
||||
private final @NonNull List<SaveEntry> mSaveEntries;
|
||||
private final @Nullable Action mRemoteSaveEntry;
|
||||
//TODO : Add actions if needed
|
||||
|
||||
private CreateCredentialResponse(@NonNull Parcel in) {
|
||||
List<SaveEntry> saveEntries = new ArrayList<>();
|
||||
in.readTypedList(saveEntries, SaveEntry.CREATOR);
|
||||
mSaveEntries = saveEntries;
|
||||
mRemoteSaveEntry = in.readTypedObject(Action.CREATOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeTypedList(mSaveEntries);
|
||||
dest.writeTypedObject(mRemoteSaveEntry, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static final @NonNull Creator<CreateCredentialResponse> CREATOR =
|
||||
new Creator<CreateCredentialResponse>() {
|
||||
@Override
|
||||
public CreateCredentialResponse createFromParcel(@NonNull Parcel in) {
|
||||
return new CreateCredentialResponse(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CreateCredentialResponse[] newArray(int size) {
|
||||
return new CreateCredentialResponse[size];
|
||||
}
|
||||
};
|
||||
|
||||
/* package-private */ CreateCredentialResponse(
|
||||
@NonNull List<SaveEntry> saveEntries,
|
||||
@Nullable Action remoteSaveEntry) {
|
||||
this.mSaveEntries = saveEntries;
|
||||
com.android.internal.util.AnnotationValidations.validate(
|
||||
NonNull.class, null, mSaveEntries);
|
||||
this.mRemoteSaveEntry = remoteSaveEntry;
|
||||
}
|
||||
|
||||
/** Returns the list of save entries to be displayed on the UI. */
|
||||
public @NonNull List<SaveEntry> getSaveEntries() {
|
||||
return mSaveEntries;
|
||||
}
|
||||
|
||||
/** Returns the remote save entry to be displayed on the UI. */
|
||||
public @NonNull Action getRemoteSaveEntry() {
|
||||
return mRemoteSaveEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder for {@link CreateCredentialResponse}
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public static final class Builder {
|
||||
private @NonNull List<SaveEntry> mSaveEntries = new ArrayList<>();
|
||||
private @Nullable Action mRemoteSaveEntry;
|
||||
|
||||
/**
|
||||
* Sets the list of save entries to be shown on the UI.
|
||||
*
|
||||
* @throws IllegalArgumentException If {@code saveEntries} is empty.
|
||||
* @throws NullPointerException If {@code saveEntries} is null, or any of its elements
|
||||
* are null.
|
||||
*/
|
||||
public @NonNull Builder setSaveEntries(@NonNull List<SaveEntry> saveEntries) {
|
||||
Preconditions.checkCollectionNotEmpty(saveEntries, "saveEntries");
|
||||
mSaveEntries = Preconditions.checkCollectionElementsNotNull(
|
||||
saveEntries, "saveEntries");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an entry to the list of save entries to be shown on the UI.
|
||||
*
|
||||
* @throws NullPointerException If {@code saveEntry} is null.
|
||||
*/
|
||||
public @NonNull Builder addSaveEntry(@NonNull SaveEntry saveEntry) {
|
||||
mSaveEntries.add(Objects.requireNonNull(saveEntry));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a remote save entry to be shown on the UI.
|
||||
*/
|
||||
public @NonNull Builder setRemoteSaveEntry(@Nullable Action remoteSaveEntry) {
|
||||
mRemoteSaveEntry = remoteSaveEntry;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the instance.
|
||||
*
|
||||
* @throws IllegalArgumentException If {@code saveEntries} is empty.
|
||||
*/
|
||||
public @NonNull CreateCredentialResponse build() {
|
||||
Preconditions.checkCollectionNotEmpty(mSaveEntries, "saveEntries must "
|
||||
+ "not be empty");
|
||||
return new CreateCredentialResponse(
|
||||
mSaveEntries,
|
||||
mRemoteSaveEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,27 +25,25 @@ import android.os.Parcelable;
|
||||
/**
|
||||
* An entry to be shown on the UI. This entry represents where the credential to be created will
|
||||
* be stored. Examples include user's account, family group etc.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class SaveEntry implements Parcelable {
|
||||
public final class CreateEntry implements Parcelable {
|
||||
private final @NonNull Slice mSlice;
|
||||
private final @NonNull PendingIntent mPendingIntent;
|
||||
|
||||
private SaveEntry(@NonNull Parcel in) {
|
||||
private CreateEntry(@NonNull Parcel in) {
|
||||
mSlice = in.readTypedObject(Slice.CREATOR);
|
||||
mPendingIntent = in.readTypedObject(PendingIntent.CREATOR);
|
||||
}
|
||||
|
||||
public static final @NonNull Creator<SaveEntry> CREATOR = new Creator<SaveEntry>() {
|
||||
public static final @NonNull Creator<CreateEntry> CREATOR = new Creator<CreateEntry>() {
|
||||
@Override
|
||||
public SaveEntry createFromParcel(@NonNull Parcel in) {
|
||||
return new SaveEntry(in);
|
||||
public CreateEntry createFromParcel(@NonNull Parcel in) {
|
||||
return new CreateEntry(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SaveEntry[] newArray(int size) {
|
||||
return new SaveEntry[size];
|
||||
public CreateEntry[] newArray(int size) {
|
||||
return new CreateEntry[size];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -61,12 +59,12 @@ public final class SaveEntry implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a save entry to be displayed on the UI.
|
||||
* Constructs a CreateEntry to be displayed on the UI.
|
||||
*
|
||||
* @param slice the display content to be displayed on the UI, along with this entry
|
||||
* @param pendingIntent the intent to be invoked when the user selects this entry
|
||||
*/
|
||||
public SaveEntry(
|
||||
public CreateEntry(
|
||||
@NonNull Slice slice,
|
||||
@NonNull PendingIntent pendingIntent) {
|
||||
this.mSlice = slice;
|
||||
@@ -77,12 +75,12 @@ public final class SaveEntry implements Parcelable {
|
||||
NonNull.class, null, mPendingIntent);
|
||||
}
|
||||
|
||||
/** Returns the content to be displayed with this save entry on the UI. */
|
||||
/** Returns the content to be displayed with this create entry on the UI. */
|
||||
public @NonNull Slice getSlice() {
|
||||
return mSlice;
|
||||
}
|
||||
|
||||
/** Returns the pendingIntent to be invoked when this save entry on the UI is selectcd. */
|
||||
/** Returns the pendingIntent to be invoked when this create entry on the UI is selectcd. */
|
||||
public @NonNull PendingIntent getPendingIntent() {
|
||||
return mPendingIntent;
|
||||
}
|
||||
@@ -31,8 +31,6 @@ 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. */
|
||||
@@ -145,61 +143,67 @@ public final class CredentialEntry implements Parcelable {
|
||||
private boolean mAutoSelectAllowed = false;
|
||||
|
||||
/**
|
||||
* Builds the instance.
|
||||
* Creates a builder for a {@link CredentialEntry} that should invoke a
|
||||
* {@link PendingIntent} when selected by the user.
|
||||
*
|
||||
* <p>The {@code pendingIntent} can be used to launch activities that require some user
|
||||
* engagement before getting the credential corresponding to this entry,
|
||||
* e.g. authentication, confirmation etc.
|
||||
* Once the activity fulfills the required user engagement, the
|
||||
* {@link android.app.Activity} result should be set to
|
||||
* {@link android.app.Activity#RESULT_OK}, and the
|
||||
* {@link CredentialProviderService#EXTRA_CREDENTIAL_RESULT} must be set with a
|
||||
* {@link Credential} object.
|
||||
*
|
||||
* @param type the type of credential underlying this credential entry
|
||||
* @param slice the content to be displayed with this entry on the UI
|
||||
* @param pendingIntent the pendingIntent to be invoked when this entry is selected by the
|
||||
* user
|
||||
*
|
||||
* @throws IllegalArgumentException If {@code type} is null or empty.
|
||||
* @throws NullPointerException If {@code slice} is null.
|
||||
* @throws NullPointerException If {@code slice}, or {@code pendingIntent} is null.
|
||||
* @throws IllegalArgumentException If {@code type} is null or empty, or if
|
||||
* {@code pendingIntent} was not created with {@link PendingIntent#getActivity}
|
||||
* or {@link PendingIntent#getActivities}.
|
||||
*/
|
||||
public Builder(@NonNull String type, @NonNull Slice slice) {
|
||||
public Builder(@NonNull String type, @NonNull Slice slice,
|
||||
@NonNull PendingIntent pendingIntent) {
|
||||
mType = Preconditions.checkStringNotEmpty(type, "type must not be "
|
||||
+ "null, or empty");
|
||||
mSlice = Objects.requireNonNull(slice,
|
||||
"slice must not be null");
|
||||
mPendingIntent = Objects.requireNonNull(pendingIntent,
|
||||
"pendingIntent must not be null");
|
||||
if (!mPendingIntent.isActivity()) {
|
||||
throw new IllegalStateException("Pending intent must start an activity");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the pendingIntent to be invoked if the user selects this entry.
|
||||
* Creates a builder for a {@link CredentialEntry} that contains a {@link Credential},
|
||||
* and does not require further action.
|
||||
* @param type the type of credential underlying this credential entry
|
||||
* @param slice the content to be displayed with this entry on the UI
|
||||
* @param credential the credential to be returned to the client app, when this entry is
|
||||
* selected by the user
|
||||
*
|
||||
* The pending intent can be used to launch activities that require some user engagement
|
||||
* before getting the credential corresponding to this entry, e.g. authentication,
|
||||
* confirmation etc.
|
||||
* Once the activity fulfills the required user engagement, a {@link Credential} object
|
||||
* must be returned as an extra on activity finish.
|
||||
*
|
||||
* @throws IllegalStateException If {@code credential} is already set. Must either set the
|
||||
* {@code credential}, or the {@code pendingIntent}.
|
||||
* @throws IllegalArgumentException If {@code type} is null or empty.
|
||||
* @throws NullPointerException If {@code slice}, or {@code credential} is null.
|
||||
*/
|
||||
public @NonNull Builder setPendingIntent(@Nullable PendingIntent pendingIntent) {
|
||||
if (pendingIntent != null) {
|
||||
Preconditions.checkState(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) {
|
||||
if (credential != null) {
|
||||
Preconditions.checkState(mPendingIntent == null,
|
||||
"pendingIntent is already set. Cannot set both the "
|
||||
+ "pendingIntent and the credential");
|
||||
}
|
||||
mCredential = credential;
|
||||
return this;
|
||||
public Builder(@NonNull String type, @NonNull Slice slice, @NonNull Credential credential) {
|
||||
mType = Preconditions.checkStringNotEmpty(type, "type must not be "
|
||||
+ "null, or empty");
|
||||
mSlice = Objects.requireNonNull(slice,
|
||||
"slice must not be null");
|
||||
mCredential = Objects.requireNonNull(credential,
|
||||
"credential must not be null");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the entry is allowed to be auto selected by the framework.
|
||||
* The default value is set to false.
|
||||
*
|
||||
* <p> The entry is only auto selected if it is the only entry on the user selector,
|
||||
* AND the developer has also enabled auto select, while building the request.
|
||||
*/
|
||||
public @NonNull Builder setAutoSelectAllowed(@NonNull boolean autoSelectAllowed) {
|
||||
mAutoSelectAllowed = autoSelectAllowed;
|
||||
|
||||
@@ -24,8 +24,6 @@ import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Contains custom exceptions to be used by credential providers on failure.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class CredentialProviderException extends Exception {
|
||||
public static final int ERROR_UNKNOWN = 0;
|
||||
@@ -59,6 +57,11 @@ public class CredentialProviderException extends Exception {
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface CredentialProviderError { }
|
||||
|
||||
public CredentialProviderException(@CredentialProviderError int errorCode,
|
||||
@NonNull String message, @NonNull Throwable cause) {
|
||||
super(message, cause);
|
||||
mErrorCode = errorCode;
|
||||
}
|
||||
|
||||
public CredentialProviderException(@CredentialProviderError int errorCode,
|
||||
@NonNull String message) {
|
||||
|
||||
@@ -37,30 +37,63 @@ import java.util.Objects;
|
||||
/**
|
||||
* Service to be extended by credential providers, in order to return user credentials
|
||||
* to the framework.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public abstract class CredentialProviderService extends Service {
|
||||
/** Extra to be used by provider to populate the credential when ending the activity started
|
||||
* through the {@code pendingIntent} on the selected {@link SaveEntry}. **/
|
||||
public static final String EXTRA_CREATE_CREDENTIAL_RESPONSE =
|
||||
"android.service.credentials.extra.CREATE_CREDENTIAL_RESPONSE";
|
||||
|
||||
/** Extra to be used by provider to populate the {@link CredentialsDisplayContent} when
|
||||
* an authentication action entry is selected. **/
|
||||
public static final String EXTRA_GET_CREDENTIALS_DISPLAY_CONTENT =
|
||||
"android.service.credentials.extra.GET_CREDENTIALS_DISPLAY_CONTENT";
|
||||
/**
|
||||
* Intent extra: The {@link android.credentials.CreateCredentialRequest} attached with
|
||||
* the {@code pendingIntent} that is invoked when the user selects a {@link CreateEntry}
|
||||
* returned as part of the {@link BeginCreateCredentialResponse}
|
||||
*
|
||||
* <p>
|
||||
* Type: {@link android.credentials.CreateCredentialRequest}
|
||||
*/
|
||||
public static final String EXTRA_CREATE_CREDENTIAL_REQUEST =
|
||||
"android.service.credentials.extra.CREATE_CREDENTIAL_REQUEST";
|
||||
|
||||
/**
|
||||
* Provider must read the value against this extra to receive the complete create credential
|
||||
* request parameters, when a pending intent is launched.
|
||||
* Intent extra: The result of a create flow operation, to be set on finish of the
|
||||
* {@link android.app.Activity} invoked through the {@code pendingIntent} set on
|
||||
* a {@link CreateEntry}.
|
||||
*
|
||||
* <p>
|
||||
* Type: {@link android.credentials.CreateCredentialResponse}
|
||||
*/
|
||||
public static final String EXTRA_CREATE_CREDENTIAL_REQUEST_PARAMS =
|
||||
"android.service.credentials.extra.CREATE_CREDENTIAL_REQUEST_PARAMS";
|
||||
public static final String EXTRA_CREATE_CREDENTIAL_RESULT =
|
||||
"android.service.credentials.extra.CREATE_CREDENTIAL_RESULT";
|
||||
|
||||
/** Extra to be used by the provider when setting the credential result. */
|
||||
public static final String EXTRA_GET_CREDENTIAL =
|
||||
"android.service.credentials.extra.GET_CREDENTIAL";
|
||||
/**
|
||||
* Intent extra: The result of a get credential flow operation, to be set on finish of the
|
||||
* {@link android.app.Activity} invoked through the {@code pendingIntent} set on
|
||||
* a {@link CredentialEntry}.
|
||||
*
|
||||
* <p>
|
||||
* Type: {@link android.credentials.Credential}
|
||||
*/
|
||||
public static final String EXTRA_CREDENTIAL_RESULT =
|
||||
"android.service.credentials.extra.CREDENTIAL_RESULT";
|
||||
|
||||
/**
|
||||
* Intent extra: The result of an authentication flow, to be set on finish of the
|
||||
* {@link android.app.Activity} invoked through the {@link android.app.PendingIntent} set on
|
||||
* a {@link GetCredentialsResponse}. This result should contain the actual content, including
|
||||
* credential entries and action entries, to be shown on the selector.
|
||||
*
|
||||
* <p>
|
||||
* Type: {@link CredentialsResponseContent}
|
||||
*/
|
||||
public static final String EXTRA_GET_CREDENTIALS_CONTENT_RESULT =
|
||||
"android.service.credentials.extra.GET_CREDENTIALS_CONTENT_RESULT";
|
||||
|
||||
/**
|
||||
* Intent extra: The error result of any {@link android.app.PendingIntent} flow, to be set
|
||||
* on finish of the corresponding {@link android.app.Activity}. This result should contain an
|
||||
* error code, representing the error encountered by the provider.
|
||||
*
|
||||
* <p>
|
||||
* Type: {@link String}
|
||||
*/
|
||||
public static final String EXTRA_ERROR =
|
||||
"android.service.credentials.extra.ERROR";
|
||||
|
||||
private static final String TAG = "CredProviderService";
|
||||
|
||||
@@ -129,20 +162,21 @@ public abstract class CredentialProviderService extends Service {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICancellationSignal onCreateCredential(CreateCredentialRequest request,
|
||||
ICreateCredentialCallback callback) {
|
||||
public ICancellationSignal onBeginCreateCredential(BeginCreateCredentialRequest request,
|
||||
IBeginCreateCredentialCallback callback) {
|
||||
Objects.requireNonNull(request);
|
||||
Objects.requireNonNull(callback);
|
||||
|
||||
ICancellationSignal transport = CancellationSignal.createTransport();
|
||||
|
||||
mHandler.sendMessage(obtainMessage(
|
||||
CredentialProviderService::onCreateCredential,
|
||||
CredentialProviderService::onBeginCreateCredential,
|
||||
CredentialProviderService.this, request,
|
||||
CancellationSignal.fromTransport(transport),
|
||||
new OutcomeReceiver<CreateCredentialResponse, CredentialProviderException>() {
|
||||
new OutcomeReceiver<
|
||||
BeginCreateCredentialResponse, CredentialProviderException>() {
|
||||
@Override
|
||||
public void onResult(CreateCredentialResponse result) {
|
||||
public void onResult(BeginCreateCredentialResponse result) {
|
||||
try {
|
||||
callback.onSuccess(result);
|
||||
} catch (RemoteException e) {
|
||||
@@ -182,8 +216,8 @@ public abstract class CredentialProviderService extends Service {
|
||||
* the android system.
|
||||
* @param callback Object used to relay the response of the credential creation request.
|
||||
*/
|
||||
public abstract void onCreateCredential(@NonNull CreateCredentialRequest request,
|
||||
public abstract void onBeginCreateCredential(@NonNull BeginCreateCredentialRequest request,
|
||||
@NonNull CancellationSignal cancellationSignal,
|
||||
@NonNull OutcomeReceiver<CreateCredentialResponse,
|
||||
@NonNull OutcomeReceiver<BeginCreateCredentialResponse,
|
||||
CredentialProviderException> callback);
|
||||
}
|
||||
|
||||
@@ -28,12 +28,10 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Content to be displayed on the account selector UI, including credential entries,
|
||||
* actions etc.
|
||||
*
|
||||
* @hide
|
||||
* The content to be displayed on the account selector UI, including credential entries,
|
||||
* actions etc. Returned as part of {@link GetCredentialsResponse}
|
||||
*/
|
||||
public final class CredentialsDisplayContent implements Parcelable {
|
||||
public final class CredentialsResponseContent implements Parcelable {
|
||||
/** List of credential entries to be displayed on the UI. */
|
||||
private final @NonNull List<CredentialEntry> mCredentialEntries;
|
||||
|
||||
@@ -41,36 +39,36 @@ public final class CredentialsDisplayContent implements Parcelable {
|
||||
private final @NonNull List<Action> mActions;
|
||||
|
||||
/** Remote credential entry to get the response from a different device. */
|
||||
private final @Nullable Action mRemoteCredentialEntry;
|
||||
private final @Nullable CredentialEntry mRemoteCredentialEntry;
|
||||
|
||||
private CredentialsDisplayContent(@NonNull List<CredentialEntry> credentialEntries,
|
||||
private CredentialsResponseContent(@NonNull List<CredentialEntry> credentialEntries,
|
||||
@NonNull List<Action> actions,
|
||||
@Nullable Action remoteCredentialEntry) {
|
||||
@Nullable CredentialEntry remoteCredentialEntry) {
|
||||
mCredentialEntries = credentialEntries;
|
||||
mActions = actions;
|
||||
mRemoteCredentialEntry = remoteCredentialEntry;
|
||||
}
|
||||
|
||||
private CredentialsDisplayContent(@NonNull Parcel in) {
|
||||
private CredentialsResponseContent(@NonNull Parcel in) {
|
||||
List<CredentialEntry> credentialEntries = new ArrayList<>();
|
||||
in.readTypedList(credentialEntries, CredentialEntry.CREATOR);
|
||||
mCredentialEntries = credentialEntries;
|
||||
List<Action> actions = new ArrayList<>();
|
||||
in.readTypedList(actions, Action.CREATOR);
|
||||
mActions = actions;
|
||||
mRemoteCredentialEntry = in.readTypedObject(Action.CREATOR);
|
||||
mRemoteCredentialEntry = in.readTypedObject(CredentialEntry.CREATOR);
|
||||
}
|
||||
|
||||
public static final @NonNull Creator<CredentialsDisplayContent> CREATOR =
|
||||
new Creator<CredentialsDisplayContent>() {
|
||||
public static final @NonNull Creator<CredentialsResponseContent> CREATOR =
|
||||
new Creator<CredentialsResponseContent>() {
|
||||
@Override
|
||||
public CredentialsDisplayContent createFromParcel(@NonNull Parcel in) {
|
||||
return new CredentialsDisplayContent(in);
|
||||
public CredentialsResponseContent createFromParcel(@NonNull Parcel in) {
|
||||
return new CredentialsResponseContent(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CredentialsDisplayContent[] newArray(int size) {
|
||||
return new CredentialsDisplayContent[size];
|
||||
public CredentialsResponseContent[] newArray(int size) {
|
||||
return new CredentialsResponseContent[size];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -103,22 +101,34 @@ public final class CredentialsDisplayContent implements Parcelable {
|
||||
/**
|
||||
* Returns the remote credential entry to be displayed on the UI.
|
||||
*/
|
||||
public @Nullable Action getRemoteCredentialEntry() {
|
||||
public @Nullable CredentialEntry getRemoteCredentialEntry() {
|
||||
return mRemoteCredentialEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an instance of {@link CredentialsDisplayContent}.
|
||||
* Builds an instance of {@link CredentialsResponseContent}.
|
||||
*/
|
||||
public static final class Builder {
|
||||
private List<CredentialEntry> mCredentialEntries = new ArrayList<>();
|
||||
private List<Action> mActions = new ArrayList<>();
|
||||
private Action mRemoteCredentialEntry;
|
||||
private CredentialEntry mRemoteCredentialEntry;
|
||||
|
||||
/**
|
||||
* Sets the remote credential entry to be displayed on the UI.
|
||||
* Sets a remote credential entry to be shown on the UI. Provider must set this if they
|
||||
* wish to get the credential from a different device.
|
||||
*
|
||||
* <p> When constructing the {@link CredentialEntry} object, the {@code pendingIntent}
|
||||
* must be set such that it leads to an activity that can provide UI to fulfill the request
|
||||
* on a remote device. When user selects this {@code remoteCredentialEntry}, the system will
|
||||
* invoke the {@code pendingIntent} set on the {@link CredentialEntry}.
|
||||
*
|
||||
* <p> Once the remote credential flow is complete, the {@link android.app.Activity}
|
||||
* result should be set to {@link android.app.Activity#RESULT_OK} and an extra with the
|
||||
* {@link CredentialProviderService#EXTRA_CREDENTIAL_RESULT} key should be populated
|
||||
* with a {@link android.credentials.Credential} object.
|
||||
*/
|
||||
public @NonNull Builder setRemoteCredentialEntry(@Nullable Action remoteCredentialEntry) {
|
||||
public @NonNull Builder setRemoteCredentialEntry(@Nullable CredentialEntry
|
||||
remoteCredentialEntry) {
|
||||
mRemoteCredentialEntry = remoteCredentialEntry;
|
||||
return this;
|
||||
}
|
||||
@@ -138,6 +148,11 @@ public final class CredentialsDisplayContent implements Parcelable {
|
||||
* Adds an {@link Action} to the list of actions to be displayed on
|
||||
* the UI.
|
||||
*
|
||||
* <p> An {@code action} must be used for independent user actions,
|
||||
* such as opening the app, intenting directly into a certain app activity etc. The
|
||||
* {@code pendingIntent} set with the {@code action} must invoke the corresponding
|
||||
* activity.
|
||||
*
|
||||
* @throws NullPointerException If {@code action} is null.
|
||||
*/
|
||||
public @NonNull Builder addAction(@NonNull Action action) {
|
||||
@@ -175,17 +190,16 @@ public final class CredentialsDisplayContent implements Parcelable {
|
||||
/**
|
||||
* Builds a {@link GetCredentialsResponse} instance.
|
||||
*
|
||||
* @throws NullPointerException If {@code credentialEntries} is null.
|
||||
* @throws IllegalStateException if both {@code credentialEntries} and
|
||||
* {@code actions} are empty.
|
||||
* @throws IllegalStateException if {@code credentialEntries}, {@code actions}
|
||||
* and {@code remoteCredentialEntry} are all null or empty.
|
||||
*/
|
||||
public @NonNull CredentialsDisplayContent build() {
|
||||
public @NonNull CredentialsResponseContent build() {
|
||||
if (mCredentialEntries != null && mCredentialEntries.isEmpty()
|
||||
&& mActions != null && mActions.isEmpty()) {
|
||||
&& mActions != null && mActions.isEmpty() && mRemoteCredentialEntry == null) {
|
||||
throw new IllegalStateException("credentialEntries and actions must not both "
|
||||
+ "be empty");
|
||||
}
|
||||
return new CredentialsDisplayContent(mCredentialEntries, mActions,
|
||||
return new CredentialsResponseContent(mCredentialEntries, mActions,
|
||||
mRemoteCredentialEntry);
|
||||
}
|
||||
}
|
||||
@@ -29,8 +29,6 @@ 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. */
|
||||
|
||||
@@ -26,12 +26,10 @@ 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;
|
||||
private final @Nullable CredentialsResponseContent mCredentialsResponseContent;
|
||||
|
||||
/**
|
||||
* Authentication action that must be launched and completed before showing any content
|
||||
@@ -40,11 +38,17 @@ public final class GetCredentialsResponse implements Parcelable {
|
||||
private final @Nullable Action mAuthenticationAction;
|
||||
|
||||
/**
|
||||
* Creates a {@link GetCredentialsRequest} instance with an authentication action set.
|
||||
* Creates a {@link GetCredentialsResponse} instance with an authentication {@link Action} set.
|
||||
* Providers must use this method when no content can be shown before authentication.
|
||||
*
|
||||
* Once the authentication action activity is launched, and the user is authenticated, providers
|
||||
* should create another response with {@link CredentialsDisplayContent} using
|
||||
* <p> When the user selects this {@code authenticationAction}, the system invokes the
|
||||
* corresponding {@code pendingIntent}. Once the authentication flow is complete,
|
||||
* the {@link android.app.Activity} result should be set
|
||||
* to {@link android.app.Activity#RESULT_OK} and the
|
||||
* {@link CredentialProviderService#EXTRA_GET_CREDENTIALS_CONTENT_RESULT} extra should be set
|
||||
* with a fully populated {@link CredentialsResponseContent} object.
|
||||
* the authentication action activity is launched, and the user is authenticated, providers
|
||||
* should create another response with {@link CredentialsResponseContent} using
|
||||
* {@code createWithDisplayContent}, and add that response to the result of the authentication
|
||||
* activity.
|
||||
*
|
||||
@@ -58,27 +62,27 @@ public final class GetCredentialsResponse implements Parcelable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link GetCredentialsRequest} instance with display content to be shown on the UI.
|
||||
* Creates a {@link GetCredentialsRequest} instance with content to be shown on the UI.
|
||||
* Providers must use this method when there is content to be shown without top level
|
||||
* authentication required.
|
||||
* authentication required, including credential entries, action entries or a remote entry,
|
||||
*
|
||||
* @throws NullPointerException If {@code credentialsDisplayContent} is null.
|
||||
* @throws NullPointerException If {@code credentialsResponseContent} is null.
|
||||
*/
|
||||
public static @NonNull GetCredentialsResponse createWithDisplayContent(
|
||||
@NonNull CredentialsDisplayContent credentialsDisplayContent) {
|
||||
Objects.requireNonNull(credentialsDisplayContent,
|
||||
"credentialsDisplayContent must not be null");
|
||||
return new GetCredentialsResponse(credentialsDisplayContent, null);
|
||||
public static @NonNull GetCredentialsResponse createWithResponseContent(
|
||||
@NonNull CredentialsResponseContent credentialsResponseContent) {
|
||||
Objects.requireNonNull(credentialsResponseContent,
|
||||
"credentialsResponseContent must not be null");
|
||||
return new GetCredentialsResponse(credentialsResponseContent, null);
|
||||
}
|
||||
|
||||
private GetCredentialsResponse(@Nullable CredentialsDisplayContent credentialsDisplayContent,
|
||||
private GetCredentialsResponse(@Nullable CredentialsResponseContent credentialsResponseContent,
|
||||
@Nullable Action authenticationAction) {
|
||||
mCredentialsDisplayContent = credentialsDisplayContent;
|
||||
mCredentialsResponseContent = credentialsResponseContent;
|
||||
mAuthenticationAction = authenticationAction;
|
||||
}
|
||||
|
||||
private GetCredentialsResponse(@NonNull Parcel in) {
|
||||
mCredentialsDisplayContent = in.readTypedObject(CredentialsDisplayContent.CREATOR);
|
||||
mCredentialsResponseContent = in.readTypedObject(CredentialsResponseContent.CREATOR);
|
||||
mAuthenticationAction = in.readTypedObject(Action.CREATOR);
|
||||
}
|
||||
|
||||
@@ -102,23 +106,23 @@ public final class GetCredentialsResponse implements Parcelable {
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeTypedObject(mCredentialsDisplayContent, flags);
|
||||
dest.writeTypedObject(mCredentialsResponseContent, flags);
|
||||
dest.writeTypedObject(mAuthenticationAction, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the authentication action to be invoked before any other content
|
||||
* can be shown to the user.
|
||||
* If this response represents a top level authentication action, returns the authentication
|
||||
* action to be invoked before any other content can be shown to the user.
|
||||
*/
|
||||
public @Nullable Action getAuthenticationAction() {
|
||||
return mAuthenticationAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the credentialDisplayContent that does not require authentication, and
|
||||
* can be shown to the user on the account selector UI.
|
||||
* Returns the actual content to be displayed on the selector, if this response does not
|
||||
* require any top level authentication.
|
||||
*/
|
||||
public @Nullable CredentialsDisplayContent getCredentialsDisplayContent() {
|
||||
return mCredentialsDisplayContent;
|
||||
public @Nullable CredentialsResponseContent getCredentialsResponseContent() {
|
||||
return mCredentialsResponseContent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package android.service.credentials;
|
||||
|
||||
import android.service.credentials.CreateCredentialResponse;
|
||||
import android.service.credentials.BeginCreateCredentialResponse;
|
||||
|
||||
/**
|
||||
* Interface from the system to a credential provider service.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
oneway interface ICreateCredentialCallback {
|
||||
void onSuccess(in CreateCredentialResponse request);
|
||||
oneway interface IBeginCreateCredentialCallback {
|
||||
void onSuccess(in BeginCreateCredentialResponse request);
|
||||
void onFailure(int errorCode, in CharSequence message);
|
||||
}
|
||||
@@ -18,9 +18,9 @@ package android.service.credentials;
|
||||
|
||||
import android.os.ICancellationSignal;
|
||||
import android.service.credentials.GetCredentialsRequest;
|
||||
import android.service.credentials.CreateCredentialRequest;
|
||||
import android.service.credentials.BeginCreateCredentialRequest;
|
||||
import android.service.credentials.IGetCredentialsCallback;
|
||||
import android.service.credentials.ICreateCredentialCallback;
|
||||
import android.service.credentials.IBeginCreateCredentialCallback;
|
||||
import android.os.ICancellationSignal;
|
||||
|
||||
/**
|
||||
@@ -30,5 +30,5 @@ import android.os.ICancellationSignal;
|
||||
*/
|
||||
interface ICredentialProviderService {
|
||||
ICancellationSignal onGetCredentials(in GetCredentialsRequest request, in IGetCredentialsCallback callback);
|
||||
ICancellationSignal onCreateCredential(in CreateCredentialRequest request, in ICreateCredentialCallback callback);
|
||||
ICancellationSignal onBeginCreateCredential(in BeginCreateCredentialRequest request, in IBeginCreateCredentialCallback callback);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ import android.graphics.drawable.Icon
|
||||
import android.os.Binder
|
||||
import android.os.Bundle
|
||||
import android.os.ResultReceiver
|
||||
import android.service.credentials.CredentialProviderService
|
||||
import com.android.credentialmanager.createflow.ActiveEntry
|
||||
import com.android.credentialmanager.createflow.CreateCredentialUiState
|
||||
import com.android.credentialmanager.createflow.CreateScreenState
|
||||
@@ -390,11 +391,12 @@ class CredentialManagerRepo(
|
||||
intent, (PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
||||
or PendingIntent.FLAG_ONE_SHOT))
|
||||
val createPasswordRequest = android.service.credentials.CreateCredentialRequest(
|
||||
context.applicationInfo.packageName,
|
||||
"PASSWORD",
|
||||
toBundle("beckett-bakert@gmail.com", "password123")
|
||||
context.applicationInfo.packageName,
|
||||
TYPE_PASSWORD_CREDENTIAL,
|
||||
toBundle("beckett-bakert@gmail.com", "password123")
|
||||
)
|
||||
val fillInIntent = Intent().putExtra("create_request_params", createPasswordRequest)
|
||||
val fillInIntent = Intent().putExtra(CredentialProviderService.EXTRA_CREATE_CREDENTIAL_REQUEST,
|
||||
createPasswordRequest)
|
||||
|
||||
val slice = Slice.Builder(
|
||||
Entry.CREDENTIAL_MANAGER_ENTRY_URI, SliceSpec(Entry.VERSION, 1)
|
||||
|
||||
@@ -35,6 +35,7 @@ import android.os.CancellationSignal;
|
||||
import android.os.ICancellationSignal;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.service.credentials.BeginCreateCredentialRequest;
|
||||
import android.service.credentials.GetCredentialsRequest;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
@@ -199,7 +200,7 @@ public final class CredentialManagerService extends
|
||||
// Iterate over all provider sessions and invoke the request
|
||||
providerSessions.forEach(providerCreateSession -> {
|
||||
providerCreateSession.getRemoteCredentialService().onCreateCredential(
|
||||
(android.service.credentials.CreateCredentialRequest)
|
||||
(BeginCreateCredentialRequest)
|
||||
providerCreateSession.getProviderRequest(),
|
||||
/*callback=*/providerCreateSession);
|
||||
});
|
||||
|
||||
@@ -22,7 +22,7 @@ import android.credentials.CreateCredentialResponse;
|
||||
import android.credentials.Credential;
|
||||
import android.credentials.ui.ProviderPendingIntentResponse;
|
||||
import android.service.credentials.CredentialProviderService;
|
||||
import android.service.credentials.CredentialsDisplayContent;
|
||||
import android.service.credentials.CredentialsResponseContent;
|
||||
|
||||
/**
|
||||
* Helper class for setting up pending intent, and extracting objects from it.
|
||||
@@ -37,14 +37,15 @@ public class PendingIntentResultHandler {
|
||||
return pendingIntentResponse.getResultCode() == Activity.RESULT_OK;
|
||||
}
|
||||
|
||||
/** Extracts the {@link CredentialsDisplayContent} object added to the result data. */
|
||||
public static CredentialsDisplayContent extractCredentialsDisplayContent(Intent resultData) {
|
||||
/** Extracts the {@link CredentialsResponseContent} object added to the result data. */
|
||||
public static CredentialsResponseContent extractResponseContent(Intent resultData) {
|
||||
if (resultData == null) {
|
||||
return null;
|
||||
}
|
||||
return resultData.getParcelableExtra(
|
||||
CredentialProviderService.EXTRA_GET_CREDENTIALS_DISPLAY_CONTENT,
|
||||
CredentialsDisplayContent.class);
|
||||
CredentialProviderService
|
||||
.EXTRA_GET_CREDENTIALS_CONTENT_RESULT,
|
||||
CredentialsResponseContent.class);
|
||||
}
|
||||
|
||||
/** Extracts the {@link CreateCredentialResponse} object added to the result data. */
|
||||
@@ -53,7 +54,7 @@ public class PendingIntentResultHandler {
|
||||
return null;
|
||||
}
|
||||
return resultData.getParcelableExtra(
|
||||
CredentialProviderService.EXTRA_CREATE_CREDENTIAL_RESPONSE,
|
||||
CredentialProviderService.EXTRA_CREATE_CREDENTIAL_RESULT,
|
||||
CreateCredentialResponse.class);
|
||||
}
|
||||
|
||||
@@ -63,7 +64,7 @@ public class PendingIntentResultHandler {
|
||||
return null;
|
||||
}
|
||||
return resultData.getParcelableExtra(
|
||||
CredentialProviderService.EXTRA_GET_CREDENTIAL,
|
||||
CredentialProviderService.EXTRA_CREDENTIAL_RESULT,
|
||||
Credential.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,11 +26,11 @@ import android.credentials.ui.CreateCredentialProviderData;
|
||||
import android.credentials.ui.Entry;
|
||||
import android.credentials.ui.ProviderPendingIntentResponse;
|
||||
import android.os.Bundle;
|
||||
import android.service.credentials.CreateCredentialRequest;
|
||||
import android.service.credentials.CreateCredentialResponse;
|
||||
import android.service.credentials.BeginCreateCredentialRequest;
|
||||
import android.service.credentials.BeginCreateCredentialResponse;
|
||||
import android.service.credentials.CreateEntry;
|
||||
import android.service.credentials.CredentialProviderInfo;
|
||||
import android.service.credentials.CredentialProviderService;
|
||||
import android.service.credentials.SaveEntry;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
|
||||
@@ -44,16 +44,16 @@ import java.util.Map;
|
||||
* Will likely split this into remote response state and UI state.
|
||||
*/
|
||||
public final class ProviderCreateSession extends ProviderSession<
|
||||
CreateCredentialRequest, CreateCredentialResponse> {
|
||||
BeginCreateCredentialRequest, BeginCreateCredentialResponse> {
|
||||
private static final String TAG = "ProviderCreateSession";
|
||||
|
||||
// Key to be used as an entry key for a save entry
|
||||
private static final String SAVE_ENTRY_KEY = "save_entry_key";
|
||||
|
||||
@NonNull
|
||||
private final Map<String, SaveEntry> mUiSaveEntries = new HashMap<>();
|
||||
private final Map<String, CreateEntry> mUiSaveEntries = new HashMap<>();
|
||||
/** The complete request to be used in the second round. */
|
||||
private final CreateCredentialRequest mCompleteRequest;
|
||||
private final BeginCreateCredentialRequest mCompleteRequest;
|
||||
|
||||
/** Creates a new provider session to be used by the request session. */
|
||||
@Nullable public static ProviderCreateSession createNewSession(
|
||||
@@ -62,7 +62,7 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
CredentialProviderInfo providerInfo,
|
||||
CreateRequestSession createRequestSession,
|
||||
RemoteCredentialService remoteCredentialService) {
|
||||
CreateCredentialRequest providerRequest =
|
||||
BeginCreateCredentialRequest providerRequest =
|
||||
createProviderRequest(providerInfo.getCapabilities(),
|
||||
createRequestSession.mClientRequest,
|
||||
createRequestSession.mClientCallingPackage);
|
||||
@@ -75,21 +75,23 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static CreateCredentialRequest createProviderRequest(List<String> providerCapabilities,
|
||||
private static BeginCreateCredentialRequest createProviderRequest(
|
||||
List<String> providerCapabilities,
|
||||
android.credentials.CreateCredentialRequest clientRequest,
|
||||
String clientCallingPackage) {
|
||||
String capability = clientRequest.getType();
|
||||
if (providerCapabilities.contains(capability)) {
|
||||
return new CreateCredentialRequest(clientCallingPackage, capability,
|
||||
return new BeginCreateCredentialRequest(clientCallingPackage, capability,
|
||||
clientRequest.getData());
|
||||
}
|
||||
Log.i(TAG, "Unable to create provider request - capabilities do not match");
|
||||
return null;
|
||||
}
|
||||
|
||||
private static CreateCredentialRequest getFirstRoundRequest(CreateCredentialRequest request) {
|
||||
private static BeginCreateCredentialRequest getFirstRoundRequest(
|
||||
BeginCreateCredentialRequest request) {
|
||||
// TODO: Replace with first round bundle from request when ready
|
||||
return new CreateCredentialRequest(
|
||||
return new BeginCreateCredentialRequest(
|
||||
request.getCallingPackage(),
|
||||
request.getType(),
|
||||
new Bundle());
|
||||
@@ -101,7 +103,7 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
@NonNull ProviderInternalCallback callbacks,
|
||||
@UserIdInt int userId,
|
||||
@NonNull RemoteCredentialService remoteCredentialService,
|
||||
@NonNull CreateCredentialRequest request) {
|
||||
@NonNull BeginCreateCredentialRequest request) {
|
||||
super(context, info, getFirstRoundRequest(request), callbacks, userId,
|
||||
remoteCredentialService);
|
||||
// TODO : Replace with proper splitting of request
|
||||
@@ -110,13 +112,13 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
}
|
||||
|
||||
/** Returns the save entry maintained in state by this provider session. */
|
||||
public SaveEntry getUiSaveEntry(String entryId) {
|
||||
public CreateEntry getUiSaveEntry(String entryId) {
|
||||
return mUiSaveEntries.get(entryId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderResponseSuccess(
|
||||
@Nullable CreateCredentialResponse response) {
|
||||
@Nullable BeginCreateCredentialResponse response) {
|
||||
Log.i(TAG, "in onProviderResponseSuccess");
|
||||
onUpdateResponse(response);
|
||||
}
|
||||
@@ -138,7 +140,7 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
}
|
||||
}
|
||||
|
||||
private void onUpdateResponse(CreateCredentialResponse response) {
|
||||
private void onUpdateResponse(BeginCreateCredentialResponse response) {
|
||||
Log.i(TAG, "updateResponse with save entries");
|
||||
mProviderResponse = response;
|
||||
updateStatusAndInvokeCallback(Status.SAVE_ENTRIES_RECEIVED);
|
||||
@@ -152,15 +154,15 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
Log.i(TAG, "In prepareUiData not in uiInvokingStatus");
|
||||
return null;
|
||||
}
|
||||
final CreateCredentialResponse response = getProviderResponse();
|
||||
final BeginCreateCredentialResponse response = getProviderResponse();
|
||||
if (response == null) {
|
||||
Log.i(TAG, "In prepareUiData response null");
|
||||
throw new IllegalStateException("Response must be in completion mode");
|
||||
}
|
||||
if (response.getSaveEntries() != null) {
|
||||
if (response.getCreateEntries() != null) {
|
||||
Log.i(TAG, "In prepareUiData save entries not null");
|
||||
return prepareUiProviderData(
|
||||
prepareUiSaveEntries(response.getSaveEntries()),
|
||||
prepareUiSaveEntries(response.getCreateEntries()),
|
||||
null,
|
||||
/*isDefaultProvider=*/false);
|
||||
}
|
||||
@@ -192,24 +194,25 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
}
|
||||
}
|
||||
|
||||
private List<Entry> prepareUiSaveEntries(@NonNull List<SaveEntry> saveEntries) {
|
||||
private List<Entry> prepareUiSaveEntries(@NonNull List<CreateEntry> saveEntries) {
|
||||
Log.i(TAG, "in populateUiSaveEntries");
|
||||
List<Entry> uiSaveEntries = new ArrayList<>();
|
||||
|
||||
// Populate the save entries
|
||||
for (SaveEntry saveEntry : saveEntries) {
|
||||
for (CreateEntry createEntry : saveEntries) {
|
||||
String entryId = generateEntryId();
|
||||
mUiSaveEntries.put(entryId, saveEntry);
|
||||
mUiSaveEntries.put(entryId, createEntry);
|
||||
Log.i(TAG, "in prepareUiProviderData creating ui entry with id " + entryId);
|
||||
uiSaveEntries.add(new Entry(SAVE_ENTRY_KEY, entryId, saveEntry.getSlice(),
|
||||
saveEntry.getPendingIntent(), setUpFillInIntent(saveEntry.getPendingIntent())));
|
||||
uiSaveEntries.add(new Entry(SAVE_ENTRY_KEY, entryId, createEntry.getSlice(),
|
||||
createEntry.getPendingIntent(), setUpFillInIntent(
|
||||
createEntry.getPendingIntent())));
|
||||
}
|
||||
return uiSaveEntries;
|
||||
}
|
||||
|
||||
private Intent setUpFillInIntent(PendingIntent pendingIntent) {
|
||||
Intent intent = pendingIntent.getIntent();
|
||||
intent.putExtra(CredentialProviderService.EXTRA_CREATE_CREDENTIAL_REQUEST_PARAMS,
|
||||
intent.putExtra(CredentialProviderService.EXTRA_CREATE_CREDENTIAL_REQUEST,
|
||||
mCompleteRequest);
|
||||
return intent;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import android.credentials.ui.ProviderPendingIntentResponse;
|
||||
import android.service.credentials.Action;
|
||||
import android.service.credentials.CredentialEntry;
|
||||
import android.service.credentials.CredentialProviderInfo;
|
||||
import android.service.credentials.CredentialsDisplayContent;
|
||||
import android.service.credentials.CredentialsResponseContent;
|
||||
import android.service.credentials.GetCredentialsRequest;
|
||||
import android.service.credentials.GetCredentialsResponse;
|
||||
import android.util.Log;
|
||||
@@ -211,20 +211,20 @@ public final class ProviderGetSession extends ProviderSession<GetCredentialsRequ
|
||||
prepareUiAuthenticationAction(mProviderResponse.getAuthenticationAction()),
|
||||
/*remoteEntry=*/null);
|
||||
}
|
||||
if (mProviderResponse.getCredentialsDisplayContent() != null) {
|
||||
Log.i(TAG, "In prepareUiData displayContent not null");
|
||||
if (mProviderResponse.getCredentialsResponseContent() != null) {
|
||||
Log.i(TAG, "In prepareUiData credentialsResponseContent not null");
|
||||
return prepareUiProviderData(prepareUiActionEntries(
|
||||
mProviderResponse.getCredentialsDisplayContent().getActions()),
|
||||
prepareUiCredentialEntries(mProviderResponse.getCredentialsDisplayContent()
|
||||
mProviderResponse.getCredentialsResponseContent().getActions()),
|
||||
prepareUiCredentialEntries(mProviderResponse.getCredentialsResponseContent()
|
||||
.getCredentialEntries()),
|
||||
/*authenticationAction=*/null,
|
||||
prepareUiRemoteEntry(mProviderResponse
|
||||
.getCredentialsDisplayContent().getRemoteCredentialEntry()));
|
||||
.getCredentialsResponseContent().getRemoteCredentialEntry()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Entry prepareUiRemoteEntry(Action remoteCredentialEntry) {
|
||||
private Entry prepareUiRemoteEntry(CredentialEntry remoteCredentialEntry) {
|
||||
if (remoteCredentialEntry == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -316,11 +316,11 @@ public final class ProviderGetSession extends ProviderSession<GetCredentialsRequ
|
||||
@Nullable ProviderPendingIntentResponse providerPendingIntentResponse) {
|
||||
if (providerPendingIntentResponse != null) {
|
||||
if (PendingIntentResultHandler.isSuccessfulResponse(providerPendingIntentResponse)) {
|
||||
CredentialsDisplayContent content = PendingIntentResultHandler
|
||||
.extractCredentialsDisplayContent(providerPendingIntentResponse
|
||||
CredentialsResponseContent content = PendingIntentResultHandler
|
||||
.extractResponseContent(providerPendingIntentResponse
|
||||
.getResultData());
|
||||
if (content != null) {
|
||||
onUpdateResponse(GetCredentialsResponse.createWithDisplayContent(content));
|
||||
onUpdateResponse(GetCredentialsResponse.createWithResponseContent(content));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -342,7 +342,7 @@ public final class ProviderGetSession extends ProviderSession<GetCredentialsRequ
|
||||
if (response.getAuthenticationAction() != null) {
|
||||
Log.i(TAG , "updateResponse with authentication entry");
|
||||
updateStatusAndInvokeCallback(Status.REQUIRES_AUTHENTICATION);
|
||||
} else if (response.getCredentialsDisplayContent() != null) {
|
||||
} else if (response.getCredentialsResponseContent() != null) {
|
||||
Log.i(TAG , "updateResponse with credentialEntries");
|
||||
// TODO validate response
|
||||
updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
|
||||
|
||||
@@ -23,7 +23,7 @@ import android.content.Context;
|
||||
import android.credentials.Credential;
|
||||
import android.credentials.ui.ProviderData;
|
||||
import android.credentials.ui.ProviderPendingIntentResponse;
|
||||
import android.service.credentials.Action;
|
||||
import android.service.credentials.CredentialEntry;
|
||||
import android.service.credentials.CredentialProviderException;
|
||||
import android.service.credentials.CredentialProviderInfo;
|
||||
import android.util.Pair;
|
||||
@@ -50,7 +50,7 @@ public abstract class ProviderSession<T, R>
|
||||
@Nullable protected Credential mFinalCredentialResponse;
|
||||
@NonNull protected final T mProviderRequest;
|
||||
@Nullable protected R mProviderResponse;
|
||||
@Nullable protected Pair<String, Action> mUiRemoteEntry;
|
||||
@Nullable protected Pair<String, CredentialEntry> mUiRemoteEntry;
|
||||
|
||||
/**
|
||||
* Returns true if the given status reflects that the provider state is ready to be shown
|
||||
|
||||
@@ -24,14 +24,14 @@ import android.content.Intent;
|
||||
import android.os.Handler;
|
||||
import android.os.ICancellationSignal;
|
||||
import android.os.RemoteException;
|
||||
import android.service.credentials.CreateCredentialRequest;
|
||||
import android.service.credentials.CreateCredentialResponse;
|
||||
import android.service.credentials.BeginCreateCredentialRequest;
|
||||
import android.service.credentials.BeginCreateCredentialResponse;
|
||||
import android.service.credentials.CredentialProviderException;
|
||||
import android.service.credentials.CredentialProviderException.CredentialProviderError;
|
||||
import android.service.credentials.CredentialProviderService;
|
||||
import android.service.credentials.GetCredentialsRequest;
|
||||
import android.service.credentials.GetCredentialsResponse;
|
||||
import android.service.credentials.ICreateCredentialCallback;
|
||||
import android.service.credentials.IBeginCreateCredentialCallback;
|
||||
import android.service.credentials.ICredentialProviderService;
|
||||
import android.service.credentials.IGetCredentialsCallback;
|
||||
import android.text.format.DateUtils;
|
||||
@@ -146,27 +146,27 @@ public class RemoteCredentialService extends ServiceConnector.Impl<ICredentialPr
|
||||
handleExecutionResponse(result, error, cancellationSink, callback)));
|
||||
}
|
||||
|
||||
/** Main entry point to be called for executing a createCredential call on the remote
|
||||
/** Main entry point to be called for executing a beginCreateCredential call on the remote
|
||||
* provider service.
|
||||
* @param request the request to be sent to the provider
|
||||
* @param callback the callback to be used to send back the provider response to the
|
||||
* {@link ProviderCreateSession} class that maintains provider state
|
||||
*/
|
||||
public void onCreateCredential(@NonNull CreateCredentialRequest request,
|
||||
ProviderCallbacks<CreateCredentialResponse> callback) {
|
||||
public void onCreateCredential(@NonNull BeginCreateCredentialRequest request,
|
||||
ProviderCallbacks<BeginCreateCredentialResponse> callback) {
|
||||
Log.i(TAG, "In onCreateCredential in RemoteCredentialService");
|
||||
AtomicReference<ICancellationSignal> cancellationSink = new AtomicReference<>();
|
||||
AtomicReference<CompletableFuture<CreateCredentialResponse>> futureRef =
|
||||
AtomicReference<CompletableFuture<BeginCreateCredentialResponse>> futureRef =
|
||||
new AtomicReference<>();
|
||||
|
||||
CompletableFuture<CreateCredentialResponse> connectThenExecute = postAsync(service -> {
|
||||
CompletableFuture<CreateCredentialResponse> createCredentialFuture =
|
||||
CompletableFuture<BeginCreateCredentialResponse> connectThenExecute = postAsync(service -> {
|
||||
CompletableFuture<BeginCreateCredentialResponse> createCredentialFuture =
|
||||
new CompletableFuture<>();
|
||||
ICancellationSignal cancellationSignal = service.onCreateCredential(
|
||||
request, new ICreateCredentialCallback.Stub() {
|
||||
ICancellationSignal cancellationSignal = service.onBeginCreateCredential(
|
||||
request, new IBeginCreateCredentialCallback.Stub() {
|
||||
@Override
|
||||
public void onSuccess(CreateCredentialResponse response) {
|
||||
Log.i(TAG, "In onSuccess onCreateCredential "
|
||||
public void onSuccess(BeginCreateCredentialResponse response) {
|
||||
Log.i(TAG, "In onSuccess onBeginCreateCredential "
|
||||
+ "in RemoteCredentialService");
|
||||
createCredentialFuture.complete(response);
|
||||
}
|
||||
@@ -179,7 +179,7 @@ public class RemoteCredentialService extends ServiceConnector.Impl<ICredentialPr
|
||||
createCredentialFuture.completeExceptionally(
|
||||
new CredentialProviderException(errorCode, errorMsg));
|
||||
}});
|
||||
CompletableFuture<CreateCredentialResponse> future = futureRef.get();
|
||||
CompletableFuture<BeginCreateCredentialResponse> future = futureRef.get();
|
||||
if (future != null && future.isCancelled()) {
|
||||
dispatchCancellationSignal(cancellationSignal);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user