1 /*
2  * Copyright (C) 2017 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.autofill;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.os.Bundle;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 import android.view.View;
26 
27 import com.android.internal.util.Preconditions;
28 
29 import java.lang.annotation.Retention;
30 import java.lang.annotation.RetentionPolicy;
31 import java.util.ArrayList;
32 import java.util.List;
33 
34 /**
35  * This class represents a request to an autofill service
36  * to interpret the screen and provide information to the system which views are
37  * interesting for saving and what are the possible ways to fill the inputs on
38  * the screen if applicable.
39  *
40  * @see AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)
41  */
42 public final class FillRequest implements Parcelable {
43 
44     /**
45      * Indicates autofill was explicitly requested by the user.
46      *
47      * <p>Users typically make an explicit request to autofill a screen in two situations:
48      * <ul>
49      *   <li>The app disabled autofill (using {@link View#setImportantForAutofill(int)}.
50      *   <li>The service could not figure out how to autofill a screen (but the user knows the
51      *       service has data for that app).
52      * </ul>
53      *
54      * <p>This flag is particularly useful for the second case. For example, the service could offer
55      * a complex UI where the user can map which screen views belong to each user data, or it could
56      * offer a simpler UI where the user picks the data for just the view used to trigger the
57      * request (that would be the view whose
58      * {@link android.app.assist.AssistStructure.ViewNode#isFocused()} method returns {@code true}).
59      *
60      * <p>An explicit autofill request is triggered when the
61      * {@link android.view.autofill.AutofillManager#requestAutofill(View)} or
62      * {@link android.view.autofill.AutofillManager#requestAutofill(View, int, android.graphics.Rect)}
63      * is called. For example, standard {@link android.widget.TextView} views show an
64      * {@code AUTOFILL} option in the overflow menu that triggers such request.
65      */
66     public static final int FLAG_MANUAL_REQUEST = 0x1;
67 
68     /**
69      * Indicates this request was made using
70      * <a href="AutofillService.html#CompatibilityMode">compatibility mode</a>.
71      */
72     public static final int FLAG_COMPATIBILITY_MODE_REQUEST = 0x2;
73 
74     /**
75      * Indicates the request came from a password field.
76      *
77      * (TODO: b/141703197) Temporary fix for augmented autofill showing passwords.
78      *
79      * @hide
80      */
81     public static final @RequestFlags int FLAG_PASSWORD_INPUT_TYPE = 0x4;
82 
83     /** @hide */
84     public static final int INVALID_REQUEST_ID = Integer.MIN_VALUE;
85 
86     /** @hide */
87     @IntDef(flag = true, prefix = { "FLAG_" }, value = {
88             FLAG_MANUAL_REQUEST, FLAG_COMPATIBILITY_MODE_REQUEST, FLAG_PASSWORD_INPUT_TYPE
89     })
90     @Retention(RetentionPolicy.SOURCE)
91     @interface RequestFlags{}
92 
93     private final int mId;
94     private final @RequestFlags int mFlags;
95     private final @NonNull ArrayList<FillContext> mContexts;
96     private final @Nullable Bundle mClientState;
97 
FillRequest(@onNull Parcel parcel)98     private FillRequest(@NonNull Parcel parcel) {
99         mId = parcel.readInt();
100         mContexts = new ArrayList<>();
101         parcel.readParcelableList(mContexts, null);
102 
103         mClientState = parcel.readBundle();
104         mFlags = parcel.readInt();
105     }
106 
107     /** @hide */
FillRequest(int id, @NonNull ArrayList<FillContext> contexts, @Nullable Bundle clientState, @RequestFlags int flags)108     public FillRequest(int id, @NonNull ArrayList<FillContext> contexts,
109             @Nullable Bundle clientState, @RequestFlags int flags) {
110         mId = id;
111         mFlags = Preconditions.checkFlagsArgument(flags,
112                 FLAG_MANUAL_REQUEST | FLAG_COMPATIBILITY_MODE_REQUEST | FLAG_PASSWORD_INPUT_TYPE);
113         mContexts = Preconditions.checkCollectionElementsNotNull(contexts, "contexts");
114         mClientState = clientState;
115     }
116 
117     /**
118      * Gets the unique id of this request.
119      */
getId()120     public int getId() {
121         return mId;
122     }
123 
124     /**
125      * Gets the flags associated with this request.
126      *
127      * @return any combination of {@link #FLAG_MANUAL_REQUEST} and
128      *         {@link #FLAG_COMPATIBILITY_MODE_REQUEST}.
129      */
getFlags()130     public @RequestFlags int getFlags() {
131         return mFlags;
132     }
133 
134     /**
135      * Gets the contexts associated with each previous fill request.
136      *
137      * <p><b>Note:</b> Starting on Android {@link android.os.Build.VERSION_CODES#Q}, it could also
138      * include contexts from requests whose {@link SaveInfo} had the
139      * {@link SaveInfo#FLAG_DELAY_SAVE} flag.
140      */
getFillContexts()141     public @NonNull List<FillContext> getFillContexts() {
142         return mContexts;
143     }
144 
145     @Override
toString()146     public String toString() {
147         return "FillRequest: [id=" + mId + ", flags=" + mFlags + ", ctxts= " + mContexts + "]";
148     }
149 
150     /**
151      * Gets the latest client state bundle set by the service in a
152      * {@link FillResponse.Builder#setClientState(Bundle) fill response}.
153      *
154      * <p><b>Note:</b> Prior to Android {@link android.os.Build.VERSION_CODES#P}, only client state
155      * bundles set by {@link FillResponse.Builder#setClientState(Bundle)} were considered. On
156      * Android {@link android.os.Build.VERSION_CODES#P} and higher, bundles set in the result of
157      * an authenticated request through the
158      * {@link android.view.autofill.AutofillManager#EXTRA_CLIENT_STATE} extra are
159      * also considered (and take precedence when set).
160      *
161      * @return The client state.
162      */
getClientState()163     public @Nullable Bundle getClientState() {
164         return mClientState;
165     }
166 
167     @Override
describeContents()168     public int describeContents() {
169         return 0;
170     }
171 
172     @Override
writeToParcel(Parcel parcel, int flags)173     public void writeToParcel(Parcel parcel, int flags) {
174         parcel.writeInt(mId);
175         parcel.writeParcelableList(mContexts, flags);
176         parcel.writeBundle(mClientState);
177         parcel.writeInt(mFlags);
178     }
179 
180     public static final @android.annotation.NonNull Parcelable.Creator<FillRequest> CREATOR =
181             new Parcelable.Creator<FillRequest>() {
182         @Override
183         public FillRequest createFromParcel(Parcel parcel) {
184             return new FillRequest(parcel);
185         }
186 
187         @Override
188         public FillRequest[] newArray(int size) {
189             return new FillRequest[size];
190         }
191     };
192 }
193