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—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‐ 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