Dataset.java revision 782043caf81055aa1c331e9cc15b24a10e1bf17a
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
190f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganovimport android.annotation.NonNull;
20436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Lemeimport android.annotation.Nullable;
210f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganovimport android.content.IntentSender;
226d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemeimport android.os.Parcel;
236d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemeimport android.os.Parcelable;
24782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganovimport android.view.autofill.AutoFillId;
25782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganovimport android.view.autofill.AutoFillValue;
266d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemeimport com.android.internal.util.Preconditions;
276d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
286d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemeimport java.util.ArrayList;
296d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
306d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme/**
31782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov * A set of data that can be used to auto-fill an {@link android.app.Activity}.
326d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme *
336d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * <p>It contains:
346d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme *
356d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * <ol>
366d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme *   <li>A name used to identify the dataset in the UI.
376d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme *   <li>A list of id/value pairs for the fields that can be auto-filled.
38782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov *   <li>A list of savable ids in addition to the ones with a provided value.
396d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme * </ol>
406d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme *
41782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov * @see android.service.autofill.FillResponse for examples.
426d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme */
436d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Lemepublic final class Dataset implements Parcelable {
44782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov    private static final boolean DEBUG = false;
45782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov
466d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    private final CharSequence mName;
470f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    private final ArrayList<AutoFillId> mFieldIds;
480f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    private final ArrayList<AutoFillValue> mFieldValues;
490f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    private final IntentSender mAuthentication;
506d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
510f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    private Dataset(Builder builder) {
526d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        mName = builder.mName;
530f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        mFieldIds = builder.mFieldIds;
540f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        mFieldValues = builder.mFieldValues;
550f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        mAuthentication = builder.mAuthentication;
566d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    }
576d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
586d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    /** @hide */
590f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    public @NonNull CharSequence getName() {
600f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        return mName;
616d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    }
626d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
63436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    /** @hide */
640f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    public @Nullable ArrayList<AutoFillId> getFieldIds() {
650f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        return mFieldIds;
66436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    }
67436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme
68436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    /** @hide */
690f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    public @Nullable ArrayList<AutoFillValue> getFieldValues() {
700f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        return mFieldValues;
71436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    }
72436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme
73436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    /** @hide */
740f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    public @Nullable IntentSender getAuthentication() {
750f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        return mAuthentication;
76436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    }
77436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme
78436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    /** @hide */
790f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov    public boolean isEmpty() {
800f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        return mFieldIds == null || mFieldIds.isEmpty();
81436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme    }
82436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme
836d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    @Override
846d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    public String toString() {
856d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        if (!DEBUG) return super.toString();
866d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
87782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov        final StringBuilder builder = new StringBuilder("Dataset [name=").append(mName)
880f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                .append(", fieldIds=").append(mFieldIds)
890f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                .append(", fieldValues=").append(mFieldValues)
90782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov                .append(", hasAuthentication=").append(mAuthentication != null);
916d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        return builder.append(']').toString();
926d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    }
936d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
946d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    /**
950f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov     * A builder for {@link Dataset} objects. You must to provide at least
960f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov     * one value for a field or set an authentication intent.
976d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme     */
986d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    public static final class Builder {
996d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        private CharSequence mName;
1000f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        private ArrayList<AutoFillId> mFieldIds;
1010f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        private ArrayList<AutoFillValue> mFieldValues;
1020f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        private IntentSender mAuthentication;
1030f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        private boolean mDestroyed;
1040f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov
1056d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        /**
1066d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme         * Creates a new builder.
1076d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme         *
1086d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme         * @param name Name used to identify the dataset in the UI. Typically it's the same value as
1090f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov         * the first field in the dataset (like username or email address) or a user-provided name
1106d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme         * (like "My Work Address").
1116d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme         */
112782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov        public Builder(@NonNull CharSequence name) {
1136d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme            mName = Preconditions.checkStringNotEmpty(name, "name cannot be empty or null");
1146d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        }
1156d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
1166d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        /**
1170f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov         * Requires a dataset authentication before auto-filling the activity with this dataset.
118436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme         *
1190f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov         * <p>This method is called when you need to provide an authentication
120782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * UI for the data set. For example, when a data set contains credit card information
1210f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov         * (such as number, expiration date, and verification code), you can display UI
1220f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov         * asking for the verification code to before filing in the data). Even if the
123782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * data set is completely populated the system will launch the specified authentication
124782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * intent and will need your approval to fill it in. Since the data set is "locked"
125782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * until the user authenticates it, typically this data set name is masked
126782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * (for example, "VISA....1234"). Typically you would want to store the data set
127782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * labels non-encrypted and the actual sensitive data encrypted and not in memory.
1280f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov         * This allows showing the labels in the UI while involving the user if one of
1290f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov         * the items with these labels is chosen. Note that if you use sensitive data as
130782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * a label, for example an email address, then it should also be encrypted.</p>
131436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme         *
132782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * <p>When a user triggers auto-fill, the system launches the provided intent
133782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * whose extras will have the {@link
134782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * android.view.autofill.AutoFillManager#EXTRA_ASSIST_STRUCTURE screen content}. Once
135782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * you complete your authentication flow you should set the activity result to {@link
136782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * android.app.Activity#RESULT_OK} and provide the fully populated {@link Dataset
137782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * dataset} by setting it to the {@link
138782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * android.view.autofill.AutoFillManager#EXTRA_AUTHENTICATION_RESULT} extra. For example,
139782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * if you provided an credit card information without the CVV for the data set in the
140782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * {@link FillResponse response} then the returned data set should contain the
141782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * CVV entry.</p>
142436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme         *
143782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * <p></><strong>Note:</strong> Do not make the provided pending intent
1440f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov         * immutable by using {@link android.app.PendingIntent#FLAG_IMMUTABLE} as the
1450f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov         * platform needs to fill in the authentication arguments.</p>
146436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme         *
147782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * @param authentication Intent to an activity with your authentication flow.
148436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme         *
149782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * @see android.app.PendingIntent
150436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme         */
1510f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        public @NonNull Builder setAuthentication(@Nullable IntentSender authentication) {
1520f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            throwIfDestroyed();
1530f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            mAuthentication = authentication;
154436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme            return this;
155436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme        }
156436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme
157436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme        /**
1586d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme         * Sets the value of a field.
1596d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme         *
160782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         * @param id id returned by {@link
161782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov         *         android.app.assist.AssistStructure.ViewNode#getAutoFillId()}.
1626d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme         * @param value value to be auto filled.
1636d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme         */
1640f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        public @NonNull Builder setValue(@NonNull AutoFillId id, @NonNull AutoFillValue value) {
1650f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            throwIfDestroyed();
1660f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            Preconditions.checkNotNull(id, "id cannot be null");
1670f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            Preconditions.checkNotNull(value, "value cannot be null");
1680f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            if (mFieldIds != null) {
1690f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                final int existingIdx = mFieldIds.indexOf(id);
1700f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                if (existingIdx >= 0) {
1710f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                    mFieldValues.set(existingIdx, value);
1720f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                    return this;
1730f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                }
1740f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            } else {
1750f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                mFieldIds = new ArrayList<>();
1760f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                mFieldValues = new ArrayList<>();
1770f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            }
1780f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            mFieldIds.add(id);
1790f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            mFieldValues.add(value);
1806d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme            return this;
1816d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        }
1826d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
1836d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        /**
1840f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov         * Creates a new {@link Dataset} instance. You should not interact
1850f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov         * with this builder once this method is called.
1866d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme         */
1870f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        public @NonNull Dataset build() {
1880f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            throwIfDestroyed();
1890f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            mDestroyed = true;
1900f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            if (mFieldIds == null && mAuthentication == null) {
1910f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                throw new IllegalArgumentException(
1920f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                        "at least one value or an authentication must be set");
1930f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            }
1940f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            return new Dataset(this);
1956d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        }
1966d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
1970f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        private void throwIfDestroyed() {
1980f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            if (mDestroyed) {
1990f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                throw new IllegalStateException("Already called #build()");
2000f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            }
2016d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        }
2026d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    }
2036d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
2046d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    /////////////////////////////////////
2056d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    //  Parcelable "contract" methods. //
2066d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    /////////////////////////////////////
2076d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
2086d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    @Override
2096d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    public int describeContents() {
2106d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        return 0;
2116d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    }
2126d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
2136d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    @Override
2146d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    public void writeToParcel(Parcel parcel, int flags) {
2156d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        parcel.writeCharSequence(mName);
2160f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        parcel.writeTypedArrayList(mFieldIds, 0);
2170f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        parcel.writeTypedArrayList(mFieldValues, 0);
2180f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        parcel.writeParcelable(mAuthentication, flags);
2196d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    }
2206d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
221782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov    public static final Creator<Dataset> CREATOR = new Creator<Dataset>() {
2226d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        @Override
2230f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov        public Dataset createFromParcel(Parcel parcel) {
2240f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            // Always go through the builder to ensure the data ingested by
2250f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            // the system obeys the contract of the builder to avoid attacks
2260f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            // using specially crafted parcels.
227782043caf81055aa1c331e9cc15b24a10e1bf17aSvet Ganov            final Builder builder = new Builder(parcel.readCharSequence());
2280f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            final ArrayList<AutoFillId> ids = parcel.readTypedArrayList(null);
2290f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            final ArrayList<AutoFillValue> values = parcel.readTypedArrayList(null);
2300f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            final int idCount = (ids != null) ? ids.size() : 0;
2310f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            final int valueCount = (values != null) ? values.size() : 0;
2320f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            for (int i = 0; i < idCount; i++) {
2330f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                AutoFillId id = ids.get(i);
2340f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                AutoFillValue value = (valueCount > i) ? values.get(i) : null;
2350f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov                builder.setValue(id, value);
2360f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            }
2370f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            builder.setAuthentication(parcel.readParcelable(null));
2380f4928f1f73407485d6d94beda1dba1a2360ebbfSvet Ganov            return builder.build();
2396d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        }
2406d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme
2416d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        @Override
2426d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        public Dataset[] newArray(int size) {
2436d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme            return new Dataset[size];
2446d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme        }
2456d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme    };
2466d553874bed06280766ae24ea605f9bbde3f5a4aFelipe Leme}
247