blob: c65e773283cb42a7d972e6ce23a34bffa6ed6158 [file] [log] [blame]
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -07001/*
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
17package android.service.autofill;
18
Felipe Leme5672def2017-12-04 14:57:09 -080019import static android.view.autofill.Helper.sVerbose;
20
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -070021import android.annotation.IntDef;
Felipe Leme59c44642017-10-13 11:05:05 -070022import android.annotation.NonNull;
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -070023import android.annotation.Nullable;
24import android.content.IntentSender;
25import android.os.Bundle;
26import android.os.Parcel;
27import android.os.Parcelable;
Felipe Leme59c44642017-10-13 11:05:05 -070028import android.util.ArrayMap;
29import android.util.ArraySet;
Felipe Leme5672def2017-12-04 14:57:09 -080030import android.util.Log;
Felipe Leme59c44642017-10-13 11:05:05 -070031import android.view.autofill.AutofillId;
Felipe Leme8f0fad82017-09-06 09:10:51 -070032import android.view.autofill.AutofillManager;
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -070033
Felipe Leme59c44642017-10-13 11:05:05 -070034import com.android.internal.util.ArrayUtils;
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -070035import com.android.internal.util.Preconditions;
36
37import java.lang.annotation.Retention;
38import java.lang.annotation.RetentionPolicy;
39import java.util.ArrayList;
Felipe Leme5672def2017-12-04 14:57:09 -080040import java.util.Arrays;
Felipe Leme59c44642017-10-13 11:05:05 -070041import java.util.Collections;
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -070042import java.util.List;
Felipe Leme59c44642017-10-13 11:05:05 -070043import java.util.Map;
44import java.util.Set;
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -070045
46/**
Felipe Leme2e30c6f2017-06-20 10:55:01 -070047 * Describes what happened after the last
48 * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}
49 * call.
50 *
51 * <p>This history is typically used to keep track of previous user actions to optimize further
52 * requests. For example, the service might return email addresses in alphabetical order by
53 * default, but change that order based on the address the user picked on previous requests.
54 *
55 * <p>The history is not persisted over reboots, and it's cleared every time the service
56 * replies to a
57 * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}
58 * by calling {@link FillCallback#onSuccess(FillResponse)} or
59 * {@link FillCallback#onFailure(CharSequence)} (if the service doesn't call any of these methods,
60 * the history will clear out after some pre-defined time).
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -070061 */
62public final class FillEventHistory implements Parcelable {
Felipe Leme5672def2017-12-04 14:57:09 -080063 private static final String TAG = "FillEventHistory";
64
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -070065 /**
Felipe Lemed013bce2017-06-20 17:15:45 -070066 * Not in parcel. The ID of the autofill session that created the {@link FillResponse}.
67 */
68 private final int mSessionId;
69
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -070070 @Nullable private final Bundle mClientState;
71 @Nullable List<Event> mEvents;
72
Felipe Lemed013bce2017-06-20 17:15:45 -070073 /** @hide */
74 public int getSessionId() {
75 return mSessionId;
76 }
77
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -070078 /**
Felipe Leme2e30c6f2017-06-20 10:55:01 -070079 * Returns the client state set in the previous {@link FillResponse}.
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -070080 *
Felipe Leme1c501eb2017-08-29 16:19:28 -070081 * <p><b>Note: </b>the state is associated with the app that was autofilled in the previous
Felipe Leme2e30c6f2017-06-20 10:55:01 -070082 * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}
83 * , which is not necessary the same app being autofilled now.
Felipe Leme1c501eb2017-08-29 16:19:28 -070084 *
85 * @deprecated use {@link #getEvents()} then {@link Event#getClientState()} instead.
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -070086 */
Felipe Leme1c501eb2017-08-29 16:19:28 -070087 @Deprecated
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -070088 @Nullable public Bundle getClientState() {
89 return mClientState;
90 }
91
92 /**
93 * Returns the events occurred after the latest call to
94 * {@link FillCallback#onSuccess(FillResponse)}.
95 *
96 * @return The list of events or {@code null} if non occurred.
97 */
98 @Nullable public List<Event> getEvents() {
99 return mEvents;
100 }
101
102 /**
103 * @hide
104 */
105 public void addEvent(Event event) {
106 if (mEvents == null) {
107 mEvents = new ArrayList<>(1);
108 }
109 mEvents.add(event);
110 }
111
112 /**
113 * @hide
114 */
Felipe Leme452886a2017-11-27 13:09:13 -0800115 public FillEventHistory(int sessionId, @Nullable Bundle clientState) {
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700116 mClientState = clientState;
Felipe Lemed013bce2017-06-20 17:15:45 -0700117 mSessionId = sessionId;
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700118 }
119
120 @Override
Felipe Leme6f12e672017-10-20 13:04:19 -0700121 public String toString() {
122 return mEvents == null ? "no events" : mEvents.toString();
123 }
124
125 @Override
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700126 public int describeContents() {
127 return 0;
128 }
129
130 @Override
Felipe Lemebb6bfea2017-12-04 11:22:25 -0800131 public void writeToParcel(Parcel parcel, int flags) {
132 parcel.writeBundle(mClientState);
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700133 if (mEvents == null) {
Felipe Lemebb6bfea2017-12-04 11:22:25 -0800134 parcel.writeInt(0);
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700135 } else {
Felipe Lemebb6bfea2017-12-04 11:22:25 -0800136 parcel.writeInt(mEvents.size());
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700137
138 int numEvents = mEvents.size();
139 for (int i = 0; i < numEvents; i++) {
140 Event event = mEvents.get(i);
Felipe Lemebb6bfea2017-12-04 11:22:25 -0800141 parcel.writeInt(event.mEventType);
142 parcel.writeString(event.mDatasetId);
143 parcel.writeBundle(event.mClientState);
144 parcel.writeStringList(event.mSelectedDatasetIds);
145 parcel.writeArraySet(event.mIgnoredDatasetIds);
146 parcel.writeTypedList(event.mChangedFieldIds);
147 parcel.writeStringList(event.mChangedDatasetIds);
Felipe Leme59c44642017-10-13 11:05:05 -0700148
Felipe Lemebb6bfea2017-12-04 11:22:25 -0800149 parcel.writeTypedList(event.mManuallyFilledFieldIds);
Felipe Leme59c44642017-10-13 11:05:05 -0700150 if (event.mManuallyFilledFieldIds != null) {
151 final int size = event.mManuallyFilledFieldIds.size();
152 for (int j = 0; j < size; j++) {
Felipe Lemebb6bfea2017-12-04 11:22:25 -0800153 parcel.writeStringList(event.mManuallyFilledDatasetIds.get(j));
Felipe Leme59c44642017-10-13 11:05:05 -0700154 }
155 }
Felipe Leme5672def2017-12-04 14:57:09 -0800156 final AutofillId[] detectedFields = event.mDetectedFieldIds;
157 parcel.writeParcelableArray(detectedFields, flags);
158 if (detectedFields != null) {
Felipe Lemef1141c02017-12-18 09:38:36 -0800159 FieldClassification.writeArrayToParcel(parcel,
160 event.mDetectedFieldClassifications);
Felipe Leme24d71732017-10-20 10:32:57 -0700161 }
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700162 }
163 }
164 }
165
166 /**
167 * Description of an event that occured after the latest call to
168 * {@link FillCallback#onSuccess(FillResponse)}.
169 */
170 public static final class Event {
171 /**
172 * A dataset was selected. The dataset selected can be read from {@link #getDatasetId()}.
Felipe Leme8f0fad82017-09-06 09:10:51 -0700173 *
174 * <p><b>Note: </b>on Android {@link android.os.Build.VERSION_CODES#O}, this event was also
175 * incorrectly reported after a
176 * {@link Dataset.Builder#setAuthentication(IntentSender) dataset authentication} was
177 * selected and the service returned a dataset in the
178 * {@link AutofillManager#EXTRA_AUTHENTICATION_RESULT} of the activity launched from that
179 * {@link IntentSender}. This behavior was fixed on Android
180 * {@link android.os.Build.VERSION_CODES#O_MR1}.
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700181 */
182 public static final int TYPE_DATASET_SELECTED = 0;
183
184 /**
185 * A {@link Dataset.Builder#setAuthentication(IntentSender) dataset authentication} was
186 * selected. The dataset authenticated can be read from {@link #getDatasetId()}.
187 */
188 public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1;
189
190 /**
Felipe Leme8f0fad82017-09-06 09:10:51 -0700191 * A {@link FillResponse.Builder#setAuthentication(android.view.autofill.AutofillId[],
192 * IntentSender, android.widget.RemoteViews) fill response authentication} was selected.
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700193 */
194 public static final int TYPE_AUTHENTICATION_SELECTED = 2;
195
196 /** A save UI was shown. */
197 public static final int TYPE_SAVE_SHOWN = 3;
198
Felipe Leme59c44642017-10-13 11:05:05 -0700199 /**
200 * A committed autofill context for which the autofill service provided datasets.
201 *
202 * <p>This event is useful to track:
203 * <ul>
204 * <li>Which datasets (if any) were selected by the user
205 * ({@link #getSelectedDatasetIds()}).
206 * <li>Which datasets (if any) were NOT selected by the user
207 * ({@link #getIgnoredDatasetIds()}).
208 * <li>Which fields in the selected datasets were changed by the user after the dataset
209 * was selected ({@link #getChangedFields()}.
Felipe Leme78172e72017-12-08 17:01:15 -0800210 * <li>Which fields match the {@link UserData} set by the service.
Felipe Leme59c44642017-10-13 11:05:05 -0700211 * </ul>
212 *
213 * <p><b>Note: </b>This event is only generated when:
214 * <ul>
215 * <li>The autofill context is committed.
216 * <li>The service provides at least one dataset in the
217 * {@link FillResponse fill responses} associated with the context.
218 * <li>The last {@link FillResponse fill responses} associated with the context has the
219 * {@link FillResponse#FLAG_TRACK_CONTEXT_COMMITED} flag.
220 * </ul>
221 *
222 * <p>See {@link android.view.autofill.AutofillManager} for more information about autofill
223 * contexts.
224 */
225 public static final int TYPE_CONTEXT_COMMITTED = 4;
226
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700227 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700228 @IntDef(prefix = { "TYPE_" }, value = {
229 TYPE_DATASET_SELECTED,
230 TYPE_DATASET_AUTHENTICATION_SELECTED,
231 TYPE_AUTHENTICATION_SELECTED,
232 TYPE_SAVE_SHOWN,
233 TYPE_CONTEXT_COMMITTED
234 })
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700235 @Retention(RetentionPolicy.SOURCE)
236 @interface EventIds{}
237
238 @EventIds private final int mEventType;
239 @Nullable private final String mDatasetId;
Felipe Leme1c501eb2017-08-29 16:19:28 -0700240 @Nullable private final Bundle mClientState;
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700241
Felipe Leme59c44642017-10-13 11:05:05 -0700242 // Note: mSelectedDatasetIds is stored as List<> instead of Set because Session already
243 // stores it as List
244 @Nullable private final List<String> mSelectedDatasetIds;
245 @Nullable private final ArraySet<String> mIgnoredDatasetIds;
246
247 @Nullable private final ArrayList<AutofillId> mChangedFieldIds;
248 @Nullable private final ArrayList<String> mChangedDatasetIds;
249
250 @Nullable private final ArrayList<AutofillId> mManuallyFilledFieldIds;
251 @Nullable private final ArrayList<ArrayList<String>> mManuallyFilledDatasetIds;
252
Felipe Leme5672def2017-12-04 14:57:09 -0800253 @Nullable private final AutofillId[] mDetectedFieldIds;
Felipe Leme51f6cd72017-12-18 09:30:53 -0800254 @Nullable private final FieldClassification[] mDetectedFieldClassifications;
Felipe Leme24d71732017-10-20 10:32:57 -0700255
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700256 /**
257 * Returns the type of the event.
258 *
259 * @return The type of the event
260 */
261 public int getType() {
262 return mEventType;
263 }
264
265 /**
266 * Returns the id of dataset the id was on.
267 *
268 * @return The id of dataset, or {@code null} the event is not associated with a dataset.
269 */
270 @Nullable public String getDatasetId() {
271 return mDatasetId;
272 }
273
274 /**
Felipe Leme1c501eb2017-08-29 16:19:28 -0700275 * Returns the client state from the {@link FillResponse} used to generate this event.
276 *
277 * <p><b>Note: </b>the state is associated with the app that was autofilled in the previous
278 * {@link
279 * AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)},
280 * which is not necessary the same app being autofilled now.
281 */
282 @Nullable public Bundle getClientState() {
283 return mClientState;
284 }
285
286 /**
Felipe Leme59c44642017-10-13 11:05:05 -0700287 * Returns which datasets were selected by the user.
288 *
289 * <p><b>Note: </b>Only set on events of type {@link #TYPE_CONTEXT_COMMITTED}.
290 */
291 @NonNull public Set<String> getSelectedDatasetIds() {
292 return mSelectedDatasetIds == null ? Collections.emptySet()
293 : new ArraySet<>(mSelectedDatasetIds);
294 }
295
296 /**
297 * Returns which datasets were NOT selected by the user.
298 *
299 * <p><b>Note: </b>Only set on events of type {@link #TYPE_CONTEXT_COMMITTED}.
300 */
301 @NonNull public Set<String> getIgnoredDatasetIds() {
302 return mIgnoredDatasetIds == null ? Collections.emptySet() : mIgnoredDatasetIds;
303 }
304
305 /**
306 * Returns which fields in the selected datasets were changed by the user after the dataset
307 * was selected.
308 *
309 * <p>For example, server provides:
310 *
311 * <pre class="prettyprint">
312 * FillResponse response = new FillResponse.Builder()
313 * .addDataset(new Dataset.Builder(presentation1)
314 * .setId("4815")
315 * .setValue(usernameId, AutofillValue.forText("MrPlow"))
316 * .build())
317 * .addDataset(new Dataset.Builder(presentation2)
318 * .setId("162342")
319 * .setValue(passwordId, AutofillValue.forText("D'OH"))
320 * .build())
321 * .build();
322 * </pre>
323 *
324 * <p>User select both datasets (for username and password) but after the fields are
325 * autofilled, user changes them to:
326 *
327 * <pre class="prettyprint">
328 * username = "ElBarto";
329 * password = "AyCaramba";
330 * </pre>
331 *
332 * <p>Then the result is the following map:
333 *
334 * <pre class="prettyprint">
335 * usernameId => "4815"
336 * passwordId => "162342"
337 * </pre>
338 *
339 * <p><b>Note: </b>Only set on events of type {@link #TYPE_CONTEXT_COMMITTED}.
340 *
341 * @return map map whose key is the id of the change fields, and value is the id of
342 * dataset that has that field and was selected by the user.
343 */
344 @NonNull public Map<AutofillId, String> getChangedFields() {
345 if (mChangedFieldIds == null || mChangedDatasetIds == null) {
346 return Collections.emptyMap();
347 }
348
349 final int size = mChangedFieldIds.size();
350 final ArrayMap<AutofillId, String> changedFields = new ArrayMap<>(size);
351 for (int i = 0; i < size; i++) {
352 changedFields.put(mChangedFieldIds.get(i), mChangedDatasetIds.get(i));
353 }
354 return changedFields;
355 }
356
357 /**
Felipe Leme78172e72017-12-08 17:01:15 -0800358 * Gets the <a href="AutofillService.html#FieldClassification">field classification</a>
359 * results.
Felipe Leme24d71732017-10-20 10:32:57 -0700360 *
361 * <p><b>Note: </b>Only set on events of type {@link #TYPE_CONTEXT_COMMITTED}, when the
Felipe Leme452886a2017-11-27 13:09:13 -0800362 * service requested {@link FillResponse.Builder#setFieldClassificationIds(AutofillId...)
Felipe Leme78172e72017-12-08 17:01:15 -0800363 * field classification}.
Felipe Leme24d71732017-10-20 10:32:57 -0700364 */
Felipe Lemebb6bfea2017-12-04 11:22:25 -0800365 @NonNull public Map<AutofillId, FieldClassification> getFieldsClassification() {
Felipe Leme5672def2017-12-04 14:57:09 -0800366 if (mDetectedFieldIds == null) {
Felipe Leme24d71732017-10-20 10:32:57 -0700367 return Collections.emptyMap();
368 }
Felipe Leme5672def2017-12-04 14:57:09 -0800369 final int size = mDetectedFieldIds.length;
370 final ArrayMap<AutofillId, FieldClassification> map = new ArrayMap<>(size);
371 for (int i = 0; i < size; i++) {
372 final AutofillId id = mDetectedFieldIds[i];
Felipe Leme51f6cd72017-12-18 09:30:53 -0800373 final FieldClassification fc = mDetectedFieldClassifications[i];
Felipe Leme5672def2017-12-04 14:57:09 -0800374 if (sVerbose) {
Felipe Leme51f6cd72017-12-18 09:30:53 -0800375 Log.v(TAG, "getFieldsClassification[" + i + "]: id=" + id + ", fc=" + fc);
Felipe Leme5672def2017-12-04 14:57:09 -0800376 }
Felipe Leme51f6cd72017-12-18 09:30:53 -0800377 map.put(id, fc);
Felipe Leme5672def2017-12-04 14:57:09 -0800378 }
Felipe Leme24d71732017-10-20 10:32:57 -0700379 return map;
380 }
381
382 /**
Felipe Leme59c44642017-10-13 11:05:05 -0700383 * Returns which fields were available on datasets provided by the service but manually
384 * entered by the user.
385 *
386 * <p>For example, server provides:
387 *
388 * <pre class="prettyprint">
389 * FillResponse response = new FillResponse.Builder()
390 * .addDataset(new Dataset.Builder(presentation1)
391 * .setId("4815")
392 * .setValue(usernameId, AutofillValue.forText("MrPlow"))
393 * .setValue(passwordId, AutofillValue.forText("AyCaramba"))
394 * .build())
395 * .addDataset(new Dataset.Builder(presentation2)
396 * .setId("162342")
397 * .setValue(usernameId, AutofillValue.forText("ElBarto"))
398 * .setValue(passwordId, AutofillValue.forText("D'OH"))
399 * .build())
400 * .addDataset(new Dataset.Builder(presentation3)
401 * .setId("108")
402 * .setValue(usernameId, AutofillValue.forText("MrPlow"))
403 * .setValue(passwordId, AutofillValue.forText("D'OH"))
404 * .build())
405 * .build();
406 * </pre>
407 *
408 * <p>User doesn't select a dataset but manually enters:
409 *
410 * <pre class="prettyprint">
411 * username = "MrPlow";
412 * password = "D'OH";
413 * </pre>
414 *
415 * <p>Then the result is the following map:
416 *
417 * <pre class="prettyprint">
418 * usernameId => { "4815", "108"}
419 * passwordId => { "162342", "108" }
420 * </pre>
421 *
422 * <p><b>Note: </b>Only set on events of type {@link #TYPE_CONTEXT_COMMITTED}.
423 *
424 * @return map map whose key is the id of the manually-entered field, and value is the
425 * ids of the datasets that have that value but were not selected by the user.
426 */
Felipe Leme7cdba9f2018-03-29 11:56:58 -0700427 @NonNull public Map<AutofillId, Set<String>> getManuallyEnteredField() {
Felipe Leme59c44642017-10-13 11:05:05 -0700428 if (mManuallyFilledFieldIds == null || mManuallyFilledDatasetIds == null) {
429 return Collections.emptyMap();
430 }
431
432 final int size = mManuallyFilledFieldIds.size();
433 final Map<AutofillId, Set<String>> manuallyFilledFields = new ArrayMap<>(size);
434 for (int i = 0; i < size; i++) {
435 final AutofillId fieldId = mManuallyFilledFieldIds.get(i);
436 final ArrayList<String> datasetIds = mManuallyFilledDatasetIds.get(i);
437 manuallyFilledFields.put(fieldId, new ArraySet<>(datasetIds));
438 }
439 return manuallyFilledFields;
440 }
441
442 /**
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700443 * Creates a new event.
444 *
445 * @param eventType The type of the event
446 * @param datasetId The dataset the event was on, or {@code null} if the event was on the
447 * whole response.
Felipe Leme1c501eb2017-08-29 16:19:28 -0700448 * @param clientState The client state associated with the event.
Felipe Leme59c44642017-10-13 11:05:05 -0700449 * @param selectedDatasetIds The ids of datasets selected by the user.
450 * @param ignoredDatasetIds The ids of datasets NOT select by the user.
451 * @param changedFieldIds The ids of fields changed by the user.
452 * @param changedDatasetIds The ids of the datasets that havd values matching the
453 * respective entry on {@code changedFieldIds}.
454 * @param manuallyFilledFieldIds The ids of fields that were manually entered by the user
455 * and belonged to datasets.
456 * @param manuallyFilledDatasetIds The ids of datasets that had values matching the
457 * respective entry on {@code manuallyFilledFieldIds}.
Felipe Leme51f6cd72017-12-18 09:30:53 -0800458 * @param detectedFieldClassifications the field classification matches.
Felipe Leme78172e72017-12-08 17:01:15 -0800459 *
Felipe Leme59c44642017-10-13 11:05:05 -0700460 * @throws IllegalArgumentException If the length of {@code changedFieldIds} and
461 * {@code changedDatasetIds} doesn't match.
462 * @throws IllegalArgumentException If the length of {@code manuallyFilledFieldIds} and
463 * {@code manuallyFilledDatasetIds} doesn't match.
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700464 *
465 * @hide
466 */
Felipe Leme59c44642017-10-13 11:05:05 -0700467 public Event(int eventType, @Nullable String datasetId, @Nullable Bundle clientState,
468 @Nullable List<String> selectedDatasetIds,
469 @Nullable ArraySet<String> ignoredDatasetIds,
470 @Nullable ArrayList<AutofillId> changedFieldIds,
471 @Nullable ArrayList<String> changedDatasetIds,
472 @Nullable ArrayList<AutofillId> manuallyFilledFieldIds,
Felipe Leme24d71732017-10-20 10:32:57 -0700473 @Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds,
Felipe Leme51f6cd72017-12-18 09:30:53 -0800474 @Nullable AutofillId[] detectedFieldIds,
475 @Nullable FieldClassification[] detectedFieldClassifications) {
Felipe Leme59c44642017-10-13 11:05:05 -0700476 mEventType = Preconditions.checkArgumentInRange(eventType, 0, TYPE_CONTEXT_COMMITTED,
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700477 "eventType");
478 mDatasetId = datasetId;
Felipe Leme1c501eb2017-08-29 16:19:28 -0700479 mClientState = clientState;
Felipe Leme59c44642017-10-13 11:05:05 -0700480 mSelectedDatasetIds = selectedDatasetIds;
481 mIgnoredDatasetIds = ignoredDatasetIds;
482 if (changedFieldIds != null) {
483 Preconditions.checkArgument(!ArrayUtils.isEmpty(changedFieldIds)
484 && changedDatasetIds != null
485 && changedFieldIds.size() == changedDatasetIds.size(),
486 "changed ids must have same length and not be empty");
487 }
488 mChangedFieldIds = changedFieldIds;
489 mChangedDatasetIds = changedDatasetIds;
490 if (manuallyFilledFieldIds != null) {
491 Preconditions.checkArgument(!ArrayUtils.isEmpty(manuallyFilledFieldIds)
492 && manuallyFilledDatasetIds != null
493 && manuallyFilledFieldIds.size() == manuallyFilledDatasetIds.size(),
494 "manually filled ids must have same length and not be empty");
495 }
496 mManuallyFilledFieldIds = manuallyFilledFieldIds;
497 mManuallyFilledDatasetIds = manuallyFilledDatasetIds;
Felipe Lemebb6bfea2017-12-04 11:22:25 -0800498
Felipe Leme5672def2017-12-04 14:57:09 -0800499 mDetectedFieldIds = detectedFieldIds;
Felipe Leme51f6cd72017-12-18 09:30:53 -0800500 mDetectedFieldClassifications = detectedFieldClassifications;
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700501 }
Felipe Leme98528972017-08-31 17:04:08 -0700502
503 @Override
504 public String toString() {
Felipe Leme59c44642017-10-13 11:05:05 -0700505 return "FillEvent [datasetId=" + mDatasetId
506 + ", type=" + mEventType
507 + ", selectedDatasets=" + mSelectedDatasetIds
508 + ", ignoredDatasetIds=" + mIgnoredDatasetIds
509 + ", changedFieldIds=" + mChangedFieldIds
510 + ", changedDatasetsIds=" + mChangedDatasetIds
511 + ", manuallyFilledFieldIds=" + mManuallyFilledFieldIds
512 + ", manuallyFilledDatasetIds=" + mManuallyFilledDatasetIds
Felipe Leme5672def2017-12-04 14:57:09 -0800513 + ", detectedFieldIds=" + Arrays.toString(mDetectedFieldIds)
Felipe Leme51f6cd72017-12-18 09:30:53 -0800514 + ", detectedFieldClassifications ="
515 + Arrays.toString(mDetectedFieldClassifications)
Felipe Leme59c44642017-10-13 11:05:05 -0700516 + "]";
Felipe Leme98528972017-08-31 17:04:08 -0700517 }
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700518 }
519
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700520 public static final @android.annotation.NonNull Parcelable.Creator<FillEventHistory> CREATOR =
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700521 new Parcelable.Creator<FillEventHistory>() {
522 @Override
523 public FillEventHistory createFromParcel(Parcel parcel) {
Felipe Leme452886a2017-11-27 13:09:13 -0800524 FillEventHistory selection = new FillEventHistory(0, parcel.readBundle());
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700525
Felipe Leme59c44642017-10-13 11:05:05 -0700526 final int numEvents = parcel.readInt();
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700527 for (int i = 0; i < numEvents; i++) {
Felipe Leme59c44642017-10-13 11:05:05 -0700528 final int eventType = parcel.readInt();
529 final String datasetId = parcel.readString();
530 final Bundle clientState = parcel.readBundle();
531 final ArrayList<String> selectedDatasetIds = parcel.createStringArrayList();
532 @SuppressWarnings("unchecked")
533 final ArraySet<String> ignoredDatasets =
534 (ArraySet<String>) parcel.readArraySet(null);
535 final ArrayList<AutofillId> changedFieldIds =
536 parcel.createTypedArrayList(AutofillId.CREATOR);
537 final ArrayList<String> changedDatasetIds = parcel.createStringArrayList();
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700538
Felipe Leme59c44642017-10-13 11:05:05 -0700539 final ArrayList<AutofillId> manuallyFilledFieldIds =
540 parcel.createTypedArrayList(AutofillId.CREATOR);
541 final ArrayList<ArrayList<String>> manuallyFilledDatasetIds;
542 if (manuallyFilledFieldIds != null) {
543 final int size = manuallyFilledFieldIds.size();
544 manuallyFilledDatasetIds = new ArrayList<>(size);
545 for (int j = 0; j < size; j++) {
546 manuallyFilledDatasetIds.add(parcel.createStringArrayList());
547 }
548 } else {
549 manuallyFilledDatasetIds = null;
550 }
Felipe Leme5672def2017-12-04 14:57:09 -0800551 final AutofillId[] detectedFieldIds = parcel.readParcelableArray(null,
552 AutofillId.class);
Felipe Leme51f6cd72017-12-18 09:30:53 -0800553 final FieldClassification[] detectedFieldClassifications =
554 (detectedFieldIds != null)
Felipe Lemef1141c02017-12-18 09:38:36 -0800555 ? FieldClassification.readArrayFromParcel(parcel)
Felipe Leme5672def2017-12-04 14:57:09 -0800556 : null;
Felipe Leme59c44642017-10-13 11:05:05 -0700557
558 selection.addEvent(new Event(eventType, datasetId, clientState,
559 selectedDatasetIds, ignoredDatasets,
560 changedFieldIds, changedDatasetIds,
Felipe Leme24d71732017-10-20 10:32:57 -0700561 manuallyFilledFieldIds, manuallyFilledDatasetIds,
Felipe Leme51f6cd72017-12-18 09:30:53 -0800562 detectedFieldIds, detectedFieldClassifications));
Felipe Leme59c44642017-10-13 11:05:05 -0700563 }
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700564 return selection;
565 }
566
567 @Override
568 public FillEventHistory[] newArray(int size) {
569 return new FillEventHistory[size];
570 }
571 };
572}