Get rid of custom negaitve save button label
Removed the ability for an autofill provider to set
a custom string for the negative button. Also make
the old hidden APIs non-abstract to avoid runime
crashes for unimplemented methods.
Test: CtsAutoFillServiceTestCases pass
bug:37649790
Change-Id: If776d26de48382eeb064bdead5d4d5fdb0ff2e7e
diff --git a/api/current.txt b/api/current.txt
index 58d617a..0491fb0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -37118,6 +37118,8 @@
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 FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 1; // 0x1
+ field public static final int NEGATIVE_BUTTON_STYLE_CANCEL = 0; // 0x0
+ field public static final int NEGATIVE_BUTTON_STYLE_REJECT = 1; // 0x1
field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 4; // 0x4
field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 16; // 0x10
@@ -37131,7 +37133,7 @@
method public android.service.autofill.SaveInfo build();
method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
method public android.service.autofill.SaveInfo.Builder setFlags(int);
- method public android.service.autofill.SaveInfo.Builder setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
+ method public android.service.autofill.SaveInfo.Builder setNegativeAction(int, android.content.IntentSender);
method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 3723e7e..c14ece6 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -40233,6 +40233,8 @@
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 FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 1; // 0x1
+ field public static final int NEGATIVE_BUTTON_STYLE_CANCEL = 0; // 0x0
+ field public static final int NEGATIVE_BUTTON_STYLE_REJECT = 1; // 0x1
field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 4; // 0x4
field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 16; // 0x10
@@ -40246,7 +40248,7 @@
method public android.service.autofill.SaveInfo build();
method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
method public android.service.autofill.SaveInfo.Builder setFlags(int);
- method public android.service.autofill.SaveInfo.Builder setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
+ method public android.service.autofill.SaveInfo.Builder setNegativeAction(int, android.content.IntentSender);
method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 9f7441c..2ed5644 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -37272,6 +37272,8 @@
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 FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 1; // 0x1
+ field public static final int NEGATIVE_BUTTON_STYLE_CANCEL = 0; // 0x0
+ field public static final int NEGATIVE_BUTTON_STYLE_REJECT = 1; // 0x1
field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 4; // 0x4
field public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 16; // 0x10
@@ -37285,7 +37287,7 @@
method public android.service.autofill.SaveInfo build();
method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
method public android.service.autofill.SaveInfo.Builder setFlags(int);
- method public android.service.autofill.SaveInfo.Builder setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
+ method public android.service.autofill.SaveInfo.Builder setNegativeAction(int, android.content.IntentSender);
method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
}
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index edb9098..32b078f 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -223,9 +223,11 @@
* @hide
*/
@Deprecated
- public abstract void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
+ public void onFillRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
int flags, @NonNull CancellationSignal cancellationSignal,
- @NonNull FillCallback callback);
+ @NonNull FillCallback callback) {
+
+ }
/**
* Called when user requests service to save the fields of an {@link Activity}.
@@ -260,8 +262,10 @@
* @hide
*/
@Deprecated
- public abstract void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
- @NonNull SaveCallback callback);
+ public void onSaveRequest(@NonNull AssistStructure structure, @Nullable Bundle data,
+ @NonNull SaveCallback callback) {
+
+ }
/**
* Called when the Android system disconnects from the service.
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 3a1529f..94e5e3e 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -139,6 +139,33 @@
*/
public static final int SAVE_DATA_TYPE_EMAIL_ADDRESS = 0x10;
+ /**
+ * Style for the negative button of the save UI to cancel the
+ * save operation. In this case, the user tapping the negative
+ * button signals that they would prefer to not save the filled
+ * content.
+ */
+ public static final int NEGATIVE_BUTTON_STYLE_CANCEL = 0;
+
+ /**
+ * Style for the negative button of the save UI to reject the
+ * save operation. This could be useful if the user needs to
+ * opt-in your service and the save prompt is an advertisement
+ * of the potential value you can add to the user. In this
+ * case, the user tapping the negative button sends a strong
+ * signal that the feature may not be useful and you may
+ * consider some backoff strategy.
+ */
+ public static final int NEGATIVE_BUTTON_STYLE_REJECT = 1;
+
+ /** @hide */
+ @IntDef(
+ value = {
+ NEGATIVE_BUTTON_STYLE_CANCEL,
+ NEGATIVE_BUTTON_STYLE_REJECT})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface NegativeButtonStyle{}
+
/** @hide */
@IntDef(
flag = true,
@@ -166,7 +193,7 @@
@interface SaveInfoFlags{}
private final @SaveDataType int mType;
- private final CharSequence mNegativeActionTitle;
+ private final @NegativeButtonStyle int mNegativeButtonStyle;
private final IntentSender mNegativeActionListener;
private final AutofillId[] mRequiredIds;
private final AutofillId[] mOptionalIds;
@@ -175,7 +202,7 @@
private SaveInfo(Builder builder) {
mType = builder.mType;
- mNegativeActionTitle = builder.mNegativeActionTitle;
+ mNegativeButtonStyle = builder.mNegativeButtonStyle;
mNegativeActionListener = builder.mNegativeActionListener;
mRequiredIds = builder.mRequiredIds;
mOptionalIds = builder.mOptionalIds;
@@ -184,8 +211,8 @@
}
/** @hide */
- public @Nullable CharSequence getNegativeActionTitle() {
- return mNegativeActionTitle;
+ public @NegativeButtonStyle int getNegativeActionStyle() {
+ return mNegativeButtonStyle;
}
/** @hide */
@@ -224,7 +251,7 @@
public static final class Builder {
private final @SaveDataType int mType;
- private CharSequence mNegativeActionTitle;
+ private @NegativeButtonStyle int mNegativeButtonStyle = NEGATIVE_BUTTON_STYLE_CANCEL;
private IntentSender mNegativeActionListener;
private final AutofillId[] mRequiredIds;
private AutofillId[] mOptionalIds;
@@ -298,38 +325,42 @@
return this;
}
- /**
- * Sets the title and listener for the negative save action.
- *
- * <p>This allows a fill-provider to customize the text and be
- * notified when the user selects the negative action in the save
- * UI. Note that selecting the negative action regardless of its text
- * and listener being customized would dismiss the save UI and if a
- * custom listener intent is provided then this intent will be
- * started.</p>
- *
- * <p>This customization could be useful for providing additional
- * semantics to the negative action. For example, a fill-provider
- * can use this mechanism to add a "Disable" function or a "More info"
- * function, etc. Note that the save action is exclusively controlled
- * by the platform to ensure user consent is collected to release
- * data from the filled app to the fill-provider.</p>
- *
- * @param title The action title.
- * @param listener The action listener.
- * @return This builder.
- *
- * @throws IllegalArgumentException If the title and the listener
- * are not both either null or non-null.
- */
+ /** @hide */
+ // TODO (b/37563972): Remove when callers migrate
public @NonNull Builder setNegativeAction(@Nullable CharSequence title,
@Nullable IntentSender listener) {
throwIfDestroyed();
- if (title == null ^ listener == null) {
- throw new IllegalArgumentException("title and listener"
- + " must be both non-null or null");
+ setNegativeAction(NEGATIVE_BUTTON_STYLE_CANCEL, listener);
+ return this;
+ }
+
+ /**
+ * Sets the style and listener for the negative save action.
+ *
+ * <p>This allows a fill-provider to customize the style and be
+ * notified when the user selects the negative action in the save
+ * UI. Note that selecting the negative action regardless of its style
+ * and listener being customized would dismiss the save UI and if a
+ * custom listener intent is provided then this intent will be
+ * started. The default style is {@link #NEGATIVE_BUTTON_STYLE_CANCEL}</p>
+ *
+ * @param style The action style.
+ * @param listener The action listener.
+ * @return This builder.
+ *
+ * @see #NEGATIVE_BUTTON_STYLE_CANCEL
+ * @see #NEGATIVE_BUTTON_STYLE_REJECT
+ *
+ * @throws IllegalArgumentException If the style is invalid
+ */
+ public @NonNull Builder setNegativeAction(@NegativeButtonStyle int style,
+ @Nullable IntentSender listener) {
+ throwIfDestroyed();
+ if (style != NEGATIVE_BUTTON_STYLE_CANCEL
+ && style != NEGATIVE_BUTTON_STYLE_REJECT) {
+ throw new IllegalArgumentException("Invalid style: " + style);
}
- mNegativeActionTitle = title;
+ mNegativeButtonStyle = style;
mNegativeActionListener = listener;
return this;
}
@@ -363,6 +394,8 @@
.append(", requiredIds=").append(Arrays.toString(mRequiredIds))
.append(", optionalIds=").append(Arrays.toString(mOptionalIds))
.append(", description=").append(mDescription)
+ .append(DebugUtils.flagsToString(SaveInfo.class, "NEGATIVE_BUTTON_STYLE_",
+ mNegativeButtonStyle))
.append(", mFlags=").append(mFlags)
.append("]").toString();
}
@@ -380,7 +413,7 @@
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(mType);
parcel.writeParcelableArray(mRequiredIds, flags);
- parcel.writeCharSequence(mNegativeActionTitle);
+ parcel.writeInt(mNegativeButtonStyle);
parcel.writeParcelable(mNegativeActionListener, flags);
parcel.writeParcelableArray(mOptionalIds, flags);
parcel.writeCharSequence(mDescription);
@@ -395,7 +428,7 @@
// using specially crafted parcels.
final Builder builder = new Builder(parcel.readInt(),
parcel.readParcelableArray(null, AutofillId.class));
- builder.setNegativeAction(parcel.readCharSequence(), parcel.readParcelable(null));
+ builder.setNegativeAction(parcel.readInt(), parcel.readParcelable(null));
builder.setOptionalIds(parcel.readParcelableArray(null, AutofillId.class));
builder.setDescription(parcel.readCharSequence());
builder.setFlags(parcel.readInt());
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 9bba1ad..cbaaef7 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -159,19 +159,20 @@
}
final TextView noButton = view.findViewById(R.id.autofill_save_no);
- if (info.getNegativeActionTitle() != null) {
- noButton.setText(info.getNegativeActionTitle());
- noButton.setOnClickListener((v) -> mListener.onCancel(
- info.getNegativeActionListener()));
+ if (info.getNegativeActionStyle() == SaveInfo.NEGATIVE_BUTTON_STYLE_REJECT) {
+ noButton.setText(R.string.save_password_notnow);
} else {
- noButton.setOnClickListener((v) -> mListener.onCancel(null));
+ noButton.setText(R.string.autofill_save_no);
}
+ noButton.setOnClickListener((v) -> mListener.onCancel(
+ info.getNegativeActionListener()));
final View yesButton = view.findViewById(R.id.autofill_save_yes);
yesButton.setOnClickListener((v) -> mListener.onSave());
final View closeButton = view.findViewById(R.id.autofill_save_close);
- closeButton.setOnClickListener((v) -> mListener.onCancel(null));
+ closeButton.setOnClickListener((v) -> mListener.onCancel(
+ info.getNegativeActionListener()));
mDialog = new Dialog(context, R.style.Theme_Material_Panel);
mDialog.setContentView(view);