diff --git a/api/current.txt b/api/current.txt index 76cd93a321343..85297ae32dc4c 100644 --- a/api/current.txt +++ b/api/current.txt @@ -37118,6 +37118,8 @@ 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 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 @@ package android.service.autofill { 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 92f146901b612..93bd99af2b929 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -40233,6 +40233,8 @@ 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 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 @@ package android.service.autofill { 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 35087d64d685f..3a3e52ec8d4bb 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -37272,6 +37272,8 @@ 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 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 @@ package android.service.autofill { 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 edb90983ae3e3..32b078f67e95b 100644 --- a/core/java/android/service/autofill/AutofillService.java +++ b/core/java/android/service/autofill/AutofillService.java @@ -223,9 +223,11 @@ public abstract class AutofillService extends Service { * @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 @@ public abstract class AutofillService extends Service { * @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 3a1529f915e4a..94e5e3ec0d50d 100644 --- a/core/java/android/service/autofill/SaveInfo.java +++ b/core/java/android/service/autofill/SaveInfo.java @@ -139,6 +139,33 @@ public final class SaveInfo implements Parcelable { */ 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 @@ public final class SaveInfo implements Parcelable { @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 @@ public final class SaveInfo implements Parcelable { 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 @@ public final class SaveInfo implements Parcelable { } /** @hide */ - public @Nullable CharSequence getNegativeActionTitle() { - return mNegativeActionTitle; + public @NegativeButtonStyle int getNegativeActionStyle() { + return mNegativeButtonStyle; } /** @hide */ @@ -224,7 +251,7 @@ public final class SaveInfo implements Parcelable { 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 @@ public final class SaveInfo implements Parcelable { return this; } - /** - * Sets the title and listener for the negative save action. - * - *

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.

- * - *

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.

- * - * @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. + * + *

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}

+ * + * @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 @@ public final class SaveInfo implements Parcelable { .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 final class SaveInfo implements Parcelable { 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 @@ public final class SaveInfo implements Parcelable { // 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 9bba1ad810a8d..cbaaef707bec0 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 class SaveUi { } 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);