Merge "Add OutcomeReceiver to provider APIs and share classes with developer APIs Test: Built locally CTS-Coverage-Bug:247549381"

This commit is contained in:
Reema Bajwa
2022-10-10 20:20:45 +00:00
committed by Android (Google) Code Review
14 changed files with 192 additions and 412 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -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<Credential> CREATOR = new Creator<Credential>() {
@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);
}
}

View File

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

View File

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

View File

@@ -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<GetCredentialsResponse, CredentialProviderException>() {
@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<CreateCredentialResponse, CredentialProviderException>() {
@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<GetCredentialsResponse, CredentialProviderException> 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<CreateCredentialResponse,
CredentialProviderException> callback);
}

View File

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

View File

@@ -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<GetCredentialOption> CREATOR =
new Creator<GetCredentialOption>() {
@Override
public GetCredentialOption createFromParcel(@NonNull Parcel in) {
return new GetCredentialOption(in);
}
@Override
public GetCredentialOption[] newArray(int size) {
return new GetCredentialOption[size];
}
};
}

View File

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

View File

@@ -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.
*/

View File

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

View File

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