/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.service.autofill;

import static android.service.autofill.AutofillServiceHelper.assertValid;
import static android.view.autofill.Helper.sDebug;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
import android.content.IntentSender;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DebugUtils;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;

import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;

/**
 * Information used to indicate that an {@link AutofillService} is interested on saving the
 * user-inputed data for future use, through a
 * {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)}
 * call.
 *
 * <p>A {@link SaveInfo} is always associated with a {@link FillResponse}, and it contains at least
 * two pieces of information:
 *
 * <ol>
 *   <li>The type(s) of user data (like password or credit card info) that would be saved.
 *   <li>The minimum set of views (represented by their {@link AutofillId}) that need to be changed
 *       to trigger a save request.
 * </ol>
 *
 * <p>Typically, the {@link SaveInfo} contains the same {@code id}s as the {@link Dataset}:
 *
 * <pre class="prettyprint">
 *   new FillResponse.Builder()
 *       .addDataset(new Dataset.Builder()
 *           .setValue(id1, AutofillValue.forText("homer"), createPresentation("homer")) // username
 *           .setValue(id2, AutofillValue.forText("D'OH!"), createPresentation("password for homer")) // password
 *           .build())
 *       .setSaveInfo(new SaveInfo.Builder(
 *           SaveInfo.SAVE_DATA_TYPE_USERNAME | SaveInfo.SAVE_DATA_TYPE_PASSWORD,
 *           new AutofillId[] { id1, id2 }).build())
 *       .build();
 * </pre>
 *
 * <p>The save type flags are used to display the appropriate strings in the autofill save UI.
 * You can pass multiple values, but try to keep it short if possible. In the above example, just
 * {@code SaveInfo.SAVE_DATA_TYPE_PASSWORD} would be enough.
 *
 * <p>There might be cases where the {@link AutofillService} knows how to fill the screen,
 * but the user has no data for it. In that case, the {@link FillResponse} should contain just the
 * {@link SaveInfo}, but no {@link Dataset Datasets}:
 *
 * <pre class="prettyprint">
 *   new FillResponse.Builder()
 *       .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_PASSWORD,
 *           new AutofillId[] { id1, id2 }).build())
 *       .build();
 * </pre>
 *
 * <p>There might be cases where the user data in the {@link AutofillService} is enough
 * to populate some fields but not all, and the service would still be interested on saving the
 * other fields. In that case, the service could set the
 * {@link SaveInfo.Builder#setOptionalIds(AutofillId[])} as well:
 *
 * <pre class="prettyprint">
 *   new FillResponse.Builder()
 *       .addDataset(new Dataset.Builder()
 *           .setValue(id1, AutofillValue.forText("742 Evergreen Terrace"),
 *               createPresentation("742 Evergreen Terrace")) // street
 *           .setValue(id2, AutofillValue.forText("Springfield"),
 *               createPresentation("Springfield")) // city
 *           .build())
 *       .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_ADDRESS,
 *           new AutofillId[] { id1, id2 }) // street and  city
 *           .setOptionalIds(new AutofillId[] { id3, id4 }) // state and zipcode
 *           .build())
 *       .build();
 * </pre>
 *
 * <a name="TriggeringSaveRequest"></a>
 * <h3>Triggering a save request</h3>
 *
 * <p>The {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)} can be triggered after
 * any of the following events:
 * <ul>
 *   <li>The {@link Activity} finishes.
 *   <li>The app explicitly calls {@link AutofillManager#commit()}.
 *   <li>All required views become invisible (if the {@link SaveInfo} was created with the
 *       {@link #FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE} flag).
 *   <li>The user clicks a specific view (defined by {@link Builder#setTriggerId(AutofillId)}.
 * </ul>
 *
 * <p>But it is only triggered when all conditions below are met:
 * <ul>
 *   <li>The {@link SaveInfo} associated with the {@link FillResponse} is not {@code null} neither
 *       has the {@link #FLAG_DELAY_SAVE} flag.
 *   <li>The {@link AutofillValue}s of all required views (as set by the {@code requiredIds} passed
 *       to the {@link SaveInfo.Builder} constructor are not empty.
 *   <li>The {@link AutofillValue} of at least one view (be it required or optional) has changed
 *       (i.e., it's neither the same value passed in a {@link Dataset}, nor the initial value
 *       presented in the view).
 *   <li>There is no {@link Dataset} in the last {@link FillResponse} that completely matches the
 *       screen state (i.e., all required and optional fields in the dataset have the same value as
 *       the fields in the screen).
 *   <li>The user explicitly tapped the autofill save UI asking to save data for autofill.
 * </ul>
 *
 * <a name="CustomizingSaveUI"></a>
 * <h3>Customizing the autofill save UI</h3>
 *
 * <p>The service can also customize some aspects of the autofill save UI:
 * <ul>
 *   <li>Add a simple subtitle by calling {@link Builder#setDescription(CharSequence)}.
 *   <li>Add a customized subtitle by calling
 *       {@link Builder#setCustomDescription(CustomDescription)}.
 *   <li>Customize the button used to reject the save request by calling
 *       {@link Builder#setNegativeAction(int, IntentSender)}.
 *   <li>Decide whether the UI should be shown based on the user input validation by calling
 *       {@link Builder#setValidator(Validator)}.
 * </ul>
 */
public final class SaveInfo implements Parcelable {

    /**
     * Type used when the service can save the contents of a screen, but cannot describe what
     * the content is for.
     */
    public static final int SAVE_DATA_TYPE_GENERIC = 0x0;

    /**
     * Type used when the {@link FillResponse} represents user credentials that have a password.
     */
    public static final int SAVE_DATA_TYPE_PASSWORD = 0x01;

    /**
     * Type used on when the {@link FillResponse} represents a physical address (such as street,
     * city, state, etc).
     */
    public static final int SAVE_DATA_TYPE_ADDRESS = 0x02;

    /**
     * Type used when the {@link FillResponse} represents a credit card.
     */
    public static final int SAVE_DATA_TYPE_CREDIT_CARD = 0x04;

    /**
     * Type used when the {@link FillResponse} represents just an username, without a password.
     */
    public static final int SAVE_DATA_TYPE_USERNAME = 0x08;

    /**
     * Type used when the {@link FillResponse} represents just an email address, without a password.
     */
    public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 0x10;

    /**
     * Style for the negative button of the save UI to cancel the
     * save operation. In this case, the user tapping the negative
     * button signals that they would prefer to not save the filled
     * content.
     */
    public static final int NEGATIVE_BUTTON_STYLE_CANCEL = 0;

    /**
     * Style for the negative button of the save UI to reject the
     * save operation. This could be useful if the user needs to
     * opt-in your service and the save prompt is an advertisement
     * of the potential value you can add to the user. In this
     * case, the user tapping the negative button sends a strong
     * signal that the feature may not be useful and you may
     * consider some backoff strategy.
     */
    public static final int NEGATIVE_BUTTON_STYLE_REJECT = 1;

    /** @hide */
    @IntDef(prefix = { "NEGATIVE_BUTTON_STYLE_" }, value = {
            NEGATIVE_BUTTON_STYLE_CANCEL,
            NEGATIVE_BUTTON_STYLE_REJECT
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface NegativeButtonStyle{}

    /** @hide */
    @IntDef(flag = true, prefix = { "SAVE_DATA_TYPE_" }, value = {
            SAVE_DATA_TYPE_GENERIC,
            SAVE_DATA_TYPE_PASSWORD,
            SAVE_DATA_TYPE_ADDRESS,
            SAVE_DATA_TYPE_CREDIT_CARD,
            SAVE_DATA_TYPE_USERNAME,
            SAVE_DATA_TYPE_EMAIL_ADDRESS
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface SaveDataType{}

    /**
     * Usually, a save request is only automatically <a href="#TriggeringSaveRequest">triggered</a>
     * once the {@link Activity} finishes. If this flag is set, it is triggered once all saved views
     * become invisible.
     */
    public static final int FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 0x1;

    /**
     * By default, a save request is automatically <a href="#TriggeringSaveRequest">triggered</a>
     * once the {@link Activity} finishes. If this flag is set, finishing the activity doesn't
     * trigger a save request.
     *
     * <p>This flag is typically used in conjunction with {@link Builder#setTriggerId(AutofillId)}.
     */
    public static final int FLAG_DONT_SAVE_ON_FINISH = 0x2;


    /**
     * Postpone the autofill save UI.
     *
     * <p>If flag is set, the autofill save UI is not triggered when the
     * autofill context associated with the response associated with this {@link SaveInfo} is
     * committed (with {@link AutofillManager#commit()}). Instead, the {@link FillContext}
     * is delivered in future fill requests (with {@link
     * AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)})
     * and save request (with {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)})
     * of an activity belonging to the same task.
     *
     * <p>This flag should be used when the service detects that the application uses
     * multiple screens to implement an autofillable workflow (for example, one screen for the
     * username field, another for password).
     */
    // TODO(b/113281366): improve documentation: add example, document relationship with other
    // flagss, etc...
    public static final int FLAG_DELAY_SAVE = 0x4;

    /** @hide */
    @IntDef(flag = true, prefix = { "FLAG_" }, value = {
            FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE,
            FLAG_DONT_SAVE_ON_FINISH,
            FLAG_DELAY_SAVE
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface SaveInfoFlags{}

    private final @SaveDataType int mType;
    private final @NegativeButtonStyle int mNegativeButtonStyle;
    private final IntentSender mNegativeActionListener;
    private final AutofillId[] mRequiredIds;
    private final AutofillId[] mOptionalIds;
    private final CharSequence mDescription;
    private final int mFlags;
    private final CustomDescription mCustomDescription;
    private final InternalValidator mValidator;
    private final InternalSanitizer[] mSanitizerKeys;
    private final AutofillId[][] mSanitizerValues;
    private final AutofillId mTriggerId;

    private SaveInfo(Builder builder) {
        mType = builder.mType;
        mNegativeButtonStyle = builder.mNegativeButtonStyle;
        mNegativeActionListener = builder.mNegativeActionListener;
        mRequiredIds = builder.mRequiredIds;
        mOptionalIds = builder.mOptionalIds;
        mDescription = builder.mDescription;
        mFlags = builder.mFlags;
        mCustomDescription = builder.mCustomDescription;
        mValidator = builder.mValidator;
        if (builder.mSanitizers == null) {
            mSanitizerKeys = null;
            mSanitizerValues = null;
        } else {
            final int size = builder.mSanitizers.size();
            mSanitizerKeys = new InternalSanitizer[size];
            mSanitizerValues = new AutofillId[size][];
            for (int i = 0; i < size; i++) {
                mSanitizerKeys[i] = builder.mSanitizers.keyAt(i);
                mSanitizerValues[i] = builder.mSanitizers.valueAt(i);
            }
        }
        mTriggerId = builder.mTriggerId;
    }

    /** @hide */
    public @NegativeButtonStyle int getNegativeActionStyle() {
        return mNegativeButtonStyle;
    }

    /** @hide */
    public @Nullable IntentSender getNegativeActionListener() {
        return mNegativeActionListener;
    }

    /** @hide */
    public @Nullable AutofillId[] getRequiredIds() {
        return mRequiredIds;
    }

    /** @hide */
    public @Nullable AutofillId[] getOptionalIds() {
        return mOptionalIds;
    }

    /** @hide */
    public @SaveDataType int getType() {
        return mType;
    }

    /** @hide */
    public @SaveInfoFlags int getFlags() {
        return mFlags;
    }

    /** @hide */
    public CharSequence getDescription() {
        return mDescription;
    }

     /** @hide */
    @Nullable
    public CustomDescription getCustomDescription() {
        return mCustomDescription;
    }

    /** @hide */
    @Nullable
    public InternalValidator getValidator() {
        return mValidator;
    }

    /** @hide */
    @Nullable
    public InternalSanitizer[] getSanitizerKeys() {
        return mSanitizerKeys;
    }

    /** @hide */
    @Nullable
    public AutofillId[][] getSanitizerValues() {
        return mSanitizerValues;
    }

    /** @hide */
    @Nullable
    public AutofillId getTriggerId() {
        return mTriggerId;
    }

    /**
     * A builder for {@link SaveInfo} objects.
     */
    public static final class Builder {

        private final @SaveDataType int mType;
        private @NegativeButtonStyle int mNegativeButtonStyle = NEGATIVE_BUTTON_STYLE_CANCEL;
        private IntentSender mNegativeActionListener;
        private final AutofillId[] mRequiredIds;
        private AutofillId[] mOptionalIds;
        private CharSequence mDescription;
        private boolean mDestroyed;
        private int mFlags;
        private CustomDescription mCustomDescription;
        private InternalValidator mValidator;
        private ArrayMap<InternalSanitizer, AutofillId[]> mSanitizers;
        // Set used to validate against duplicate ids.
        private ArraySet<AutofillId> mSanitizerIds;
        private AutofillId mTriggerId;

        /**
         * Creates a new builder.
         *
         * @param type the type of information the associated {@link FillResponse} represents. It
         * can be any combination of {@link SaveInfo#SAVE_DATA_TYPE_GENERIC},
         * {@link SaveInfo#SAVE_DATA_TYPE_PASSWORD},
         * {@link SaveInfo#SAVE_DATA_TYPE_ADDRESS}, {@link SaveInfo#SAVE_DATA_TYPE_CREDIT_CARD},
         * {@link SaveInfo#SAVE_DATA_TYPE_USERNAME}, or
         * {@link SaveInfo#SAVE_DATA_TYPE_EMAIL_ADDRESS}.
         * @param requiredIds ids of all required views that will trigger a save request.
         *
         * <p>See {@link SaveInfo} for more info.
         *
         * @throws IllegalArgumentException if {@code requiredIds} is {@code null} or empty, or if
         * it contains any {@code null} entry.
         */
        public Builder(@SaveDataType int type, @NonNull AutofillId[] requiredIds) {
            mType = type;
            mRequiredIds = assertValid(requiredIds);
        }

        /**
         * Creates a new builder when no id is required.
         *
         * <p>When using this builder, caller must call {@link #setOptionalIds(AutofillId[])} before
         * calling {@link #build()}.
         *
         * @param type the type of information the associated {@link FillResponse} represents. It
         * can be any combination of {@link SaveInfo#SAVE_DATA_TYPE_GENERIC},
         * {@link SaveInfo#SAVE_DATA_TYPE_PASSWORD},
         * {@link SaveInfo#SAVE_DATA_TYPE_ADDRESS}, {@link SaveInfo#SAVE_DATA_TYPE_CREDIT_CARD},
         * {@link SaveInfo#SAVE_DATA_TYPE_USERNAME}, or
         * {@link SaveInfo#SAVE_DATA_TYPE_EMAIL_ADDRESS}.
         *
         * <p>See {@link SaveInfo} for more info.
         */
        public Builder(@SaveDataType int type) {
            mType = type;
            mRequiredIds = null;
        }

        /**
         * Sets flags changing the save behavior.
         *
         * @param flags {@link #FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE},
         * {@link #FLAG_DONT_SAVE_ON_FINISH}, {@link #FLAG_DELAY_SAVE}, or {@code 0}.
         * @return This builder.
         */
        public @NonNull Builder setFlags(@SaveInfoFlags int flags) {
            throwIfDestroyed();

            mFlags = Preconditions.checkFlagsArgument(flags,
                    FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE | FLAG_DONT_SAVE_ON_FINISH
                            | FLAG_DELAY_SAVE);
            return this;
        }

        /**
         * Sets the ids of additional, optional views the service would be interested to save.
         *
         * <p>See {@link SaveInfo} for more info.
         *
         * @param ids The ids of the optional views.
         * @return This builder.
         *
         * @throws IllegalArgumentException if {@code ids} is {@code null} or empty, or if
         * it contains any {@code null} entry.
         */
        public @NonNull Builder setOptionalIds(@NonNull AutofillId[] ids) {
            throwIfDestroyed();
            mOptionalIds = assertValid(ids);
            return this;
        }

        /**
         * Sets an optional description to be shown in the UI when the user is asked to save.
         *
         * <p>Typically, it describes how the data will be stored by the service, so it can help
         * users to decide whether they can trust the service to save their data.
         *
         * @param description a succint description.
         * @return This Builder.
         *
         * @throws IllegalStateException if this call was made after calling
         * {@link #setCustomDescription(CustomDescription)}.
         */
        public @NonNull Builder setDescription(@Nullable CharSequence description) {
            throwIfDestroyed();
            Preconditions.checkState(mCustomDescription == null,
                    "Can call setDescription() or setCustomDescription(), but not both");
            mDescription = description;
            return this;
        }

        /**
         * Sets a custom description to be shown in the UI when the user is asked to save.
         *
         * <p>Typically used when the service must show more info about the object being saved,
         * like a credit card logo, masked number, and expiration date.
         *
         * @param customDescription the custom description.
         * @return This Builder.
         *
         * @throws IllegalStateException if this call was made after calling
         * {@link #setDescription(CharSequence)}.
         */
        public @NonNull Builder setCustomDescription(@NonNull CustomDescription customDescription) {
            throwIfDestroyed();
            Preconditions.checkState(mDescription == null,
                    "Can call setDescription() or setCustomDescription(), but not both");
            mCustomDescription = customDescription;
            return this;
        }

        /**
         * Sets the style and listener for the negative save action.
         *
         * <p>This allows an autofill service to customize the style and be
         * notified when the user selects the negative action in the save
         * UI. Note that selecting the negative action regardless of its style
         * and listener being customized would dismiss the save UI and if a
         * custom listener intent is provided then this intent is
         * started. The default style is {@link #NEGATIVE_BUTTON_STYLE_CANCEL}</p>
         *
         * @param style The action style.
         * @param listener The action listener.
         * @return This builder.
         *
         * @see #NEGATIVE_BUTTON_STYLE_CANCEL
         * @see #NEGATIVE_BUTTON_STYLE_REJECT
         *
         * @throws IllegalArgumentException If the style is invalid
         */
        public @NonNull Builder setNegativeAction(@NegativeButtonStyle int style,
                @Nullable IntentSender listener) {
            throwIfDestroyed();
            if (style != NEGATIVE_BUTTON_STYLE_CANCEL
                    && style != NEGATIVE_BUTTON_STYLE_REJECT) {
                throw new IllegalArgumentException("Invalid style: " + style);
            }
            mNegativeButtonStyle = style;
            mNegativeActionListener = listener;
            return this;
        }

        /**
         * Sets an object used to validate the user input - if the input is not valid, the
         * autofill save UI is not shown.
         *
         * <p>Typically used to validate credit card numbers. Examples:
         *
         * <p>Validator for a credit number that must have exactly 16 digits:
         *
         * <pre class="prettyprint">
         * Validator validator = new RegexValidator(ccNumberId, Pattern.compile(""^\\d{16}$"))
         * </pre>
         *
         * <p>Validator for a credit number that must pass a Luhn checksum and either have
         * 16 digits, or 15 digits starting with 108:
         *
         * <pre class="prettyprint">
         * import static android.service.autofill.Validators.and;
         * import static android.service.autofill.Validators.or;
         *
         * Validator validator =
         *   and(
         *     new LuhnChecksumValidator(ccNumberId),
         *     or(
         *       new RegexValidator(ccNumberId, Pattern.compile("^\\d{16}$")),
         *       new RegexValidator(ccNumberId, Pattern.compile("^108\\d{12}$"))
         *     )
         *   );
         * </pre>
         *
         * <p><b>Note:</b> the example above is just for illustrative purposes; the same validator
         * could be created using a single regex for the {@code OR} part:
         *
         * <pre class="prettyprint">
         * Validator validator =
         *   and(
         *     new LuhnChecksumValidator(ccNumberId),
         *     new RegexValidator(ccNumberId, Pattern.compile(""^(\\d{16}|108\\d{12})$"))
         *   );
         * </pre>
         *
         * <p>Validator for a credit number contained in just 4 fields and that must have exactly
         * 4 digits on each field:
         *
         * <pre class="prettyprint">
         * import static android.service.autofill.Validators.and;
         *
         * Validator validator =
         *   and(
         *     new RegexValidator(ccNumberId1, Pattern.compile("^\\d{4}$")),
         *     new RegexValidator(ccNumberId2, Pattern.compile("^\\d{4}$")),
         *     new RegexValidator(ccNumberId3, Pattern.compile("^\\d{4}$")),
         *     new RegexValidator(ccNumberId4, Pattern.compile("^\\d{4}$"))
         *   );
         * </pre>
         *
         * @param validator an implementation provided by the Android System.
         * @return this builder.
         *
         * @throws IllegalArgumentException if {@code validator} is not a class provided
         * by the Android System.
         */
        public @NonNull Builder setValidator(@NonNull Validator validator) {
            throwIfDestroyed();
            Preconditions.checkArgument((validator instanceof InternalValidator),
                    "not provided by Android System: " + validator);
            mValidator = (InternalValidator) validator;
            return this;
        }

        /**
         * Adds a sanitizer for one or more field.
         *
         * <p>When a sanitizer is set for a field, the {@link AutofillValue} is sent to the
         * sanitizer before a save request is <a href="#TriggeringSaveRequest">triggered</a>.
         *
         * <p>Typically used to avoid displaying the save UI for values that are autofilled but
         * reformattedby the app. For example, to remove spaces between every 4 digits of a
         * credit card number:
         *
         * <pre class="prettyprint">
         * builder.addSanitizer(new TextValueSanitizer(
         *     Pattern.compile("^(\\d{4})\\s?(\\d{4})\\s?(\\d{4})\\s?(\\d{4})$", "$1$2$3$4")),
         *     ccNumberId);
         * </pre>
         *
         * <p>The same sanitizer can be reused to sanitize multiple fields. For example, to trim
         * both the username and password fields:
         *
         * <pre class="prettyprint">
         * builder.addSanitizer(
         *     new TextValueSanitizer(Pattern.compile("^\\s*(.*)\\s*$"), "$1"),
         *         usernameId, passwordId);
         * </pre>
         *
         * <p>The sanitizer can also be used as an alternative for a
         * {@link #setValidator(Validator) validator}. If any of the {@code ids} is a
         * {@link #SaveInfo.Builder(int, AutofillId[]) required id} and the {@code sanitizer} fails
         * because of it, then the save UI is not shown.
         *
         * @param sanitizer an implementation provided by the Android System.
         * @param ids id of fields whose value will be sanitized.
         * @return this builder.
         *
         * @throws IllegalArgumentException if a sanitizer for any of the {@code ids} has already
         * been added or if {@code ids} is empty.
         */
        public @NonNull Builder addSanitizer(@NonNull Sanitizer sanitizer,
                @NonNull AutofillId... ids) {
            throwIfDestroyed();
            Preconditions.checkArgument(!ArrayUtils.isEmpty(ids), "ids cannot be empty or null");
            Preconditions.checkArgument((sanitizer instanceof InternalSanitizer),
                    "not provided by Android System: " + sanitizer);

            if (mSanitizers == null) {
                mSanitizers = new ArrayMap<>();
                mSanitizerIds = new ArraySet<>(ids.length);
            }

            // Check for duplicates first.
            for (AutofillId id : ids) {
                Preconditions.checkArgument(!mSanitizerIds.contains(id), "already added %s", id);
                mSanitizerIds.add(id);
            }

            mSanitizers.put((InternalSanitizer) sanitizer, ids);

            return this;
        }

       /**
         * Explicitly defines the view that should commit the autofill context when clicked.
         *
         * <p>Usually, the save request is only automatically
         * <a href="#TriggeringSaveRequest">triggered</a> after the activity is
         * finished or all relevant views become invisible, but there are scenarios where the
         * autofill context is automatically commited too late
         * &mdash;for example, when the activity manually clears the autofillable views when a
         * button is tapped. This method can be used to trigger the autofill save UI earlier in
         * these scenarios.
         *
         * <p><b>Note:</b> This method should only be used in scenarios where the automatic workflow
         * is not enough, otherwise it could trigger the autofill save UI when it should not&mdash;
         * for example, when the user entered invalid credentials for the autofillable views.
         */
        public @NonNull Builder setTriggerId(@NonNull AutofillId id) {
            throwIfDestroyed();
            mTriggerId = Preconditions.checkNotNull(id);
            return this;
        }

        /**
         * Builds a new {@link SaveInfo} instance.
         *
         * @throws IllegalStateException if no
         * {@link #SaveInfo.Builder(int, AutofillId[]) required ids},
         * or {@link #setOptionalIds(AutofillId[]) optional ids}, or {@link #FLAG_DELAY_SAVE}
         * were set
         */
        public SaveInfo build() {
            throwIfDestroyed();
            Preconditions.checkState(
                    !ArrayUtils.isEmpty(mRequiredIds) || !ArrayUtils.isEmpty(mOptionalIds)
                            || (mFlags & FLAG_DELAY_SAVE) != 0,
                    "must have at least one required or optional id or FLAG_DELAYED_SAVE");
            mDestroyed = true;
            return new SaveInfo(this);
        }

        private void throwIfDestroyed() {
            if (mDestroyed) {
                throw new IllegalStateException("Already called #build()");
            }
        }
    }

    /////////////////////////////////////
    // Object "contract" methods. //
    /////////////////////////////////////
    @Override
    public String toString() {
        if (!sDebug) return super.toString();

        final StringBuilder builder = new StringBuilder("SaveInfo: [type=")
                .append(DebugUtils.flagsToString(SaveInfo.class, "SAVE_DATA_TYPE_", mType))
                .append(", requiredIds=").append(Arrays.toString(mRequiredIds))
                .append(", style=").append(DebugUtils.flagsToString(SaveInfo.class,
                        "NEGATIVE_BUTTON_STYLE_", mNegativeButtonStyle));
        if (mOptionalIds != null) {
            builder.append(", optionalIds=").append(Arrays.toString(mOptionalIds));
        }
        if (mDescription != null) {
            builder.append(", description=").append(mDescription);
        }
        if (mFlags != 0) {
            builder.append(", flags=").append(mFlags);
        }
        if (mCustomDescription != null) {
            builder.append(", customDescription=").append(mCustomDescription);
        }
        if (mValidator != null) {
            builder.append(", validator=").append(mValidator);
        }
        if (mSanitizerKeys != null) {
            builder.append(", sanitizerKeys=").append(mSanitizerKeys.length);
        }
        if (mSanitizerValues != null) {
            builder.append(", sanitizerValues=").append(mSanitizerValues.length);
        }
        if (mTriggerId != null) {
            builder.append(", triggerId=").append(mTriggerId);
        }

        return builder.append("]").toString();
    }

    /////////////////////////////////////
    // Parcelable "contract" methods. //
    /////////////////////////////////////

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeInt(mType);
        parcel.writeParcelableArray(mRequiredIds, flags);
        parcel.writeParcelableArray(mOptionalIds, flags);
        parcel.writeInt(mNegativeButtonStyle);
        parcel.writeParcelable(mNegativeActionListener, flags);
        parcel.writeCharSequence(mDescription);
        parcel.writeParcelable(mCustomDescription, flags);
        parcel.writeParcelable(mValidator, flags);
        parcel.writeParcelableArray(mSanitizerKeys, flags);
        if (mSanitizerKeys != null) {
            for (int i = 0; i < mSanitizerValues.length; i++) {
                parcel.writeParcelableArray(mSanitizerValues[i], flags);
            }
        }
        parcel.writeParcelable(mTriggerId, flags);
        parcel.writeInt(mFlags);
    }

    public static final @android.annotation.NonNull Parcelable.Creator<SaveInfo> CREATOR = new Parcelable.Creator<SaveInfo>() {
        @Override
        public SaveInfo createFromParcel(Parcel parcel) {

            // Always go through the builder to ensure the data ingested by
            // the system obeys the contract of the builder to avoid attacks
            // using specially crafted parcels.
            final int type = parcel.readInt();
            final AutofillId[] requiredIds = parcel.readParcelableArray(null, AutofillId.class);
            final Builder builder = requiredIds != null
                    ? new Builder(type, requiredIds)
                    : new Builder(type);
            final AutofillId[] optionalIds = parcel.readParcelableArray(null, AutofillId.class);
            if (optionalIds != null) {
                builder.setOptionalIds(optionalIds);
            }

            builder.setNegativeAction(parcel.readInt(), parcel.readParcelable(null));
            builder.setDescription(parcel.readCharSequence());
            final CustomDescription customDescripton = parcel.readParcelable(null);
            if (customDescripton != null) {
                builder.setCustomDescription(customDescripton);
            }
            final InternalValidator validator = parcel.readParcelable(null);
            if (validator != null) {
                builder.setValidator(validator);
            }
            final InternalSanitizer[] sanitizers =
                    parcel.readParcelableArray(null, InternalSanitizer.class);
            if (sanitizers != null) {
                final int size = sanitizers.length;
                for (int i = 0; i < size; i++) {
                    final AutofillId[] autofillIds =
                            parcel.readParcelableArray(null, AutofillId.class);
                    builder.addSanitizer(sanitizers[i], autofillIds);
                }
            }
            final AutofillId triggerId = parcel.readParcelable(null);
            if (triggerId != null) {
                builder.setTriggerId(triggerId);
            }
            builder.setFlags(parcel.readInt());
            return builder.build();
        }

        @Override
        public SaveInfo[] newArray(int size) {
            return new SaveInfo[size];
        }
    };
}
