1 /*
2  * Copyright (C) 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.service.credentials;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.app.PendingIntent;
22 import android.content.Intent;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 
26 import com.android.internal.util.AnnotationValidations;
27 import com.android.internal.util.Preconditions;
28 
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.Objects;
32 
33 /**
34  * Query stage request for getting user's credentials from a given credential provider.
35  *
36  * <p>This request contains a list of {@link BeginGetCredentialOption} that have parameters
37  * to be used to query credentials, and return a list of {@link CredentialEntry} to be set
38  * on the {@link BeginGetCredentialResponse}. This list is then shown to the user on a selector.
39  *
40  * If a {@link PendingIntent} is set on a {@link CredentialEntry}, and the user selects that
41  * entry, a {@link GetCredentialRequest} with all parameters needed to get the actual
42  * {@link android.credentials.Credential} will be sent as part of the {@link Intent} fired
43  * through the {@link PendingIntent}.
44  */
45 public final class BeginGetCredentialRequest implements Parcelable {
46     /** Info pertaining to the app requesting for credentials. */
47     @Nullable private final CallingAppInfo mCallingAppInfo;
48 
49     /**
50      * List of credential options. Each {@link BeginGetCredentialOption} object holds parameters to
51      * be used for populating a list of {@link CredentialEntry} for a specific type of credential.
52      *
53      * This request does not reveal sensitive parameters. Complete list of parameters
54      * is retrieved through the {@link PendingIntent} set on each {@link CredentialEntry}
55      * on {@link BeginGetCredentialResponse} set on {@link BeginGetCredentialResponse},
56      * when the user selects one of these entries.
57      */
58     @NonNull private final List<BeginGetCredentialOption> mBeginGetCredentialOptions;
59 
BeginGetCredentialRequest(@ullable CallingAppInfo callingAppInfo, @NonNull List<BeginGetCredentialOption> getBeginCredentialOptions)60     private BeginGetCredentialRequest(@Nullable CallingAppInfo callingAppInfo,
61             @NonNull List<BeginGetCredentialOption> getBeginCredentialOptions) {
62         this.mCallingAppInfo = callingAppInfo;
63         this.mBeginGetCredentialOptions = getBeginCredentialOptions;
64     }
65 
BeginGetCredentialRequest(@onNull Parcel in)66     private BeginGetCredentialRequest(@NonNull Parcel in) {
67         mCallingAppInfo = in.readTypedObject(CallingAppInfo.CREATOR);
68         List<BeginGetCredentialOption> getBeginCredentialOptions = new ArrayList<>();
69         in.readTypedList(getBeginCredentialOptions, BeginGetCredentialOption.CREATOR);
70         mBeginGetCredentialOptions = getBeginCredentialOptions;
71         AnnotationValidations.validate(NonNull.class, null, mBeginGetCredentialOptions);
72     }
73 
74     @NonNull
75     public static final Creator<BeginGetCredentialRequest> CREATOR =
76             new Creator<BeginGetCredentialRequest>() {
77                 @Override
78                 public BeginGetCredentialRequest createFromParcel(Parcel in) {
79                     return new BeginGetCredentialRequest(in);
80                 }
81 
82                 @Override
83                 public BeginGetCredentialRequest[] newArray(int size) {
84                     return new BeginGetCredentialRequest[size];
85                 }
86             };
87 
88     @Override
describeContents()89     public int describeContents() {
90         return 0;
91     }
92 
93     @Override
writeToParcel(@onNull Parcel dest, int flags)94     public void writeToParcel(@NonNull Parcel dest, int flags) {
95         dest.writeTypedObject(mCallingAppInfo, flags);
96         dest.writeTypedList(mBeginGetCredentialOptions);
97     }
98 
99     /**
100      * Returns info pertaining to the app requesting credentials.
101      */
getCallingAppInfo()102     public @Nullable CallingAppInfo getCallingAppInfo() {
103         return mCallingAppInfo;
104     }
105 
106     /**
107      * Returns the list of type specific credential options to list credentials for in
108      * {@link BeginGetCredentialResponse}.
109      */
getBeginGetCredentialOptions()110     public @NonNull List<BeginGetCredentialOption> getBeginGetCredentialOptions() {
111         return mBeginGetCredentialOptions;
112     }
113 
114     /**
115      * Builder for {@link BeginGetCredentialRequest}.
116      */
117     public static final class Builder {
118         private CallingAppInfo mCallingAppInfo = null;
119         private List<BeginGetCredentialOption> mBeginGetCredentialOptions = new ArrayList<>();
120 
121         /**
122          * Sets information pertaining to the calling app.
123          * @param callingAppInfo the info object containing the package name, and app signatures
124          */
setCallingAppInfo(@ullable CallingAppInfo callingAppInfo)125         public @NonNull Builder setCallingAppInfo(@Nullable CallingAppInfo callingAppInfo) {
126             mCallingAppInfo = callingAppInfo;
127             return this;
128         }
129 
130         /**
131          * Sets the list of credential options.
132          *
133          * @throws NullPointerException If {@code getBeginCredentialOptions} itself or any of its
134          * elements is null.
135          * @throws IllegalArgumentException If {@code getBeginCredentialOptions} is empty.
136          */
setBeginGetCredentialOptions( @onNull List<BeginGetCredentialOption> getBeginCredentialOptions)137         public @NonNull Builder setBeginGetCredentialOptions(
138                 @NonNull List<BeginGetCredentialOption> getBeginCredentialOptions) {
139             Preconditions.checkCollectionNotEmpty(getBeginCredentialOptions,
140                     "getBeginCredentialOptions");
141             Preconditions.checkCollectionElementsNotNull(getBeginCredentialOptions,
142                     "getBeginCredentialOptions");
143             mBeginGetCredentialOptions = getBeginCredentialOptions;
144             return this;
145         }
146 
147         /**
148          * Adds a single {@link BeginGetCredentialOption} object to the list of credential options.
149          *
150          * @throws NullPointerException If {@code beginGetCredentialOption} is null.
151          */
addBeginGetCredentialOption( @onNull BeginGetCredentialOption beginGetCredentialOption)152         public @NonNull Builder addBeginGetCredentialOption(
153                 @NonNull BeginGetCredentialOption beginGetCredentialOption) {
154             Objects.requireNonNull(beginGetCredentialOption,
155                     "beginGetCredentialOption must not be null");
156             mBeginGetCredentialOptions.add(beginGetCredentialOption);
157             return this;
158         }
159 
160         /**
161          * Builds a new {@link BeginGetCredentialRequest} instance.
162          *
163          * @throws NullPointerException If {@code beginGetCredentialOptions} is null.
164          * @throws IllegalArgumentException If {@code beginGetCredentialOptions} is empty, or if
165          * {@code callingAppInfo} is null or empty.
166          */
build()167         public @NonNull BeginGetCredentialRequest build() {
168             Preconditions.checkCollectionNotEmpty(mBeginGetCredentialOptions,
169                     "beginGetCredentialOptions");
170             return new BeginGetCredentialRequest(mCallingAppInfo, mBeginGetCredentialOptions);
171         }
172     }
173 }
174