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