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