1 /* 2 * Copyright 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.credentials.selection; 18 19 import static android.credentials.flags.Flags.FLAG_CONFIGURABLE_SELECTOR_UI_ENABLED; 20 21 import android.annotation.FlaggedApi; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.StringDef; 25 import android.annotation.SystemApi; 26 import android.annotation.TestApi; 27 import android.credentials.CreateCredentialRequest; 28 import android.credentials.GetCredentialRequest; 29 import android.os.IBinder; 30 import android.os.Parcel; 31 import android.os.Parcelable; 32 33 import com.android.internal.util.AnnotationValidations; 34 35 import java.lang.annotation.Retention; 36 import java.lang.annotation.RetentionPolicy; 37 import java.util.ArrayList; 38 import java.util.List; 39 40 /** 41 * Contains information about the request that initiated this UX flow. 42 * 43 * @hide 44 */ 45 @SystemApi 46 @FlaggedApi(FLAG_CONFIGURABLE_SELECTOR_UI_ENABLED) 47 public final class RequestInfo implements Parcelable { 48 49 /** 50 * The intent extra key for the {@code RequestInfo} object when launching the UX 51 * activities. 52 * 53 * @hide 54 */ 55 @NonNull 56 public static final String EXTRA_REQUEST_INFO = 57 "android.credentials.selection.extra.REQUEST_INFO"; 58 59 /** 60 * Type value for any request that does not require UI. 61 */ 62 @NonNull 63 public static final String TYPE_UNDEFINED = "android.credentials.selection.TYPE_UNDEFINED"; 64 /** 65 * Type value for a getCredential request. 66 */ 67 @NonNull 68 public static final String TYPE_GET = "android.credentials.selection.TYPE_GET"; 69 /** 70 * Type value for a getCredential request that utilizes the credential registry. 71 * 72 * @hide 73 */ 74 @NonNull 75 public static final String TYPE_GET_VIA_REGISTRY = 76 "android.credentials.selection.TYPE_GET_VIA_REGISTRY"; 77 /** 78 * Type value for a createCredential request. 79 */ 80 @NonNull 81 public static final String TYPE_CREATE = "android.credentials.selection.TYPE_CREATE"; 82 83 /** @hide */ 84 @Retention(RetentionPolicy.SOURCE) 85 @StringDef(value = {TYPE_GET, TYPE_CREATE, TYPE_UNDEFINED}) 86 public @interface RequestType { 87 } 88 89 @NonNull 90 private final IBinder mToken; 91 92 @Nullable 93 private final CreateCredentialRequest mCreateCredentialRequest; 94 95 @NonNull 96 private final List<String> mDefaultProviderIds; 97 98 @NonNull 99 private final List<String> mRegistryProviderIds; 100 101 @Nullable 102 private final GetCredentialRequest mGetCredentialRequest; 103 104 @NonNull 105 @RequestType 106 private final String mType; 107 108 @NonNull 109 private final String mPackageName; 110 111 private final boolean mHasPermissionToOverrideDefault; 112 113 private final boolean mIsShowAllOptionsRequested; 114 115 /** 116 * Creates new {@code RequestInfo} for a create-credential flow. 117 * 118 * @hide 119 */ 120 @TestApi 121 @FlaggedApi(FLAG_CONFIGURABLE_SELECTOR_UI_ENABLED) 122 @NonNull newCreateRequestInfo( @onNull IBinder token, @NonNull CreateCredentialRequest createCredentialRequest, @NonNull String appPackageName, boolean hasPermissionToOverrideDefault, @NonNull List<String> defaultProviderIds, boolean isShowAllOptionsRequested)123 public static RequestInfo newCreateRequestInfo( 124 @NonNull IBinder token, @NonNull CreateCredentialRequest createCredentialRequest, 125 @NonNull String appPackageName, boolean hasPermissionToOverrideDefault, 126 @NonNull List<String> defaultProviderIds, boolean isShowAllOptionsRequested) { 127 return new RequestInfo( 128 token, TYPE_CREATE, appPackageName, createCredentialRequest, null, 129 hasPermissionToOverrideDefault, defaultProviderIds, isShowAllOptionsRequested); 130 } 131 132 /** 133 * Creates new {@code RequestInfo} for a get-credential flow. 134 * 135 * @hide 136 */ 137 @TestApi 138 @FlaggedApi(FLAG_CONFIGURABLE_SELECTOR_UI_ENABLED) 139 @NonNull newGetRequestInfo( @onNull IBinder token, @NonNull GetCredentialRequest getCredentialRequest, @NonNull String appPackageName, boolean hasPermissionToOverrideDefault, boolean isShowAllOptionsRequested)140 public static RequestInfo newGetRequestInfo( 141 @NonNull IBinder token, @NonNull GetCredentialRequest getCredentialRequest, 142 @NonNull String appPackageName, boolean hasPermissionToOverrideDefault, 143 boolean isShowAllOptionsRequested) { 144 return new RequestInfo( 145 token, TYPE_GET, appPackageName, null, getCredentialRequest, 146 hasPermissionToOverrideDefault, 147 /*defaultProviderIds=*/ new ArrayList<>(), isShowAllOptionsRequested); 148 } 149 150 151 /** Returns whether the calling package has the permission. */ hasPermissionToOverrideDefault()152 public boolean hasPermissionToOverrideDefault() { 153 return mHasPermissionToOverrideDefault; 154 } 155 156 /** 157 * Returns the request token matching the user request. 158 * 159 * @hide 160 */ 161 @NonNull getToken()162 public IBinder getToken() { 163 return mToken; 164 } 165 166 /** Returns the request type. */ 167 @NonNull 168 @RequestType getType()169 public String getType() { 170 return mType; 171 } 172 173 /** Returns the display name of the app that made this request. */ 174 @NonNull getPackageName()175 public String getPackageName() { 176 return mPackageName; 177 } 178 179 /** 180 * Returns the non-null CreateCredentialRequest when the type of the request is {@link 181 * #TYPE_CREATE}, or null otherwise. 182 */ 183 @Nullable getCreateCredentialRequest()184 public CreateCredentialRequest getCreateCredentialRequest() { 185 return mCreateCredentialRequest; 186 } 187 188 /** Returns the request token matching the app request that should be cancelled. */ 189 @NonNull getRequestToken()190 public RequestToken getRequestToken() { 191 return new RequestToken(mToken); 192 } 193 194 /** 195 * Returns default provider identifiers (component or package name) configured from the user 196 * settings. 197 * 198 * Will only be possibly non-empty for the create use case. Not meaningful for the sign-in use 199 * case. 200 */ 201 @NonNull getDefaultProviderIds()202 public List<String> getDefaultProviderIds() { 203 return mDefaultProviderIds; 204 } 205 206 /** 207 * Returns provider identifiers (component or package name) that have been validated to provide 208 * registry entries. 209 */ 210 @NonNull getRegistryProviderIds()211 public List<String> getRegistryProviderIds() { 212 return mRegistryProviderIds; 213 } 214 215 /** 216 * Returns the non-null GetCredentialRequest when the type of the request is {@link 217 * #TYPE_GET}, or null otherwise. 218 */ 219 @Nullable getGetCredentialRequest()220 public GetCredentialRequest getGetCredentialRequest() { 221 return mGetCredentialRequest; 222 } 223 224 /** 225 * Returns true if all options should be immediately displayed in the UI, and false otherwise. 226 * 227 * Normally this bit is set to false, upon which the selection UI should first display a 228 * condensed view of popular, deduplicated options that is determined based on signals like 229 * last-used timestamps, credential type priorities, and preferred providers configured from the 230 * user settings {@link #getDefaultProviderIds()}; at the same time, the UI should offer an 231 * option (button) that navigates the user to viewing all options from this condensed view. 232 * 233 * In some special occasions, e.g. when a request is initiated from the autofill drop-down 234 * suggestion, this bit will be set to true to indicate that the selection UI should immediately 235 * render the all option UI. This means that the request initiator has collected a user signal 236 * to confirm that the user wants to view all the available options at once. 237 */ isShowAllOptionsRequested()238 public boolean isShowAllOptionsRequested() { 239 return mIsShowAllOptionsRequested; 240 } 241 RequestInfo(@onNull IBinder token, @NonNull @RequestType String type, @NonNull String appPackageName, @Nullable CreateCredentialRequest createCredentialRequest, @Nullable GetCredentialRequest getCredentialRequest, boolean hasPermissionToOverrideDefault, @NonNull List<String> defaultProviderIds, boolean isShowAllOptionsRequested)242 private RequestInfo(@NonNull IBinder token, @NonNull @RequestType String type, 243 @NonNull String appPackageName, 244 @Nullable CreateCredentialRequest createCredentialRequest, 245 @Nullable GetCredentialRequest getCredentialRequest, 246 boolean hasPermissionToOverrideDefault, 247 @NonNull List<String> defaultProviderIds, 248 boolean isShowAllOptionsRequested) { 249 mToken = token; 250 mType = type; 251 mPackageName = appPackageName; 252 mCreateCredentialRequest = createCredentialRequest; 253 mGetCredentialRequest = getCredentialRequest; 254 mHasPermissionToOverrideDefault = hasPermissionToOverrideDefault; 255 mDefaultProviderIds = defaultProviderIds == null ? new ArrayList<>() : defaultProviderIds; 256 mRegistryProviderIds = new ArrayList<>(); 257 mIsShowAllOptionsRequested = isShowAllOptionsRequested; 258 } 259 RequestInfo(@onNull Parcel in)260 private RequestInfo(@NonNull Parcel in) { 261 IBinder token = in.readStrongBinder(); 262 String type = in.readString8(); 263 String appPackageName = in.readString8(); 264 CreateCredentialRequest createCredentialRequest = 265 in.readTypedObject(CreateCredentialRequest.CREATOR); 266 GetCredentialRequest getCredentialRequest = 267 in.readTypedObject(GetCredentialRequest.CREATOR); 268 269 mToken = token; 270 AnnotationValidations.validate(NonNull.class, null, mToken); 271 mType = type; 272 AnnotationValidations.validate(NonNull.class, null, mType); 273 mPackageName = appPackageName; 274 AnnotationValidations.validate(NonNull.class, null, mPackageName); 275 mCreateCredentialRequest = createCredentialRequest; 276 mGetCredentialRequest = getCredentialRequest; 277 mHasPermissionToOverrideDefault = in.readBoolean(); 278 mDefaultProviderIds = in.createStringArrayList(); 279 mRegistryProviderIds = in.createStringArrayList(); 280 mIsShowAllOptionsRequested = in.readBoolean(); 281 } 282 283 @Override writeToParcel(@onNull Parcel dest, int flags)284 public void writeToParcel(@NonNull Parcel dest, int flags) { 285 dest.writeStrongBinder(mToken); 286 dest.writeString8(mType); 287 dest.writeString8(mPackageName); 288 dest.writeTypedObject(mCreateCredentialRequest, flags); 289 dest.writeTypedObject(mGetCredentialRequest, flags); 290 dest.writeBoolean(mHasPermissionToOverrideDefault); 291 dest.writeStringList(mDefaultProviderIds); 292 dest.writeStringList(mRegistryProviderIds); 293 dest.writeBoolean(mIsShowAllOptionsRequested); 294 } 295 296 @Override describeContents()297 public int describeContents() { 298 return 0; 299 } 300 301 @NonNull 302 public static final Creator<RequestInfo> CREATOR = new Creator<>() { 303 @Override 304 public RequestInfo createFromParcel(@NonNull Parcel in) { 305 return new RequestInfo(in); 306 } 307 308 @Override 309 public RequestInfo[] newArray(int size) { 310 return new RequestInfo[size]; 311 } 312 }; 313 } 314