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
199f9ee25515591ef33281708c0ab911962f4364a6Felipe Lemeimport static android.view.autofill.Helper.sDebug;
20f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
21f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Lemeimport android.annotation.IntDef;
22f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Lemeimport android.annotation.NonNull;
23f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Lemeimport android.annotation.Nullable;
242ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Lemeimport android.app.Activity;
2533d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganovimport android.content.IntentSender;
26f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Lemeimport android.os.Parcel;
27f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Lemeimport android.os.Parcelable;
287d5adb5b86a83759c52a3b7aa7bc58beb8ce1c43Felipe Lemeimport android.util.DebugUtils;
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
42e5f9c30688f0277505fb6b50ea385e5df6271ed8Felipe Leme * {@link AutofillService#onSaveRequest(SaveRequest, 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>
492ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *   <li>The type(s) of user data (like password or credit card info) that would be saved.
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 *
542ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * <p>Typically, the {@link SaveInfo} contains the same {@code id}s as the {@link Dataset}:
5582e3793c15298f9c62edee23259c116606f10911Felipe Leme *
5682e3793c15298f9c62edee23259c116606f10911Felipe Leme * <pre class="prettyprint">
572ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *   new FillResponse.Builder()
582ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *       .addDataset(new Dataset.Builder()
592ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *           .setValue(id1, AutofillValue.forText("homer"), createPresentation("homer")) // username
602ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *           .setValue(id2, AutofillValue.forText("D'OH!"), createPresentation("password for homer")) // password
612ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *           .build())
622ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *       .setSaveInfo(new SaveInfo.Builder(
632ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *           SaveInfo.SAVE_DATA_TYPE_USERNAME | SaveInfo.SAVE_DATA_TYPE_PASSWORD,
642ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *           new AutofillId[] { id1, id2 }).build())
652ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *       .build();
6682e3793c15298f9c62edee23259c116606f10911Felipe Leme * </pre>
6782e3793c15298f9c62edee23259c116606f10911Felipe Leme *
682ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * <p>The save type flags are used to display the appropriate strings in the save UI affordance.
692ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * You can pass multiple values, but try to keep it short if possible. In the above example, just
702ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * {@code SaveInfo.SAVE_DATA_TYPE_PASSWORD} would be enough.
712ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *
722ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * <p>There might be cases where the {@link AutofillService} knows how to fill the screen,
732ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * but the user has no data for it. In that case, the {@link FillResponse} should contain just the
742ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * {@link SaveInfo}, but no {@link Dataset Datasets}:
75f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme *
7682e3793c15298f9c62edee23259c116606f10911Felipe Leme * <pre class="prettyprint">
772ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *   new FillResponse.Builder()
782ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *       .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_PASSWORD,
792ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *           new AutofillId[] { id1, id2 }).build())
802ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *       .build();
8182e3793c15298f9c62edee23259c116606f10911Felipe Leme * </pre>
82f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme *
8382e3793c15298f9c62edee23259c116606f10911Felipe Leme * <p>There might be cases where the user data in the {@link AutofillService} is enough
8482e3793c15298f9c62edee23259c116606f10911Felipe Leme * to populate some fields but not all, and the service would still be interested on saving the
852ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * other fields. In that case, the service could set the
8682e3793c15298f9c62edee23259c116606f10911Felipe Leme * {@link SaveInfo.Builder#setOptionalIds(AutofillId[])} as well:
87f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme *
8882e3793c15298f9c62edee23259c116606f10911Felipe Leme * <pre class="prettyprint">
8982e3793c15298f9c62edee23259c116606f10911Felipe Leme *   new FillResponse.Builder()
902ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *       .addDataset(new Dataset.Builder()
912ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *           .setValue(id1, AutofillValue.forText("742 Evergreen Terrace"),
922ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *               createPresentation("742 Evergreen Terrace")) // street
932ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *           .setValue(id2, AutofillValue.forText("Springfield"),
942ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *               createPresentation("Springfield")) // city
952ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *           .build())
962ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *       .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_ADDRESS,
972ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *           new AutofillId[] { id1, id2 }) // street and  city
982ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *           .setOptionalIds(new AutofillId[] { id3, id4 }) // state and zipcode
992ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *           .build())
10082e3793c15298f9c62edee23259c116606f10911Felipe Leme *       .build();
10182e3793c15298f9c62edee23259c116606f10911Felipe Leme * </pre>
10282e3793c15298f9c62edee23259c116606f10911Felipe Leme *
1032ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * <p>The {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)} can be triggered after
1042ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * any of the following events:
1052ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * <ul>
1062ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *   <li>The {@link Activity} finishes.
1072ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *   <li>The app explicitly called {@link AutofillManager#commit()}.
1082ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *   <li>All required views became invisible (if the {@link SaveInfo} was created with the
1092ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *       {@link #FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE} flag).
1102ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * </ul>
11182e3793c15298f9c62edee23259c116606f10911Felipe Leme *
1122ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * <p>But it is only triggered when all conditions below are met:
1132ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * <ul>
11482e3793c15298f9c62edee23259c116606f10911Felipe Leme *   <li>The {@link SaveInfo} associated with the {@link FillResponse} is not {@code null}.
1152ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *   <li>The {@link AutofillValue}s of all required views (as set by the {@code requiredIds} passed
1162ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *       to the {@link SaveInfo.Builder} constructor are not empty.
11782e3793c15298f9c62edee23259c116606f10911Felipe Leme *   <li>The {@link AutofillValue} of at least one view (be it required or optional) has changed
1182ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *       (i.e., it's neither the same value passed in a {@link Dataset}, nor the initial value
1192ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *       presented in the view).
1202ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *   <li>The user explicitly tapped the UI affordance asking to save data for autofill.
1212ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * </ul>
1222ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *
1232ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * <p>The service can also customize some aspects of the save UI affordance:
1242ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * <ul>
1252ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *   <li>Add a subtitle by calling {@link Builder#setDescription(CharSequence)}.
1262ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *   <li>Customize the button used to reject the save request by calling
1272ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme *       {@link Builder#setNegativeAction(int, IntentSender)}.
1282ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme * </ul>
129f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme */
130f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Lemepublic final class SaveInfo implements Parcelable {
131f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
132f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /**
1332ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme     * Type used when the service can save the contents of a screen, but cannot describe what
134f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme     * the content is for.
135f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme     */
1367d5adb5b86a83759c52a3b7aa7bc58beb8ce1c43Felipe Leme    public static final int SAVE_DATA_TYPE_GENERIC = 0x0;
137f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
138f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /**
139b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme     * Type used when the {@link FillResponse} represents user credentials that have a password.
140f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme     */
1417d5adb5b86a83759c52a3b7aa7bc58beb8ce1c43Felipe Leme    public static final int SAVE_DATA_TYPE_PASSWORD = 0x01;
142b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme
143f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /**
144f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme     * Type used on when the {@link FillResponse} represents a physical address (such as street,
145f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme     * city, state, etc).
146f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme     */
1477d5adb5b86a83759c52a3b7aa7bc58beb8ce1c43Felipe Leme    public static final int SAVE_DATA_TYPE_ADDRESS = 0x02;
148f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
149f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /**
150b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme     * Type used when the {@link FillResponse} represents a credit card.
151f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme     */
1527d5adb5b86a83759c52a3b7aa7bc58beb8ce1c43Felipe Leme    public static final int SAVE_DATA_TYPE_CREDIT_CARD = 0x04;
153f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
1540962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme    /**
1550962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme     * Type used when the {@link FillResponse} represents just an username, without a password.
1560962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme     */
1577d5adb5b86a83759c52a3b7aa7bc58beb8ce1c43Felipe Leme    public static final int SAVE_DATA_TYPE_USERNAME = 0x08;
1580962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme
1590962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme    /**
1600962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme     * Type used when the {@link FillResponse} represents just an email address, without a password.
1610962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme     */
1627d5adb5b86a83759c52a3b7aa7bc58beb8ce1c43Felipe Leme    public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 0x10;
1630962262f42e3636270689100e1bb90b8f3cf6d77Felipe Leme
164dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov    /**
165dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov     * Style for the negative button of the save UI to cancel the
166dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov     * save operation. In this case, the user tapping the negative
167dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov     * button signals that they would prefer to not save the filled
168dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov     * content.
169dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov     */
170dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov    public static final int NEGATIVE_BUTTON_STYLE_CANCEL = 0;
171dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov
172dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov    /**
173dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov     * Style for the negative button of the save UI to reject the
174dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov     * save operation. This could be useful if the user needs to
175dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov     * opt-in your service and the save prompt is an advertisement
176dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov     * of the potential value you can add to the user. In this
177dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov     * case, the user tapping the negative button sends a strong
178dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov     * signal that the feature may not be useful and you may
179dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov     * consider some backoff strategy.
180dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov     */
181dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov    public static final int NEGATIVE_BUTTON_STYLE_REJECT = 1;
182dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov
183dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov    /** @hide */
184dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov    @IntDef(
185dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov        value = {
186dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov                NEGATIVE_BUTTON_STYLE_CANCEL,
187dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov                NEGATIVE_BUTTON_STYLE_REJECT})
188dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov    @Retention(RetentionPolicy.SOURCE)
189dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov    @interface NegativeButtonStyle{}
190dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov
191013efe173e56612a910ebd8576480ce4ef005e3cSvet Ganov    /** @hide */
192013efe173e56612a910ebd8576480ce4ef005e3cSvet Ganov    @IntDef(
193013efe173e56612a910ebd8576480ce4ef005e3cSvet Ganov       flag = true,
194013efe173e56612a910ebd8576480ce4ef005e3cSvet Ganov       value = {
195013efe173e56612a910ebd8576480ce4ef005e3cSvet Ganov               SAVE_DATA_TYPE_GENERIC,
196013efe173e56612a910ebd8576480ce4ef005e3cSvet Ganov               SAVE_DATA_TYPE_PASSWORD,
197013efe173e56612a910ebd8576480ce4ef005e3cSvet Ganov               SAVE_DATA_TYPE_ADDRESS,
198013efe173e56612a910ebd8576480ce4ef005e3cSvet Ganov               SAVE_DATA_TYPE_CREDIT_CARD,
1998fd057532783fda6f5187431ed2afac72d3bb0e8Felipe Leme               SAVE_DATA_TYPE_USERNAME,
200013efe173e56612a910ebd8576480ce4ef005e3cSvet Ganov               SAVE_DATA_TYPE_EMAIL_ADDRESS})
201013efe173e56612a910ebd8576480ce4ef005e3cSvet Ganov    @Retention(RetentionPolicy.SOURCE)
202013efe173e56612a910ebd8576480ce4ef005e3cSvet Ganov    @interface SaveDataType{}
203013efe173e56612a910ebd8576480ce4ef005e3cSvet Ganov
2049023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann    /**
2050d3db06d1d287c3efe18c951e08f4e7c6b3ebd47Felipe Leme     * Usually {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)}
2062ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme     * is called once the {@link Activity} finishes. If this flag is set it is called once all
2072ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme     * saved views become invisible.
2089023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann     */
2099023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann    public static final int FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 0x1;
2109023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann
2119023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann    /** @hide */
2129023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann    @IntDef(
2139023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann            flag = true,
2149023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann            value = {FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE})
2159023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann    @Retention(RetentionPolicy.SOURCE)
2169023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann    @interface SaveInfoFlags{}
2179023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann
218013efe173e56612a910ebd8576480ce4ef005e3cSvet Ganov    private final @SaveDataType int mType;
219dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov    private final @NegativeButtonStyle int mNegativeButtonStyle;
22082e3793c15298f9c62edee23259c116606f10911Felipe Leme    private final IntentSender mNegativeActionListener;
22182e3793c15298f9c62edee23259c116606f10911Felipe Leme    private final AutofillId[] mRequiredIds;
22282e3793c15298f9c62edee23259c116606f10911Felipe Leme    private final AutofillId[] mOptionalIds;
223b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme    private final CharSequence mDescription;
2249023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann    private final int mFlags;
225f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
226f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    private SaveInfo(Builder builder) {
227f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        mType = builder.mType;
228dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov        mNegativeButtonStyle = builder.mNegativeButtonStyle;
22933d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov        mNegativeActionListener = builder.mNegativeActionListener;
23082e3793c15298f9c62edee23259c116606f10911Felipe Leme        mRequiredIds = builder.mRequiredIds;
23182e3793c15298f9c62edee23259c116606f10911Felipe Leme        mOptionalIds = builder.mOptionalIds;
232b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        mDescription = builder.mDescription;
2339023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann        mFlags = builder.mFlags;
234f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    }
235f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
236f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /** @hide */
237dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov    public @NegativeButtonStyle int getNegativeActionStyle() {
238dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov        return mNegativeButtonStyle;
23933d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov    }
24033d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov
24133d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov    /** @hide */
24233d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov    public @Nullable IntentSender getNegativeActionListener() {
24333d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov        return mNegativeActionListener;
24433d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov    }
24533d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov
24633d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov    /** @hide */
24782e3793c15298f9c62edee23259c116606f10911Felipe Leme    public AutofillId[] getRequiredIds() {
24882e3793c15298f9c62edee23259c116606f10911Felipe Leme        return mRequiredIds;
24982e3793c15298f9c62edee23259c116606f10911Felipe Leme    }
25082e3793c15298f9c62edee23259c116606f10911Felipe Leme
25182e3793c15298f9c62edee23259c116606f10911Felipe Leme    /** @hide */
25282e3793c15298f9c62edee23259c116606f10911Felipe Leme    public @Nullable AutofillId[] getOptionalIds() {
25382e3793c15298f9c62edee23259c116606f10911Felipe Leme        return mOptionalIds;
254f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    }
255f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
256f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /** @hide */
257013efe173e56612a910ebd8576480ce4ef005e3cSvet Ganov    public @SaveDataType int getType() {
258b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        return mType;
259b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme    }
260b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme
261b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme    /** @hide */
2629023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann    public @SaveInfoFlags int getFlags() {
2639023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann        return mFlags;
264494c3f5da2c467ad07f50b4e1ad01065a8e3aa4fPhilip P. Moltmann    }
265494c3f5da2c467ad07f50b4e1ad01065a8e3aa4fPhilip P. Moltmann
266494c3f5da2c467ad07f50b4e1ad01065a8e3aa4fPhilip P. Moltmann    /** @hide */
267b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme    public CharSequence getDescription() {
268b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        return mDescription;
269b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme    }
270b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme
271f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /**
272f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme     * A builder for {@link SaveInfo} objects.
273f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme     */
274f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    public static final class Builder {
275f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
276013efe173e56612a910ebd8576480ce4ef005e3cSvet Ganov        private final @SaveDataType int mType;
277dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov        private @NegativeButtonStyle int mNegativeButtonStyle = NEGATIVE_BUTTON_STYLE_CANCEL;
27833d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov        private IntentSender mNegativeActionListener;
2790d3db06d1d287c3efe18c951e08f4e7c6b3ebd47Felipe Leme        private final AutofillId[] mRequiredIds;
28082e3793c15298f9c62edee23259c116606f10911Felipe Leme        private AutofillId[] mOptionalIds;
281b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        private CharSequence mDescription;
282f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        private boolean mDestroyed;
2839023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann        private int mFlags;
284f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
285f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        /**
286f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme         * Creates a new builder.
287f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme         *
2887d5adb5b86a83759c52a3b7aa7bc58beb8ce1c43Felipe Leme         * @param type the type of information the associated {@link FillResponse} represents, can
2897d5adb5b86a83759c52a3b7aa7bc58beb8ce1c43Felipe Leme         * be any combination of {@link SaveInfo#SAVE_DATA_TYPE_GENERIC},
2907d5adb5b86a83759c52a3b7aa7bc58beb8ce1c43Felipe Leme         * {@link SaveInfo#SAVE_DATA_TYPE_PASSWORD},
2917d5adb5b86a83759c52a3b7aa7bc58beb8ce1c43Felipe Leme         * {@link SaveInfo#SAVE_DATA_TYPE_ADDRESS}, {@link SaveInfo#SAVE_DATA_TYPE_CREDIT_CARD},
2927d5adb5b86a83759c52a3b7aa7bc58beb8ce1c43Felipe Leme         * {@link SaveInfo#SAVE_DATA_TYPE_USERNAME}, or
2937d5adb5b86a83759c52a3b7aa7bc58beb8ce1c43Felipe Leme         * {@link SaveInfo#SAVE_DATA_TYPE_EMAIL_ADDRESS}.
29482e3793c15298f9c62edee23259c116606f10911Felipe Leme         * @param requiredIds ids of all required views that will trigger a save request.
29582e3793c15298f9c62edee23259c116606f10911Felipe Leme         *
29682e3793c15298f9c62edee23259c116606f10911Felipe Leme         * <p>See {@link SaveInfo} for more info.
29782e3793c15298f9c62edee23259c116606f10911Felipe Leme         *
29818d0ef70b09ee17523056849483e4a182faddf98Felipe Leme         * @throws IllegalArgumentException if {@code requiredIds} is {@code null} or empty, or if
29918d0ef70b09ee17523056849483e4a182faddf98Felipe Leme         * it contains any {@code null} entry.
300f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme         */
301013efe173e56612a910ebd8576480ce4ef005e3cSvet Ganov        public Builder(@SaveDataType int type, @NonNull AutofillId[] requiredIds) {
30218d0ef70b09ee17523056849483e4a182faddf98Felipe Leme            // TODO: add CTS unit tests (not integration) to assert the null cases
3037d5adb5b86a83759c52a3b7aa7bc58beb8ce1c43Felipe Leme            mType = type;
30418d0ef70b09ee17523056849483e4a182faddf98Felipe Leme            mRequiredIds = assertValid(requiredIds);
30518d0ef70b09ee17523056849483e4a182faddf98Felipe Leme        }
30618d0ef70b09ee17523056849483e4a182faddf98Felipe Leme
30718d0ef70b09ee17523056849483e4a182faddf98Felipe Leme        private AutofillId[] assertValid(AutofillId[] ids) {
30818d0ef70b09ee17523056849483e4a182faddf98Felipe Leme            Preconditions.checkArgument(ids != null && ids.length > 0,
30918d0ef70b09ee17523056849483e4a182faddf98Felipe Leme                    "must have at least one id: " + Arrays.toString(ids));
31018d0ef70b09ee17523056849483e4a182faddf98Felipe Leme            for (int i = 0; i < ids.length; i++) {
31118d0ef70b09ee17523056849483e4a182faddf98Felipe Leme                final AutofillId id = ids[i];
31218d0ef70b09ee17523056849483e4a182faddf98Felipe Leme                Preconditions.checkArgument(id != null,
31318d0ef70b09ee17523056849483e4a182faddf98Felipe Leme                        "cannot have null id: " + Arrays.toString(ids));
31418d0ef70b09ee17523056849483e4a182faddf98Felipe Leme            }
31518d0ef70b09ee17523056849483e4a182faddf98Felipe Leme            return ids;
316f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        }
317f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
318f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        /**
3192ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme         * Sets flags changing the save behavior.
320494c3f5da2c467ad07f50b4e1ad01065a8e3aa4fPhilip P. Moltmann         *
3212ef19c1d73f89ca4718b5a8f0c2e7221621e844fFelipe Leme         * @param flags {@link #FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE} or {@code 0}.
322494c3f5da2c467ad07f50b4e1ad01065a8e3aa4fPhilip P. Moltmann         * @return This builder.
323494c3f5da2c467ad07f50b4e1ad01065a8e3aa4fPhilip P. Moltmann         */
3249023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann        public @NonNull Builder setFlags(@SaveInfoFlags int flags) {
325494c3f5da2c467ad07f50b4e1ad01065a8e3aa4fPhilip P. Moltmann            throwIfDestroyed();
3269023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann
3279023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann            mFlags = Preconditions.checkFlagsArgument(flags, FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE);
328494c3f5da2c467ad07f50b4e1ad01065a8e3aa4fPhilip P. Moltmann            return this;
329494c3f5da2c467ad07f50b4e1ad01065a8e3aa4fPhilip P. Moltmann        }
330494c3f5da2c467ad07f50b4e1ad01065a8e3aa4fPhilip P. Moltmann
331494c3f5da2c467ad07f50b4e1ad01065a8e3aa4fPhilip P. Moltmann        /**
33282e3793c15298f9c62edee23259c116606f10911Felipe Leme         * Sets the ids of additional, optional views the service would be interested to save.
33382e3793c15298f9c62edee23259c116606f10911Felipe Leme         *
33482e3793c15298f9c62edee23259c116606f10911Felipe Leme         * <p>See {@link SaveInfo} for more info.
33582e3793c15298f9c62edee23259c116606f10911Felipe Leme         *
33682e3793c15298f9c62edee23259c116606f10911Felipe Leme         * @param ids The ids of the optional views.
33782e3793c15298f9c62edee23259c116606f10911Felipe Leme         * @return This builder.
33818d0ef70b09ee17523056849483e4a182faddf98Felipe Leme         *
33918d0ef70b09ee17523056849483e4a182faddf98Felipe Leme         * @throws IllegalArgumentException if {@code ids} is {@code null} or empty, or if
34018d0ef70b09ee17523056849483e4a182faddf98Felipe Leme         * it contains any {@code null} entry.
34182e3793c15298f9c62edee23259c116606f10911Felipe Leme         */
34218d0ef70b09ee17523056849483e4a182faddf98Felipe Leme        public @NonNull Builder setOptionalIds(@NonNull AutofillId[] ids) {
34318d0ef70b09ee17523056849483e4a182faddf98Felipe Leme            // TODO: add CTS unit tests (not integration) to assert the null cases
34482e3793c15298f9c62edee23259c116606f10911Felipe Leme            throwIfDestroyed();
34518d0ef70b09ee17523056849483e4a182faddf98Felipe Leme            mOptionalIds = assertValid(ids);
346f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            return this;
347f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        }
348f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
349f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        /**
350b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme         * Sets an optional description to be shown in the UI when the user is asked to save.
351b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme         *
352b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme         * <p>Typically, it describes how the data will be stored by the service, so it can help
353b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme         * users to decide whether they can trust the service to save their data.
354b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme         *
355b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme         * @param description a succint description.
356b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme         * @return This Builder.
357b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme         */
358b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        public @NonNull Builder setDescription(@Nullable CharSequence description) {
35982e3793c15298f9c62edee23259c116606f10911Felipe Leme            throwIfDestroyed();
360b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme            mDescription = description;
361b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme            return this;
362b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        }
363b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme
364b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        /**
365dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov         * Sets the style and listener for the negative save action.
36633d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         *
367dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov         * <p>This allows a fill-provider to customize the style and be
36833d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * notified when the user selects the negative action in the save
369dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov         * UI. Note that selecting the negative action regardless of its style
37033d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * and listener being customized would dismiss the save UI and if a
37133d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * custom listener intent is provided then this intent will be
372dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov         * started. The default style is {@link #NEGATIVE_BUTTON_STYLE_CANCEL}</p>
37333d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         *
374dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov         * @param style The action style.
37533d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * @param listener The action listener.
37633d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         * @return This builder.
37733d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         *
378dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov         * @see #NEGATIVE_BUTTON_STYLE_CANCEL
379dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov         * @see #NEGATIVE_BUTTON_STYLE_REJECT
380dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov         *
381dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov         * @throws IllegalArgumentException If the style is invalid
38233d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov         */
383dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov        public @NonNull Builder setNegativeAction(@NegativeButtonStyle int style,
38433d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov                @Nullable IntentSender listener) {
38533d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov            throwIfDestroyed();
386dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov            if (style != NEGATIVE_BUTTON_STYLE_CANCEL
387dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov                    && style != NEGATIVE_BUTTON_STYLE_REJECT) {
388dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov                throw new IllegalArgumentException("Invalid style: " + style);
38933d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov            }
390dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov            mNegativeButtonStyle = style;
39133d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov            mNegativeActionListener = listener;
39233d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov            return this;
39333d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov        }
39433d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov
39533d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov        /**
396f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme         * Builds a new {@link SaveInfo} instance.
397f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme         */
398f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        public SaveInfo build() {
399f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            throwIfDestroyed();
400f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            mDestroyed = true;
401f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            return new SaveInfo(this);
402f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        }
403f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
404f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        private void throwIfDestroyed() {
405f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            if (mDestroyed) {
406f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme                throw new IllegalStateException("Already called #build()");
407f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            }
408f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        }
409f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
410f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    }
411f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
412f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /////////////////////////////////////
413f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    // Object "contract" methods. //
414f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /////////////////////////////////////
415f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    @Override
416f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    public String toString() {
4179f9ee25515591ef33281708c0ab911962f4364a6Felipe Leme        if (!sDebug) return super.toString();
418f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
4197d5adb5b86a83759c52a3b7aa7bc58beb8ce1c43Felipe Leme        return new StringBuilder("SaveInfo: [type=")
4207d5adb5b86a83759c52a3b7aa7bc58beb8ce1c43Felipe Leme                .append(DebugUtils.flagsToString(SaveInfo.class, "SAVE_DATA_TYPE_", mType))
42182e3793c15298f9c62edee23259c116606f10911Felipe Leme                .append(", requiredIds=").append(Arrays.toString(mRequiredIds))
42282e3793c15298f9c62edee23259c116606f10911Felipe Leme                .append(", optionalIds=").append(Arrays.toString(mOptionalIds))
42382e3793c15298f9c62edee23259c116606f10911Felipe Leme                .append(", description=").append(mDescription)
424dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov                .append(DebugUtils.flagsToString(SaveInfo.class, "NEGATIVE_BUTTON_STYLE_",
425dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov                        mNegativeButtonStyle))
4269023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann                .append(", mFlags=").append(mFlags)
427f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme                .append("]").toString();
428f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    }
429f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
430f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /////////////////////////////////////
431f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    // Parcelable "contract" methods. //
432f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    /////////////////////////////////////
433f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
434f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    @Override
435f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    public int describeContents() {
436f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        return 0;
437f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    }
438f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
439f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    @Override
440f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    public void writeToParcel(Parcel parcel, int flags) {
441f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        parcel.writeInt(mType);
44282e3793c15298f9c62edee23259c116606f10911Felipe Leme        parcel.writeParcelableArray(mRequiredIds, flags);
443dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov        parcel.writeInt(mNegativeButtonStyle);
44433d06fcac5abdded783d1b59f5b299ca5d27d5c7Svet Ganov        parcel.writeParcelable(mNegativeActionListener, flags);
44582e3793c15298f9c62edee23259c116606f10911Felipe Leme        parcel.writeParcelableArray(mOptionalIds, flags);
446b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme        parcel.writeCharSequence(mDescription);
4479023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann        parcel.writeInt(mFlags);
448f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    }
449f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
450f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    public static final Parcelable.Creator<SaveInfo> CREATOR = new Parcelable.Creator<SaveInfo>() {
451f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        @Override
452f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        public SaveInfo createFromParcel(Parcel parcel) {
453f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            // Always go through the builder to ensure the data ingested by
454f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            // the system obeys the contract of the builder to avoid attacks
455f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            // using specially crafted parcels.
45682e3793c15298f9c62edee23259c116606f10911Felipe Leme            final Builder builder = new Builder(parcel.readInt(),
45782e3793c15298f9c62edee23259c116606f10911Felipe Leme                    parcel.readParcelableArray(null, AutofillId.class));
458dc6cccb905d77b1fd954c883e4369e7b401cb457Svetoslav Ganov            builder.setNegativeAction(parcel.readInt(), parcel.readParcelable(null));
45918d0ef70b09ee17523056849483e4a182faddf98Felipe Leme            final AutofillId[] optionalIds = parcel.readParcelableArray(null, AutofillId.class);
46018d0ef70b09ee17523056849483e4a182faddf98Felipe Leme            if (optionalIds != null) {
46118d0ef70b09ee17523056849483e4a182faddf98Felipe Leme                builder.setOptionalIds(optionalIds);
46218d0ef70b09ee17523056849483e4a182faddf98Felipe Leme            }
463b72f012cb49a5930010fb0766776b40c2955ee3eFelipe Leme            builder.setDescription(parcel.readCharSequence());
4649023d14fb30c23ef58171a5133f893b2ee4e743cPhilip P. Moltmann            builder.setFlags(parcel.readInt());
465f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            return builder.build();
466f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        }
467f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme
468f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        @Override
469f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        public SaveInfo[] newArray(int size) {
470f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme            return new SaveInfo[size];
471f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme        }
472f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme    };
473f69761ffbe3098067ae720263ef05262f4b5d41eFelipe Leme}
474