SaveInfo.java revision 0962262f42e3636270689100e1bb90b8f3cf6d77
1f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme/*
2f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme * Copyright (C) 2017 The Android Open Source Project
3f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme *
4f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme * Licensed under the Apache License, Version 2.0 (the "License");
5f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme * you may not use this file except in compliance with the License.
6f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme * You may obtain a copy of the License at
7f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme *
8f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme *      http://www.apache.org/licenses/LICENSE-2.0
9f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme *
10f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme * Unless required by applicable law or agreed to in writing, software
11f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme * distributed under the License is distributed on an "AS IS" BASIS,
12f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme * See the License for the specific language governing permissions and
14f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme * limitations under the License.
15f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme */
16f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
17f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Lemepackage android.service.autofill;
18f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
19f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Lemeimport static android.view.autofill.Helper.DEBUG;
20f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
21f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Lemeimport android.annotation.IntDef;
22f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Lemeimport android.annotation.NonNull;
23f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Lemeimport android.annotation.Nullable;
2433d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganovimport android.content.IntentSender;
25f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Lemeimport android.os.Bundle;
26f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Lemeimport android.os.Parcel;
27f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Lemeimport android.os.Parcelable;
28f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Lemeimport android.view.autofill.AutoFillId;
29640f30a7763b0a4b80c767acb84c740aac04768bFelipe Lemeimport android.view.autofill.AutofillId;
3082e3793c15298f9c62edee23259c116606f10911Felipe Lemeimport android.view.autofill.AutofillManager;
3182e3793c15298f9c62edee23259c116606f10911Felipe Lemeimport android.view.autofill.AutofillValue;
3282e3793c15298f9c62edee23259c116606f10911Felipe Leme
3382e3793c15298f9c62edee23259c116606f10911Felipe Lemeimport com.android.internal.util.Preconditions;
34f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
35f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Lemeimport java.lang.annotation.Retention;
36f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Lemeimport java.lang.annotation.RetentionPolicy;
3782e3793c15298f9c62edee23259c116606f10911Felipe Lemeimport java.util.Arrays;
38f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
39f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme/**
4082e3793c15298f9c62edee23259c116606f10911Felipe Leme * Information used to indicate that an {@link AutofillService} is interested on saving the
4182e3793c15298f9c62edee23259c116606f10911Felipe Leme * user-inputed data for future use, through a
4282e3793c15298f9c62edee23259c116606f10911Felipe Leme * {@link AutofillService#onSaveRequest(android.app.assist.AssistStructure, Bundle, SaveCallback)}
4382e3793c15298f9c62edee23259c116606f10911Felipe Leme * call.
4482e3793c15298f9c62edee23259c116606f10911Felipe Leme *
4582e3793c15298f9c62edee23259c116606f10911Felipe Leme * <p>A {@link SaveInfo} is always associated with a {@link FillResponse}, and it contains at least
4682e3793c15298f9c62edee23259c116606f10911Felipe Leme * two pieces of information:
4782e3793c15298f9c62edee23259c116606f10911Felipe Leme *
4882e3793c15298f9c62edee23259c116606f10911Felipe Leme * <ol>
4982e3793c15298f9c62edee23259c116606f10911Felipe Leme *   <li>The type of user data that would be saved (like passoword or credit card info).
5082e3793c15298f9c62edee23259c116606f10911Felipe Leme *   <li>The minimum set of views (represented by their {@link AutofillId}) that need to be changed
5182e3793c15298f9c62edee23259c116606f10911Felipe Leme *       to trigger a save request.
5282e3793c15298f9c62edee23259c116606f10911Felipe Leme * </ol>
5382e3793c15298f9c62edee23259c116606f10911Felipe Leme *
5482e3793c15298f9c62edee23259c116606f10911Felipe Leme *  Typically, the {@link SaveInfo} contains the same {@code id}s as the {@link Dataset}:
5582e3793c15298f9c62edee23259c116606f10911Felipe Leme *
5682e3793c15298f9c62edee23259c116606f10911Felipe Leme * <pre class="prettyprint">
5782e3793c15298f9c62edee23259c116606f10911Felipe Leme *  new FillResponse.Builder()
5882e3793c15298f9c62edee23259c116606f10911Felipe Leme *      .add(new Dataset.Builder(createPresentation())
5982e3793c15298f9c62edee23259c116606f10911Felipe Leme *          .setValue(id1, AutofillValue.forText("homer"))
6082e3793c15298f9c62edee23259c116606f10911Felipe Leme *          .setValue(id2, AutofillValue.forText("D'OH!"))
6182e3793c15298f9c62edee23259c116606f10911Felipe Leme *          .build())
6282e3793c15298f9c62edee23259c116606f10911Felipe Leme *      .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_INFO_TYPE_PASSWORD, new int[] {id1, id2})
6382e3793c15298f9c62edee23259c116606f10911Felipe Leme *                  .build())
6482e3793c15298f9c62edee23259c116606f10911Felipe Leme *      .build();
6582e3793c15298f9c62edee23259c116606f10911Felipe Leme * </pre>
6682e3793c15298f9c62edee23259c116606f10911Felipe Leme *
6782e3793c15298f9c62edee23259c116606f10911Felipe Leme * There might be cases where the {@link AutofillService} knows how to fill the
6882e3793c15298f9c62edee23259c116606f10911Felipe Leme * {@link android.app.Activity}, but the user has no data for it. In that case, the
6982e3793c15298f9c62edee23259c116606f10911Felipe Leme * {@link FillResponse} should contain just the {@link SaveInfo}, but no {@link Dataset}s:
70f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme *
7182e3793c15298f9c62edee23259c116606f10911Felipe Leme * <pre class="prettyprint">
7282e3793c15298f9c62edee23259c116606f10911Felipe Leme *  new FillResponse.Builder()
7382e3793c15298f9c62edee23259c116606f10911Felipe Leme *      .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_INFO_TYPE_PASSWORD, new int[] {id1, id2})
7482e3793c15298f9c62edee23259c116606f10911Felipe Leme *                  .build())
7582e3793c15298f9c62edee23259c116606f10911Felipe Leme *      .build();
7682e3793c15298f9c62edee23259c116606f10911Felipe Leme * </pre>
77f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme *
7882e3793c15298f9c62edee23259c116606f10911Felipe Leme * <p>There might be cases where the user data in the {@link AutofillService} is enough
7982e3793c15298f9c62edee23259c116606f10911Felipe Leme * to populate some fields but not all, and the service would still be interested on saving the
8082e3793c15298f9c62edee23259c116606f10911Felipe Leme * other fields. In this scenario, the service could set the
8182e3793c15298f9c62edee23259c116606f10911Felipe Leme * {@link SaveInfo.Builder#setOptionalIds(AutofillId[])} as well:
82f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme *
8382e3793c15298f9c62edee23259c116606f10911Felipe Leme * <pre class="prettyprint">
8482e3793c15298f9c62edee23259c116606f10911Felipe Leme *   new FillResponse.Builder()
8582e3793c15298f9c62edee23259c116606f10911Felipe Leme *       .add(new Dataset.Builder(createPresentation())
8682e3793c15298f9c62edee23259c116606f10911Felipe Leme *          .setValue(id1, AutofillValue.forText("742 Evergreen Terrace"))  // street
8782e3793c15298f9c62edee23259c116606f10911Felipe Leme *          .setValue(id2, AutofillValue.forText("Springfield"))            // city
8882e3793c15298f9c62edee23259c116606f10911Felipe Leme *          .build())
8982e3793c15298f9c62edee23259c116606f10911Felipe Leme *       .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_INFO_TYPE_ADDRESS, new int[] {id1, id2})
9082e3793c15298f9c62edee23259c116606f10911Felipe Leme *                   .setOptionalIds(new int[] {id3, id4}) // state and zipcode
9182e3793c15298f9c62edee23259c116606f10911Felipe Leme *                   .build())
9282e3793c15298f9c62edee23259c116606f10911Felipe Leme *       .build();
9382e3793c15298f9c62edee23259c116606f10911Felipe Leme * </pre>
9482e3793c15298f9c62edee23259c116606f10911Felipe Leme *
9582e3793c15298f9c62edee23259c116606f10911Felipe Leme * The
9682e3793c15298f9c62edee23259c116606f10911Felipe Leme * {@link AutofillService#onSaveRequest(android.app.assist.AssistStructure, Bundle, SaveCallback)}
9782e3793c15298f9c62edee23259c116606f10911Felipe Leme * is triggered after a call to {@link AutofillManager#commit()}, but only when all conditions
9882e3793c15298f9c62edee23259c116606f10911Felipe Leme * below are met:
9982e3793c15298f9c62edee23259c116606f10911Felipe Leme *
10082e3793c15298f9c62edee23259c116606f10911Felipe Leme * <ol>
10182e3793c15298f9c62edee23259c116606f10911Felipe Leme *   <li>The {@link SaveInfo} associated with the {@link FillResponse} is not {@code null}.
10282e3793c15298f9c62edee23259c116606f10911Felipe Leme *   <li>The {@link AutofillValue} of all required views (as set by the {@code requiredIds} passed
10382e3793c15298f9c62edee23259c116606f10911Felipe Leme *       to {@link SaveInfo.Builder} constructor are not empty.
10482e3793c15298f9c62edee23259c116606f10911Felipe Leme *   <li>The {@link AutofillValue} of at least one view (be it required or optional) has changed
10582e3793c15298f9c62edee23259c116606f10911Felipe Leme *       (i.e., it's not the same value passed in a {@link Dataset}).
10682e3793c15298f9c62edee23259c116606f10911Felipe Leme *   <li>The user explicitly tapped the affordance asking to save data for autofill.
10782e3793c15298f9c62edee23259c116606f10911Felipe Leme * </ol>
108f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme */
109f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Lemepublic final class SaveInfo implements Parcelable {
110f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
111f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /**
112f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme     * Type used on when the service can save the contents of an activity, but cannot describe what
113f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme     * the content is for.
114f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme     */
115b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme    public static final int SAVE_DATA_TYPE_GENERIC = 0;
116f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
117f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /**
118b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme     * Type used when the {@link FillResponse} represents user credentials that have a password.
119f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme     */
120b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme    public static final int SAVE_DATA_TYPE_PASSWORD = 1;
121b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme
122f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /**
123f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme     * Type used on when the {@link FillResponse} represents a physical address (such as street,
124f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme     * city, state, etc).
125f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme     */
126b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme    public static final int SAVE_DATA_TYPE_ADDRESS = 2;
127f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
128f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /**
129b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme     * Type used when the {@link FillResponse} represents a credit card.
130f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme     */
131b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme    public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3;
132f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
1330962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme    /**
1340962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme     * Type used when the {@link FillResponse} represents just an username, without a password.
1350962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme     */
1360962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme    public static final int SAVE_DATA_TYPE_USERNAME = 4;
1370962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme
1380962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme    /**
1390962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme     * Type used when the {@link FillResponse} represents just an email address, without a password.
1400962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme     */
1410962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme    public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 5;
1420962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme
143b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme    private final @SaveDataType int mType;
14482e3793c15298f9c62edee23259c116606f10911Felipe Leme    private final CharSequence mNegativeActionTitle;
14582e3793c15298f9c62edee23259c116606f10911Felipe Leme    private final IntentSender mNegativeActionListener;
14682e3793c15298f9c62edee23259c116606f10911Felipe Leme    private final AutofillId[] mRequiredIds;
14782e3793c15298f9c62edee23259c116606f10911Felipe Leme    private final AutofillId[] mOptionalIds;
148b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme    private final CharSequence mDescription;
149f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
150f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /** @hide */
151f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    @IntDef({
152b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        SAVE_DATA_TYPE_GENERIC,
153b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        SAVE_DATA_TYPE_PASSWORD,
154b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        SAVE_DATA_TYPE_ADDRESS,
155b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        SAVE_DATA_TYPE_CREDIT_CARD
156f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    })
157f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    @Retention(RetentionPolicy.SOURCE)
158b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme    public @interface SaveDataType {
159f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    }
160f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
161f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    private SaveInfo(Builder builder) {
162f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        mType = builder.mType;
16333d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov        mNegativeActionTitle = builder.mNegativeActionTitle;
16433d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov        mNegativeActionListener = builder.mNegativeActionListener;
16582e3793c15298f9c62edee23259c116606f10911Felipe Leme        mRequiredIds = builder.mRequiredIds;
16682e3793c15298f9c62edee23259c116606f10911Felipe Leme        mOptionalIds = builder.mOptionalIds;
167b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        mDescription = builder.mDescription;
168f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    }
169f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
170f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /** @hide */
17133d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov    public @Nullable CharSequence getNegativeActionTitle() {
17233d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov        return mNegativeActionTitle;
17333d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov    }
17433d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov
17533d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov    /** @hide */
17633d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov    public @Nullable IntentSender getNegativeActionListener() {
17733d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov        return mNegativeActionListener;
17833d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov    }
17933d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov
18033d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov    /** @hide */
18182e3793c15298f9c62edee23259c116606f10911Felipe Leme    public AutofillId[] getRequiredIds() {
18282e3793c15298f9c62edee23259c116606f10911Felipe Leme        return mRequiredIds;
18382e3793c15298f9c62edee23259c116606f10911Felipe Leme    }
18482e3793c15298f9c62edee23259c116606f10911Felipe Leme
18582e3793c15298f9c62edee23259c116606f10911Felipe Leme    /** @hide */
18682e3793c15298f9c62edee23259c116606f10911Felipe Leme    public @Nullable AutofillId[] getOptionalIds() {
18782e3793c15298f9c62edee23259c116606f10911Felipe Leme        return mOptionalIds;
188f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    }
189f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
190f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /** @hide */
191b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme    public int getType() {
192b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        return mType;
193b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme    }
194b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme
195b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme    /** @hide */
196b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme    public CharSequence getDescription() {
197b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        return mDescription;
198b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme    }
199b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme
200f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /**
201f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme     * A builder for {@link SaveInfo} objects.
202f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme     */
203f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    public static final class Builder {
204f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
205b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        private final @SaveDataType int mType;
20633d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov        private CharSequence mNegativeActionTitle;
20733d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov        private IntentSender mNegativeActionListener;
20882e3793c15298f9c62edee23259c116606f10911Felipe Leme        // TODO(b/33197203): make mRequiredIds final once addSavableIds() is gone
20982e3793c15298f9c62edee23259c116606f10911Felipe Leme        private AutofillId[] mRequiredIds;
21082e3793c15298f9c62edee23259c116606f10911Felipe Leme        private AutofillId[] mOptionalIds;
211b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        private CharSequence mDescription;
212f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        private boolean mDestroyed;
213f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
214f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        /**
215f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme         * Creates a new builder.
216f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme         *
217f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme         * @param type the type of information the associated {@link FillResponse} represents. Must
218b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme         * be {@link SaveInfo#SAVE_DATA_TYPE_GENERIC}, {@link SaveInfo#SAVE_DATA_TYPE_PASSWORD},
219b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme         * {@link SaveInfo#SAVE_DATA_TYPE_ADDRESS}, or {@link SaveInfo#SAVE_DATA_TYPE_CREDIT_CARD};
220b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme         * otherwise it will assume {@link SaveInfo#SAVE_DATA_TYPE_GENERIC}.
22182e3793c15298f9c62edee23259c116606f10911Felipe Leme         * @param requiredIds ids of all required views that will trigger a save request.
22282e3793c15298f9c62edee23259c116606f10911Felipe Leme         *
22382e3793c15298f9c62edee23259c116606f10911Felipe Leme         * <p>See {@link SaveInfo} for more info.
22482e3793c15298f9c62edee23259c116606f10911Felipe Leme         *
22582e3793c15298f9c62edee23259c116606f10911Felipe Leme         * @throws IllegalArgumentException if {@code requiredIds} is {@code null} or empty.
226f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme         */
22782e3793c15298f9c62edee23259c116606f10911Felipe Leme        public Builder(@SaveDataType int type, @NonNull AutofillId[] requiredIds) {
228fe4e6a219a072e844f65b7722531307a039a2d63Felipe Leme            if (false) {// TODO(b/33197203): re-move when clients use it
22982e3793c15298f9c62edee23259c116606f10911Felipe Leme            Preconditions.checkArgument(requiredIds != null && requiredIds.length > 0,
230fe4e6a219a072e844f65b7722531307a039a2d63Felipe Leme                    "must have at least one required id: " + Arrays.toString(requiredIds));
231fe4e6a219a072e844f65b7722531307a039a2d63Felipe Leme            }
232f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            switch (type) {
233b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme                case SAVE_DATA_TYPE_PASSWORD:
234b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme                case SAVE_DATA_TYPE_ADDRESS:
235b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme                case SAVE_DATA_TYPE_CREDIT_CARD:
2360962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme                case SAVE_DATA_TYPE_USERNAME:
2370962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme                case SAVE_DATA_TYPE_EMAIL_ADDRESS:
238f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme                    mType = type;
239f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme                    break;
240f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme                default:
241b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme                    mType = SAVE_DATA_TYPE_GENERIC;
242f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            }
24382e3793c15298f9c62edee23259c116606f10911Felipe Leme            mRequiredIds = requiredIds;
244f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        }
245f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
246f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        /**
24782e3793c15298f9c62edee23259c116606f10911Felipe Leme         * @hide
24882e3793c15298f9c62edee23259c116606f10911Felipe Leme         * @deprecated
24982e3793c15298f9c62edee23259c116606f10911Felipe Leme         * // TODO(b/33197203): make sure is removed when clients migrated
250f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme         */
25182e3793c15298f9c62edee23259c116606f10911Felipe Leme        @Deprecated
25282e3793c15298f9c62edee23259c116606f10911Felipe Leme        public Builder(@SaveDataType int type) {
25382e3793c15298f9c62edee23259c116606f10911Felipe Leme            this(type, null);
25482e3793c15298f9c62edee23259c116606f10911Felipe Leme        }
25582e3793c15298f9c62edee23259c116606f10911Felipe Leme
25682e3793c15298f9c62edee23259c116606f10911Felipe Leme        /**
25782e3793c15298f9c62edee23259c116606f10911Felipe Leme         * @hide
25882e3793c15298f9c62edee23259c116606f10911Felipe Leme         * @deprecated
25982e3793c15298f9c62edee23259c116606f10911Felipe Leme         * // TODO(b/33197203): make sure is removed when clients migrated
26082e3793c15298f9c62edee23259c116606f10911Felipe Leme         */
26182e3793c15298f9c62edee23259c116606f10911Felipe Leme        @Deprecated
262640f30a7763b0a4b80c767acb84c740aac04768bFelipe Leme        public @NonNull Builder addSavableIds(@Nullable AutofillId... ids) {
263f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            throwIfDestroyed();
26482e3793c15298f9c62edee23259c116606f10911Felipe Leme            mRequiredIds = ids;
26582e3793c15298f9c62edee23259c116606f10911Felipe Leme            return this;
26682e3793c15298f9c62edee23259c116606f10911Felipe Leme        }
267f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
26882e3793c15298f9c62edee23259c116606f10911Felipe Leme        /**
26982e3793c15298f9c62edee23259c116606f10911Felipe Leme         * Sets the ids of additional, optional views the service would be interested to save.
27082e3793c15298f9c62edee23259c116606f10911Felipe Leme         *
27182e3793c15298f9c62edee23259c116606f10911Felipe Leme         * <p>See {@link SaveInfo} for more info.
27282e3793c15298f9c62edee23259c116606f10911Felipe Leme         *
27382e3793c15298f9c62edee23259c116606f10911Felipe Leme         * @param ids The ids of the optional views.
27482e3793c15298f9c62edee23259c116606f10911Felipe Leme         * @return This builder.
27582e3793c15298f9c62edee23259c116606f10911Felipe Leme         */
27682e3793c15298f9c62edee23259c116606f10911Felipe Leme        public @NonNull Builder setOptionalIds(@Nullable AutofillId[] ids) {
27782e3793c15298f9c62edee23259c116606f10911Felipe Leme            throwIfDestroyed();
27882e3793c15298f9c62edee23259c116606f10911Felipe Leme            if (ids != null && ids.length != 0) {
27982e3793c15298f9c62edee23259c116606f10911Felipe Leme                mOptionalIds = ids;
280f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            }
281f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            return this;
282f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        }
283f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
28443818a73eb535ba462ef7a56ffc3ab37e77c2ea0Felipe Leme
28543818a73eb535ba462ef7a56ffc3ab37e77c2ea0Felipe Leme        /**
28643818a73eb535ba462ef7a56ffc3ab37e77c2ea0Felipe Leme         * @hide
28743818a73eb535ba462ef7a56ffc3ab37e77c2ea0Felipe Leme         */
28843818a73eb535ba462ef7a56ffc3ab37e77c2ea0Felipe Leme        // TODO(b/33197203): temporary fix to runtime crash
28943818a73eb535ba462ef7a56ffc3ab37e77c2ea0Felipe Leme        public @NonNull Builder addSavableIds(@Nullable AutoFillId... ids) {
29043818a73eb535ba462ef7a56ffc3ab37e77c2ea0Felipe Leme            throwIfDestroyed();
29143818a73eb535ba462ef7a56ffc3ab37e77c2ea0Felipe Leme
29282e3793c15298f9c62edee23259c116606f10911Felipe Leme            if (ids == null || ids.length == 0) {
29343818a73eb535ba462ef7a56ffc3ab37e77c2ea0Felipe Leme                return this;
29443818a73eb535ba462ef7a56ffc3ab37e77c2ea0Felipe Leme            }
29582e3793c15298f9c62edee23259c116606f10911Felipe Leme            if (mRequiredIds == null) {
29682e3793c15298f9c62edee23259c116606f10911Felipe Leme                mRequiredIds = new AutofillId[ids.length];
29782e3793c15298f9c62edee23259c116606f10911Felipe Leme            }
29882e3793c15298f9c62edee23259c116606f10911Felipe Leme            for (int i = 0; i < ids.length; i++) {
29982e3793c15298f9c62edee23259c116606f10911Felipe Leme                mRequiredIds[i] = ids[i].getDaRealId();
30043818a73eb535ba462ef7a56ffc3ab37e77c2ea0Felipe Leme            }
30143818a73eb535ba462ef7a56ffc3ab37e77c2ea0Felipe Leme            return this;
30243818a73eb535ba462ef7a56ffc3ab37e77c2ea0Felipe Leme        }
30343818a73eb535ba462ef7a56ffc3ab37e77c2ea0Felipe Leme
304f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        /**
305b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme         * Sets an optional description to be shown in the UI when the user is asked to save.
306b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme         *
307b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme         * <p>Typically, it describes how the data will be stored by the service, so it can help
308b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme         * users to decide whether they can trust the service to save their data.
309b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme         *
310b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme         * @param description a succint description.
311b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme         * @return This Builder.
312b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme         */
313b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        public @NonNull Builder setDescription(@Nullable CharSequence description) {
31482e3793c15298f9c62edee23259c116606f10911Felipe Leme            throwIfDestroyed();
315b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme            mDescription = description;
316b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme            return this;
317b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        }
318b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme
319b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        /**
32033d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * Sets the title and listener for the negative save action.
32133d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         *
32233d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * <p>This allows a fill-provider to customize the text and be
32333d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * notified when the user selects the negative action in the save
32433d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * UI. Note that selecting the negative action regardless of its text
32533d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * and listener being customized would dismiss the save UI and if a
32633d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * custom listener intent is provided then this intent will be
32733d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * started.</p>
32833d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         *
32933d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * <p>This customization could be useful for providing additional
33033d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * semantics to the negative action. For example, a fill-provider
33133d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * can use this mechanism to add a "Disable" function or a "More info"
33233d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * function, etc. Note that the save action is exclusively controlled
33333d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * by the platform to ensure user consent is collected to release
33433d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * data from the filled app to the fill-provider.</p>
33533d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         *
33633d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * @param title The action title.
33733d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * @param listener The action listener.
33833d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * @return This builder.
33933d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         *
34033d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * @throws IllegalArgumentException If the title and the listener
34133d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         *     are not both either null or non-null.
34233d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         */
34333d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov        public @NonNull Builder setNegativeAction(@Nullable CharSequence title,
34433d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov                @Nullable IntentSender listener) {
34533d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov            throwIfDestroyed();
34633d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov            if (title == null ^ listener == null) {
34733d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov                throw new IllegalArgumentException("title and listener"
34833d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov                        + " must be both non-null or null");
34933d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov            }
35033d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov            mNegativeActionTitle = title;
35133d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov            mNegativeActionListener = listener;
35233d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov            return this;
35333d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov        }
35433d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov
35533d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov        /**
356f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme         * Builds a new {@link SaveInfo} instance.
357f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme         */
358f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        public SaveInfo build() {
359f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            throwIfDestroyed();
360f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            mDestroyed = true;
361f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            return new SaveInfo(this);
362f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        }
363f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
364f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        private void throwIfDestroyed() {
365f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            if (mDestroyed) {
366f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme                throw new IllegalStateException("Already called #build()");
367f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            }
368f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        }
369f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
370f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    }
371f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
372f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /////////////////////////////////////
373f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    // Object "contract" methods. //
374f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /////////////////////////////////////
375f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    @Override
376f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    public String toString() {
377f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        if (!DEBUG) return super.toString();
378f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
379f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        return new StringBuilder("SaveInfo: [type=").append(mType)
38082e3793c15298f9c62edee23259c116606f10911Felipe Leme                .append(", requiredIds=").append(Arrays.toString(mRequiredIds))
38182e3793c15298f9c62edee23259c116606f10911Felipe Leme                .append(", optionalIds=").append(Arrays.toString(mOptionalIds))
38282e3793c15298f9c62edee23259c116606f10911Felipe Leme                .append(", description=").append(mDescription)
383f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme                .append("]").toString();
384f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    }
385f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
386f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /////////////////////////////////////
387f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    // Parcelable "contract" methods. //
388f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /////////////////////////////////////
389f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
390f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    @Override
391f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    public int describeContents() {
392f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        return 0;
393f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    }
394f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
395f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    @Override
396f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    public void writeToParcel(Parcel parcel, int flags) {
397f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        parcel.writeInt(mType);
39882e3793c15298f9c62edee23259c116606f10911Felipe Leme        parcel.writeParcelableArray(mRequiredIds, flags);
39933d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov        parcel.writeCharSequence(mNegativeActionTitle);
40033d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov        parcel.writeParcelable(mNegativeActionListener, flags);
40182e3793c15298f9c62edee23259c116606f10911Felipe Leme        parcel.writeParcelableArray(mOptionalIds, flags);
402b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        parcel.writeCharSequence(mDescription);
403f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    }
404f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
405f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    public static final Parcelable.Creator<SaveInfo> CREATOR = new Parcelable.Creator<SaveInfo>() {
406f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        @Override
407f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        public SaveInfo createFromParcel(Parcel parcel) {
408f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            // Always go through the builder to ensure the data ingested by
409f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            // the system obeys the contract of the builder to avoid attacks
410f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            // using specially crafted parcels.
41182e3793c15298f9c62edee23259c116606f10911Felipe Leme            final Builder builder = new Builder(parcel.readInt(),
41282e3793c15298f9c62edee23259c116606f10911Felipe Leme                    parcel.readParcelableArray(null, AutofillId.class));
41333d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov            builder.setNegativeAction(parcel.readCharSequence(), parcel.readParcelable(null));
41482e3793c15298f9c62edee23259c116606f10911Felipe Leme            builder.setOptionalIds(parcel.readParcelableArray(null, AutofillId.class));
415b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme            builder.setDescription(parcel.readCharSequence());
416f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            return builder.build();
417f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        }
418f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
419f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        @Override
420f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        public SaveInfo[] newArray(int size) {
421f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            return new SaveInfo[size];
422f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        }
423f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    };
424f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme}
425