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