summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt1
-rw-r--r--api/system-current.txt1
-rw-r--r--api/test-current.txt1
-rw-r--r--core/java/android/service/autofill/FillResponse.java6
-rw-r--r--core/java/android/service/autofill/SaveInfo.java56
-rw-r--r--services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java1
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java13
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/SaveUi.java17
8 files changed, 86 insertions, 10 deletions
diff --git a/api/current.txt b/api/current.txt
index 5099c2b62a98..6e054fc5f240 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -36535,6 +36535,7 @@ package android.service.autofill {
method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
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 setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
}
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 41b52ec999d5..0cef28e0a80a 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -39458,6 +39458,7 @@ package android.service.autofill {
method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
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 setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
}
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 5183e27a9e07..478a3ed42444 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -36674,6 +36674,7 @@ package android.service.autofill {
method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
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 setNegativeAction(java.lang.CharSequence, android.content.IntentSender);
}
}
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index ba75c8bee039..ef551ad29623 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -171,7 +171,7 @@ public final class FillResponse implements Parcelable {
if (false) {
// TODO(b/33197203, 35727295): this is how mSaveInfo will be set once we don't support
- // FillResponse.setSavableIds()
+ // FillResponse.addSavableIds()
mSaveInfo = builder.mSaveInfo;
if (mSaveInfo != null) {
mSaveInfo.addSavableIds(mDatasets);
@@ -181,11 +181,11 @@ public final class FillResponse implements Parcelable {
}
}
} else {
- // Temporary workaround to support FillResponse.setSavableIds()
+ // Temporary workaround to support FillResponse.addSavableIds()
SaveInfo saveInfo = builder.mSaveInfoBuilder != null ? builder.mSaveInfoBuilder.build()
: builder.mSaveInfo;
- // Handle the the case where service didn't call setSavableIds() because it would
+ // Handle the the case where service didn't call addSavableIds() because it would
// contain just the ids from the datasets.
if (saveInfo == null && mDatasets != null) {
saveInfo = new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_GENERIC).build();
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 096f28b60687..a8f9aeedb6b9 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -21,6 +21,7 @@ import static android.view.autofill.Helper.DEBUG;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.IntentSender;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -72,6 +73,8 @@ public final class SaveInfo implements Parcelable {
public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3;
private final @SaveDataType int mType;
+ private CharSequence mNegativeActionTitle;
+ private IntentSender mNegativeActionListener;
private ArraySet<AutoFillId> mSavableIds;
private final CharSequence mDescription;
@@ -88,11 +91,23 @@ public final class SaveInfo implements Parcelable {
private SaveInfo(Builder builder) {
mType = builder.mType;
+ mNegativeActionTitle = builder.mNegativeActionTitle;
+ mNegativeActionListener = builder.mNegativeActionListener;
mSavableIds = builder.mSavableIds;
mDescription = builder.mDescription;
}
/** @hide */
+ public @Nullable CharSequence getNegativeActionTitle() {
+ return mNegativeActionTitle;
+ }
+
+ /** @hide */
+ public @Nullable IntentSender getNegativeActionListener() {
+ return mNegativeActionListener;
+ }
+
+ /** @hide */
public @Nullable ArraySet<AutoFillId> getSavableIds() {
return mSavableIds;
}
@@ -132,6 +147,8 @@ public final class SaveInfo implements Parcelable {
public static final class Builder {
private final @SaveDataType int mType;
+ private CharSequence mNegativeActionTitle;
+ private IntentSender mNegativeActionListener;
private ArraySet<AutoFillId> mSavableIds;
private CharSequence mDescription;
private boolean mDestroyed;
@@ -195,6 +212,42 @@ public final class SaveInfo implements Parcelable {
}
/**
+ * 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.
+ */
+ 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");
+ }
+ mNegativeActionTitle = title;
+ mNegativeActionListener = listener;
+ return this;
+ }
+
+ /**
* Builds a new {@link SaveInfo} instance.
*/
public SaveInfo build() {
@@ -235,6 +288,8 @@ public final class SaveInfo implements Parcelable {
@Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(mType);
+ parcel.writeCharSequence(mNegativeActionTitle);
+ parcel.writeParcelable(mNegativeActionListener, flags);
parcel.writeTypedArraySet(mSavableIds, flags);
parcel.writeCharSequence(mDescription);
}
@@ -246,6 +301,7 @@ public final class SaveInfo implements Parcelable {
// the system obeys the contract of the builder to avoid attacks
// using specially crafted parcels.
final Builder builder = new Builder(parcel.readInt());
+ builder.setNegativeAction(parcel.readCharSequence(), parcel.readParcelable(null));
final ArraySet<AutoFillId> savableIds = parcel.readTypedArraySet(null);
final int savableIdsCount = (savableIds != null) ? savableIds.size() : 0;
for (int i = 0; i < savableIdsCount; i++) {
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
index ad4dac070d38..5e852f1738f1 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
@@ -59,7 +59,6 @@ import android.service.autofill.IAutoFillService;
import android.service.autofill.SaveInfo;
import android.text.TextUtils;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.LocalLog;
import android.util.PrintWriterPrinter;
import android.util.Slog;
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index 949a80c7bfdc..0da36c8936c8 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -26,6 +26,7 @@ import android.service.autofill.Dataset;
import android.service.autofill.FillResponse;
import android.service.autofill.SaveInfo;
import android.text.TextUtils;
+import android.util.Slog;
import android.view.autofill.AutoFillId;
import android.widget.Toast;
@@ -41,6 +42,8 @@ import java.io.PrintWriter;
* managing saving of user edits.
*/
public final class AutoFillUI {
+ private static final String TAG = "AutoFillUI";
+
private final Handler mHandler = UiThread.getHandler();
private final @NonNull Context mContext;
@@ -191,9 +194,17 @@ public final class AutoFillUI {
}
@Override
- public void onCancel() {
+ public void onCancel(IntentSender listener) {
// TODO(b/33197203): add MetricsLogger call
hideSaveUiUiThread();
+ if (listener != null) {
+ try {
+ listener.sendIntent(mContext, 0, null, null, null);
+ } catch (IntentSender.SendIntentException e) {
+ Slog.e(TAG, "Error starting negative action listener: "
+ + listener, e);
+ }
+ }
}
});
});
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 afe93c7d6e06..d443dc34f949 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -19,6 +19,7 @@ package com.android.server.autofill.ui;
import android.annotation.NonNull;
import android.app.Dialog;
import android.content.Context;
+import android.content.IntentSender;
import android.os.Handler;
import android.service.autofill.SaveInfo;
import android.text.format.DateUtils;
@@ -38,7 +39,7 @@ import com.android.server.UiThread;
final class SaveUi {
public interface OnSaveListener {
void onSave();
- void onCancel();
+ void onCancel(IntentSender listener);
}
private static final long LIFETIME_MILLIS = 5 * DateUtils.SECOND_IN_MILLIS;
@@ -87,14 +88,20 @@ final class SaveUi {
subTitleView.setVisibility(View.VISIBLE);
}
- final View noButton = view.findViewById(R.id.autofill_save_no);
- noButton.setOnClickListener((v) -> mListener.onCancel());
+ 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()));
+ } else {
+ noButton.setOnClickListener((v) -> mListener.onCancel(null));
+ }
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());
+ closeButton.setOnClickListener((v) -> mListener.onCancel(null));
mDialog = new Dialog(context, R.style.Theme_Material_Panel);
mDialog.setContentView(view);
@@ -112,7 +119,7 @@ final class SaveUi {
mDialog.show();
- mHandler.postDelayed(() -> mListener.onCancel(), LIFETIME_MILLIS);
+ mHandler.postDelayed(() -> mListener.onCancel(null), LIFETIME_MILLIS);
}
void destroy() {