Merge "Autofill Partitioning: support multiple SaveInfos." into oc-dev am: 5c8d88e855
am: 49b37310ab
Change-Id: I5967cd823a11dc049a593918c29b5950f36ef0e4
diff --git a/api/current.txt b/api/current.txt
index 3efbd4c..08dfa13 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -37042,11 +37042,11 @@
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> 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 bf75f9f..405cd91 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -40140,11 +40140,11 @@
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> 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 ec845b6..6572a9d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -37201,11 +37201,11 @@
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> 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 f75b7af..4ad0f08 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -25,6 +25,7 @@
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 @@
* 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 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 @@
/**
* 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.
*
* <p>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 @@
* // 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 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 ae28797..75de4da 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4594,6 +4594,14 @@
<!-- Title for the autofill save dialog shown when the the contents of the activity can be saved
by an autofill service, and the service does knows what the activity represents (for example, credit card info) [CHAR LIMIT=NONE] -->
<string name="autofill_save_title_with_type">Save <xliff:g id="type" example="Credit Card">%1$s</xliff:g> to <xliff:g id="label" example="MyPass">%2$s</xliff:g>?</string>
+ <!-- Title for the autofill save dialog shown when the the contents of the activity can be saved
+ by an autofill service, and the service does knows what the activity represents, and it represents 2 types of
+ data (for example, password and credit card info) [CHAR LIMIT=NONE] -->
+ <string name="autofill_save_title_with_2types">Save <xliff:g id="type" example="Password">%1$s</xliff:g>, <xliff:g id="type" example="Credit Card">%2$s</xliff:g> to <xliff:g id="label" example="MyPass">%3$s</xliff:g>?</string>
+ <!-- Title for the autofill save dialog shown when the the contents of the activity can be saved
+ by an autofill service, and the service does knows what the activity represents, and it represents 3 types of
+ data (for example, username, password and credit card info) [CHAR LIMIT=NONE] -->
+ <string name="autofill_save_title_with_3types">Save <xliff:g id="type" example="Username">%1$s</xliff:g>, <xliff:g id="type" example="Password">%2$s</xliff:g>, <xliff:g id="type" example="Credit Card">%3$s</xliff:g> to <xliff:g id="label" example="MyPass">%4$s</xliff:g>?</string>
<!-- Label for the autofill save button [CHAR LIMIT=NONE] -->
<string name="autofill_save_yes">Save</string>
<!-- Label for the autofill cancel button [CHAR LIMIT=NONE] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index cd8d7d5..df604dc 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2881,6 +2881,8 @@
<java-symbol type="string" name="autofill_picker_accessibility_title " />
<java-symbol type="string" name="autofill_save_title" />
<java-symbol type="string" name="autofill_save_title_with_type" />
+ <java-symbol type="string" name="autofill_save_title_with_2types" />
+ <java-symbol type="string" name="autofill_save_title_with_3types" />
<java-symbol type="string" name="autofill_save_yes" />
<java-symbol type="string" name="autofill_save_no" />
<java-symbol type="string" name="autofill_save_type_password" />
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 9092bdb..c3cbf18 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 @@
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 d35cc95..f94d456 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.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 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<String> 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 @@
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());