From 7d5adb5b86a83759c52a3b7aa7bc58beb8ce1c43 Mon Sep 17 00:00:00 2001 From: Felipe Leme Date: Thu, 6 Apr 2017 17:57:43 -0700 Subject: [PATCH] Autofill Partitioning: support multiple SaveInfos. Bug: 35707731 Test: CtsAutoFillServiceTestCases (with new tests) pass Change-Id: I2f234ca13c7e74f84c762473e38f938ed47f216f --- api/current.txt | 6 +- api/system-current.txt | 6 +- api/test-current.txt | 6 +- .../android/service/autofill/SaveInfo.java | 57 ++++++----------- core/res/res/values/strings.xml | 8 +++ core/res/res/values/symbols.xml | 2 + .../com/android/server/autofill/Session.java | 3 +- .../android/server/autofill/ui/SaveUi.java | 63 ++++++++++++------- 8 files changed, 80 insertions(+), 71 deletions(-) diff --git a/api/current.txt b/api/current.txt index a8e5da8ec03e9..3018d9176abeb 100644 --- a/api/current.txt +++ b/api/current.txt @@ -37073,11 +37073,11 @@ package android.service.autofill { method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2 - field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3; // 0x3 - field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 5; // 0x5 + field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 4; // 0x4 + field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 16; // 0x10 field public static final int SAVE_DATA_TYPE_GENERIC = 0; // 0x0 field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1 - field public static final int SAVE_DATA_TYPE_USERNAME = 4; // 0x4 + field public static final int SAVE_DATA_TYPE_USERNAME = 8; // 0x8 } public static final class SaveInfo.Builder { diff --git a/api/system-current.txt b/api/system-current.txt index 4bf1d6bad6007..f5406d5f02e78 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -40169,11 +40169,11 @@ package android.service.autofill { method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2 - field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3; // 0x3 - field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 5; // 0x5 + field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 4; // 0x4 + field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 16; // 0x10 field public static final int SAVE_DATA_TYPE_GENERIC = 0; // 0x0 field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1 - field public static final int SAVE_DATA_TYPE_USERNAME = 4; // 0x4 + field public static final int SAVE_DATA_TYPE_USERNAME = 8; // 0x8 } public static final class SaveInfo.Builder { diff --git a/api/test-current.txt b/api/test-current.txt index 82d5080c9c985..9ad2ab4cac314 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -37231,11 +37231,11 @@ package android.service.autofill { method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2 - field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3; // 0x3 - field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 5; // 0x5 + field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 4; // 0x4 + field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 16; // 0x10 field public static final int SAVE_DATA_TYPE_GENERIC = 0; // 0x0 field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1 - field public static final int SAVE_DATA_TYPE_USERNAME = 4; // 0x4 + field public static final int SAVE_DATA_TYPE_USERNAME = 8; // 0x8 } public static final class SaveInfo.Builder { diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java index f75b7afe4c46a..4ad0f086691a8 100644 --- a/core/java/android/service/autofill/SaveInfo.java +++ b/core/java/android/service/autofill/SaveInfo.java @@ -25,6 +25,7 @@ import android.content.IntentSender; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import android.util.DebugUtils; import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; @@ -111,52 +112,41 @@ public final class SaveInfo implements Parcelable { * Type used on when the service can save the contents of an activity, but cannot describe what * the content is for. */ - public static final int SAVE_DATA_TYPE_GENERIC = 0; + public static final int SAVE_DATA_TYPE_GENERIC = 0x0; /** * Type used when the {@link FillResponse} represents user credentials that have a password. */ - public static final int SAVE_DATA_TYPE_PASSWORD = 1; + public static final int SAVE_DATA_TYPE_PASSWORD = 0x01; /** * Type used on when the {@link FillResponse} represents a physical address (such as street, * city, state, etc). */ - public static final int SAVE_DATA_TYPE_ADDRESS = 2; + public static final int SAVE_DATA_TYPE_ADDRESS = 0x02; /** * Type used when the {@link FillResponse} represents a credit card. */ - public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3; + public static final int SAVE_DATA_TYPE_CREDIT_CARD = 0x04; /** * Type used when the {@link FillResponse} represents just an username, without a password. */ - public static final int SAVE_DATA_TYPE_USERNAME = 4; + public static final int SAVE_DATA_TYPE_USERNAME = 0x08; /** * Type used when the {@link FillResponse} represents just an email address, without a password. */ - public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 5; + public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 0x10; - private final @SaveDataType int mType; + private final int mType; private final CharSequence mNegativeActionTitle; private final IntentSender mNegativeActionListener; private final AutofillId[] mRequiredIds; private final AutofillId[] mOptionalIds; private final CharSequence mDescription; - /** @hide */ - @IntDef({ - SAVE_DATA_TYPE_GENERIC, - SAVE_DATA_TYPE_PASSWORD, - SAVE_DATA_TYPE_ADDRESS, - SAVE_DATA_TYPE_CREDIT_CARD - }) - @Retention(RetentionPolicy.SOURCE) - public @interface SaveDataType { - } - private SaveInfo(Builder builder) { mType = builder.mType; mNegativeActionTitle = builder.mNegativeActionTitle; @@ -201,7 +191,7 @@ public final class SaveInfo implements Parcelable { */ public static final class Builder { - private final @SaveDataType int mType; + private final int mType; private CharSequence mNegativeActionTitle; private IntentSender mNegativeActionListener; // TODO(b/33197203): make mRequiredIds final once addSavableIds() is gone @@ -213,32 +203,24 @@ public final class SaveInfo implements Parcelable { /** * Creates a new builder. * - * @param type the type of information the associated {@link FillResponse} represents. Must - * be {@link SaveInfo#SAVE_DATA_TYPE_GENERIC}, {@link SaveInfo#SAVE_DATA_TYPE_PASSWORD}, - * {@link SaveInfo#SAVE_DATA_TYPE_ADDRESS}, or {@link SaveInfo#SAVE_DATA_TYPE_CREDIT_CARD}; - * otherwise it will assume {@link SaveInfo#SAVE_DATA_TYPE_GENERIC}. + * @param type the type of information the associated {@link FillResponse} represents, can + * be any combination of {@link SaveInfo#SAVE_DATA_TYPE_GENERIC}, + * {@link SaveInfo#SAVE_DATA_TYPE_PASSWORD}, + * {@link SaveInfo#SAVE_DATA_TYPE_ADDRESS}, {@link SaveInfo#SAVE_DATA_TYPE_CREDIT_CARD}, + * {@link SaveInfo#SAVE_DATA_TYPE_USERNAME}, or + * {@link SaveInfo#SAVE_DATA_TYPE_EMAIL_ADDRESS}. * @param requiredIds ids of all required views that will trigger a save request. * *

See {@link SaveInfo} for more info. * * @throws IllegalArgumentException if {@code requiredIds} is {@code null} or empty. */ - public Builder(@SaveDataType int type, @NonNull AutofillId[] requiredIds) { + public Builder(int type, @NonNull AutofillId[] requiredIds) { if (false) {// TODO(b/33197203): re-move when clients use it Preconditions.checkArgument(requiredIds != null && requiredIds.length > 0, "must have at least one required id: " + Arrays.toString(requiredIds)); } - switch (type) { - case SAVE_DATA_TYPE_PASSWORD: - case SAVE_DATA_TYPE_ADDRESS: - case SAVE_DATA_TYPE_CREDIT_CARD: - case SAVE_DATA_TYPE_USERNAME: - case SAVE_DATA_TYPE_EMAIL_ADDRESS: - mType = type; - break; - default: - mType = SAVE_DATA_TYPE_GENERIC; - } + mType = type; mRequiredIds = requiredIds; } @@ -248,7 +230,7 @@ public final class SaveInfo implements Parcelable { * // TODO(b/33197203): make sure is removed when clients migrated */ @Deprecated - public Builder(@SaveDataType int type) { + public Builder(int type) { this(type, null); } @@ -355,7 +337,8 @@ public final class SaveInfo implements Parcelable { public String toString() { if (!DEBUG) return super.toString(); - return new StringBuilder("SaveInfo: [type=").append(mType) + return new StringBuilder("SaveInfo: [type=") + .append(DebugUtils.flagsToString(SaveInfo.class, "SAVE_DATA_TYPE_", mType)) .append(", requiredIds=").append(Arrays.toString(mRequiredIds)) .append(", optionalIds=").append(Arrays.toString(mOptionalIds)) .append(", description=").append(mDescription) diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index ae28797c32aad..75de4dad33901 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -4594,6 +4594,14 @@ Save %1$s to %2$s? + + Save %1$s, %2$s to %3$s? + + Save %1$s, %2$s, %3$s to %4$s? Save diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 379c376bf2ffd..1b495508656d3 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2881,6 +2881,8 @@ + + diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 9092bdb4e9998..c3cbf18135fc8 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -398,8 +398,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return true; } - // TODO(b/33197203 , b/35707731): must iterate over all responses - final FillResponse response = mResponses.get(0); + final FillResponse response = mResponses.get(mResponses.size() - 1); final SaveInfo saveInfo = response.getSaveInfo(); if (DEBUG) { diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java index d35cc95e6d268..f94d456cb47f0 100644 --- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java @@ -24,7 +24,7 @@ import android.content.Context; import android.content.IntentSender; import android.os.Handler; import android.service.autofill.SaveInfo; -import android.text.format.DateUtils; +import android.util.ArraySet; import android.util.Slog; import android.view.Gravity; import android.view.Window; @@ -105,31 +105,44 @@ final class SaveUi { final View view = inflater.inflate(R.layout.autofill_save, null); final TextView titleView = (TextView) view.findViewById(R.id.autofill_save_title); - final String type; - switch(info.getType()) { - case SaveInfo.SAVE_DATA_TYPE_PASSWORD: - type = context.getString(R.string.autofill_save_type_password); - break; - case SaveInfo.SAVE_DATA_TYPE_ADDRESS: - type = context.getString(R.string.autofill_save_type_address); - break; - case SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD: - type = context.getString(R.string.autofill_save_type_credit_card); - break; - case SaveInfo.SAVE_DATA_TYPE_USERNAME: - type = context.getString(R.string.autofill_save_type_username); - break; - case SaveInfo.SAVE_DATA_TYPE_EMAIL_ADDRESS: - type = context.getString(R.string.autofill_save_type_email_address); - break; - default: - type = null; + final ArraySet types = new ArraySet<>(3); + final int type = info.getType(); + + if ((type & SaveInfo.SAVE_DATA_TYPE_PASSWORD) != 0) { + types.add(context.getString(R.string.autofill_save_type_password)); + } + if ((type & SaveInfo.SAVE_DATA_TYPE_ADDRESS) != 0) { + types.add(context.getString(R.string.autofill_save_type_address)); + } + if ((type & SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD) != 0) { + types.add(context.getString(R.string.autofill_save_type_credit_card)); + } + if ((type & SaveInfo.SAVE_DATA_TYPE_USERNAME) != 0) { + types.add(context.getString(R.string.autofill_save_type_username)); + } + if ((type & SaveInfo.SAVE_DATA_TYPE_EMAIL_ADDRESS) != 0) { + types.add(context.getString(R.string.autofill_save_type_email_address)); } - final String title = (type == null) - ? context.getString(R.string.autofill_save_title, providerLabel) - : context.getString(R.string.autofill_save_title_with_type, type, providerLabel); + final String title; + switch (types.size()) { + case 1: + title = context.getString(R.string.autofill_save_title_with_type, + types.valueAt(0), providerLabel); + break; + case 2: + title = context.getString(R.string.autofill_save_title_with_2types, + types.valueAt(0), types.valueAt(1), providerLabel); + break; + case 3: + title = context.getString(R.string.autofill_save_title_with_3types, + types.valueAt(0), types.valueAt(1), types.valueAt(2), providerLabel); + break; + default: + // Use generic if more than 3 or invalid type (size 0). + title = context.getString(R.string.autofill_save_title, providerLabel); + } titleView.setText(title); final CharSequence subTitle = info.getDescription(); @@ -139,6 +152,10 @@ final class SaveUi { subTitleView.setVisibility(View.VISIBLE); } + if (DEBUG) { + Slog.d(TAG, "Title: " + title + " SubTitle: " + subTitle); + } + final TextView noButton = view.findViewById(R.id.autofill_save_no); if (info.getNegativeActionTitle() != null) { noButton.setText(info.getNegativeActionTitle());