Merge "Framework credential manager developer APIs definitions."

This commit is contained in:
Helen Qin
2022-10-03 17:33:24 +00:00
committed by Android (Google) Code Review
19 changed files with 1180 additions and 6 deletions

View File

@@ -9820,6 +9820,7 @@ package android.content {
field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2
field public static final int CONTEXT_INCLUDE_CODE = 1; // 0x1
field public static final int CONTEXT_RESTRICTED = 4; // 0x4
field public static final String CREDENTIAL_SERVICE = "credential";
field public static final String CROSS_PROFILE_APPS_SERVICE = "crossprofileapps";
field public static final String DEVICE_POLICY_SERVICE = "device_policy";
field public static final String DISPLAY_HASH_SERVICE = "display_hash";
@@ -12879,6 +12880,82 @@ package android.content.res.loader {
}
package android.credentials {
public final class CreateCredentialRequest implements android.os.Parcelable {
ctor public CreateCredentialRequest(@NonNull String, @NonNull android.os.Bundle);
method public int describeContents();
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.credentials.CreateCredentialRequest> CREATOR;
}
public final class CreateCredentialResponse implements android.os.Parcelable {
ctor public CreateCredentialResponse(@NonNull android.os.Bundle);
method public int describeContents();
method @NonNull public android.os.Bundle getData();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.credentials.CreateCredentialResponse> CREATOR;
}
public final class Credential implements android.os.Parcelable {
ctor public Credential(@NonNull String, @NonNull android.os.Bundle);
method public int describeContents();
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.credentials.Credential> CREATOR;
}
public final class CredentialManager {
method public void executeCreateCredential(@NonNull android.credentials.CreateCredentialRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.credentials.CreateCredentialResponse,android.credentials.CredentialManagerException>);
method public void executeGetCredential(@NonNull android.credentials.GetCredentialRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.credentials.GetCredentialResponse,android.credentials.CredentialManagerException>);
}
public class CredentialManagerException extends java.lang.Exception {
ctor public CredentialManagerException(int, @Nullable String);
ctor public CredentialManagerException(int, @Nullable String, @Nullable Throwable);
ctor public CredentialManagerException(int, @Nullable Throwable);
ctor public CredentialManagerException(int);
field public static final int ERROR_UNKNOWN = 0; // 0x0
field public final int errorCode;
}
public final class GetCredentialOption implements android.os.Parcelable {
ctor public GetCredentialOption(@NonNull String, @NonNull android.os.Bundle);
method public int describeContents();
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.credentials.GetCredentialOption> CREATOR;
}
public final class GetCredentialRequest implements android.os.Parcelable {
method public int describeContents();
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.credentials.GetCredentialRequest> CREATOR;
}
public static final class GetCredentialRequest.Builder {
ctor public GetCredentialRequest.Builder();
method @NonNull public android.credentials.GetCredentialRequest.Builder addGetCredentialOption(@NonNull android.credentials.GetCredentialOption);
method @NonNull public android.credentials.GetCredentialRequest build();
method @NonNull public android.credentials.GetCredentialRequest.Builder setGetCredentialOptions(@NonNull java.util.List<android.credentials.GetCredentialOption>);
}
public final class GetCredentialResponse implements android.os.Parcelable {
ctor public GetCredentialResponse(@NonNull android.credentials.Credential);
ctor public GetCredentialResponse();
method public int describeContents();
method @Nullable public android.credentials.Credential getCredential();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.credentials.GetCredentialResponse> CREATOR;
}
}
package android.database {
public abstract class AbstractCursor implements android.database.CrossProcessCursor {

View File

@@ -57,6 +57,7 @@ import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.credentials.CredentialManager;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
@@ -3933,6 +3934,7 @@ public abstract class Context {
//@hide: ATTESTATION_VERIFICATION_SERVICE,
//@hide: SAFETY_CENTER_SERVICE,
DISPLAY_HASH_SERVICE,
CREDENTIAL_SERVICE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ServiceName {}
@@ -6058,6 +6060,15 @@ public abstract class Context {
*/
public static final String HEALTHCONNECT_SERVICE = "healthconnect";
/**
* Use with {@link #getSystemService(String)} to retrieve a
* {@link android.credentials.CredentialManager} to authenticate a user to your app.
*
* @see #getSystemService(String)
* @see CredentialManager
*/
public static final String CREDENTIAL_SERVICE = "credential";
/**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.

View File

@@ -0,0 +1,19 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.credentials;
parcelable CreateCredentialRequest;

View File

@@ -0,0 +1,114 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.credentials;
import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.util.AnnotationValidations;
import com.android.internal.util.Preconditions;
/**
* A request to register a specific type of user credential, potentially launching UI flows to
* collect user consent and any other operation needed.
*/
public final class CreateCredentialRequest implements Parcelable {
/**
* The requested credential type.
*/
@NonNull
private final String mType;
/**
* The request data.
*/
@NonNull
private final Bundle mData;
/**
* Returns the requested credential type.
*/
@NonNull
public String getType() {
return mType;
}
/**
* Returns the request data.
*/
@NonNull
public Bundle getData() {
return mData;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString8(mType);
dest.writeBundle(mData);
}
@Override
public int describeContents() {
return 0;
}
@Override
public String toString() {
return "CreateCredentialRequest {" + "type=" + mType + ", data=" + mData + "}";
}
/**
* Constructs a {@link CreateCredentialRequest}.
*
* @param type the requested credential type.
* @param data the request data.
*
* @throws IllegalArgumentException If type is empty.
*/
public CreateCredentialRequest(@NonNull String type, @NonNull Bundle data) {
mType = Preconditions.checkStringNotEmpty(type, "type must not be empty");
mData = requireNonNull(data, "data must not be null");
}
private CreateCredentialRequest(@NonNull Parcel in) {
String type = in.readString8();
Bundle data = in.readBundle();
mType = type;
AnnotationValidations.validate(NonNull.class, null, mType);
mData = data;
AnnotationValidations.validate(NonNull.class, null, mData);
}
public static final @NonNull Parcelable.Creator<CreateCredentialRequest> CREATOR =
new Parcelable.Creator<CreateCredentialRequest>() {
@Override
public CreateCredentialRequest[] newArray(int size) {
return new CreateCredentialRequest[size];
}
@Override
public CreateCredentialRequest createFromParcel(@NonNull Parcel in) {
return new CreateCredentialRequest(in);
}
};
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.credentials;
parcelable CreateCredentialResponse;

View File

@@ -0,0 +1,89 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.credentials;
import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.util.AnnotationValidations;
/**
* A response object that encapsulates the result of a successful credential creation execution.
*/
public final class CreateCredentialResponse implements Parcelable {
/**
* The response data.
*/
@NonNull
private final Bundle mData;
/**
* Returns the response data.
*/
@NonNull
public Bundle getData() {
return mData;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeBundle(mData);
}
@Override
public int describeContents() {
return 0;
}
@Override
public String toString() {
return "CreateCredentialResponse {data=" + mData + "}";
}
/**
* Constructs a {@link CreateCredentialResponse}.
*
* @param data the data associated with the credential created.
*/
public CreateCredentialResponse(@NonNull Bundle data) {
mData = requireNonNull(data, "data must not be null");
}
private CreateCredentialResponse(@NonNull Parcel in) {
Bundle data = in.readBundle();
mData = data;
AnnotationValidations.validate(NonNull.class, null, mData);
}
public static final @NonNull Parcelable.Creator<CreateCredentialResponse> CREATOR =
new Parcelable.Creator<CreateCredentialResponse>() {
@Override
public CreateCredentialResponse[] newArray(int size) {
return new CreateCredentialResponse[size];
}
@Override
public CreateCredentialResponse createFromParcel(@NonNull Parcel in) {
return new CreateCredentialResponse(in);
}
};
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.credentials;
import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.util.AnnotationValidations;
import com.android.internal.util.Preconditions;
/**
* Represents a user credential that can be used to authenticate to your app.
*/
public final class Credential implements Parcelable {
/**
* The credential type.
*/
@NonNull
private final String mType;
/**
* The credential data.
*/
@NonNull
private final Bundle mData;
/**
* Returns the credential type.
*/
@NonNull
public String getType() {
return mType;
}
/**
* Returns the credential data.
*/
@NonNull
public Bundle getData() {
return mData;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString8(mType);
dest.writeBundle(mData);
}
@Override
public int describeContents() {
return 0;
}
@Override
public String toString() {
return "Credential {" + "type=" + mType + ", data=" + mData + "}";
}
/**
* Constructs a {@link Credential}.
*
* @param type the type of the credential returned.
* @param data the data associated with the credential returned.
*
* @throws IllegalArgumentException If type is empty.
*/
public Credential(@NonNull String type, @NonNull Bundle data) {
mType = Preconditions.checkStringNotEmpty(type, "type must not be empty");
mData = requireNonNull(data, "data must not be null");
}
private Credential(@NonNull Parcel in) {
String type = in.readString8();
Bundle data = in.readBundle();
mType = type;
AnnotationValidations.validate(NonNull.class, null, mType);
mData = data;
AnnotationValidations.validate(NonNull.class, null, mData);
}
public static final @NonNull Parcelable.Creator<Credential> CREATOR =
new Parcelable.Creator<Credential>() {
@Override
public Credential[] newArray(int size) {
return new Credential[size];
}
@Override
public Credential createFromParcel(@NonNull Parcel in) {
return new Credential(in);
}
};
}

View File

@@ -0,0 +1,186 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.credentials;
import static java.util.Objects.requireNonNull;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
import android.content.Context;
import android.os.CancellationSignal;
import android.os.ICancellationSignal;
import android.os.OutcomeReceiver;
import android.os.RemoteException;
import android.util.Log;
import java.util.concurrent.Executor;
/**
* Manages user authentication flows.
*
* <p>Note that an application should call the Jetpack CredentialManager apis instead of directly
* calling these framework apis.
*
* <p>The CredentialManager apis launch framework UI flows for a user to
* register a new credential or to consent to a saved credential from supported credential
* providers, which can then be used to authenticate to the app.
*/
@SystemService(Context.CREDENTIAL_SERVICE)
public final class CredentialManager {
private static final String TAG = "CredentialManager";
private final Context mContext;
private final ICredentialManager mService;
/**
* @hide instantiated by ContextImpl.
*/
public CredentialManager(Context context, ICredentialManager service) {
mContext = context;
mService = service;
}
/**
* Launches the necessary flows to retrieve an app credential from the user.
*
* <p>The execution can potentially launch UI flows to collect user consent to using a
* credential, display a picker when multiple credentials exist, etc.
*
* @param request the request specifying type(s) of credentials to get from the user.
* @param cancellationSignal an optional signal that allows for cancelling this call.
* @param executor the callback will take place on this {@link Executor}.
* @param callback the callback invoked when the request succeeds or fails.
*/
public void executeGetCredential(
@NonNull GetCredentialRequest request,
@Nullable CancellationSignal cancellationSignal,
@CallbackExecutor @NonNull Executor executor,
@NonNull OutcomeReceiver<
GetCredentialResponse, CredentialManagerException> callback) {
requireNonNull(request, "request must not be null");
requireNonNull(executor, "executor must not be null");
requireNonNull(callback, "callback must not be null");
if (cancellationSignal != null && cancellationSignal.isCanceled()) {
Log.w(TAG, "executeGetCredential already canceled");
return;
}
ICancellationSignal cancelRemote = null;
try {
cancelRemote = mService.executeGetCredential(request,
new GetCredentialTransport(executor, callback));
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
if (cancellationSignal != null && cancelRemote != null) {
cancellationSignal.setRemote(cancelRemote);
}
}
/**
* Launches the necessary flows to register an app credential for the user.
*
* <p>The execution can potentially launch UI flows to collect user consent to creating
* or storing the new credential, etc.
*
* @param request the request specifying type(s) of credentials to get from the user.
* @param cancellationSignal an optional signal that allows for cancelling this call.
* @param executor the callback will take place on this {@link Executor}.
* @param callback the callback invoked when the request succeeds or fails.
*/
public void executeCreateCredential(
@NonNull CreateCredentialRequest request,
@Nullable CancellationSignal cancellationSignal,
@CallbackExecutor @NonNull Executor executor,
@NonNull OutcomeReceiver<
CreateCredentialResponse, CredentialManagerException> callback) {
requireNonNull(request, "request must not be null");
requireNonNull(executor, "executor must not be null");
requireNonNull(callback, "callback must not be null");
if (cancellationSignal != null && cancellationSignal.isCanceled()) {
Log.w(TAG, "executeCreateCredential already canceled");
return;
}
ICancellationSignal cancelRemote = null;
try {
cancelRemote = mService.executeCreateCredential(request,
new CreateCredentialTransport(executor, callback));
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
if (cancellationSignal != null && cancelRemote != null) {
cancellationSignal.setRemote(cancelRemote);
}
}
private static class GetCredentialTransport extends IGetCredentialCallback.Stub {
// TODO: listen for cancellation to release callback.
private final Executor mExecutor;
private final OutcomeReceiver<
GetCredentialResponse, CredentialManagerException> mCallback;
private GetCredentialTransport(Executor executor,
OutcomeReceiver<GetCredentialResponse, CredentialManagerException> callback) {
mExecutor = executor;
mCallback = callback;
}
@Override
public void onResponse(GetCredentialResponse response) {
mExecutor.execute(() -> mCallback.onResult(response));
}
@Override
public void onError(int errorCode, String message) {
mExecutor.execute(
() -> mCallback.onError(new CredentialManagerException(errorCode, message)));
}
}
private static class CreateCredentialTransport extends ICreateCredentialCallback.Stub {
// TODO: listen for cancellation to release callback.
private final Executor mExecutor;
private final OutcomeReceiver<
CreateCredentialResponse, CredentialManagerException> mCallback;
private CreateCredentialTransport(Executor executor,
OutcomeReceiver<CreateCredentialResponse, CredentialManagerException> callback) {
mExecutor = executor;
mCallback = callback;
}
@Override
public void onResponse(CreateCredentialResponse response) {
mExecutor.execute(() -> mCallback.onResult(response));
}
@Override
public void onError(int errorCode, String message) {
mExecutor.execute(
() -> mCallback.onError(new CredentialManagerException(errorCode, message)));
}
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.credentials;
import android.annotation.Nullable;
/** Exception class for CredentialManager operations. */
public class CredentialManagerException extends Exception {
/** Indicates that an unknown error was encountered. */
public static final int ERROR_UNKNOWN = 0;
public final int errorCode;
public CredentialManagerException(int errorCode, @Nullable String message) {
super(message);
this.errorCode = errorCode;
}
public CredentialManagerException(
int errorCode, @Nullable String message, @Nullable Throwable cause) {
super(message, cause);
this.errorCode = errorCode;
}
public CredentialManagerException(int errorCode, @Nullable Throwable cause) {
super(cause);
this.errorCode = errorCode;
}
public CredentialManagerException(int errorCode) {
super();
this.errorCode = errorCode;
}
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.credentials;
import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.util.AnnotationValidations;
import com.android.internal.util.Preconditions;
/**
* A specific type of credential request.
*/
public final class GetCredentialOption implements Parcelable {
/**
* The requested credential type.
*/
@NonNull
private final String mType;
/**
* The request data.
*/
@NonNull
private final Bundle mData;
/**
* Returns the requested credential type.
*/
@NonNull
public String getType() {
return mType;
}
/**
* Returns the request data.
*/
@NonNull
public Bundle getData() {
return mData;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString8(mType);
dest.writeBundle(mData);
}
@Override
public int describeContents() {
return 0;
}
@Override
public String toString() {
return "GetCredentialOption {" + "type=" + mType + ", data=" + mData + "}";
}
/**
* Constructs a {@link GetCredentialOption}.
*
* @param type the requested credential type.
* @param data the request data.
*
* @throws IllegalArgumentException If type is empty.
*/
public GetCredentialOption(@NonNull String type, @NonNull Bundle data) {
mType = Preconditions.checkStringNotEmpty(type, "type must not be empty");
mData = requireNonNull(data, "data must not be null");
}
private GetCredentialOption(@NonNull Parcel in) {
String type = in.readString8();
Bundle data = in.readBundle();
mType = type;
AnnotationValidations.validate(NonNull.class, null, mType);
mData = data;
AnnotationValidations.validate(NonNull.class, null, mData);
}
public static final @NonNull Parcelable.Creator<GetCredentialOption> CREATOR =
new Parcelable.Creator<GetCredentialOption>() {
@Override
public GetCredentialOption[] newArray(int size) {
return new GetCredentialOption[size];
}
@Override
public GetCredentialOption createFromParcel(@NonNull Parcel in) {
return new GetCredentialOption(in);
}
};
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.credentials;
parcelable GetCredentialRequest;

View File

@@ -0,0 +1,138 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.credentials;
import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.util.AnnotationValidations;
import com.android.internal.util.Preconditions;
import java.util.ArrayList;
import java.util.List;
/**
* A request to retrieve the user credential, potentially launching UI flows to let the user pick
* from different credential sources.
*/
public final class GetCredentialRequest implements Parcelable {
/**
* The list of credential requests.
*/
@NonNull
private final List<GetCredentialOption> mGetCredentialOptions;
/**
* Returns the list of credential options to be requested.
*/
@NonNull
public List<GetCredentialOption> getGetCredentialOptions() {
return mGetCredentialOptions;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeTypedList(mGetCredentialOptions, flags);
}
@Override
public int describeContents() {
return 0;
}
@Override
public String toString() {
return "GetCredentialRequest {getCredentialOption=" + mGetCredentialOptions + "}";
}
private GetCredentialRequest(@NonNull List<GetCredentialOption> getCredentialOptions) {
Preconditions.checkCollectionNotEmpty(
getCredentialOptions,
/*valueName=*/ "getCredentialOptions");
Preconditions.checkCollectionElementsNotNull(
getCredentialOptions,
/*valueName=*/ "getCredentialOptions");
mGetCredentialOptions = getCredentialOptions;
}
private GetCredentialRequest(@NonNull Parcel in) {
List<GetCredentialOption> getCredentialOptions = new ArrayList<GetCredentialOption>();
in.readTypedList(getCredentialOptions, GetCredentialOption.CREATOR);
mGetCredentialOptions = getCredentialOptions;
AnnotationValidations.validate(NonNull.class, null, mGetCredentialOptions);
}
public static final @NonNull Parcelable.Creator<GetCredentialRequest> CREATOR =
new Parcelable.Creator<GetCredentialRequest>() {
@Override
public GetCredentialRequest[] newArray(int size) {
return new GetCredentialRequest[size];
}
@Override
public GetCredentialRequest createFromParcel(@NonNull Parcel in) {
return new GetCredentialRequest(in);
}
};
/** A builder for {@link GetCredentialRequest}. */
public static final class Builder {
private @NonNull List<GetCredentialOption> mGetCredentialOptions = new ArrayList<>();
/**
* Adds a specific type of {@link GetCredentialOption}.
*/
public @NonNull Builder addGetCredentialOption(
@NonNull GetCredentialOption getCredentialOption) {
mGetCredentialOptions.add(requireNonNull(
getCredentialOption, "getCredentialOption must not be null"));
return this;
}
/**
* Sets the list of {@link GetCredentialOption}.
*/
public @NonNull Builder setGetCredentialOptions(
@NonNull List<GetCredentialOption> getCredentialOptions) {
Preconditions.checkCollectionElementsNotNull(
getCredentialOptions,
/*valueName=*/ "getCredentialOptions");
mGetCredentialOptions = new ArrayList<>(getCredentialOptions);
return this;
}
/**
* Builds a {@link GetCredentialRequest}.
*
* @throws IllegalArgumentException If getCredentialOptions is empty.
*/
public @NonNull GetCredentialRequest build() {
Preconditions.checkCollectionNotEmpty(
mGetCredentialOptions,
/*valueName=*/ "getCredentialOptions");
Preconditions.checkCollectionElementsNotNull(
mGetCredentialOptions,
/*valueName=*/ "getCredentialOptions");
return new GetCredentialRequest(mGetCredentialOptions);
}
}
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.credentials;
parcelable GetCredentialResponse;

View File

@@ -0,0 +1,97 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.credentials;
import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.util.AnnotationValidations;
/**
* A response object that encapsulates the credential successfully retrieved from the user.
*/
public final class GetCredentialResponse implements Parcelable {
/**
* The credential that can be used to authenticate the user.
*/
@Nullable
private final Credential mCredential;
/**
* Returns the credential that can be used to authenticate the user, or {@code null} if no
* credential is available.
*/
@Nullable
public Credential getCredential() {
return mCredential;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeTypedObject(mCredential, flags);
}
@Override
public int describeContents() {
return 0;
}
@Override
public String toString() {
return "GetCredentialResponse {" + "credential=" + mCredential + "}";
}
/**
* Constructs a {@link GetCredentialResponse}.
*
* @param credential the credential successfully retrieved from the user.
*/
public GetCredentialResponse(@NonNull Credential credential) {
mCredential = requireNonNull(credential, "credential must not be null");
}
/**
* Constructs a {@link GetCredentialResponse}.
*/
public GetCredentialResponse() {
mCredential = null;
}
private GetCredentialResponse(@NonNull Parcel in) {
Credential credential = in.readTypedObject(Credential.CREATOR);
mCredential = credential;
AnnotationValidations.validate(NonNull.class, null, mCredential);
}
public static final @NonNull Parcelable.Creator<GetCredentialResponse> CREATOR =
new Parcelable.Creator<GetCredentialResponse>() {
@Override
public GetCredentialResponse[] newArray(int size) {
return new GetCredentialResponse[size];
}
@Override
public GetCredentialResponse createFromParcel(@NonNull Parcel in) {
return new GetCredentialResponse(in);
}
};
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.credentials;
import android.credentials.CreateCredentialResponse;
/**
* Listener for an executeCreateCredential request.
*
* @hide
*/
interface ICreateCredentialCallback {
oneway void onResponse(in CreateCredentialResponse response);
oneway void onError(int errorCode, String message);
}

View File

@@ -1,10 +1,35 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.credentials;
import android.credentials.CreateCredentialRequest;
import android.credentials.GetCredentialRequest;
import android.credentials.ICreateCredentialCallback;
import android.credentials.IGetCredentialCallback;
import android.os.ICancellationSignal;
/**
* Mediator between apps and credential manager service implementations.
* System private interface for talking to the credential manager service.
*
* {@hide}
* @hide
*/
oneway interface ICredentialManager {
void getCredential();
}
interface ICredentialManager {
@nullable ICancellationSignal executeGetCredential(in GetCredentialRequest request, in IGetCredentialCallback callback);
@nullable ICancellationSignal executeCreateCredential(in CreateCredentialRequest request, in ICreateCredentialCallback callback);
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.credentials;
import android.credentials.GetCredentialResponse;
/**
* Listener for an executeGetCredential request.
*
* @hide
*/
interface IGetCredentialCallback {
oneway void onResponse(in GetCredentialResponse response);
oneway void onError(int errorCode, String message);
}

View File

@@ -93,6 +93,7 @@ filegroup {
":services.contentcapture-sources",
":services.contentsuggestions-sources",
":services.coverage-sources",
":services.credentials-sources",
":services.devicepolicy-sources",
":services.midi-sources",
":services.musicsearch-sources",
@@ -146,6 +147,7 @@ java_library {
"services.contentcapture",
"services.contentsuggestions",
"services.coverage",
"services.credentials",
"services.devicepolicy",
"services.midi",
"services.musicsearch",

View File

@@ -16,10 +16,18 @@
package com.android.server.credentials;
import static android.content.Context.CREDENTIAL_SERVICE;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.content.Context;
import android.credentials.CreateCredentialRequest;
import android.credentials.GetCredentialRequest;
import android.credentials.ICreateCredentialCallback;
import android.credentials.ICredentialManager;
import android.credentials.IGetCredentialCallback;
import android.os.CancellationSignal;
import android.os.ICancellationSignal;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
@@ -59,11 +67,17 @@ public final class CredentialManagerService extends
@Override
public void onStart() {
Log.i(TAG, "onStart");
publishBinderService(CREDENTIAL_SERVICE, new CredentialManagerServiceStub());
}
final class CredentialManagerServiceStub extends ICredentialManager.Stub {
@Override
public void getCredential() {
public ICancellationSignal executeGetCredential(
GetCredentialRequest request,
IGetCredentialCallback callback) {
// TODO: implement.
Log.i(TAG, "executeGetCredential");
final int userId = UserHandle.getCallingUserId();
synchronized (mLock) {
final CredentialManagerServiceImpl service = peekServiceForUserLocked(userId);
@@ -72,6 +86,19 @@ public final class CredentialManagerService extends
service.getCredential();
}
}
ICancellationSignal cancelTransport = CancellationSignal.createTransport();
return cancelTransport;
}
@Override
public ICancellationSignal executeCreateCredential(
CreateCredentialRequest request,
ICreateCredentialCallback callback) {
// TODO: implement.
Log.i(TAG, "executeCreateCredential");
ICancellationSignal cancelTransport = CancellationSignal.createTransport();
return cancelTransport;
}
}
}