/*
 * Copyright (C) 2016 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.service.autofill.FillRequest.INVALID_REQUEST_ID;
import static android.view.autofill.Helper.sDebug;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.app.Activity;
import android.content.IntentSender;
import android.content.pm.ParceledListSlice;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.view.autofill.AutofillId;
import android.widget.RemoteViews;

import com.android.internal.util.Preconditions;

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

/**
 * Response for an {@link
 * AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}.
 *
 * <p>See the main {@link AutofillService} documentation for more details and examples.
 */
public final class FillResponse implements Parcelable {

    /**
     * Flag used to generate {@link FillEventHistory.Event events} of type
     * {@link FillEventHistory.Event#TYPE_CONTEXT_COMMITTED}&mdash;if this flag is not passed to
     * {@link Builder#setFlags(int)}, these events are not generated.
     */
    public static final int FLAG_TRACK_CONTEXT_COMMITED = 0x1;

    /**
     * Flag used to change the behavior of {@link FillResponse.Builder#disableAutofill(long)}&mdash;
     * when this flag is passed to {@link Builder#setFlags(int)}, autofill is disabled only for the
     * activiy that generated the {@link FillRequest}, not the whole app.
     */
    public static final int FLAG_DISABLE_ACTIVITY_ONLY = 0x2;

    /** @hide */
    @IntDef(flag = true, prefix = { "FLAG_" }, value = {
            FLAG_TRACK_CONTEXT_COMMITED,
            FLAG_DISABLE_ACTIVITY_ONLY
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface FillResponseFlags {}

    private final @Nullable ParceledListSlice<Dataset> mDatasets;
    private final @Nullable SaveInfo mSaveInfo;
    private final @Nullable Bundle mClientState;
    private final @Nullable RemoteViews mPresentation;
    private final @Nullable InlinePresentation mInlinePresentation;
    private final @Nullable RemoteViews mHeader;
    private final @Nullable RemoteViews mFooter;
    private final @Nullable IntentSender mAuthentication;
    private final @Nullable AutofillId[] mAuthenticationIds;
    private final @Nullable AutofillId[] mIgnoredIds;
    private final long mDisableDuration;
    private final @Nullable AutofillId[] mFieldClassificationIds;
    private final int mFlags;
    private int mRequestId;
    private final @Nullable UserData mUserData;
    private final @Nullable int[] mCancelIds;
    private final boolean mSupportsInlineSuggestions;

    private FillResponse(@NonNull Builder builder) {
        mDatasets = (builder.mDatasets != null) ? new ParceledListSlice<>(builder.mDatasets) : null;
        mSaveInfo = builder.mSaveInfo;
        mClientState = builder.mClientState;
        mPresentation = builder.mPresentation;
        mInlinePresentation = builder.mInlinePresentation;
        mHeader = builder.mHeader;
        mFooter = builder.mFooter;
        mAuthentication = builder.mAuthentication;
        mAuthenticationIds = builder.mAuthenticationIds;
        mIgnoredIds = builder.mIgnoredIds;
        mDisableDuration = builder.mDisableDuration;
        mFieldClassificationIds = builder.mFieldClassificationIds;
        mFlags = builder.mFlags;
        mRequestId = INVALID_REQUEST_ID;
        mUserData = builder.mUserData;
        mCancelIds = builder.mCancelIds;
        mSupportsInlineSuggestions = builder.mSupportsInlineSuggestions;
    }

    /** @hide */
    public @Nullable Bundle getClientState() {
        return mClientState;
    }

    /** @hide */
    public @Nullable List<Dataset> getDatasets() {
        return (mDatasets != null) ? mDatasets.getList() : null;
    }

    /** @hide */
    public @Nullable SaveInfo getSaveInfo() {
        return mSaveInfo;
    }

    /** @hide */
    public @Nullable RemoteViews getPresentation() {
        return mPresentation;
    }

    /** @hide */
    public @Nullable InlinePresentation getInlinePresentation() {
        return mInlinePresentation;
    }

    /** @hide */
    public @Nullable RemoteViews getHeader() {
        return mHeader;
    }

    /** @hide */
    public @Nullable RemoteViews getFooter() {
        return mFooter;
    }

    /** @hide */
    public @Nullable IntentSender getAuthentication() {
        return mAuthentication;
    }

    /** @hide */
    public @Nullable AutofillId[] getAuthenticationIds() {
        return mAuthenticationIds;
    }

    /** @hide */
    public @Nullable AutofillId[] getIgnoredIds() {
        return mIgnoredIds;
    }

    /** @hide */
    public long getDisableDuration() {
        return mDisableDuration;
    }

    /** @hide */
    public @Nullable AutofillId[] getFieldClassificationIds() {
        return mFieldClassificationIds;
    }

    /** @hide */
    public @Nullable UserData getUserData() {
        return mUserData;
    }

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

    /**
     * Associates a {@link FillResponse} to a request.
     *
     * <p>Set inside of the {@link FillCallback} code, not the {@link AutofillService}.
     *
     * @param requestId The id of the request to associate the response to.
     *
     * @hide
     */
    public void setRequestId(int requestId) {
        mRequestId = requestId;
    }

    /** @hide */
    public int getRequestId() {
        return mRequestId;
    }

    /** @hide */
    @Nullable
    public int[] getCancelIds() {
        return mCancelIds;
    }

    /** @hide */
    public boolean supportsInlineSuggestions() {
        return mSupportsInlineSuggestions;
    }

    /**
     * Builder for {@link FillResponse} objects. You must to provide at least
     * one dataset or set an authentication intent with a presentation view.
     */
    public static final class Builder {
        private ArrayList<Dataset> mDatasets;
        private SaveInfo mSaveInfo;
        private Bundle mClientState;
        private RemoteViews mPresentation;
        private InlinePresentation mInlinePresentation;
        private RemoteViews mHeader;
        private RemoteViews mFooter;
        private IntentSender mAuthentication;
        private AutofillId[] mAuthenticationIds;
        private AutofillId[] mIgnoredIds;
        private long mDisableDuration;
        private AutofillId[] mFieldClassificationIds;
        private int mFlags;
        private boolean mDestroyed;
        private UserData mUserData;
        private int[] mCancelIds;
        private boolean mSupportsInlineSuggestions;

        /**
         * Triggers a custom UI before before autofilling the screen with any data set in this
         * response.
         *
         * <p><b>Note:</b> Although the name of this method suggests that it should be used just for
         * authentication flow, it can be used for other advanced flows; see {@link AutofillService}
         * for examples.
         *
         * <p>This is typically useful when a user interaction is required to unlock their
         * data vault if you encrypt the data set labels and data set data. It is recommended
         * to encrypt only the sensitive data and not the data set labels which would allow
         * auth on the data set level leading to a better user experience. Note that if you
         * use sensitive data as a label, for example an email address, then it should also
         * be encrypted. The provided {@link android.app.PendingIntent intent} must be an
         * {@link Activity} which implements your authentication flow. Also if you provide an auth
         * intent you also need to specify the presentation view to be shown in the fill UI
         * for the user to trigger your authentication flow.
         *
         * <p>When a user triggers autofill, the system launches the provided intent
         * whose extras will have the
         * {@link android.view.autofill.AutofillManager#EXTRA_ASSIST_STRUCTURE screen
         * content} and your {@link android.view.autofill.AutofillManager#EXTRA_CLIENT_STATE
         * client state}. Once you complete your authentication flow you should set the
         * {@link Activity} result to {@link android.app.Activity#RESULT_OK} and set the
         * {@link android.view.autofill.AutofillManager#EXTRA_AUTHENTICATION_RESULT} extra
         * with the fully populated {@link FillResponse response} (or {@code null} if the screen
         * cannot be autofilled).
         *
         * <p>For example, if you provided an empty {@link FillResponse response} because the
         * user's data was locked and marked that the response needs an authentication then
         * in the response returned if authentication succeeds you need to provide all
         * available data sets some of which may need to be further authenticated, for
         * example a credit card whose CVV needs to be entered.
         *
         * <p>If you provide an authentication intent you must also provide a presentation
         * which is used to visualize visualize the response for triggering the authentication
         * flow.
         *
         * <p><b>Note:</b> Do not make the provided pending intent
         * immutable by using {@link android.app.PendingIntent#FLAG_IMMUTABLE} as the
         * platform needs to fill in the authentication arguments.
         *
         * <p>Theme does not work with RemoteViews layout. Avoid hardcoded text color
         * or background color: Autofill on different platforms may have different themes.
         *
         * @param authentication Intent to an activity with your authentication flow.
         * @param presentation The presentation to visualize the response.
         * @param ids id of Views that when focused will display the authentication UI.
         *
         * @return This builder.
         *
         * @throws IllegalArgumentException if any of the following occurs:
         * <ul>
         *   <li>{@code ids} is {@code null}</li>
         *   <li>{@code ids} is empty</li>
         *   <li>{@code ids} contains a {@code null} element</li>
         *   <li>both {@code authentication} and {@code presentation} are {@code null}</li>
         *   <li>both {@code authentication} and {@code presentation} are non-{@code null}</li>
         * </ul>
         *
         * @throws IllegalStateException if a {@link #setHeader(RemoteViews) header} or a
         * {@link #setFooter(RemoteViews) footer} are already set for this builder.
         *
         * @see android.app.PendingIntent#getIntentSender()
         */
        @NonNull
        public Builder setAuthentication(@NonNull AutofillId[] ids,
                @Nullable IntentSender authentication, @Nullable RemoteViews presentation) {
            throwIfDestroyed();
            throwIfDisableAutofillCalled();
            if (mHeader != null || mFooter != null) {
                throw new IllegalStateException("Already called #setHeader() or #setFooter()");
            }

            if (authentication == null ^ presentation == null) {
                throw new IllegalArgumentException("authentication and presentation"
                        + " must be both non-null or null");
            }
            mAuthentication = authentication;
            mPresentation = presentation;
            mAuthenticationIds = assertValid(ids);
            return this;
        }

        /**
         * Triggers a custom UI before before autofilling the screen with any data set in this
         * response.
         *
         * <p><b>Note:</b> Although the name of this method suggests that it should be used just for
         * authentication flow, it can be used for other advanced flows; see {@link AutofillService}
         * for examples.
         *
         * <p>This method is similar to
         * {@link #setAuthentication(AutofillId[], IntentSender, RemoteViews)}, but also accepts
         * an {@link InlinePresentation} presentation which is required for authenticating through
         * the inline autofill flow.
         *
         * <p><b>Note:</b> {@link #setHeader(RemoteViews)} or {@link #setFooter(RemoteViews)} does
         * not work with {@link InlinePresentation}.</p>
         *
         * @param authentication Intent to an activity with your authentication flow.
         * @param presentation The presentation to visualize the response.
         * @param inlinePresentation The inlinePresentation to visualize the response inline.
         * @param ids id of Views that when focused will display the authentication UI.
         *
         * @return This builder.
         *
         * @throws IllegalArgumentException if any of the following occurs:
         * <ul>
         *   <li>{@code ids} is {@code null}</li>
         *   <li>{@code ids} is empty</li>
         *   <li>{@code ids} contains a {@code null} element</li>
         *   <li>both {@code authentication} and {@code presentation} are {@code null}</li>
         *   <li>both {@code authentication} and {@code presentation} are non-{@code null}</li>
         *   <li>both {@code authentication} and {@code inlinePresentation} are {@code null}</li>
         *   <li>both {@code authentication} and {@code inlinePresentation} are
         *   non-{@code null}</li>
         * </ul>
         *
         * @throws IllegalStateException if a {@link #setHeader(RemoteViews) header} or a
         * {@link #setFooter(RemoteViews) footer} are already set for this builder.
         *
         * @see android.app.PendingIntent#getIntentSender()
         */
        @NonNull
        public Builder setAuthentication(@NonNull AutofillId[] ids,
                @Nullable IntentSender authentication, @Nullable RemoteViews presentation,
                @Nullable InlinePresentation inlinePresentation) {
            throwIfDestroyed();
            throwIfDisableAutofillCalled();
            if (mHeader != null || mFooter != null) {
                throw new IllegalStateException("Already called #setHeader() or #setFooter()");
            }

            if (authentication == null ^ (presentation == null && inlinePresentation == null)) {
                throw new IllegalArgumentException("authentication and presentation "
                        + "(dropdown or inline), must be both non-null or null");
            }
            mAuthentication = authentication;
            mPresentation = presentation;
            mInlinePresentation = inlinePresentation;
            mAuthenticationIds = assertValid(ids);
            return this;
        }

        /**
         * Specifies views that should not trigger new
         * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal,
         * FillCallback)} requests.
         *
         * <p>This is typically used when the service cannot autofill the view; for example, a
         * text field representing the result of a Captcha challenge.
         */
        @NonNull
        public Builder setIgnoredIds(AutofillId...ids) {
            throwIfDestroyed();
            mIgnoredIds = ids;
            return this;
        }

        /**
         * Adds a new {@link Dataset} to this response.
         *
         * <p><b>Note: </b> on Android {@link android.os.Build.VERSION_CODES#O}, the total number of
         * datasets is limited by the Binder transaction size, so it's recommended to keep it
         * small (in the range of 10-20 at most) and use pagination by adding a fake
         * {@link Dataset.Builder#setAuthentication(IntentSender) authenticated dataset} at the end
         * with a presentation string like "Next 10" that would return a new {@link FillResponse}
         * with the next 10 datasets, and so on. This limitation was lifted on
         * Android {@link android.os.Build.VERSION_CODES#O_MR1}, although the Binder transaction
         * size can still be reached if each dataset itself is too big.
         *
         * @return This builder.
         */
        @NonNull
        public Builder addDataset(@Nullable Dataset dataset) {
            throwIfDestroyed();
            throwIfDisableAutofillCalled();
            if (dataset == null) {
                return this;
            }
            if (mDatasets == null) {
                mDatasets = new ArrayList<>();
            }
            if (!mDatasets.add(dataset)) {
                return this;
            }
            return this;
        }

        /**
         * Sets the {@link SaveInfo} associated with this response.
         *
         * @return This builder.
         */
        public @NonNull Builder setSaveInfo(@NonNull SaveInfo saveInfo) {
            throwIfDestroyed();
            throwIfDisableAutofillCalled();
            mSaveInfo = saveInfo;
            return this;
        }

        /**
         * Sets a bundle with state that is passed to subsequent APIs that manipulate this response.
         *
         * <p>You can use this bundle to store intermediate state that is passed to subsequent calls
         * to {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal,
         * FillCallback)} and {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)}, and
         * you can also retrieve it by calling {@link FillEventHistory.Event#getClientState()}.
         *
         * <p>If this method is called on multiple {@link FillResponse} objects for the same
         * screen, just the latest bundle is passed back to the service.
         *
         * @param clientState The custom client state.
         * @return This builder.
         */
        @NonNull
        public Builder setClientState(@Nullable Bundle clientState) {
            throwIfDestroyed();
            throwIfDisableAutofillCalled();
            mClientState = clientState;
            return this;
        }

        /**
         * Sets which fields are used for
         * <a href="AutofillService.html#FieldClassification">field classification</a>
         *
         * <p><b>Note:</b> This method automatically adds the
         * {@link FillResponse#FLAG_TRACK_CONTEXT_COMMITED} to the {@link #setFlags(int) flags}.

         * @throws IllegalArgumentException is length of {@code ids} args is more than
         * {@link UserData#getMaxFieldClassificationIdsSize()}.
         * @throws IllegalStateException if {@link #build()} or {@link #disableAutofill(long)} was
         * already called.
         * @throws NullPointerException if {@code ids} or any element on it is {@code null}.
         */
        @NonNull
        public Builder setFieldClassificationIds(@NonNull AutofillId... ids) {
            throwIfDestroyed();
            throwIfDisableAutofillCalled();
            Preconditions.checkArrayElementsNotNull(ids, "ids");
            Preconditions.checkArgumentInRange(ids.length, 1,
                    UserData.getMaxFieldClassificationIdsSize(), "ids length");
            mFieldClassificationIds = ids;
            mFlags |= FLAG_TRACK_CONTEXT_COMMITED;
            return this;
        }

        /**
         * Sets flags changing the response behavior.
         *
         * @param flags a combination of {@link #FLAG_TRACK_CONTEXT_COMMITED} and
         * {@link #FLAG_DISABLE_ACTIVITY_ONLY}, or {@code 0}.
         *
         * @return This builder.
         */
        @NonNull
        public Builder setFlags(@FillResponseFlags int flags) {
            throwIfDestroyed();
            mFlags = Preconditions.checkFlagsArgument(flags,
                    FLAG_TRACK_CONTEXT_COMMITED | FLAG_DISABLE_ACTIVITY_ONLY);
            return this;
        }

        /**
         * Disables autofill for the app or activity.
         *
         * <p>This method is useful to optimize performance in cases where the service knows it
         * can not autofill an app&mdash;for example, when the service has a list of "blacklisted"
         * apps such as office suites.
         *
         * <p>By default, it disables autofill for all activities in the app, unless the response is
         * {@link #setFlags(int) flagged} with {@link #FLAG_DISABLE_ACTIVITY_ONLY}.
         *
         * <p>Autofill for the app or activity is automatically re-enabled after any of the
         * following conditions:
         *
         * <ol>
         *   <li>{@code duration} milliseconds have passed.
         *   <li>The autofill service for the user has changed.
         *   <li>The device has rebooted.
         * </ol>
         *
         * <p><b>Note:</b> Activities that are running when autofill is re-enabled remain
         * disabled for autofill until they finish and restart.
         *
         * @param duration duration to disable autofill, in milliseconds.
         *
         * @return this builder
         *
         * @throws IllegalArgumentException if {@code duration} is not a positive number.
         * @throws IllegalStateException if either {@link #addDataset(Dataset)},
         *       {@link #setAuthentication(AutofillId[], IntentSender, RemoteViews)},
         *       {@link #setSaveInfo(SaveInfo)}, {@link #setClientState(Bundle)}, or
         *       {@link #setFieldClassificationIds(AutofillId...)} was already called.
         */
        @NonNull
        public Builder disableAutofill(long duration) {
            throwIfDestroyed();
            if (duration <= 0) {
                throw new IllegalArgumentException("duration must be greater than 0");
            }
            if (mAuthentication != null || mDatasets != null || mSaveInfo != null
                    || mFieldClassificationIds != null || mClientState != null) {
                throw new IllegalStateException("disableAutofill() must be the only method called");
            }

            mDisableDuration = duration;
            return this;
        }

        /**
         * Sets a header to be shown as the first element in the list of datasets.
         *
         * <p>When this method is called, you must also {@link #addDataset(Dataset) add a dataset},
         * otherwise {@link #build()} throws an {@link IllegalStateException}. Similarly, this
         * method should only be used on {@link FillResponse FillResponses} that do not require
         * authentication (as the header could have been set directly in the main presentation in
         * these cases).
         *
         * <p>Theme does not work with RemoteViews layout. Avoid hardcoded text color
         * or background color: Autofill on different platforms may have different themes.
         *
         * @param header a presentation to represent the header. This presentation is not clickable
         * &mdash;calling
         * {@link RemoteViews#setOnClickPendingIntent(int, android.app.PendingIntent)} on it would
         * have no effect.
         *
         * @return this builder
         *
         * @throws IllegalStateException if an
         * {@link #setAuthentication(AutofillId[], IntentSender, RemoteViews) authentication} was
         * already set for this builder.
         */
        // TODO(b/69796626): make it sticky / update javadoc
        @NonNull
        public Builder setHeader(@NonNull RemoteViews header) {
            throwIfDestroyed();
            throwIfAuthenticationCalled();
            mHeader = Preconditions.checkNotNull(header);
            return this;
        }

        /**
         * Sets a footer to be shown as the last element in the list of datasets.
         *
         * <p>When this method is called, you must also {@link #addDataset(Dataset) add a dataset},
         * otherwise {@link #build()} throws an {@link IllegalStateException}. Similarly, this
         * method should only be used on {@link FillResponse FillResponses} that do not require
         * authentication (as the footer could have been set directly in the main presentation in
         * these cases).
         *
         * <p>Theme does not work with RemoteViews layout. Avoid hardcoded text color
         * or background color: Autofill on different platforms may have different themes.
         *
         * @param footer a presentation to represent the footer. This presentation is not clickable
         * &mdash;calling
         * {@link RemoteViews#setOnClickPendingIntent(int, android.app.PendingIntent)} on it would
         * have no effect.
         *
         * @return this builder
         *
         * @throws IllegalStateException if the FillResponse
         * {@link #setAuthentication(AutofillId[], IntentSender, RemoteViews)
         * requires authentication}.
         */
        // TODO(b/69796626): make it sticky / update javadoc
        @NonNull
        public Builder setFooter(@NonNull RemoteViews footer) {
            throwIfDestroyed();
            throwIfAuthenticationCalled();
            mFooter = Preconditions.checkNotNull(footer);
            return this;
        }

        /**
         * Sets a specific {@link UserData} for field classification for this request only.
         *
         * <p>Any fields in this UserData will override corresponding fields in the generic
         * UserData object
         *
         * @return this builder
         * @throws IllegalStateException if the FillResponse
         * {@link #setAuthentication(AutofillId[], IntentSender, RemoteViews)
         * requires authentication}.
         */
        @NonNull
        public Builder setUserData(@NonNull UserData userData) {
            throwIfDestroyed();
            throwIfAuthenticationCalled();
            mUserData = Preconditions.checkNotNull(userData);
            return this;
        }

        /**
         * Sets target resource IDs of the child view in {@link RemoteViews Presentation Template}
         * which will cancel the session when clicked.
         * Those targets will be respectively applied to a child of the header, footer and
         * each {@link Dataset}.
         *
         * @param ids array of the resource id. Empty list or non-existing id has no effect.
         *
         * @return this builder
         *
         * @throws IllegalStateException if {@link #build()} was already called.
         */
        @NonNull
        public Builder setPresentationCancelIds(@Nullable int[] ids) {
            throwIfDestroyed();
            mCancelIds = ids;
            return this;
        }

        /**
         * Builds a new {@link FillResponse} instance.
         *
         * @throws IllegalStateException if any of the following conditions occur:
         * <ol>
         *   <li>{@link #build()} was already called.
         *   <li>No call was made to {@link #addDataset(Dataset)},
         *       {@link #setAuthentication(AutofillId[], IntentSender, RemoteViews)},
         *       {@link #setSaveInfo(SaveInfo)}, {@link #disableAutofill(long)},
         *       {@link #setClientState(Bundle)},
         *       or {@link #setFieldClassificationIds(AutofillId...)}.
         *   <li>{@link #setHeader(RemoteViews)} or {@link #setFooter(RemoteViews)} is called
         *       without any previous calls to {@link #addDataset(Dataset)}.
         * </ol>
         *
         * @return A built response.
         */
        @NonNull
        public FillResponse build() {
            throwIfDestroyed();
            if (mAuthentication == null && mDatasets == null && mSaveInfo == null
                    && mDisableDuration == 0 && mFieldClassificationIds == null
                    && mClientState == null) {
                throw new IllegalStateException("need to provide: at least one DataSet, or a "
                        + "SaveInfo, or an authentication with a presentation, "
                        + "or a FieldsDetection, or a client state, or disable autofill");
            }
            if (mDatasets == null && (mHeader != null || mFooter != null)) {
                throw new IllegalStateException(
                        "must add at least 1 dataset when using header or footer");
            }

            if (mDatasets != null) {
                for (final Dataset dataset : mDatasets) {
                    if (dataset.getFieldInlinePresentation(0) != null) {
                        mSupportsInlineSuggestions = true;
                        break;
                    }
                }
            } else if (mInlinePresentation != null) {
                mSupportsInlineSuggestions = true;
            }

            mDestroyed = true;
            return new FillResponse(this);
        }

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

        private void throwIfDisableAutofillCalled() {
            if (mDisableDuration > 0) {
                throw new IllegalStateException("Already called #disableAutofill()");
            }
        }

        private void throwIfAuthenticationCalled() {
            if (mAuthentication != null) {
                throw new IllegalStateException("Already called #setAuthentication()");
            }
        }
    }

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

        // TODO: create a dump() method instead
        final StringBuilder builder = new StringBuilder(
                "FillResponse : [mRequestId=" + mRequestId);
        if (mDatasets != null) {
            builder.append(", datasets=").append(mDatasets.getList());
        }
        if (mSaveInfo != null) {
            builder.append(", saveInfo=").append(mSaveInfo);
        }
        if (mClientState != null) {
            builder.append(", hasClientState");
        }
        if (mPresentation != null) {
            builder.append(", hasPresentation");
        }
        if (mInlinePresentation != null) {
            builder.append(", hasInlinePresentation");
        }
        if (mHeader != null) {
            builder.append(", hasHeader");
        }
        if (mFooter != null) {
            builder.append(", hasFooter");
        }
        if (mAuthentication != null) {
            builder.append(", hasAuthentication");
        }
        if (mAuthenticationIds != null) {
            builder.append(", authenticationIds=").append(Arrays.toString(mAuthenticationIds));
        }
        builder.append(", disableDuration=").append(mDisableDuration);
        if (mFlags != 0) {
            builder.append(", flags=").append(mFlags);
        }
        if (mFieldClassificationIds != null) {
            builder.append(Arrays.toString(mFieldClassificationIds));
        }
        if (mUserData != null) {
            builder.append(", userData=").append(mUserData);
        }
        if (mCancelIds != null) {
            builder.append(", mCancelIds=").append(mCancelIds.length);
        }
        builder.append(", mSupportInlinePresentations=").append(mSupportsInlineSuggestions);
        return builder.append("]").toString();
    }

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

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

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeParcelable(mDatasets, flags);
        parcel.writeParcelable(mSaveInfo, flags);
        parcel.writeParcelable(mClientState, flags);
        parcel.writeParcelableArray(mAuthenticationIds, flags);
        parcel.writeParcelable(mAuthentication, flags);
        parcel.writeParcelable(mPresentation, flags);
        parcel.writeParcelable(mInlinePresentation, flags);
        parcel.writeParcelable(mHeader, flags);
        parcel.writeParcelable(mFooter, flags);
        parcel.writeParcelable(mUserData, flags);
        parcel.writeParcelableArray(mIgnoredIds, flags);
        parcel.writeLong(mDisableDuration);
        parcel.writeParcelableArray(mFieldClassificationIds, flags);
        parcel.writeInt(mFlags);
        parcel.writeIntArray(mCancelIds);
        parcel.writeInt(mRequestId);
    }

    public static final @android.annotation.NonNull Parcelable.Creator<FillResponse> CREATOR =
            new Parcelable.Creator<FillResponse>() {
        @Override
        public FillResponse 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 Builder builder = new Builder();
            final ParceledListSlice<Dataset> datasetSlice = parcel.readParcelable(null);
            final List<Dataset> datasets = (datasetSlice != null) ? datasetSlice.getList() : null;
            final int datasetCount = (datasets != null) ? datasets.size() : 0;
            for (int i = 0; i < datasetCount; i++) {
                builder.addDataset(datasets.get(i));
            }
            builder.setSaveInfo(parcel.readParcelable(null));
            builder.setClientState(parcel.readParcelable(null));

            // Sets authentication state.
            final AutofillId[] authenticationIds = parcel.readParcelableArray(null,
                    AutofillId.class);
            final IntentSender authentication = parcel.readParcelable(null);
            final RemoteViews presentation = parcel.readParcelable(null);
            final InlinePresentation inlinePresentation = parcel.readParcelable(null);
            if (authenticationIds != null) {
                builder.setAuthentication(authenticationIds, authentication, presentation,
                        inlinePresentation);
            }
            final RemoteViews header = parcel.readParcelable(null);
            if (header != null) {
                builder.setHeader(header);
            }
            final RemoteViews footer = parcel.readParcelable(null);
            if (footer != null) {
                builder.setFooter(footer);
            }
            final UserData userData = parcel.readParcelable(null);
            if (userData != null) {
                builder.setUserData(userData);
            }

            builder.setIgnoredIds(parcel.readParcelableArray(null, AutofillId.class));
            final long disableDuration = parcel.readLong();
            if (disableDuration > 0) {
                builder.disableAutofill(disableDuration);
            }
            final AutofillId[] fieldClassifactionIds =
                    parcel.readParcelableArray(null, AutofillId.class);
            if (fieldClassifactionIds != null) {
                builder.setFieldClassificationIds(fieldClassifactionIds);
            }
            builder.setFlags(parcel.readInt());
            final int[] cancelIds = parcel.createIntArray();
            builder.setPresentationCancelIds(cancelIds);

            final FillResponse response = builder.build();
            response.setRequestId(parcel.readInt());

            return response;
        }

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