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; 336d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme 346d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme/** 352ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * A dataset object represents a group of key/value pairs used to autofill parts of a screen. 366d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * 372ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * <p>In its simplest form, a dataset contains one or more key / value pairs (comprised of 382ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * {@link AutofillId} and {@link AutofillValue} respectively); and one or more 392ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * {@link RemoteViews presentation} for these pairs (a pair could have its own 402ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * {@link RemoteViews presentation}, or use the default {@link RemoteViews presentation} associated 412ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * with the whole dataset). When an autofill service returns datasets in a {@link FillResponse} 422ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * and the screen input is focused in a view that is present in at least one of these datasets, 432ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * the Android System displays a UI affordance containing the {@link RemoteViews presentation} of 442ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * all datasets pairs that have that view's {@link AutofillId}. Then, when the user selects a 452ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * dataset from the affordance, all views in that dataset are autofilled. 466d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * 472ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * <p>In a more sophisticated form, the dataset value can be protected until the user authenticates 482ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * the dataset - see {@link Dataset.Builder#setAuthentication(IntentSender)}. 496d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * 502ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * @see android.service.autofill.AutofillService for more information and examples about the 512ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * role of datasets in the autofill workflow. 526d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme */ 536d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemepublic final class Dataset implements Parcelable { 54782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov 55640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme private final ArrayList<AutofillId> mFieldIds; 56640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme private final ArrayList<AutofillValue> mFieldValues; 575311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme private final ArrayList<RemoteViews> mFieldPresentations; 5800c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov private final RemoteViews mPresentation; 590f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov private final IntentSender mAuthentication; 60cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann @Nullable String mId; 616d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme 620f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov private Dataset(Builder builder) { 630f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov mFieldIds = builder.mFieldIds; 640f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov mFieldValues = builder.mFieldValues; 655311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme mFieldPresentations = builder.mFieldPresentations; 6600c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov mPresentation = builder.mPresentation; 670f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov mAuthentication = builder.mAuthentication; 68cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann mId = builder.mId; 696d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme } 706d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme 716d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme /** @hide */ 72640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme public @Nullable ArrayList<AutofillId> getFieldIds() { 730f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov return mFieldIds; 74436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme } 75436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme 76436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme /** @hide */ 77640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme public @Nullable ArrayList<AutofillValue> getFieldValues() { 780f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov return mFieldValues; 79436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme } 80436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme 81436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme /** @hide */ 825311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme public RemoteViews getFieldPresentation(int index) { 835311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme final RemoteViews customPresentation = mFieldPresentations.get(index); 845311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme return customPresentation != null ? customPresentation : mPresentation; 855311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme } 865311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme 875311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme /** @hide */ 880f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov public @Nullable IntentSender getAuthentication() { 890f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov return mAuthentication; 90436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme } 91436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme 92436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme /** @hide */ 930f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov public boolean isEmpty() { 940f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov return mFieldIds == null || mFieldIds.isEmpty(); 95436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme } 96436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme 976d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme @Override 986d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme public String toString() { 999f9ee25515591ef33281708c0ab911962f4364a6Felipe Leme if (!sDebug) return super.toString(); 1006d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme 101cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann return new StringBuilder("Dataset " + mId + " [") 10278696bfeb7ac5ae298765bfb9f82cf24d12b7dccFelipe Leme .append("fieldIds=").append(mFieldIds) 1030f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov .append(", fieldValues=").append(mFieldValues) 1045311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme .append(", fieldPresentations=") 1055311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme .append(mFieldPresentations == null ? 0 : mFieldPresentations.size()) 10600c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov .append(", hasPresentation=").append(mPresentation != null) 10700c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov .append(", hasAuthentication=").append(mAuthentication != null) 10800c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov .append(']').toString(); 1096d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme } 1106d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme 1116d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme /** 112cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann * Gets the id of this dataset. 113cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann * 114cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann * @return The id of this dataset or {@code null} if not set 115cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann * 116cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann * @hide 117cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann */ 118cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann public String getId() { 119cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann return mId; 120cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann } 121cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann 122cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann /** 1232ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * A builder for {@link Dataset} objects. You must provide at least 1240f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov * one value for a field or set an authentication intent. 1256d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme */ 1266d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme public static final class Builder { 127640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme private ArrayList<AutofillId> mFieldIds; 128640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme private ArrayList<AutofillValue> mFieldValues; 1295311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme private ArrayList<RemoteViews> mFieldPresentations; 13000c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov private RemoteViews mPresentation; 1310f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov private IntentSender mAuthentication; 1320f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov private boolean mDestroyed; 133cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann @Nullable private String mId; 1340f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov 1356d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme /** 136eb49515abd2353f32e0eb7b3964847c6399986c9Svet Ganov * Creates a new builder. 13700c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov * 138eb49515abd2353f32e0eb7b3964847c6399986c9Svet Ganov * @param presentation The presentation used to visualize this dataset. 1396d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme */ 140eb49515abd2353f32e0eb7b3964847c6399986c9Svet Ganov public Builder(@NonNull RemoteViews presentation) { 141eb49515abd2353f32e0eb7b3964847c6399986c9Svet Ganov Preconditions.checkNotNull(presentation, "presentation must be non-null"); 14200c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov mPresentation = presentation; 1436d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme } 1446d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme 1456d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme /** 1465311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme * Creates a new builder for a dataset where each field will be visualized independently. 1475311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme * 1485311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme * <p>When using this constructor, fields must be set through 1495311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme * {@link #setValue(AutofillId, AutofillValue, RemoteViews)}. 1505311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme */ 1515311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme public Builder() { 1525311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme } 1535311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme 1545311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme /** 155640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme * Requires a dataset authentication before autofilling the activity with this dataset. 156436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme * 1570f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov * <p>This method is called when you need to provide an authentication 158782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov * UI for the data set. For example, when a data set contains credit card information 1590f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov * (such as number, expiration date, and verification code), you can display UI 16000c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov * asking for the verification code before filing in the data. Even if the 161782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov * data set is completely populated the system will launch the specified authentication 162782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov * intent and will need your approval to fill it in. Since the data set is "locked" 163782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov * until the user authenticates it, typically this data set name is masked 164782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov * (for example, "VISA....1234"). Typically you would want to store the data set 165782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov * labels non-encrypted and the actual sensitive data encrypted and not in memory. 1660f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov * This allows showing the labels in the UI while involving the user if one of 1670f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov * the items with these labels is chosen. Note that if you use sensitive data as 168782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov * a label, for example an email address, then it should also be encrypted.</p> 169436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme * 170640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme * <p>When a user triggers autofill, the system launches the provided intent 171782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov * whose extras will have the {@link 172a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov * android.view.autofill.AutofillManager#EXTRA_ASSIST_STRUCTURE screen content}, 173a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov * and your {@link android.view.autofill.AutofillManager#EXTRA_CLIENT_STATE client 174a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov * state}. Once you complete your authentication flow you should set the activity 175a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov * result to {@link android.app.Activity#RESULT_OK} and provide the fully populated 176a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov * {@link Dataset dataset} or a fully-populated {@link FillResponse response} by 177a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov * setting it to the {@link 178a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov * android.view.autofill.AutofillManager#EXTRA_AUTHENTICATION_RESULT} extra. If you 179a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov * provide a dataset in the result, it will replace the authenticated dataset and 180a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov * will be immediately filled in. If you provide a response, it will replace the 181a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov * current response and the UI will be refreshed. For example, if you provided 182a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov * credit card information without the CVV for the data set in the {@link FillResponse 183a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov * response} then the returned data set should contain the CVV entry. 184436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme * 1852ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * <p><b>NOTE:</b> Do not make the provided pending intent 1860f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov * immutable by using {@link android.app.PendingIntent#FLAG_IMMUTABLE} as the 1872ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * platform needs to fill in the authentication arguments. 188436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme * 189782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov * @param authentication Intent to an activity with your authentication flow. 19000c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov * @return This builder. 191436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme * 192782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov * @see android.app.PendingIntent 193436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme */ 1940f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov public @NonNull Builder setAuthentication(@Nullable IntentSender authentication) { 1950f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov throwIfDestroyed(); 1960f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov mAuthentication = authentication; 197436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme return this; 198436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme } 199436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme 200436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme /** 2012ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * Sets the id for the dataset so its usage history can be retrieved later. 202cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann * 203cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann * <p>The id of the last selected dataset can be read from 204cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann * {@link AutofillService#getFillEventHistory()}. If the id is not set it will not be clear 205cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann * if a dataset was selected as {@link AutofillService#getFillEventHistory()} uses 206cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann * {@code null} to indicate that no dataset was selected. 207cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann * 208cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann * @param id id for this dataset or {@code null} to unset. 209cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann 210cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann * @return This builder. 211cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann */ 212cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann public @NonNull Builder setId(@Nullable String id) { 213cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann throwIfDestroyed(); 214cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann 215cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann mId = id; 216cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann return this; 217cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann } 218cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann 219cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann /** 2206d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * Sets the value of a field. 2216d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * 222782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov * @param id id returned by {@link 223640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme * android.app.assist.AssistStructure.ViewNode#getAutofillId()}. 2242ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * @param value value to be autofilled. Pass {@code null} if you do not have the value 225a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov * but the target view is a logical part of the dataset. For example, if 226a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov * the dataset needs an authentication and you have no access to the value. 22700c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov * @return This builder. 2282ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * @throws IllegalStateException if the builder was constructed without a 2292ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * {@link RemoteViews presentation}. 2306d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme */ 231a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value) { 2320f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov throwIfDestroyed(); 2335311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme if (mPresentation == null) { 2345311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme throw new IllegalStateException("Dataset presentation not set on constructor"); 2355311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme } 2365311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme setValueAndPresentation(id, value, null); 2375311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme return this; 2385311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme } 2395311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme 2405311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme /** 2412ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * Sets the value of a field, using a custom {@link RemoteViews presentation} to 2422ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * visualize it. 2435311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme * 2445311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme * @param id id returned by {@link 2455311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme * android.app.assist.AssistStructure.ViewNode#getAutofillId()}. 246a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov * @param value value to be auto filled. Pass {@code null} if you do not have the value 247a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov * but the target view is a logical part of the dataset. For example, if 248a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov * the dataset needs an authentication and you have no access to the value. 249a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov * Filtering matches any user typed string to {@code null} values. 2505311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme * @param presentation The presentation used to visualize this field. 2515311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme * @return This builder. 2525311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme */ 253a9379d0b44ca1f68a0036d2b65218e17fa348514Svetoslav Ganov public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value, 2545311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme @NonNull RemoteViews presentation) { 2555311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme throwIfDestroyed(); 2565311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme Preconditions.checkNotNull(presentation, "presentation cannot be null"); 2575311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme setValueAndPresentation(id, value, presentation); 2585311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme return this; 2595311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme } 2605311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme 2615311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme private void setValueAndPresentation(AutofillId id, AutofillValue value, 2625311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme RemoteViews presentation) { 2630f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov Preconditions.checkNotNull(id, "id cannot be null"); 2640f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov if (mFieldIds != null) { 2650f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov final int existingIdx = mFieldIds.indexOf(id); 2660f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov if (existingIdx >= 0) { 2670f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov mFieldValues.set(existingIdx, value); 2685311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme mFieldPresentations.set(existingIdx, presentation); 2695311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme return; 2700f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov } 2710f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov } else { 2720f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov mFieldIds = new ArrayList<>(); 2730f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov mFieldValues = new ArrayList<>(); 2745311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme mFieldPresentations = new ArrayList<>(); 2750f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov } 2760f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov mFieldIds.add(id); 2770f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov mFieldValues.add(value); 2785311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme mFieldPresentations.add(presentation); 2796d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme } 2806d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme 2816d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme /** 2822ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * Creates a new {@link Dataset} instance. 2832ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * 2842ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * <p>You should not interact with this builder once this method is called. 2852ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * 2862ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * <p>It is required that you specify at least one field before calling this method. It's 2872ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * also mandatory to provide a presentation view to visualize the data set in the UI. 28800c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov * 28900c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov * @return The built dataset. 2906d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme */ 2910f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov public @NonNull Dataset build() { 2920f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov throwIfDestroyed(); 2930f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov mDestroyed = true; 29400c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov if (mFieldIds == null) { 29524d5893b25ce62b7bc9ed9f35fa72b9d47f23cddFelipe Leme throw new IllegalArgumentException("at least one value must be set"); 29600c771dc7d8242362f1491ae4ce3efd641235b36Svet Ganov } 2970f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov return new Dataset(this); 2986d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme } 2996d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme 3000f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov private void throwIfDestroyed() { 3010f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov if (mDestroyed) { 3020f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov throw new IllegalStateException("Already called #build()"); 3030f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov } 3046d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme } 3056d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme } 3066d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme 3076d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme ///////////////////////////////////// 3086d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme // Parcelable "contract" methods. // 3096d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme ///////////////////////////////////// 3106d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme 3116d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme @Override 3126d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme public int describeContents() { 3136d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme return 0; 3146d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme } 3156d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme 3166d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme @Override 3176d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme public void writeToParcel(Parcel parcel, int flags) { 318eb49515abd2353f32e0eb7b3964847c6399986c9Svet Ganov parcel.writeParcelable(mPresentation, flags); 319fe88b6028b7615f75f871ad79b436ebaa5efcad4Fyodor Kupolov parcel.writeTypedList(mFieldIds, flags); 320fe88b6028b7615f75f871ad79b436ebaa5efcad4Fyodor Kupolov parcel.writeTypedList(mFieldValues, flags); 3215311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme parcel.writeParcelableList(mFieldPresentations, flags); 3220f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov parcel.writeParcelable(mAuthentication, flags); 323cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann parcel.writeString(mId); 3246d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme } 3256d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme 326782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov public static final Creator<Dataset> CREATOR = new Creator<Dataset>() { 3276d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme @Override 3280f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov public Dataset createFromParcel(Parcel parcel) { 3290f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov // Always go through the builder to ensure the data ingested by 3300f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov // the system obeys the contract of the builder to avoid attacks 3310f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov // using specially crafted parcels. 3325311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme final RemoteViews presentation = parcel.readParcelable(null); 3335311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme final Builder builder = (presentation == null) 3345311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme ? new Builder() 3355311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme : new Builder(presentation); 336fe88b6028b7615f75f871ad79b436ebaa5efcad4Fyodor Kupolov final ArrayList<AutofillId> ids = parcel.createTypedArrayList(AutofillId.CREATOR); 337fe88b6028b7615f75f871ad79b436ebaa5efcad4Fyodor Kupolov final ArrayList<AutofillValue> values = 338fe88b6028b7615f75f871ad79b436ebaa5efcad4Fyodor Kupolov parcel.createTypedArrayList(AutofillValue.CREATOR); 3395311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme final ArrayList<RemoteViews> presentations = new ArrayList<>(); 3405311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme parcel.readParcelableList(presentations, null); 3410f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov final int idCount = (ids != null) ? ids.size() : 0; 3420f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov final int valueCount = (values != null) ? values.size() : 0; 3430f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov for (int i = 0; i < idCount; i++) { 344640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme final AutofillId id = ids.get(i); 345640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme final AutofillValue value = (valueCount > i) ? values.get(i) : null; 3465311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme final RemoteViews fieldPresentation = presentations.isEmpty() ? null 3475311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme : presentations.get(i); 3485311206f3434d631c6ea81ab2e76a46ca18119b6Felipe Leme builder.setValueAndPresentation(id, value, fieldPresentation); 3490f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov } 3500f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov builder.setAuthentication(parcel.readParcelable(null)); 351cc684ed41f17ccdce45a056fd4034efc35b213d5Philip P. Moltmann builder.setId(parcel.readString()); 3520f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov return builder.build(); 3536d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme } 3546d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme 3556d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme @Override 3566d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme public Dataset[] newArray(int size) { 3576d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme return new Dataset[size]; 3586d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme } 3596d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme }; 3606d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme} 361