From 01e3d07d32f190dff7fcaddf57cf8f82bdc7cfac Mon Sep 17 00:00:00 2001 From: Reema Bajwa Date: Wed, 28 Sep 2022 19:51:05 +0000 Subject: [PATCH] Add OutcomeReceiver to provider APIs and share classes with developer APIs Test: Built locally CTS-Coverage-Bug:247549381 Change-Id: I95a4149124b1e446727a093d54e10a5a39173e56 --- .../android/service/credentials/Action.java | 32 +++--- .../credentials/CreateCredentialCallback.java | 64 ----------- .../credentials/CreateCredentialRequest.java | 3 +- .../credentials/CreateCredentialResponse.java | 3 +- .../service/credentials/Credential.java | 100 ------------------ .../service/credentials/CredentialEntry.java | 48 +++++---- .../CredentialProviderException.java | 65 ++++++++++++ .../CredentialProviderService.java | 66 +++++++++--- .../CredentialsDisplayContent.java | 3 +- .../credentials/GetCredentialOption.java | 96 ----------------- .../credentials/GetCredentialsCallback.java | 65 ------------ .../credentials/GetCredentialsRequest.java | 6 +- .../credentials/GetCredentialsResponse.java | 19 ++-- .../service/credentials/SaveEntry.java | 34 +++--- 14 files changed, 192 insertions(+), 412 deletions(-) delete mode 100644 core/java/android/service/credentials/CreateCredentialCallback.java delete mode 100644 core/java/android/service/credentials/Credential.java create mode 100644 core/java/android/service/credentials/CredentialProviderException.java delete mode 100644 core/java/android/service/credentials/GetCredentialOption.java delete mode 100644 core/java/android/service/credentials/GetCredentialsCallback.java diff --git a/core/java/android/service/credentials/Action.java b/core/java/android/service/credentials/Action.java index 186b2a60c4304..e2c11fbac008f 100644 --- a/core/java/android/service/credentials/Action.java +++ b/core/java/android/service/credentials/Action.java @@ -16,13 +16,12 @@ package android.service.credentials; +import android.annotation.NonNull; import android.app.PendingIntent; import android.app.slice.Slice; import android.os.Parcel; import android.os.Parcelable; -import androidx.annotation.NonNull; - import java.util.Objects; /** @@ -32,29 +31,26 @@ import java.util.Objects; * @hide */ public final class Action implements Parcelable { - /** Info to be displayed with this action on the UI. */ - private final @NonNull Slice mInfo; - /** - * The pending intent to be invoked when the user selects this action. - */ + /** Slice object containing display content to be displayed with this action on the UI. */ + private final @NonNull Slice mSlice; + /** The pending intent to be invoked when the user selects this action. */ private final @NonNull PendingIntent mPendingIntent; /** * Constructs an action to be displayed on the UI. * - * @param actionInfo The info to be displayed along with this action. - * @param pendingIntent The intent to be invoked when the user selects this action. - * @throws NullPointerException If {@code actionInfo}, or {@code pendingIntent} is null. + * @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 */ - public Action(@NonNull Slice actionInfo, @NonNull PendingIntent pendingIntent) { - Objects.requireNonNull(actionInfo, "actionInfo must not be null"); + public Action(@NonNull Slice slice, @NonNull PendingIntent pendingIntent) { + Objects.requireNonNull(slice, "slice must not be null"); Objects.requireNonNull(pendingIntent, "pendingIntent must not be null"); - mInfo = actionInfo; + mSlice = slice; mPendingIntent = pendingIntent; } private Action(@NonNull Parcel in) { - mInfo = in.readParcelable(Slice.class.getClassLoader(), Slice.class); + mSlice = in.readParcelable(Slice.class.getClassLoader(), Slice.class); mPendingIntent = in.readParcelable(PendingIntent.class.getClassLoader(), PendingIntent.class); } @@ -78,15 +74,15 @@ public final class Action implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { - mInfo.writeToParcel(dest, flags); + mSlice.writeToParcel(dest, flags); mPendingIntent.writeToParcel(dest, flags); } /** - * Returns the action info as a {@link Slice} object, to be displayed on the UI. + * Returns a {@code Slice} object containing the display content to be displayed on the UI. */ - public @NonNull Slice getActionInfo() { - return mInfo; + public @NonNull Slice getSlice() { + return mSlice; } /** diff --git a/core/java/android/service/credentials/CreateCredentialCallback.java b/core/java/android/service/credentials/CreateCredentialCallback.java deleted file mode 100644 index 6108eea5bea19..0000000000000 --- a/core/java/android/service/credentials/CreateCredentialCallback.java +++ /dev/null @@ -1,64 +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.RemoteException; -import android.util.Log; - -/** - * Callback to be invoked as a response to {@link CreateCredentialRequest}. - * - * @hide - */ -public final class CreateCredentialCallback { - private static final String TAG = "CreateCredentialCallback"; - - private final ICreateCredentialCallback mCallback; - - /** @hide */ - public CreateCredentialCallback(@NonNull ICreateCredentialCallback callback) { - mCallback = callback; - } - - /** - * Invoked on a successful response for {@link CreateCredentialRequest} - * @param response The response from the credential provider. - */ - public void onSuccess(@NonNull CreateCredentialResponse response) { - try { - mCallback.onSuccess(response); - } catch (RemoteException e) { - e.rethrowAsRuntimeException(); - } - } - - /** - * Invoked on a failure response for {@link CreateCredentialRequest} - * @param errorCode The code defining the type of error. - * @param message The message corresponding to the failure. - */ - public void onFailure(int errorCode, @Nullable CharSequence message) { - Log.w(TAG, "onFailure: " + message); - try { - mCallback.onFailure(errorCode, message); - } catch (RemoteException e) { - e.rethrowAsRuntimeException(); - } - } -} diff --git a/core/java/android/service/credentials/CreateCredentialRequest.java b/core/java/android/service/credentials/CreateCredentialRequest.java index ac11e04bcb77d..6a0bbc0bd9179 100644 --- a/core/java/android/service/credentials/CreateCredentialRequest.java +++ b/core/java/android/service/credentials/CreateCredentialRequest.java @@ -16,12 +16,11 @@ package android.service.credentials; +import android.annotation.NonNull; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; -import androidx.annotation.NonNull; - import com.android.internal.util.Preconditions; import java.util.Objects; diff --git a/core/java/android/service/credentials/CreateCredentialResponse.java b/core/java/android/service/credentials/CreateCredentialResponse.java index f2ad7272f2071..613eba8c9bb28 100644 --- a/core/java/android/service/credentials/CreateCredentialResponse.java +++ b/core/java/android/service/credentials/CreateCredentialResponse.java @@ -16,12 +16,11 @@ package android.service.credentials; +import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; -import androidx.annotation.NonNull; - import com.android.internal.util.Preconditions; import java.util.ArrayList; diff --git a/core/java/android/service/credentials/Credential.java b/core/java/android/service/credentials/Credential.java deleted file mode 100644 index 7d5da8a7c4e0b..0000000000000 --- a/core/java/android/service/credentials/Credential.java +++ /dev/null @@ -1,100 +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.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; - -import androidx.annotation.NonNull; - -import static java.util.Objects.requireNonNull; - -import com.android.internal.util.Preconditions; - -/** - * A Credential object that contains type specific data that is returned from the credential - * provider to the framework. Framework then converts it to an app facing representation and - * returns to the calling app. - * - * @hide - */ -public final class Credential implements Parcelable { - /** The type of this credential. */ - private final @NonNull String mType; - - /** The data associated with this credential. */ - private final @NonNull Bundle mData; - - /** - * Constructs a credential object. - * - * @param type The type of the credential. - * @param data The data of the credential that is passed back to the framework, and eventually - * to the calling app. - * @throws NullPointerException If {@code data} is null. - * @throws IllegalArgumentException If {@code type} is null or empty. - */ - public Credential(@NonNull String type, @NonNull Bundle data) { - Preconditions.checkStringNotEmpty(type, "type must not be null, or empty"); - requireNonNull(data, "data must not be null"); - this.mType = type; - this.mData = data; - } - - private Credential(@NonNull Parcel in) { - mType = in.readString16NoHelper(); - mData = in.readBundle(); - } - - /** - * Returns the type of the credential. - */ - public @NonNull String getType() { - return mType; - } - - /** - * Returns the data associated with the credential. - */ - public @NonNull Bundle getData() { - return mData; - } - - public static final @NonNull Creator CREATOR = new Creator() { - @Override - public Credential createFromParcel(@NonNull Parcel in) { - return new Credential(in); - } - - @Override - public Credential[] newArray(int size) { - return new Credential[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeString8(mType); - dest.writeBundle(mData); - } -} diff --git a/core/java/android/service/credentials/CredentialEntry.java b/core/java/android/service/credentials/CredentialEntry.java index b49215a08bfb7..49b84359d94a2 100644 --- a/core/java/android/service/credentials/CredentialEntry.java +++ b/core/java/android/service/credentials/CredentialEntry.java @@ -16,14 +16,14 @@ package android.service.credentials; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.PendingIntent; import android.app.slice.Slice; +import android.credentials.Credential; import android.os.Parcel; import android.os.Parcelable; -import androidx.annotation.NonNull; - import com.android.internal.util.Preconditions; import java.util.Objects; @@ -38,8 +38,9 @@ public final class CredentialEntry implements Parcelable { /** The type of the credential entry to be shown on the UI. */ private final @NonNull String mType; - /** The info to be displayed along with this credential entry on the UI. */ - private final @NonNull Slice mInfo; + /** The object containing display content to be shown along with this credential entry + * on the UI. */ + private final @NonNull Slice mSlice; /** The pending intent to be invoked when this credential entry is selected. */ private final @Nullable PendingIntent mPendingIntent; @@ -53,11 +54,11 @@ public final class CredentialEntry implements Parcelable { /** A flag denoting whether auto-select is enabled for this entry. */ private final @NonNull boolean mAutoSelectAllowed; - private CredentialEntry(@NonNull String type, @NonNull Slice entryInfo, + private CredentialEntry(@NonNull String type, @NonNull Slice slice, @Nullable PendingIntent pendingIntent, @Nullable Credential credential, @NonNull boolean autoSeletAllowed) { mType = type; - mInfo = entryInfo; + mSlice = slice; mPendingIntent = pendingIntent; mCredential = credential; mAutoSelectAllowed = autoSeletAllowed; @@ -65,7 +66,7 @@ public final class CredentialEntry implements Parcelable { private CredentialEntry(@NonNull Parcel in) { mType = in.readString(); - mInfo = in.readParcelable(Slice.class.getClassLoader(), Slice.class); + mSlice = in.readParcelable(Slice.class.getClassLoader(), Slice.class); mPendingIntent = in.readParcelable(PendingIntent.class.getClassLoader(), PendingIntent.class); mCredential = in.readParcelable(Credential.class.getClassLoader(), @@ -94,7 +95,7 @@ public final class CredentialEntry implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeString8(mType); - mInfo.writeToParcel(dest, flags); + mSlice.writeToParcel(dest, flags); mPendingIntent.writeToParcel(dest, flags); mCredential.writeToParcel(dest, flags); dest.writeBoolean(mAutoSelectAllowed); @@ -108,10 +109,10 @@ public final class CredentialEntry implements Parcelable { } /** - * Returns the UI info to be displayed for this entry. + * Returns the {@link Slice} object containing UI display content to be shown for this entry. */ - public @NonNull Slice getInfo() { - return mInfo; + public @NonNull Slice getSlice() { + return mSlice; } /** @@ -131,7 +132,7 @@ public final class CredentialEntry implements Parcelable { /** * Returns whether this entry can be auto selected if it is the only option for the user. */ - public @NonNull boolean isAutoSelectAllowed() { + public boolean isAutoSelectAllowed() { return mAutoSelectAllowed; } @@ -140,28 +141,35 @@ public final class CredentialEntry implements Parcelable { */ public static final class Builder { private String mType; - private Slice mInfo; + private Slice mSlice; private PendingIntent mPendingIntent; private Credential mCredential; private boolean mAutoSelectAllowed = false; /** * Builds the instance. - * @param type The type of credential underlying this credential entry. - * @param info The info to be displayed with this entry on the UI. + * @param type the type of credential underlying this credential entry + * @param slice the content to be displayed with this entry on the UI * * @throws IllegalArgumentException If {@code type} is null or empty. - * @throws NullPointerException If {@code info} is null. + * @throws NullPointerException If {@code slice} is null. */ - public Builder(@NonNull String type, @NonNull Slice info) { + public Builder(@NonNull String type, @NonNull Slice slice) { mType = Preconditions.checkStringNotEmpty(type, "type must not be " + "null, or empty"); - mInfo = Objects.requireNonNull(info, "info must not be null"); + mSlice = Objects.requireNonNull(slice, + "slice must not be null"); } /** * Sets the pendingIntent to be invoked if the user selects this entry. * + * 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}. */ @@ -199,7 +207,7 @@ public final class CredentialEntry implements Parcelable { /** * Creates a new {@link CredentialEntry} instance. * - * @throws NullPointerException If {@code info} is null. + * @throws NullPointerException If {@code slice} is null. * @throws IllegalArgumentException If {@code type} is null, or empty. * @throws IllegalStateException If neither {@code pendingIntent} nor {@code credential} * is set, or if both are set. @@ -209,7 +217,7 @@ public final class CredentialEntry implements Parcelable { "Either pendingIntent or credential must be set"); Preconditions.checkState(mPendingIntent != null && mCredential != null, "Cannot set both the pendingIntent and credential"); - return new CredentialEntry(mType, mInfo, mPendingIntent, + return new CredentialEntry(mType, mSlice, mPendingIntent, mCredential, mAutoSelectAllowed); } } diff --git a/core/java/android/service/credentials/CredentialProviderException.java b/core/java/android/service/credentials/CredentialProviderException.java new file mode 100644 index 0000000000000..b39b4a0cc1808 --- /dev/null +++ b/core/java/android/service/credentials/CredentialProviderException.java @@ -0,0 +1,65 @@ +/* + * 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.IntDef; +import android.annotation.NonNull; + +import java.lang.annotation.Retention; +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; + + private final int mErrorCode; + + /** + * @hide + */ + @IntDef(prefix = {"ERROR_"}, value = { + ERROR_UNKNOWN, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface CredentialProviderError { } + + + public CredentialProviderException(@CredentialProviderError int errorCode, + @NonNull String message) { + super(message); + mErrorCode = errorCode; + } + + public CredentialProviderException(@CredentialProviderError int errorCode, + @NonNull Throwable cause) { + super(cause); + mErrorCode = errorCode; + } + + public CredentialProviderException(@CredentialProviderError int errorCode) { + super(); + mErrorCode = errorCode; + } + + public @CredentialProviderError int getErrorCode() { + return mErrorCode; + } +} diff --git a/core/java/android/service/credentials/CredentialProviderService.java b/core/java/android/service/credentials/CredentialProviderService.java index 1fe89dffaa0f8..1cdf186d898c9 100644 --- a/core/java/android/service/credentials/CredentialProviderService.java +++ b/core/java/android/service/credentials/CredentialProviderService.java @@ -20,6 +20,7 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa import android.annotation.CallSuper; import android.annotation.NonNull; +import android.annotation.SdkConstant; import android.app.Service; import android.content.Intent; import android.os.CancellationSignal; @@ -27,13 +28,14 @@ import android.os.Handler; import android.os.IBinder; import android.os.ICancellationSignal; import android.os.Looper; +import android.os.OutcomeReceiver; import android.os.RemoteException; import android.util.Log; import java.util.Objects; /** - * Main service to be extended by credential providers, in order to return user credentials + * Service to be extended by credential providers, in order to return user credentials * to the framework. * * @hide @@ -42,6 +44,12 @@ public abstract class CredentialProviderService extends Service { private static final String TAG = "CredProviderService"; private Handler mHandler; + /** + * The {@link Intent} that must be declared as handled by the service. The service must also + * require the {android.Manifest.permission#BIND_CREDENTIAL_PROVIDER_SERVICE} permission + * so that only the system can bind to it. + */ + @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) public static final String SERVICE_INTERFACE = "android.service.credentials.CredentialProviderService"; @@ -64,7 +72,7 @@ public abstract class CredentialProviderService extends Service { private final ICredentialProviderService mInterface = new ICredentialProviderService.Stub() { @Override public void onGetCredentials(GetCredentialsRequest request, ICancellationSignal transport, - IGetCredentialsCallback callback) throws RemoteException { + IGetCredentialsCallback callback) { Objects.requireNonNull(request); Objects.requireNonNull(transport); Objects.requireNonNull(callback); @@ -73,14 +81,30 @@ public abstract class CredentialProviderService extends Service { CredentialProviderService::onGetCredentials, CredentialProviderService.this, request, CancellationSignal.fromTransport(transport), - new GetCredentialsCallback(callback) + new OutcomeReceiver() { + @Override + public void onResult(GetCredentialsResponse result) { + try { + callback.onSuccess(result); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + @Override + public void onError(CredentialProviderException e) { + try { + callback.onFailure(e.getErrorCode(), e.getMessage()); + } catch (RemoteException ex) { + ex.rethrowFromSystemServer(); + } + } + } )); } @Override public void onCreateCredential(CreateCredentialRequest request, - ICancellationSignal transport, ICreateCredentialCallback callback) - throws RemoteException { + ICancellationSignal transport, ICreateCredentialCallback callback) { Objects.requireNonNull(request); Objects.requireNonNull(transport); Objects.requireNonNull(callback); @@ -89,7 +113,24 @@ public abstract class CredentialProviderService extends Service { CredentialProviderService::onCreateCredential, CredentialProviderService.this, request, CancellationSignal.fromTransport(transport), - new CreateCredentialCallback(callback) + new OutcomeReceiver() { + @Override + public void onResult(CreateCredentialResponse result) { + try { + callback.onSuccess(result); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + @Override + public void onError(CredentialProviderException e) { + try { + callback.onFailure(e.getErrorCode(), e.getMessage()); + } catch (RemoteException ex) { + ex.rethrowFromSystemServer(); + } + } + } )); } }; @@ -97,14 +138,14 @@ public abstract class CredentialProviderService extends Service { /** * Called by the android system to retrieve user credentials from the connected provider * service. - * @param request The credential request for the provider to handle. - * @param cancellationSignal Signal for providers to listen to any cancellation requests from - * the android system. - * @param callback Object used to relay the response of the credentials request. + * @param request the credential request for the provider to handle + * @param cancellationSignal signal for providers to listen to any cancellation requests from + * the android system + * @param callback object used to relay the response of the credentials request */ public abstract void onGetCredentials(@NonNull GetCredentialsRequest request, @NonNull CancellationSignal cancellationSignal, - @NonNull GetCredentialsCallback callback); + @NonNull OutcomeReceiver callback); /** * Called by the android system to create a credential. @@ -115,5 +156,6 @@ public abstract class CredentialProviderService extends Service { */ public abstract void onCreateCredential(@NonNull CreateCredentialRequest request, @NonNull CancellationSignal cancellationSignal, - @NonNull CreateCredentialCallback callback); + @NonNull OutcomeReceiver callback); } diff --git a/core/java/android/service/credentials/CredentialsDisplayContent.java b/core/java/android/service/credentials/CredentialsDisplayContent.java index 106f322c4ab4d..4133ea5955c4a 100644 --- a/core/java/android/service/credentials/CredentialsDisplayContent.java +++ b/core/java/android/service/credentials/CredentialsDisplayContent.java @@ -16,12 +16,11 @@ package android.service.credentials; +import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; -import androidx.annotation.NonNull; - import com.android.internal.util.Preconditions; import java.util.ArrayList; diff --git a/core/java/android/service/credentials/GetCredentialOption.java b/core/java/android/service/credentials/GetCredentialOption.java deleted file mode 100644 index c6cda1d1abf6f..0000000000000 --- a/core/java/android/service/credentials/GetCredentialOption.java +++ /dev/null @@ -1,96 +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.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; - -import com.android.internal.util.Preconditions; - -import static java.util.Objects.requireNonNull; - -/** - * A type specific credential request, containing the associated data to be used for - * retrieving credentials. - * - * @hide - */ -public final class GetCredentialOption implements Parcelable { - /** The type of credential requested. */ - private final @NonNull String mType; - - /** The data associated with the request. */ - private final @NonNull Bundle mData; - - /** - * Constructs a new instance of {@link GetCredentialOption} - * - * @throws IllegalArgumentException If {@code type} string is null or empty. - * @throws NullPointerException If {@code data} is null. - */ - public GetCredentialOption(@NonNull String type, @NonNull Bundle data) { - Preconditions.checkStringNotEmpty(type, "type must not be null, or empty"); - requireNonNull(data, "data must not be null"); - mType = type; - mData = data; - } - - /** - * Returns the data associated with this credential request option. - */ - public @NonNull Bundle getData() { - return mData; - } - - /** - * Returns the type associated with this credential request option. - */ - public @NonNull String getType() { - return mType; - } - - private GetCredentialOption(@NonNull Parcel in) { - mType = in.readString16NoHelper(); - mData = in.readBundle(); - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeString16NoHelper(mType); - dest.writeBundle(mData); - } - - @Override - public int describeContents() { - return 0; - } - - public static final @NonNull Creator CREATOR = - new Creator() { - @Override - public GetCredentialOption createFromParcel(@NonNull Parcel in) { - return new GetCredentialOption(in); - } - - @Override - public GetCredentialOption[] newArray(int size) { - return new GetCredentialOption[size]; - } - }; -} diff --git a/core/java/android/service/credentials/GetCredentialsCallback.java b/core/java/android/service/credentials/GetCredentialsCallback.java deleted file mode 100644 index 42a73946b5cca..0000000000000 --- a/core/java/android/service/credentials/GetCredentialsCallback.java +++ /dev/null @@ -1,65 +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.RemoteException; -import android.util.Log; - -/** - * Callback to be invoked as a response to {@link GetCredentialsRequest}. - * - * @hide - */ -public final class GetCredentialsCallback { - - private static final String TAG = "GetCredentialsCallback"; - - private final IGetCredentialsCallback mCallback; - - /** @hide */ - public GetCredentialsCallback(@NonNull IGetCredentialsCallback callback) { - mCallback = callback; - } - - /** - * Invoked on a successful response for {@link GetCredentialsRequest} - * @param response The response from the credential provider. - */ - public void onSuccess(@NonNull GetCredentialsResponse response) { - try { - mCallback.onSuccess(response); - } catch (RemoteException e) { - e.rethrowAsRuntimeException(); - } - } - - /** - * Invoked on a failure response for {@link GetCredentialsRequest} - * @param errorCode The code defining the kind of error. - * @param message The message corresponding to the failure. - */ - public void onFailure(int errorCode, @Nullable CharSequence message) { - Log.w(TAG, "onFailure: " + message); - try { - mCallback.onFailure(errorCode, message); - } catch (RemoteException e) { - e.rethrowAsRuntimeException(); - } - } -} diff --git a/core/java/android/service/credentials/GetCredentialsRequest.java b/core/java/android/service/credentials/GetCredentialsRequest.java index cf7c2834f75f6..5b1a1713ee513 100644 --- a/core/java/android/service/credentials/GetCredentialsRequest.java +++ b/core/java/android/service/credentials/GetCredentialsRequest.java @@ -16,11 +16,11 @@ package android.service.credentials; +import android.annotation.NonNull; +import android.credentials.GetCredentialOption; import android.os.Parcel; import android.os.Parcelable; -import androidx.annotation.NonNull; - import com.android.internal.util.Preconditions; import java.util.ArrayList; @@ -100,7 +100,7 @@ public final class GetCredentialsRequest implements Parcelable { /** * Creates a new builder. - * @param callingPackage The calling package of the app requesting credentials. + * @param callingPackage the calling package of the app requesting credentials * * @throws IllegalArgumentException If {@code callingPackag}e is null or empty. */ diff --git a/core/java/android/service/credentials/GetCredentialsResponse.java b/core/java/android/service/credentials/GetCredentialsResponse.java index 293867ba55b28..980d9ae47aa77 100644 --- a/core/java/android/service/credentials/GetCredentialsResponse.java +++ b/core/java/android/service/credentials/GetCredentialsResponse.java @@ -16,12 +16,11 @@ package android.service.credentials; +import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; -import androidx.annotation.NonNull; - import java.util.Objects; /** @@ -44,6 +43,11 @@ public final class GetCredentialsResponse implements Parcelable { * Creates a {@link GetCredentialsRequest} instance with an authentication 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 + * {@code createWithDisplayContent}, and add that response to the result of the authentication + * activity. + * * @throws NullPointerException If {@code authenticationAction} is null. */ public static @NonNull GetCredentialsResponse createWithAuthentication( @@ -103,18 +107,11 @@ public final class GetCredentialsResponse implements Parcelable { dest.writeParcelable(mAuthenticationAction, flags); } - /** - * Returns whether the response contains a top level authentication action. - */ - public @NonNull boolean isAuthenticationActionSet() { - return mAuthenticationAction != null; - } - /** * Returns the authentication action to be invoked before any other content * can be shown to the user. */ - public @NonNull Action getAuthenticationAction() { + public @Nullable Action getAuthenticationAction() { return mAuthenticationAction; } @@ -122,7 +119,7 @@ public final class GetCredentialsResponse implements Parcelable { * Returns the credentialDisplayContent that does not require authentication, and * can be shown to the user on the account selector UI. */ - public @NonNull CredentialsDisplayContent getCredentialsDisplayContent() { + public @Nullable CredentialsDisplayContent getCredentialsDisplayContent() { return mCredentialsDisplayContent; } } diff --git a/core/java/android/service/credentials/SaveEntry.java b/core/java/android/service/credentials/SaveEntry.java index 28fec30caa89f..18644f09ecefd 100644 --- a/core/java/android/service/credentials/SaveEntry.java +++ b/core/java/android/service/credentials/SaveEntry.java @@ -16,14 +16,14 @@ package android.service.credentials; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.PendingIntent; import android.app.slice.Slice; +import android.credentials.Credential; import android.os.Parcel; import android.os.Parcelable; -import androidx.annotation.NonNull; - import com.android.internal.util.Preconditions; import java.util.Objects; @@ -35,12 +35,12 @@ import java.util.Objects; * @hide */ public final class SaveEntry implements Parcelable { - private final @NonNull Slice mInfo; + private final @NonNull Slice mSlice; private final @Nullable PendingIntent mPendingIntent; private final @Nullable Credential mCredential; private SaveEntry(@NonNull Parcel in) { - mInfo = in.readParcelable(Slice.class.getClassLoader(), Slice.class); + mSlice = in.readParcelable(Slice.class.getClassLoader(), Slice.class); mPendingIntent = in.readParcelable(PendingIntent.class.getClassLoader(), PendingIntent.class); mCredential = in.readParcelable(Credential.class.getClassLoader(), Credential.class); @@ -65,25 +65,25 @@ public final class SaveEntry implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { - mInfo.writeToParcel(dest, flags); + mSlice.writeToParcel(dest, flags); mPendingIntent.writeToParcel(dest, flags); mCredential.writeToParcel(dest, flags); } /* package-private */ SaveEntry( - @NonNull Slice info, + @NonNull Slice slice, @Nullable PendingIntent pendingIntent, @Nullable Credential credential) { - this.mInfo = info; + this.mSlice = slice; com.android.internal.util.AnnotationValidations.validate( - NonNull.class, null, mInfo); + NonNull.class, null, mSlice); this.mPendingIntent = pendingIntent; this.mCredential = credential; } - /** Returns the info to be displayed with this save entry on the UI. */ - public @NonNull Slice getInfo() { - return mInfo; + /** Returns the content to be displayed with this save 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. */ @@ -101,18 +101,18 @@ public final class SaveEntry implements Parcelable { */ public static final class Builder { - private @NonNull Slice mInfo; + private @NonNull Slice mSlice; private @Nullable PendingIntent mPendingIntent; private @Nullable Credential mCredential; /** * Builds the instance. - * @param info The info to be displayed with this save entry. + * @param slice the content to be displayed with this save entry * - * @throws NullPointerException If {@code info} is null. + * @throws NullPointerException If {@code slice} is null. */ - public Builder(@NonNull Slice info) { - mInfo = Objects.requireNonNull(info, "info must not be null"); + public Builder(@NonNull Slice slice) { + mSlice = Objects.requireNonNull(slice, "slice must not be null"); } /** @@ -154,7 +154,7 @@ public final class SaveEntry implements Parcelable { "pendingIntent and credential both must not be null. Must set " + "either the pendingIntnet or the credential"); return new SaveEntry( - mInfo, + mSlice, mPendingIntent, mCredential); }