| /* |
| * 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.selection; |
| |
| import static android.credentials.flags.Flags.FLAG_CONFIGURABLE_SELECTOR_UI_ENABLED; |
| |
| import android.annotation.FlaggedApi; |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import android.annotation.StringDef; |
| import android.annotation.SystemApi; |
| import android.annotation.TestApi; |
| import android.credentials.CreateCredentialRequest; |
| import android.credentials.GetCredentialRequest; |
| import android.os.IBinder; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| |
| import com.android.internal.util.AnnotationValidations; |
| |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * Contains information about the request that initiated this UX flow. |
| * |
| * @hide |
| */ |
| @SystemApi |
| @FlaggedApi(FLAG_CONFIGURABLE_SELECTOR_UI_ENABLED) |
| public final class RequestInfo implements Parcelable { |
| |
| /** |
| * The intent extra key for the {@code RequestInfo} object when launching the UX |
| * activities. |
| * |
| * @hide |
| */ |
| @NonNull |
| public static final String EXTRA_REQUEST_INFO = |
| "android.credentials.selection.extra.REQUEST_INFO"; |
| |
| /** |
| * Type value for any request that does not require UI. |
| */ |
| @NonNull |
| public static final String TYPE_UNDEFINED = "android.credentials.selection.TYPE_UNDEFINED"; |
| /** |
| * Type value for a getCredential request. |
| */ |
| @NonNull |
| public static final String TYPE_GET = "android.credentials.selection.TYPE_GET"; |
| /** |
| * Type value for a getCredential request that utilizes the credential registry. |
| * |
| * @hide |
| */ |
| @NonNull |
| public static final String TYPE_GET_VIA_REGISTRY = |
| "android.credentials.selection.TYPE_GET_VIA_REGISTRY"; |
| /** |
| * Type value for a createCredential request. |
| */ |
| @NonNull |
| public static final String TYPE_CREATE = "android.credentials.selection.TYPE_CREATE"; |
| |
| /** @hide */ |
| @Retention(RetentionPolicy.SOURCE) |
| @StringDef(value = {TYPE_GET, TYPE_CREATE, TYPE_UNDEFINED}) |
| public @interface RequestType { |
| } |
| |
| @NonNull |
| private final IBinder mToken; |
| |
| @Nullable |
| private final CreateCredentialRequest mCreateCredentialRequest; |
| |
| @NonNull |
| private final List<String> mDefaultProviderIds; |
| |
| @NonNull |
| private final List<String> mRegistryProviderIds; |
| |
| @Nullable |
| private final GetCredentialRequest mGetCredentialRequest; |
| |
| @NonNull |
| @RequestType |
| private final String mType; |
| |
| @NonNull |
| private final String mPackageName; |
| |
| private final boolean mHasPermissionToOverrideDefault; |
| |
| private final boolean mIsShowAllOptionsRequested; |
| |
| /** |
| * Creates new {@code RequestInfo} for a create-credential flow. |
| * |
| * @hide |
| */ |
| @TestApi |
| @FlaggedApi(FLAG_CONFIGURABLE_SELECTOR_UI_ENABLED) |
| @NonNull |
| public static RequestInfo newCreateRequestInfo( |
| @NonNull IBinder token, @NonNull CreateCredentialRequest createCredentialRequest, |
| @NonNull String appPackageName, boolean hasPermissionToOverrideDefault, |
| @NonNull List<String> defaultProviderIds, boolean isShowAllOptionsRequested) { |
| return new RequestInfo( |
| token, TYPE_CREATE, appPackageName, createCredentialRequest, null, |
| hasPermissionToOverrideDefault, defaultProviderIds, isShowAllOptionsRequested); |
| } |
| |
| /** |
| * Creates new {@code RequestInfo} for a get-credential flow. |
| * |
| * @hide |
| */ |
| @TestApi |
| @FlaggedApi(FLAG_CONFIGURABLE_SELECTOR_UI_ENABLED) |
| @NonNull |
| public static RequestInfo newGetRequestInfo( |
| @NonNull IBinder token, @NonNull GetCredentialRequest getCredentialRequest, |
| @NonNull String appPackageName, boolean hasPermissionToOverrideDefault, |
| boolean isShowAllOptionsRequested) { |
| return new RequestInfo( |
| token, TYPE_GET, appPackageName, null, getCredentialRequest, |
| hasPermissionToOverrideDefault, |
| /*defaultProviderIds=*/ new ArrayList<>(), isShowAllOptionsRequested); |
| } |
| |
| |
| /** Returns whether the calling package has the permission. */ |
| public boolean hasPermissionToOverrideDefault() { |
| return mHasPermissionToOverrideDefault; |
| } |
| |
| /** |
| * Returns the request token matching the user request. |
| * |
| * @hide |
| */ |
| @NonNull |
| public IBinder getToken() { |
| return mToken; |
| } |
| |
| /** Returns the request type. */ |
| @NonNull |
| @RequestType |
| public String getType() { |
| return mType; |
| } |
| |
| /** Returns the display name of the app that made this request. */ |
| @NonNull |
| public String getPackageName() { |
| return mPackageName; |
| } |
| |
| /** |
| * Returns the non-null CreateCredentialRequest when the type of the request is {@link |
| * #TYPE_CREATE}, or null otherwise. |
| */ |
| @Nullable |
| public CreateCredentialRequest getCreateCredentialRequest() { |
| return mCreateCredentialRequest; |
| } |
| |
| /** Returns the request token matching the app request that should be cancelled. */ |
| @NonNull |
| public RequestToken getRequestToken() { |
| return new RequestToken(mToken); |
| } |
| |
| /** |
| * Returns default provider identifiers (component or package name) configured from the user |
| * settings. |
| * |
| * Will only be possibly non-empty for the create use case. Not meaningful for the sign-in use |
| * case. |
| */ |
| @NonNull |
| public List<String> getDefaultProviderIds() { |
| return mDefaultProviderIds; |
| } |
| |
| /** |
| * Returns provider identifiers (component or package name) that have been validated to provide |
| * registry entries. |
| */ |
| @NonNull |
| public List<String> getRegistryProviderIds() { |
| return mRegistryProviderIds; |
| } |
| |
| /** |
| * Returns the non-null GetCredentialRequest when the type of the request is {@link |
| * #TYPE_GET}, or null otherwise. |
| */ |
| @Nullable |
| public GetCredentialRequest getGetCredentialRequest() { |
| return mGetCredentialRequest; |
| } |
| |
| /** |
| * Returns true if all options should be immediately displayed in the UI, and false otherwise. |
| * |
| * Normally this bit is set to false, upon which the selection UI should first display a |
| * condensed view of popular, deduplicated options that is determined based on signals like |
| * last-used timestamps, credential type priorities, and preferred providers configured from the |
| * user settings {@link #getDefaultProviderIds()}; at the same time, the UI should offer an |
| * option (button) that navigates the user to viewing all options from this condensed view. |
| * |
| * In some special occasions, e.g. when a request is initiated from the autofill drop-down |
| * suggestion, this bit will be set to true to indicate that the selection UI should immediately |
| * render the all option UI. This means that the request initiator has collected a user signal |
| * to confirm that the user wants to view all the available options at once. |
| */ |
| public boolean isShowAllOptionsRequested() { |
| return mIsShowAllOptionsRequested; |
| } |
| |
| private RequestInfo(@NonNull IBinder token, @NonNull @RequestType String type, |
| @NonNull String appPackageName, |
| @Nullable CreateCredentialRequest createCredentialRequest, |
| @Nullable GetCredentialRequest getCredentialRequest, |
| boolean hasPermissionToOverrideDefault, |
| @NonNull List<String> defaultProviderIds, |
| boolean isShowAllOptionsRequested) { |
| mToken = token; |
| mType = type; |
| mPackageName = appPackageName; |
| mCreateCredentialRequest = createCredentialRequest; |
| mGetCredentialRequest = getCredentialRequest; |
| mHasPermissionToOverrideDefault = hasPermissionToOverrideDefault; |
| mDefaultProviderIds = defaultProviderIds == null ? new ArrayList<>() : defaultProviderIds; |
| mRegistryProviderIds = new ArrayList<>(); |
| mIsShowAllOptionsRequested = isShowAllOptionsRequested; |
| } |
| |
| private RequestInfo(@NonNull Parcel in) { |
| IBinder token = in.readStrongBinder(); |
| String type = in.readString8(); |
| String appPackageName = in.readString8(); |
| CreateCredentialRequest createCredentialRequest = |
| in.readTypedObject(CreateCredentialRequest.CREATOR); |
| GetCredentialRequest getCredentialRequest = |
| in.readTypedObject(GetCredentialRequest.CREATOR); |
| |
| mToken = token; |
| AnnotationValidations.validate(NonNull.class, null, mToken); |
| mType = type; |
| AnnotationValidations.validate(NonNull.class, null, mType); |
| mPackageName = appPackageName; |
| AnnotationValidations.validate(NonNull.class, null, mPackageName); |
| mCreateCredentialRequest = createCredentialRequest; |
| mGetCredentialRequest = getCredentialRequest; |
| mHasPermissionToOverrideDefault = in.readBoolean(); |
| mDefaultProviderIds = in.createStringArrayList(); |
| mRegistryProviderIds = in.createStringArrayList(); |
| mIsShowAllOptionsRequested = in.readBoolean(); |
| } |
| |
| @Override |
| public void writeToParcel(@NonNull Parcel dest, int flags) { |
| dest.writeStrongBinder(mToken); |
| dest.writeString8(mType); |
| dest.writeString8(mPackageName); |
| dest.writeTypedObject(mCreateCredentialRequest, flags); |
| dest.writeTypedObject(mGetCredentialRequest, flags); |
| dest.writeBoolean(mHasPermissionToOverrideDefault); |
| dest.writeStringList(mDefaultProviderIds); |
| dest.writeStringList(mRegistryProviderIds); |
| dest.writeBoolean(mIsShowAllOptionsRequested); |
| } |
| |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| @NonNull |
| public static final Creator<RequestInfo> CREATOR = new Creator<>() { |
| @Override |
| public RequestInfo createFromParcel(@NonNull Parcel in) { |
| return new RequestInfo(in); |
| } |
| |
| @Override |
| public RequestInfo[] newArray(int size) { |
| return new RequestInfo[size]; |
| } |
| }; |
| } |