blob: 768e743612ed1cc076fdc022932f2ccd110e69ce [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
19import android.annotation.IntDef;
20import android.annotation.Nullable;
21import android.content.IntentSender;
22import android.os.Bundle;
23import android.os.Parcel;
24import android.os.Parcelable;
Felipe Leme63f79062017-09-06 09:10:51 -070025import android.view.autofill.AutofillManager;
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -070026
27import com.android.internal.util.Preconditions;
28
29import java.lang.annotation.Retention;
30import java.lang.annotation.RetentionPolicy;
31import java.util.ArrayList;
32import java.util.List;
33
34/**
Felipe Leme2e30c6f2017-06-20 10:55:01 -070035 * Describes what happened after the last
36 * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}
37 * call.
38 *
39 * <p>This history is typically used to keep track of previous user actions to optimize further
40 * requests. For example, the service might return email addresses in alphabetical order by
41 * default, but change that order based on the address the user picked on previous requests.
42 *
43 * <p>The history is not persisted over reboots, and it's cleared every time the service
44 * replies to a
45 * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}
46 * by calling {@link FillCallback#onSuccess(FillResponse)} or
47 * {@link FillCallback#onFailure(CharSequence)} (if the service doesn't call any of these methods,
48 * the history will clear out after some pre-defined time).
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -070049 */
50public final class FillEventHistory implements Parcelable {
51 /**
52 * Not in parcel. The UID of the {@link AutofillService} that created the {@link FillResponse}.
53 */
54 private final int mServiceUid;
55
Felipe Lemed013bce2017-06-20 17:15:45 -070056 /**
57 * Not in parcel. The ID of the autofill session that created the {@link FillResponse}.
58 */
59 private final int mSessionId;
60
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -070061 @Nullable private final Bundle mClientState;
62 @Nullable List<Event> mEvents;
63
64 /**
65 * Gets the UID of the {@link AutofillService} that created the {@link FillResponse}.
66 *
67 * @return The UID of the {@link AutofillService}
68 *
69 * @hide
70 */
71 public int getServiceUid() {
72 return mServiceUid;
73 }
74
Felipe Lemed013bce2017-06-20 17:15:45 -070075 /** @hide */
76 public int getSessionId() {
77 return mSessionId;
78 }
79
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -070080 /**
Felipe Leme2e30c6f2017-06-20 10:55:01 -070081 * Returns the client state set in the previous {@link FillResponse}.
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -070082 *
Felipe Leme63f79062017-09-06 09:10:51 -070083 * <p><b>Note: </b>the state is associated with the app that was autofilled in the previous
Felipe Leme2e30c6f2017-06-20 10:55:01 -070084 * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}
85 * , which is not necessary the same app being autofilled now.
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -070086 */
87 @Nullable public Bundle getClientState() {
88 return mClientState;
89 }
90
91 /**
92 * Returns the events occurred after the latest call to
93 * {@link FillCallback#onSuccess(FillResponse)}.
94 *
95 * @return The list of events or {@code null} if non occurred.
96 */
97 @Nullable public List<Event> getEvents() {
98 return mEvents;
99 }
100
101 /**
102 * @hide
103 */
104 public void addEvent(Event event) {
105 if (mEvents == null) {
106 mEvents = new ArrayList<>(1);
107 }
108 mEvents.add(event);
109 }
110
111 /**
112 * @hide
113 */
Felipe Lemed013bce2017-06-20 17:15:45 -0700114 public FillEventHistory(int serviceUid, int sessionId, @Nullable Bundle clientState) {
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700115 mClientState = clientState;
116 mServiceUid = serviceUid;
Felipe Lemed013bce2017-06-20 17:15:45 -0700117 mSessionId = sessionId;
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700118 }
119
120 @Override
121 public int describeContents() {
122 return 0;
123 }
124
125 @Override
126 public void writeToParcel(Parcel dest, int flags) {
127 dest.writeBundle(mClientState);
128
129 if (mEvents == null) {
130 dest.writeInt(0);
131 } else {
132 dest.writeInt(mEvents.size());
133
134 int numEvents = mEvents.size();
135 for (int i = 0; i < numEvents; i++) {
136 Event event = mEvents.get(i);
137 dest.writeInt(event.getType());
138 dest.writeString(event.getDatasetId());
139 }
140 }
141 }
142
143 /**
144 * Description of an event that occured after the latest call to
145 * {@link FillCallback#onSuccess(FillResponse)}.
146 */
147 public static final class Event {
148 /**
149 * A dataset was selected. The dataset selected can be read from {@link #getDatasetId()}.
Felipe Leme63f79062017-09-06 09:10:51 -0700150 *
151 * <p><b>Note: </b>on Android {@link android.os.Build.VERSION_CODES#O}, this event was also
152 * incorrectly reported after a
153 * {@link Dataset.Builder#setAuthentication(IntentSender) dataset authentication} was
154 * selected and the service returned a dataset in the
155 * {@link AutofillManager#EXTRA_AUTHENTICATION_RESULT} of the activity launched from that
156 * {@link IntentSender}. This behavior was fixed on Android
157 * {@link android.os.Build.VERSION_CODES#O_MR1}.
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700158 */
159 public static final int TYPE_DATASET_SELECTED = 0;
160
161 /**
162 * A {@link Dataset.Builder#setAuthentication(IntentSender) dataset authentication} was
163 * selected. The dataset authenticated can be read from {@link #getDatasetId()}.
164 */
165 public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1;
166
167 /**
Felipe Leme63f79062017-09-06 09:10:51 -0700168 * A {@link FillResponse.Builder#setAuthentication(android.view.autofill.AutofillId[],
169 * IntentSender, android.widget.RemoteViews) fill response authentication} was selected.
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700170 */
171 public static final int TYPE_AUTHENTICATION_SELECTED = 2;
172
173 /** A save UI was shown. */
174 public static final int TYPE_SAVE_SHOWN = 3;
175
176 /** @hide */
177 @IntDef(
178 value = {TYPE_DATASET_SELECTED,
179 TYPE_DATASET_AUTHENTICATION_SELECTED,
180 TYPE_AUTHENTICATION_SELECTED,
181 TYPE_SAVE_SHOWN})
182 @Retention(RetentionPolicy.SOURCE)
183 @interface EventIds{}
184
185 @EventIds private final int mEventType;
186 @Nullable private final String mDatasetId;
187
188 /**
189 * Returns the type of the event.
190 *
191 * @return The type of the event
192 */
193 public int getType() {
194 return mEventType;
195 }
196
197 /**
198 * Returns the id of dataset the id was on.
199 *
200 * @return The id of dataset, or {@code null} the event is not associated with a dataset.
201 */
202 @Nullable public String getDatasetId() {
203 return mDatasetId;
204 }
205
206 /**
207 * Creates a new event.
208 *
209 * @param eventType The type of the event
210 * @param datasetId The dataset the event was on, or {@code null} if the event was on the
211 * whole response.
212 *
213 * @hide
214 */
215 public Event(int eventType, String datasetId) {
216 mEventType = Preconditions.checkArgumentInRange(eventType, 0, TYPE_SAVE_SHOWN,
217 "eventType");
218 mDatasetId = datasetId;
219 }
220 }
221
222 public static final Parcelable.Creator<FillEventHistory> CREATOR =
223 new Parcelable.Creator<FillEventHistory>() {
224 @Override
225 public FillEventHistory createFromParcel(Parcel parcel) {
Felipe Lemed013bce2017-06-20 17:15:45 -0700226 FillEventHistory selection = new FillEventHistory(0, 0, parcel.readBundle());
Philip P. Moltmanncc684ed2017-04-17 14:18:33 -0700227
228 int numEvents = parcel.readInt();
229 for (int i = 0; i < numEvents; i++) {
230 selection.addEvent(new Event(parcel.readInt(), parcel.readString()));
231 }
232
233 return selection;
234 }
235
236 @Override
237 public FillEventHistory[] newArray(int size) {
238 return new FillEventHistory[size];
239 }
240 };
241}