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
17package android.service.autofill;
18
19import android.annotation.IntDef;
20import android.annotation.NonNull;
21import android.annotation.Nullable;
22import android.os.Bundle;
23import android.os.CancellationSignal;
24import android.os.Parcel;
25import android.os.Parcelable;
26import android.view.View;
27
28import com.android.internal.util.Preconditions;
29
30import java.lang.annotation.Retention;
31import java.lang.annotation.RetentionPolicy;
32import java.util.ArrayList;
33import java.util.List;
34
35/**
36 * This class represents a request to an autofill service
37 * to interpret the screen and provide information to the system which views are
38 * interesting for saving and what are the possible ways to fill the inputs on
39 * the screen if applicable.
40 *
41 * @see AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)
42 */
43public final class FillRequest implements Parcelable {
44
45    /**
46     * Indicates autofill was explicitly requested by the user.
47     *
48     * <p>Users typically make an explicit request to autofill a screen in two situations:
49     * <ul>
50     *   <li>The app disabled autofill (using {@link View#setImportantForAutofill(int)}.
51     *   <li>The service could not figure out how to autofill a screen (but the user knows the
52     *       service has data for that app).
53     * </ul>
54     *
55     * <p>This flag is particularly useful for the second case. For example, the service could offer
56     * a complex UI where the user can map which screen views belong to each user data, or it could
57     * offer a simpler UI where the user picks the data for just the view used to trigger the
58     * request (that would be the view whose
59     * {@link android.app.assist.AssistStructure.ViewNode#isFocused()} method returns {@code true}).
60     *
61     * <p>An explicit autofill request is triggered when the
62     * {@link android.view.autofill.AutofillManager#requestAutofill(View)} or
63     * {@link android.view.autofill.AutofillManager#requestAutofill(View, int, android.graphics.Rect)}
64     * is called. For example, standard {@link android.widget.TextView} views that use
65     * an {@link android.widget.Editor} shows an {@code AUTOFILL} option in the overflow menu that
66     * triggers such request.
67     */
68    public static final int FLAG_MANUAL_REQUEST = 0x1;
69
70    /** @hide */
71    public static final int INVALID_REQUEST_ID = Integer.MIN_VALUE;
72
73    /** @hide */
74    @IntDef(
75        flag = true,
76        value = {FLAG_MANUAL_REQUEST})
77    @Retention(RetentionPolicy.SOURCE)
78    @interface RequestFlags{}
79
80    private final int mId;
81    private final @RequestFlags int mFlags;
82    private final @NonNull ArrayList<FillContext> mContexts;
83    private final @Nullable Bundle mClientState;
84
85    private FillRequest(@NonNull Parcel parcel) {
86        mId = parcel.readInt();
87        mContexts = new ArrayList<>();
88        parcel.readParcelableList(mContexts, null);
89
90        mClientState = parcel.readBundle();
91        mFlags = parcel.readInt();
92    }
93
94    /** @hide */
95    public FillRequest(int id, @NonNull ArrayList<FillContext> contexts,
96            @Nullable Bundle clientState, @RequestFlags int flags) {
97        mId = id;
98        mFlags = Preconditions.checkFlagsArgument(flags, FLAG_MANUAL_REQUEST);
99        mContexts = Preconditions.checkCollectionElementsNotNull(contexts, "contexts");
100        mClientState = clientState;
101    }
102
103    /**
104     * Gets the unique id of this request.
105     */
106    public int getId() {
107        return mId;
108    }
109
110    /**
111     * Gets the flags associated with this request.
112     *
113     * @see #FLAG_MANUAL_REQUEST
114     */
115    public @RequestFlags int getFlags() {
116        return mFlags;
117    }
118
119    /**
120     * Gets the contexts associated with each previous fill request.
121     */
122    public @NonNull List<FillContext> getFillContexts() {
123        return mContexts;
124    }
125
126    /**
127     * Gets the extra client state returned from the last {@link
128     * AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)
129     * fill request}, so the service can use it for state management.
130     *
131     * <p>Once a {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)
132     * save request} is made, the client state is cleared.
133     *
134     * @return The client state.
135     */
136    public @Nullable Bundle getClientState() {
137        return mClientState;
138    }
139
140    @Override
141    public int describeContents() {
142        return 0;
143    }
144
145    @Override
146    public void writeToParcel(Parcel parcel, int flags) {
147        parcel.writeInt(mId);
148        parcel.writeParcelableList(mContexts, flags);
149        parcel.writeBundle(mClientState);
150        parcel.writeInt(mFlags);
151    }
152
153    public static final Parcelable.Creator<FillRequest> CREATOR =
154            new Parcelable.Creator<FillRequest>() {
155        @Override
156        public FillRequest createFromParcel(Parcel parcel) {
157            return new FillRequest(parcel);
158        }
159
160        @Override
161        public FillRequest[] newArray(int size) {
162            return new FillRequest[size];
163        }
164    };
165}
166