Merge "Added customization to SaveInfo."

This commit is contained in:
TreeHugger Robot
2017-02-27 19:49:15 +00:00
committed by Android (Google) Code Review
12 changed files with 130 additions and 47 deletions

View File

@@ -36392,16 +36392,17 @@ package android.service.autofill {
method public int describeContents();
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_UI_TYPE_ADDRESS = 2; // 0x2
field public static final int SAVE_UI_TYPE_CREDENTIALS = 1; // 0x1
field public static final int SAVE_UI_TYPE_GENERIC = 0; // 0x0
field public static final int SAVE_UI_TYPE_PAYMENT = 3; // 0x3
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_GENERIC = 0; // 0x0
field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1
}
public static final class SaveInfo.Builder {
ctor public SaveInfo.Builder(int);
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);
}
}

View File

@@ -39312,16 +39312,17 @@ package android.service.autofill {
method public int describeContents();
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_UI_TYPE_ADDRESS = 2; // 0x2
field public static final int SAVE_UI_TYPE_CREDENTIALS = 1; // 0x1
field public static final int SAVE_UI_TYPE_GENERIC = 0; // 0x0
field public static final int SAVE_UI_TYPE_PAYMENT = 3; // 0x3
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_GENERIC = 0; // 0x0
field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1
}
public static final class SaveInfo.Builder {
ctor public SaveInfo.Builder(int);
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);
}
}

View File

@@ -36531,16 +36531,17 @@ package android.service.autofill {
method public int describeContents();
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_UI_TYPE_ADDRESS = 2; // 0x2
field public static final int SAVE_UI_TYPE_CREDENTIALS = 1; // 0x1
field public static final int SAVE_UI_TYPE_GENERIC = 0; // 0x0
field public static final int SAVE_UI_TYPE_PAYMENT = 3; // 0x3
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_GENERIC = 0; // 0x0
field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1
}
public static final class SaveInfo.Builder {
ctor public SaveInfo.Builder(int);
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);
}
}

View File

@@ -188,7 +188,7 @@ public final class FillResponse implements Parcelable {
// Handle the the case where service didn't call setSavableIds() because it would
// contain just the ids from the datasets.
if (saveInfo == null && mDatasets != null) {
saveInfo = new SaveInfo.Builder(SaveInfo.SAVE_UI_TYPE_GENERIC).build();
saveInfo = new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_GENERIC).build();
}
if (saveInfo != null) {
saveInfo.addSavableIds(mDatasets);
@@ -324,7 +324,7 @@ public final class FillResponse implements Parcelable {
throw new IllegalStateException("setSaveInfo() already called");
}
if (mSaveInfoBuilder == null) {
mSaveInfoBuilder = new SaveInfo.Builder(SaveInfo.SAVE_UI_TYPE_GENERIC);
mSaveInfoBuilder = new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_GENERIC);
}
mSaveInfoBuilder.addSavableIds(ids);

View File

@@ -52,43 +52,44 @@ public final class SaveInfo implements Parcelable {
* 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_UI_TYPE_GENERIC = 0;
public static final int SAVE_DATA_TYPE_GENERIC = 0;
/**
* Type used when the {@link FillResponse} represents user credentials (such as username and
* password).
* Type used when the {@link FillResponse} represents user credentials that have a password.
*/
public static final int SAVE_UI_TYPE_CREDENTIALS = 1;
public static final int SAVE_DATA_TYPE_PASSWORD = 1;
/**
* Type used on when the {@link FillResponse} represents a physical address (such as street,
* city, state, etc).
*/
public static final int SAVE_UI_TYPE_ADDRESS = 2;
public static final int SAVE_DATA_TYPE_ADDRESS = 2;
/**
* Type used when the {@link FillResponse} represents a payment (such as credit card number
* and expiration date).
* Type used when the {@link FillResponse} represents a credit card.
*/
public static final int SAVE_UI_TYPE_PAYMENT = 3;
public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3;
private final @SaveUiType int mType;
private final @SaveDataType int mType;
private ArraySet<AutoFillId> mSavableIds;
private final CharSequence mDescription;
/** @hide */
@IntDef({
SAVE_UI_TYPE_GENERIC,
SAVE_UI_TYPE_CREDENTIALS,
SAVE_UI_TYPE_ADDRESS,
SAVE_UI_TYPE_PAYMENT
SAVE_DATA_TYPE_GENERIC,
SAVE_DATA_TYPE_PASSWORD,
SAVE_DATA_TYPE_ADDRESS,
SAVE_DATA_TYPE_CREDIT_CARD
})
@Retention(RetentionPolicy.SOURCE)
public @interface SaveUiType {
public @interface SaveDataType {
}
private SaveInfo(Builder builder) {
mType = builder.mType;
mSavableIds = builder.mSavableIds;
mDescription = builder.mDescription;
}
/** @hide */
@@ -96,6 +97,16 @@ public final class SaveInfo implements Parcelable {
return mSavableIds;
}
/** @hide */
public int getType() {
return mType;
}
/** @hide */
public CharSequence getDescription() {
return mDescription;
}
/** @hide */
public void addSavableIds(@Nullable ArrayList<Dataset> datasets) {
if (datasets != null) {
@@ -120,27 +131,28 @@ public final class SaveInfo implements Parcelable {
*/
public static final class Builder {
private final @SaveUiType int mType;
private final @SaveDataType int mType;
private ArraySet<AutoFillId> mSavableIds;
private CharSequence mDescription;
private boolean mDestroyed;
/**
* Creates a new builder.
*
* @param type the type of information the associated {@link FillResponse} represents. Must
* be {@link SaveInfo#SAVE_UI_TYPE_GENERIC}, {@link SaveInfo#SAVE_UI_TYPE_CREDENTIALS},
* {@link SaveInfo#SAVE_UI_TYPE_ADDRESS}, or {@link SaveInfo#SAVE_UI_TYPE_PAYMENT};
* otherwise it will assume {@link SaveInfo#SAVE_UI_TYPE_GENERIC}.
* 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}.
*/
public Builder(@SaveUiType int type) {
public Builder(@SaveDataType int type) {
switch (type) {
case SAVE_UI_TYPE_CREDENTIALS:
case SAVE_UI_TYPE_ADDRESS:
case SAVE_UI_TYPE_PAYMENT:
case SAVE_DATA_TYPE_PASSWORD:
case SAVE_DATA_TYPE_ADDRESS:
case SAVE_DATA_TYPE_CREDIT_CARD:
mType = type;
break;
default:
mType = SAVE_UI_TYPE_GENERIC;
mType = SAVE_DATA_TYPE_GENERIC;
}
}
@@ -168,6 +180,20 @@ public final class SaveInfo implements Parcelable {
return this;
}
/**
* Sets an optional description to be shown in the UI when the user is asked to save.
*
* <p>Typically, it describes how the data will be stored by the service, so it can help
* users to decide whether they can trust the service to save their data.
*
* @param description a succint description.
* @return This Builder.
*/
public @NonNull Builder setDescription(@Nullable CharSequence description) {
mDescription = description;
return this;
}
/**
* Builds a new {@link SaveInfo} instance.
*/
@@ -210,6 +236,7 @@ public final class SaveInfo implements Parcelable {
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(mType);
parcel.writeTypedArraySet(mSavableIds, flags);
parcel.writeCharSequence(mDescription);
}
public static final Parcelable.Creator<SaveInfo> CREATOR = new Parcelable.Creator<SaveInfo>() {
@@ -224,7 +251,7 @@ public final class SaveInfo implements Parcelable {
for (int i = 0; i < savableIdsCount; i++) {
builder.addSavableIds(savableIds.valueAt(i));
}
builder.setDescription(parcel.readCharSequence());
return builder.build();
}

View File

@@ -15,7 +15,7 @@
-->
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/list"
android:id="@+id/autofill_dataset_picker"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:divider="?android:attr/listDivider"

View File

@@ -16,6 +16,7 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/autofill_save"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingStart="16dip"
@@ -39,6 +40,13 @@
android:singleLine="true">
</TextView>
<TextView
android:id="@+id/autofill_save_subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible">
</TextView>
<Space
android:layout_width="0dp"
android:layout_height="0dp"

View File

@@ -4510,11 +4510,22 @@
<!-- Accessibility string used for describing the button in time picker that changes the dialog to circular clock mode. [CHAR LIMIT=NONE] -->
<string name="time_picker_radial_mode_description">Switch to clock mode for the time input.</string>
<!-- Title for the auto-fill save dialog shown when the user entered savable text [CHAR LIMIT=NONE] -->
<!-- Title for the auto-fill save dialog shown when the the contents of the activity can be saved
by an auto-fill service, but the service does not know what the activity represents [CHAR LIMIT=NONE] -->
<string name="autofill_save_title">Save to <xliff:g id="label" example="MyPass">%1$s</xliff:g>?</string>
<!-- Title for the auto-fill save dialog shown when the the contents of the activity can be saved
by an auto-fill 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>
<!-- Label for the auto-fill save button [CHAR LIMIT=NONE] -->
<string name="autofill_save_yes">Save</string>
<!-- Label for the auto-fill cancel button [CHAR LIMIT=NONE] -->
<string name="autofill_save_no">No thanks</string>
<!-- Label for the type of data being saved for auto-fill when it represent user credentials with a password [CHAR LIMIT=NONE] -->
<string name="autofill_save_type_password">password</string>
<!-- Label for the type of data being saved for auto-fill when it represent an address (street, city, etc.) [CHAR LIMIT=NONE] -->
<string name="autofill_save_type_address">address</string>
<!-- Label for the type of data being saved for auto-fill when it represents a credit card [CHAR LIMIT=NONE] -->
<string name="autofill_save_type_credit_card">credit card</string>
</resources>

View File

@@ -2838,12 +2838,17 @@
<java-symbol type="layout" name="autofill_save"/>
<java-symbol type="layout" name="autofill_dataset_picker"/>
<java-symbol type="id" name="autofill_save_title" />
<java-symbol type="id" name="autofill_save_subtitle" />
<java-symbol type="id" name="autofill_save_no" />
<java-symbol type="id" name="autofill_save_yes" />
<java-symbol type="id" name="autofill_save_close" />
<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_yes" />
<java-symbol type="string" name="autofill_save_no" />
<java-symbol type="string" name="autofill_save_type_password" />
<java-symbol type="string" name="autofill_save_type_address" />
<java-symbol type="string" name="autofill_save_type_credit_card" />
<!-- Accessibility fingerprint gestures -->
<java-symbol type="string" name="capability_title_canCaptureFingerprintGestures" />

View File

@@ -743,8 +743,9 @@ final class AutoFillManagerServiceImpl {
Slog.d(TAG, "finishSessionLocked(): found a change on " + id + ": "
+ state.mAutoFillValue);
}
getUiForShowing().showSaveUi(mInfo.getServiceInfo()
.loadLabel(mContext.getPackageManager()));
getUiForShowing().showSaveUi(
mInfo.getServiceInfo().loadLabel(mContext.getPackageManager()),
saveInfo);
return;
}
}

View File

@@ -24,6 +24,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.service.autofill.Dataset;
import android.service.autofill.FillResponse;
import android.service.autofill.SaveInfo;
import android.text.TextUtils;
import android.view.autofill.AutoFillId;
import android.widget.Toast;
@@ -172,13 +173,13 @@ public final class AutoFillUI {
/**
* Shows the UI asking the user to save for auto-fill.
*/
public void showSaveUi(@NonNull CharSequence providerLabel) {
public void showSaveUi(@NonNull CharSequence providerLabel, @NonNull SaveInfo info) {
mHandler.post(() -> {
if (!hasCallback()) {
return;
}
hideAllUiThread();
mSaveUi = new SaveUi(mContext, providerLabel,
mSaveUi = new SaveUi(mContext, providerLabel, info,
new SaveUi.OnSaveListener() {
@Override
public void onSave() {

View File

@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.app.Dialog;
import android.content.Context;
import android.os.Handler;
import android.service.autofill.SaveInfo;
import android.text.format.DateUtils;
import android.view.Gravity;
import android.view.Window;
@@ -50,15 +51,41 @@ final class SaveUi {
private boolean mDestroyed;
SaveUi(@NonNull Context context, @NonNull CharSequence providerLabel,
SaveUi(@NonNull Context context, @NonNull CharSequence providerLabel, @NonNull SaveInfo info,
@NonNull OnSaveListener listener) {
mListener = listener;
final LayoutInflater inflater = LayoutInflater.from(context);
final View view = inflater.inflate(R.layout.autofill_save, null);
final TextView title = (TextView) view.findViewById(R.id.autofill_save_title);
title.setText(context.getString(R.string.autofill_save_title, providerLabel));
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;
default:
type = null;
}
final String title = (type == null)
? context.getString(R.string.autofill_save_title, providerLabel)
: context.getString(R.string.autofill_save_title_with_type, type, providerLabel);
titleView.setText(title);
final CharSequence subTitle = info.getDescription();
if (subTitle != null) {
final TextView subTitleView = (TextView) view.findViewById(R.id.autofill_save_subtitle);
subTitleView.setText(subTitle);
subTitleView.setVisibility(View.VISIBLE);
}
final View noButton = view.findViewById(R.id.autofill_save_no);
noButton.setOnClickListener((v) -> mListener.onCancel());