Merge "Fill-provider can control the negative button label and listener"

This commit is contained in:
TreeHugger Robot
2017-03-03 04:45:35 +00:00
committed by Android (Google) Code Review
8 changed files with 86 additions and 10 deletions

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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();

View File

@@ -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,10 +91,22 @@ 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;
@@ -194,6 +211,42 @@ public final class SaveInfo implements Parcelable {
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.
*/
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.
*/
@@ -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++) {

View File

@@ -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;

View File

@@ -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);
}
}
}
});
});

View File

@@ -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() {