16d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme/*
26d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * Copyright (C) 2016 The Android Open Source Project
36d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme *
46d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * Licensed under the Apache License, Version 2.0 (the "License");
56d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * you may not use this file except in compliance with the License.
66d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * You may obtain a copy of the License at
76d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme *
86d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme *      http://www.apache.org/licenses/LICENSE-2.0
96d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme *
106d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * Unless required by applicable law or agreed to in writing, software
116d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * distributed under the License is distributed on an "AS IS" BASIS,
126d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * See the License for the specific language governing permissions and
146d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * limitations under the License.
156d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme */
166d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
17782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganovpackage android.service.autofill;
186d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
199f9ee25515591ef33281708c0ab911962f4364a6Felipe Lemeimport static android.view.autofill.Helper.sDebug;
20d633f072552815301a559520a1f93eb7e79ba319Felipe Leme
210f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganovimport android.annotation.NonNull;
22436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Lemeimport android.annotation.Nullable;
230f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganovimport android.content.IntentSender;
246d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemeimport android.os.Parcel;
256d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemeimport android.os.Parcelable;
26640f30a7763b0a4b80c767acb84c740aac04768bFelipe Lemeimport android.view.autofill.AutofillId;
27640f30a7763b0a4b80c767acb84c740aac04768bFelipe Lemeimport android.view.autofill.AutofillValue;
2800c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganovimport android.widget.RemoteViews;
29d0b18d665ff8a42ccdc46be7a2382c67476c3c7bFelipe Leme
306d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemeimport com.android.internal.util.Preconditions;
316d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
326d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemeimport java.util.ArrayList;
3327a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Lemeimport java.util.regex.Pattern;
346d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
356d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme/**
3627a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * A dataset object represents a group of fields (key / value pairs) used to autofill parts of a
3727a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * screen.
386d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme *
3927a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * <a name="BasicUsage"></a>
4027a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * <h3>Basic usage</h3>
4127a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme *
4227a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * <p>In its simplest form, a dataset contains one or more fields (comprised of
4327a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * an {@link AutofillId id}, a {@link AutofillValue value}, and an optional filter
4427a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * {@link Pattern regex}); and one or more {@link RemoteViews presentations} for these fields
4527a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * (each field could have its own {@link RemoteViews presentation}, or use the default
4627a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * {@link RemoteViews presentation} associated with the whole dataset).
4727a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme *
4827a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * <p>When an autofill service returns datasets in a {@link FillResponse}
492ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * and the screen input is focused in a view that is present in at least one of these datasets,
5027a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * the Android System displays a UI containing the {@link RemoteViews presentation} of
512ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * all datasets pairs that have that view's {@link AutofillId}. Then, when the user selects a
5227a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * dataset from the UI, all views in that dataset are autofilled.
5327a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme *
5427a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * <a name="Authentication"></a>
5527a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * <h3>Dataset authentication</h3>
5627a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme *
5727a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * <p>In a more sophisticated form, the dataset values can be protected until the user authenticates
5827a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * the dataset&mdash;in that case, when a dataset is selected by the user, the Android System
5927a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * launches an intent set by the service to "unlock" the dataset.
6027a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme *
6127a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * <p>For example, when a data set contains credit card information (such as number,
6227a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * expiration date, and verification code), you could provide a dataset presentation saying
6327a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * "Tap to authenticate". Then when the user taps that option, you would launch an activity asking
6427a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * the user to enter the credit card code, and if the user enters a valid code, you could then
6527a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * "unlock" the dataset.
6627a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme *
6727a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * <p>You can also use authenticated datasets to offer an interactive UI for the user. For example,
6827a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * if the activity being autofilled is an account creation screen, you could use an authenticated
6927a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * dataset to automatically generate a random password for the user.
706d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme *
7127a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * <p>See {@link Dataset.Builder#setAuthentication(IntentSender)} for more details about the dataset
7227a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * authentication mechanism.
736d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme *
7427a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * <a name="Filtering"></a>
7527a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * <h3>Filtering</h3>
7627a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * <p>The autofill UI automatically changes which values are shown based on value of the view
7727a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * anchoring it, following the rules below:
7827a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * <ol>
7927a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme *   <li>If the view's {@link android.view.View#getAutofillValue() autofill value} is not
8027a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * {@link AutofillValue#isText() text} or is empty, all datasets are shown.
8127a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme *   <li>Datasets that have a filter regex (set through
8227a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * {@link Dataset.Builder#setValue(AutofillId, AutofillValue, Pattern)} or
8327a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * {@link Dataset.Builder#setValue(AutofillId, AutofillValue, Pattern, RemoteViews)}) and whose
8427a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * regex matches the view's text value converted to lower case are shown.
8527a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme *   <li>Datasets that do not require authentication, have a field value that is
8627a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * {@link AutofillValue#isText() text} and whose {@link AutofillValue#getTextValue() value} starts
8727a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * with the lower case value of the view's text are shown.
8827a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme *   <li>All other datasets are hidden.
8927a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * </ol>
9027a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme *
9127a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * <a name="MoreInfo"></a>
9227a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * <h3>More information</h3>
9327a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * <p>See {@link android.service.autofill.AutofillService} for more information and examples about
9427a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme * the role of datasets in the autofill workflow.
956d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme */
966d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemepublic final class Dataset implements Parcelable {
97782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov
98640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme    private final ArrayList<AutofillId> mFieldIds;
99640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme    private final ArrayList<AutofillValue> mFieldValues;
1005311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme    private final ArrayList<RemoteViews> mFieldPresentations;
10109d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme    private final ArrayList<DatasetFieldFilter> mFieldFilters;
10200c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov    private final RemoteViews mPresentation;
1030f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    private final IntentSender mAuthentication;
104cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann    @Nullable String mId;
1056d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
1060f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    private Dataset(Builder builder) {
1070f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        mFieldIds = builder.mFieldIds;
1080f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        mFieldValues = builder.mFieldValues;
1095311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme        mFieldPresentations = builder.mFieldPresentations;
11027a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme        mFieldFilters = builder.mFieldFilters;
11100c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov        mPresentation = builder.mPresentation;
1120f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        mAuthentication = builder.mAuthentication;
113cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann        mId = builder.mId;
1146d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    }
1156d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
1166d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    /** @hide */
117640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme    public @Nullable ArrayList<AutofillId> getFieldIds() {
1180f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        return mFieldIds;
119436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    }
120436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme
121436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    /** @hide */
122640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme    public @Nullable ArrayList<AutofillValue> getFieldValues() {
1230f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        return mFieldValues;
124436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    }
125436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme
126436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    /** @hide */
1275311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme    public RemoteViews getFieldPresentation(int index) {
1285311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme        final RemoteViews customPresentation = mFieldPresentations.get(index);
1295311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme        return customPresentation != null ? customPresentation : mPresentation;
1305311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme    }
1315311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme
1325311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme    /** @hide */
13327a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme    @Nullable
13409d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme    public DatasetFieldFilter getFilter(int index) {
13527a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme        return mFieldFilters.get(index);
13627a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme    }
13727a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme
13827a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme    /** @hide */
1390f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    public @Nullable IntentSender getAuthentication() {
1400f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        return mAuthentication;
141436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    }
142436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme
143436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    /** @hide */
1440f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    public boolean isEmpty() {
1450f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        return mFieldIds == null || mFieldIds.isEmpty();
146436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    }
147436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme
1486d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    @Override
1496d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    public String toString() {
1509f9ee25515591ef33281708c0ab911962f4364a6Felipe Leme        if (!sDebug) return super.toString();
1516d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
152da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme        final StringBuilder builder = new StringBuilder("Dataset[");
1536f12e67e1724cc52d0f5a5ca0b201a612d2859d8Felipe Leme        if (mId == null) {
154da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme            builder.append("noId");
1556f12e67e1724cc52d0f5a5ca0b201a612d2859d8Felipe Leme        } else {
1566f12e67e1724cc52d0f5a5ca0b201a612d2859d8Felipe Leme            // Cannot disclose id because it could contain PII.
157da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme            builder.append("id=").append(mId.length()).append("_chars");
1586f12e67e1724cc52d0f5a5ca0b201a612d2859d8Felipe Leme        }
159da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme        if (mFieldIds != null) {
160da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme            builder.append(", fieldIds=").append(mFieldIds);
161da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme        }
162da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme        if (mFieldValues != null) {
163da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme            builder.append(", fieldValues=").append(mFieldValues);
164da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme        }
165da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme        if (mFieldPresentations != null) {
166da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme            builder.append(", fieldPresentations=").append(mFieldPresentations.size());
1676f12e67e1724cc52d0f5a5ca0b201a612d2859d8Felipe Leme
168da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme        }
169da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme        if (mFieldFilters != null) {
170da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme            builder.append(", fieldFilters=").append(mFieldFilters.size());
171da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme        }
172da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme        if (mPresentation != null) {
173da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme            builder.append(", hasPresentation");
174da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme        }
175da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme        if (mAuthentication != null) {
176da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme            builder.append(", hasAuthentication");
177da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme        }
178da9ea34c029df809e6b833a483408662e13ca9a1Felipe Leme        return builder.append(']').toString();
1796d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    }
1806d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
1816d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    /**
182cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann     * Gets the id of this dataset.
183cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann     *
184cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann     * @return The id of this dataset or {@code null} if not set
185cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann     *
186cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann     * @hide
187cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann     */
188cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann    public String getId() {
189cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann        return mId;
190cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann    }
191cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann
192cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann    /**
1932ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme     * A builder for {@link Dataset} objects. You must provide at least
1940f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov     * one value for a field or set an authentication intent.
1956d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme     */
1966d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    public static final class Builder {
197640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme        private ArrayList<AutofillId> mFieldIds;
198640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme        private ArrayList<AutofillValue> mFieldValues;
1995311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme        private ArrayList<RemoteViews> mFieldPresentations;
20009d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme        private ArrayList<DatasetFieldFilter> mFieldFilters;
20100c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov        private RemoteViews mPresentation;
2020f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        private IntentSender mAuthentication;
2030f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        private boolean mDestroyed;
204cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann        @Nullable private String mId;
2050f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov
2066d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        /**
207eb49515abd2353f32e0eb7b3964847c6399986c9Svet Ganov         * Creates a new builder.
20800c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov         *
209eb49515abd2353f32e0eb7b3964847c6399986c9Svet Ganov         * @param presentation The presentation used to visualize this dataset.
2106d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme         */
211eb49515abd2353f32e0eb7b3964847c6399986c9Svet Ganov        public Builder(@NonNull RemoteViews presentation) {
212eb49515abd2353f32e0eb7b3964847c6399986c9Svet Ganov            Preconditions.checkNotNull(presentation, "presentation must be non-null");
21300c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov            mPresentation = presentation;
2146d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        }
2156d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
2166d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        /**
2175311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme         * Creates a new builder for a dataset where each field will be visualized independently.
2185311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme         *
2195311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme         * <p>When using this constructor, fields must be set through
2203a585a8ef14ffe57fe8addc690d06614f10e2033Felipe Leme         * {@link #setValue(AutofillId, AutofillValue, RemoteViews)} or
2213a585a8ef14ffe57fe8addc690d06614f10e2033Felipe Leme         * {@link #setValue(AutofillId, AutofillValue, Pattern, RemoteViews)}.
2225311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme         */
2235311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme        public Builder() {
2245311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme        }
2255311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme
2265311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme        /**
227601d22007488145f8651930d23aeb7a7a95cc591Felipe Leme         * Triggers a custom UI before before autofilling the screen with the contents of this
228601d22007488145f8651930d23aeb7a7a95cc591Felipe Leme         * dataset.
229601d22007488145f8651930d23aeb7a7a95cc591Felipe Leme         *
230601d22007488145f8651930d23aeb7a7a95cc591Felipe Leme         * <p><b>Note:</b> Although the name of this method suggests that it should be used just for
231601d22007488145f8651930d23aeb7a7a95cc591Felipe Leme         * authentication flow, it can be used for other advanced flows; see {@link AutofillService}
232601d22007488145f8651930d23aeb7a7a95cc591Felipe Leme         * for examples.
233436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme         *
2340f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov         * <p>This method is called when you need to provide an authentication
235782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * UI for the data set. For example, when a data set contains credit card information
2360f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov         * (such as number, expiration date, and verification code), you can display UI
23700c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov         * asking for the verification code before filing in the data. Even if the
238782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * data set is completely populated the system will launch the specified authentication
239782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * intent and will need your approval to fill it in. Since the data set is "locked"
240782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * until the user authenticates it, typically this data set name is masked
241782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * (for example, "VISA....1234"). Typically you would want to store the data set
242782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * labels non-encrypted and the actual sensitive data encrypted and not in memory.
2430f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov         * This allows showing the labels in the UI while involving the user if one of
2440f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov         * the items with these labels is chosen. Note that if you use sensitive data as
245782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * a label, for example an email address, then it should also be encrypted.</p>
246436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme         *
247640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme         * <p>When a user triggers autofill, the system launches the provided intent
248782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * whose extras will have the {@link
249a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov         * android.view.autofill.AutofillManager#EXTRA_ASSIST_STRUCTURE screen content},
250a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov         * and your {@link android.view.autofill.AutofillManager#EXTRA_CLIENT_STATE client
251a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov         * state}. Once you complete your authentication flow you should set the activity
252a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov         * result to {@link android.app.Activity#RESULT_OK} and provide the fully populated
253a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov         * {@link Dataset dataset} or a fully-populated {@link FillResponse response} by
254a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov         * setting it to the {@link
255a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov         * android.view.autofill.AutofillManager#EXTRA_AUTHENTICATION_RESULT} extra. If you
256a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov         * provide a dataset in the result, it will replace the authenticated dataset and
257a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov         * will be immediately filled in. If you provide a response, it will replace the
258a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov         * current response and the UI will be refreshed. For example, if you provided
259a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov         * credit card information without the CVV for the data set in the {@link FillResponse
260a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov         * response} then the returned data set should contain the CVV entry.
261436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme         *
26227a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * <p><b>Note:</b> Do not make the provided pending intent
2630f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov         * immutable by using {@link android.app.PendingIntent#FLAG_IMMUTABLE} as the
2642ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme         * platform needs to fill in the authentication arguments.
265436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme         *
266782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * @param authentication Intent to an activity with your authentication flow.
26727a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * @return this builder.
268436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme         *
269782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * @see android.app.PendingIntent
270436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme         */
2710f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        public @NonNull Builder setAuthentication(@Nullable IntentSender authentication) {
2720f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            throwIfDestroyed();
2730f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            mAuthentication = authentication;
274436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme            return this;
275436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme        }
276436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme
277436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme        /**
2789852897bf6a1d4c01ebb5afddaa13be5285810b9Felipe Leme         * Sets the id for the dataset so its usage can be tracked.
279cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann         *
2809852897bf6a1d4c01ebb5afddaa13be5285810b9Felipe Leme         * <p>Dataset usage can be tracked for 2 purposes:
2819852897bf6a1d4c01ebb5afddaa13be5285810b9Felipe Leme         *
2829852897bf6a1d4c01ebb5afddaa13be5285810b9Felipe Leme         * <ul>
2839852897bf6a1d4c01ebb5afddaa13be5285810b9Felipe Leme         *   <li>For statistical purposes, the service can call
2849852897bf6a1d4c01ebb5afddaa13be5285810b9Felipe Leme         * {@link AutofillService#getFillEventHistory()} when handling {@link
2859852897bf6a1d4c01ebb5afddaa13be5285810b9Felipe Leme         * AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}
2869852897bf6a1d4c01ebb5afddaa13be5285810b9Felipe Leme         * calls.
2879852897bf6a1d4c01ebb5afddaa13be5285810b9Felipe Leme         *   <li>For normal autofill workflow, the service can call
2889852897bf6a1d4c01ebb5afddaa13be5285810b9Felipe Leme         *   {@link SaveRequest#getDatasetIds()} when handling
2899852897bf6a1d4c01ebb5afddaa13be5285810b9Felipe Leme         *   {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)} calls.
2909852897bf6a1d4c01ebb5afddaa13be5285810b9Felipe Leme         * </ul>
291cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann         *
292cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann         * @param id id for this dataset or {@code null} to unset.
2939852897bf6a1d4c01ebb5afddaa13be5285810b9Felipe Leme         *
29427a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * @return this builder.
295cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann         */
296cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann        public @NonNull Builder setId(@Nullable String id) {
297cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann            throwIfDestroyed();
298cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann            mId = id;
299cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann            return this;
300cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann        }
301cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann
302cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann        /**
3036d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme         * Sets the value of a field.
3046d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme         *
3059856b19f4beb19164921de7dd1da638b61e58177Felipe Leme         * <b>Note:</b> Prior to Android {@link android.os.Build.VERSION_CODES#P}, this method would
3069856b19f4beb19164921de7dd1da638b61e58177Felipe Leme         * throw an {@link IllegalStateException} if this builder was constructed without a
3079856b19f4beb19164921de7dd1da638b61e58177Felipe Leme         * {@link RemoteViews presentation}. Android {@link android.os.Build.VERSION_CODES#P} and
3089856b19f4beb19164921de7dd1da638b61e58177Felipe Leme         * higher removed this restriction because datasets used as an
3099856b19f4beb19164921de7dd1da638b61e58177Felipe Leme         * {@link android.view.autofill.AutofillManager#EXTRA_AUTHENTICATION_RESULT
3109856b19f4beb19164921de7dd1da638b61e58177Felipe Leme         * authentication result} do not need a presentation. But if you don't set the presentation
3119856b19f4beb19164921de7dd1da638b61e58177Felipe Leme         * in the constructor in a dataset that is meant to be shown to the user, the autofill UI
3129856b19f4beb19164921de7dd1da638b61e58177Felipe Leme         * for this field will not be displayed.
3139856b19f4beb19164921de7dd1da638b61e58177Felipe Leme         *
314bbf8549ad0bab9f73501956278b25c57a17eb5abFelipe Leme         * <p><b>Note:</b> On Android {@link android.os.Build.VERSION_CODES#P} and
315bbf8549ad0bab9f73501956278b25c57a17eb5abFelipe Leme         * higher, datasets that require authentication can be also be filtered by passing a
316bbf8549ad0bab9f73501956278b25c57a17eb5abFelipe Leme         * {@link AutofillValue#forText(CharSequence) text value} as the {@code value} parameter.
317bbf8549ad0bab9f73501956278b25c57a17eb5abFelipe Leme         *
318782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * @param id id returned by {@link
319640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme         *         android.app.assist.AssistStructure.ViewNode#getAutofillId()}.
3202ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme         * @param value value to be autofilled. Pass {@code null} if you do not have the value
321a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov         *        but the target view is a logical part of the dataset. For example, if
32227a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         *        the dataset needs authentication and you have no access to the value.
32327a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * @return this builder.
3246d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme         */
325a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov        public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value) {
3260f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            throwIfDestroyed();
32727a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme            setLifeTheUniverseAndEverything(id, value, null, null);
3285311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme            return this;
3295311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme        }
3305311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme
3315311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme        /**
3322ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme         * Sets the value of a field, using a custom {@link RemoteViews presentation} to
3332ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme         * visualize it.
3345311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme         *
335bbf8549ad0bab9f73501956278b25c57a17eb5abFelipe Leme         * <p><b>Note:</b> On Android {@link android.os.Build.VERSION_CODES#P} and
336bbf8549ad0bab9f73501956278b25c57a17eb5abFelipe Leme         * higher, datasets that require authentication can be also be filtered by passing a
337bbf8549ad0bab9f73501956278b25c57a17eb5abFelipe Leme         * {@link AutofillValue#forText(CharSequence) text value} as the  {@code value} parameter.
338bbf8549ad0bab9f73501956278b25c57a17eb5abFelipe Leme         *
33936b86c28f88e4c7853a4255a0fd9b754cbb547c4Dake Gu         * <p>Theme does not work with RemoteViews layout. Avoid hardcoded text color
34036b86c28f88e4c7853a4255a0fd9b754cbb547c4Dake Gu         * or background color: Autofill on different platforms may have different themes.
34136b86c28f88e4c7853a4255a0fd9b754cbb547c4Dake Gu         *
3425311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme         * @param id id returned by {@link
3435311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme         *         android.app.assist.AssistStructure.ViewNode#getAutofillId()}.
34427a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * @param value the value to be autofilled. Pass {@code null} if you do not have the value
345a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov         *        but the target view is a logical part of the dataset. For example, if
34627a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         *        the dataset needs authentication and you have no access to the value.
34727a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * @param presentation the presentation used to visualize this field.
34827a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * @return this builder.
34927a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         *
3505311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme         */
351a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov        public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value,
3525311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                @NonNull RemoteViews presentation) {
3535311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme            throwIfDestroyed();
3545311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme            Preconditions.checkNotNull(presentation, "presentation cannot be null");
35527a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme            setLifeTheUniverseAndEverything(id, value, presentation, null);
35627a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme            return this;
35727a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme        }
35827a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme
35927a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme        /**
36027a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * Sets the value of a field using an <a href="#Filtering">explicit filter</a>.
36127a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         *
362bbf8549ad0bab9f73501956278b25c57a17eb5abFelipe Leme         * <p>This method is typically used when the dataset requires authentication and the service
363601d22007488145f8651930d23aeb7a7a95cc591Felipe Leme         * does not know its value but wants to hide the dataset after the user enters a minimum
364601d22007488145f8651930d23aeb7a7a95cc591Felipe Leme         * number of characters. For example, if the dataset represents a credit card number and the
365601d22007488145f8651930d23aeb7a7a95cc591Felipe Leme         * service does not want to show the "Tap to authenticate" message until the user tapped
366601d22007488145f8651930d23aeb7a7a95cc591Felipe Leme         * 4 digits, in which case the filter would be {@code Pattern.compile("\\d.{4,}")}.
36727a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         *
368bbf8549ad0bab9f73501956278b25c57a17eb5abFelipe Leme         * <p><b>Note:</b> If the dataset requires authentication but the service knows its text
369bbf8549ad0bab9f73501956278b25c57a17eb5abFelipe Leme         * value it's easier to filter by calling {@link #setValue(AutofillId, AutofillValue)} and
370bbf8549ad0bab9f73501956278b25c57a17eb5abFelipe Leme         * use the value to filter.
371bbf8549ad0bab9f73501956278b25c57a17eb5abFelipe Leme         *
37227a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * @param id id returned by {@link
37327a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         *         android.app.assist.AssistStructure.ViewNode#getAutofillId()}.
37427a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * @param value the value to be autofilled. Pass {@code null} if you do not have the value
37527a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         *        but the target view is a logical part of the dataset. For example, if
37627a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         *        the dataset needs authentication and you have no access to the value.
37709d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme         * @param filter regex used to determine if the dataset should be shown in the autofill UI;
37809d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme         *        when {@code null}, it disables filtering on that dataset (this is the recommended
37909d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme         *        approach when {@code value} is not {@code null} and field contains sensitive data
38009d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme         *        such as passwords).
38127a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         *
38227a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * @return this builder.
38327a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * @throws IllegalStateException if the builder was constructed without a
3849856b19f4beb19164921de7dd1da638b61e58177Felipe Leme         *         {@link RemoteViews presentation}.
38527a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         */
38627a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme        public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value,
38709d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme                @Nullable Pattern filter) {
38827a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme            throwIfDestroyed();
38927a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme            Preconditions.checkState(mPresentation != null,
39027a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme                    "Dataset presentation not set on constructor");
39109d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme            setLifeTheUniverseAndEverything(id, value, null, new DatasetFieldFilter(filter));
39227a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme            return this;
39327a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme        }
39427a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme
39527a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme        /**
39627a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * Sets the value of a field, using a custom {@link RemoteViews presentation} to
39727a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * visualize it and a <a href="#Filtering">explicit filter</a>.
39827a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         *
399bbf8549ad0bab9f73501956278b25c57a17eb5abFelipe Leme         * <p>This method is typically used when the dataset requires authentication and the service
400601d22007488145f8651930d23aeb7a7a95cc591Felipe Leme         * does not know its value but wants to hide the dataset after the user enters a minimum
401601d22007488145f8651930d23aeb7a7a95cc591Felipe Leme         * number of characters. For example, if the dataset represents a credit card number and the
402601d22007488145f8651930d23aeb7a7a95cc591Felipe Leme         * service does not want to show the "Tap to authenticate" message until the user tapped
403601d22007488145f8651930d23aeb7a7a95cc591Felipe Leme         * 4 digits, in which case the filter would be {@code Pattern.compile("\\d.{4,}")}.
40427a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         *
405bbf8549ad0bab9f73501956278b25c57a17eb5abFelipe Leme         * <p><b>Note:</b> If the dataset requires authentication but the service knows its text
406bbf8549ad0bab9f73501956278b25c57a17eb5abFelipe Leme         * value it's easier to filter by calling
407bbf8549ad0bab9f73501956278b25c57a17eb5abFelipe Leme         * {@link #setValue(AutofillId, AutofillValue, RemoteViews)} and using the value to filter.
408bbf8549ad0bab9f73501956278b25c57a17eb5abFelipe Leme         *
40927a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * @param id id returned by {@link
41027a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         *         android.app.assist.AssistStructure.ViewNode#getAutofillId()}.
41127a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * @param value the value to be autofilled. Pass {@code null} if you do not have the value
41227a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         *        but the target view is a logical part of the dataset. For example, if
41327a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         *        the dataset needs authentication and you have no access to the value.
41409d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme         * @param filter regex used to determine if the dataset should be shown in the autofill UI;
41509d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme         *        when {@code null}, it disables filtering on that dataset (this is the recommended
41609d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme         *        approach when {@code value} is not {@code null} and field contains sensitive data
41709d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme         *        such as passwords).
41827a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * @param presentation the presentation used to visualize this field.
41927a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         *
42027a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * @return this builder.
42127a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         */
42227a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme        public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value,
42309d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme                @Nullable Pattern filter, @NonNull RemoteViews presentation) {
42427a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme            throwIfDestroyed();
42527a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme            Preconditions.checkNotNull(presentation, "presentation cannot be null");
42609d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme            setLifeTheUniverseAndEverything(id, value, presentation,
42709d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme                    new DatasetFieldFilter(filter));
4285311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme            return this;
4295311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme        }
4305311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme
43127a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme        private void setLifeTheUniverseAndEverything(@NonNull AutofillId id,
43227a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme                @Nullable AutofillValue value, @Nullable RemoteViews presentation,
43309d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme                @Nullable DatasetFieldFilter filter) {
4340f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            Preconditions.checkNotNull(id, "id cannot be null");
4350f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            if (mFieldIds != null) {
4360f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                final int existingIdx = mFieldIds.indexOf(id);
4370f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                if (existingIdx >= 0) {
4380f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                    mFieldValues.set(existingIdx, value);
4395311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    mFieldPresentations.set(existingIdx, presentation);
440bbf8549ad0bab9f73501956278b25c57a17eb5abFelipe Leme                    mFieldFilters.set(existingIdx, filter);
4415311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    return;
4420f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                }
4430f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            } else {
4440f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                mFieldIds = new ArrayList<>();
4450f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                mFieldValues = new ArrayList<>();
4465311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                mFieldPresentations = new ArrayList<>();
44727a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme                mFieldFilters = new ArrayList<>();
4480f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            }
4490f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            mFieldIds.add(id);
4500f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            mFieldValues.add(value);
4515311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme            mFieldPresentations.add(presentation);
45227a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme            mFieldFilters.add(filter);
4536d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        }
4546d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
4556d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        /**
4562ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme         * Creates a new {@link Dataset} instance.
4572ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme         *
4582ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme         * <p>You should not interact with this builder once this method is called.
4592ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme         *
46027a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * @throws IllegalStateException if no field was set (through
46127a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * {@link #setValue(AutofillId, AutofillValue)} or
46227a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme         * {@link #setValue(AutofillId, AutofillValue, RemoteViews)}).
46300c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov         *
46400c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov         * @return The built dataset.
4656d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme         */
4660f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        public @NonNull Dataset build() {
4670f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            throwIfDestroyed();
4680f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            mDestroyed = true;
46900c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov            if (mFieldIds == null) {
47027a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme                throw new IllegalStateException("at least one value must be set");
47100c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov            }
4720f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            return new Dataset(this);
4736d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        }
4746d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
4750f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        private void throwIfDestroyed() {
4760f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            if (mDestroyed) {
4770f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                throw new IllegalStateException("Already called #build()");
4780f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            }
4796d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        }
4806d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    }
4816d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
4826d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    /////////////////////////////////////
4836d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    //  Parcelable "contract" methods. //
4846d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    /////////////////////////////////////
4856d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
4866d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    @Override
4876d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    public int describeContents() {
4886d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        return 0;
4896d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    }
4906d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
4916d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    @Override
4926d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    public void writeToParcel(Parcel parcel, int flags) {
493eb49515abd2353f32e0eb7b3964847c6399986c9Svet Ganov        parcel.writeParcelable(mPresentation, flags);
4940e60f22d2dd0ad2b30f38f4b55847a239d27eef5Sunny Goyal        parcel.writeTypedList(mFieldIds, flags);
4950e60f22d2dd0ad2b30f38f4b55847a239d27eef5Sunny Goyal        parcel.writeTypedList(mFieldValues, flags);
49609d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme        parcel.writeTypedList(mFieldPresentations, flags);
49709d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme        parcel.writeTypedList(mFieldFilters, flags);
4980f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        parcel.writeParcelable(mAuthentication, flags);
499cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann        parcel.writeString(mId);
5006d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    }
5016d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
502782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov    public static final Creator<Dataset> CREATOR = new Creator<Dataset>() {
5036d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        @Override
5040f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        public Dataset createFromParcel(Parcel parcel) {
5050f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            // Always go through the builder to ensure the data ingested by
5060f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            // the system obeys the contract of the builder to avoid attacks
5070f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            // using specially crafted parcels.
5085311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme            final RemoteViews presentation = parcel.readParcelable(null);
5095311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme            final Builder builder = (presentation == null)
5105311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    ? new Builder()
5115311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme                    : new Builder(presentation);
51209d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme            final ArrayList<AutofillId> ids =
51309d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme                    parcel.createTypedArrayList(AutofillId.CREATOR);
5140e60f22d2dd0ad2b30f38f4b55847a239d27eef5Sunny Goyal            final ArrayList<AutofillValue> values =
5150e60f22d2dd0ad2b30f38f4b55847a239d27eef5Sunny Goyal                    parcel.createTypedArrayList(AutofillValue.CREATOR);
51609d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme            final ArrayList<RemoteViews> presentations =
51709d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme                    parcel.createTypedArrayList(RemoteViews.CREATOR);
51809d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme            final ArrayList<DatasetFieldFilter> filters =
51909d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme                    parcel.createTypedArrayList(DatasetFieldFilter.CREATOR);
52009d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme            for (int i = 0; i < ids.size(); i++) {
521640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme                final AutofillId id = ids.get(i);
52209d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme                final AutofillValue value = values.get(i);
52309d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme                final RemoteViews fieldPresentation = presentations.get(i);
52409d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme                final DatasetFieldFilter filter = filters.get(i);
52527a026ac1aefe639f41b5c79817abb9ea09a03d3Felipe Leme                builder.setLifeTheUniverseAndEverything(id, value, fieldPresentation, filter);
5260f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            }
5270f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            builder.setAuthentication(parcel.readParcelable(null));
528cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann            builder.setId(parcel.readString());
5290f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            return builder.build();
5306d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        }
5316d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
5326d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        @Override
5336d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        public Dataset[] newArray(int size) {
5346d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme            return new Dataset[size];
5356d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        }
5366d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    };
53709d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme
53809d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme    /**
53909d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme     * Helper class used to indicate when the service explicitly set a {@link Pattern} filter for a
54009d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme     * dataset field&dash; we cannot use a {@link Pattern} directly because then we wouldn't be
54109d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme     * able to differentiate whether the service explicitly passed a {@code null} filter to disable
54209d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme     * filter, or when it called the methods that does not take a filter {@link Pattern}.
54309d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme     *
54409d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme     * @hide
54509d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme     */
54609d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme    public static final class DatasetFieldFilter implements Parcelable {
54709d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme
54809d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme        @Nullable
54909d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme        public final Pattern pattern;
55009d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme
55109d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme        private DatasetFieldFilter(@Nullable Pattern pattern) {
55209d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme            this.pattern = pattern;
55309d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme        }
55409d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme
55509d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme        @Override
55609d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme        public String toString() {
55709d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme            if (!sDebug) return super.toString();
55809d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme
55909d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme            // Cannot log pattern because it could contain PII
56009d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme            return pattern == null ? "null" : pattern.pattern().length() + "_chars";
56109d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme        }
56209d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme
56309d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme        @Override
56409d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme        public int describeContents() {
56509d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme            return 0;
56609d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme        }
56709d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme
56809d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme        @Override
56909d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme        public void writeToParcel(Parcel parcel, int flags) {
57009d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme            parcel.writeSerializable(pattern);
57109d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme        }
57209d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme
57309d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme        @SuppressWarnings("hiding")
57409d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme        public static final Creator<DatasetFieldFilter> CREATOR =
57509d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme                new Creator<DatasetFieldFilter>() {
57609d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme
57709d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme            @Override
57809d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme            public DatasetFieldFilter createFromParcel(Parcel parcel) {
57909d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme                return new DatasetFieldFilter((Pattern) parcel.readSerializable());
58009d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme            }
58109d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme
58209d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme            @Override
58309d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme            public DatasetFieldFilter[] newArray(int size) {
58409d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme                return new DatasetFieldFilter[size];
58509d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme            }
58609d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme        };
58709d58a4e3b374609601182c1dccb71a297bc97c8Felipe Leme    }
5886d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme}
589