Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f69761ff authored by Felipe Leme's avatar Felipe Leme
Browse files

Refactored savableIds() into a SaveInfo class.

For now it's a "1-to-1" refactoring that keeps the same
functionalities, but soon SaveInfo will be expanded to
allow the AutoFillService to customize it.

Bug: 35727295
Test: CtsAutoFillServiceTestCases pass
Test: m update-api

Change-Id: I5aaa705be2b32590048f70ed0142437e05df94b7
parent 38a65f6c
Loading
Loading
Loading
Loading
+17 −1
Original line number Original line Diff line number Diff line
@@ -36321,10 +36321,10 @@ package android.service.autofill {
  public static final class FillResponse.Builder {
  public static final class FillResponse.Builder {
    ctor public FillResponse.Builder();
    ctor public FillResponse.Builder();
    method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
    method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
    method public android.service.autofill.FillResponse.Builder addSavableFields(android.view.autofill.AutoFillId...);
    method public android.service.autofill.FillResponse build();
    method public android.service.autofill.FillResponse build();
    method public android.service.autofill.FillResponse.Builder setAuthentication(android.content.IntentSender, android.widget.RemoteViews);
    method public android.service.autofill.FillResponse.Builder setAuthentication(android.content.IntentSender, android.widget.RemoteViews);
    method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
    method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
    method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
  }
  }
  public final class SaveCallback {
  public final class SaveCallback {
@@ -36332,6 +36332,22 @@ package android.service.autofill {
    method public void onSuccess();
    method public void onSuccess();
  }
  }
  public final class SaveInfo implements android.os.Parcelable {
    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
  }
  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();
  }
}
}
package android.service.carrier {
package android.service.carrier {
+17 −1
Original line number Original line Diff line number Diff line
@@ -39234,10 +39234,10 @@ package android.service.autofill {
  public static final class FillResponse.Builder {
  public static final class FillResponse.Builder {
    ctor public FillResponse.Builder();
    ctor public FillResponse.Builder();
    method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
    method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
    method public android.service.autofill.FillResponse.Builder addSavableFields(android.view.autofill.AutoFillId...);
    method public android.service.autofill.FillResponse build();
    method public android.service.autofill.FillResponse build();
    method public android.service.autofill.FillResponse.Builder setAuthentication(android.content.IntentSender, android.widget.RemoteViews);
    method public android.service.autofill.FillResponse.Builder setAuthentication(android.content.IntentSender, android.widget.RemoteViews);
    method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
    method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
    method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
  }
  }
  public final class SaveCallback {
  public final class SaveCallback {
@@ -39245,6 +39245,22 @@ package android.service.autofill {
    method public void onSuccess();
    method public void onSuccess();
  }
  }
  public final class SaveInfo implements android.os.Parcelable {
    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
  }
  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();
  }
}
}
package android.service.carrier {
package android.service.carrier {
+17 −1
Original line number Original line Diff line number Diff line
@@ -36460,10 +36460,10 @@ package android.service.autofill {
  public static final class FillResponse.Builder {
  public static final class FillResponse.Builder {
    ctor public FillResponse.Builder();
    ctor public FillResponse.Builder();
    method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
    method public android.service.autofill.FillResponse.Builder addDataset(android.service.autofill.Dataset);
    method public android.service.autofill.FillResponse.Builder addSavableFields(android.view.autofill.AutoFillId...);
    method public android.service.autofill.FillResponse build();
    method public android.service.autofill.FillResponse build();
    method public android.service.autofill.FillResponse.Builder setAuthentication(android.content.IntentSender, android.widget.RemoteViews);
    method public android.service.autofill.FillResponse.Builder setAuthentication(android.content.IntentSender, android.widget.RemoteViews);
    method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
    method public android.service.autofill.FillResponse.Builder setExtras(android.os.Bundle);
    method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
  }
  }
  public final class SaveCallback {
  public final class SaveCallback {
@@ -36471,6 +36471,22 @@ package android.service.autofill {
    method public void onSuccess();
    method public void onSuccess();
  }
  }
  public final class SaveInfo implements android.os.Parcelable {
    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
  }
  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();
  }
}
}
package android.service.carrier {
package android.service.carrier {
+81 −49
Original line number Original line Diff line number Diff line
@@ -23,7 +23,6 @@ import android.content.IntentSender;
import android.os.Bundle;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable;
import android.util.ArraySet;
import android.view.autofill.AutoFillId;
import android.view.autofill.AutoFillId;
import android.view.autofill.AutoFillManager;
import android.view.autofill.AutoFillManager;
import android.widget.RemoteViews;
import android.widget.RemoteViews;
@@ -69,18 +68,19 @@ import java.util.ArrayList;
 *
 *
 * <p>If the user does not have any data associated with this {@link android.app.Activity} but
 * <p>If the user does not have any data associated with this {@link android.app.Activity} but
 * the service wants to offer the user the option to save the data that was entered, then the
 * the service wants to offer the user the option to save the data that was entered, then the
 * service could populate the response with {@code savableIds} instead of {@link Dataset}s:
 * service could populate the response with a {@link SaveInfo} instead of {@link Dataset}s:
 *
 *
 * <pre class="prettyprint">
 * <pre class="prettyprint">
 *  new FillResponse.Builder()
 *  new FillResponse.Builder()
 *      .addSavableFields(id1, id2)
 *      .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_INFO_TYPE_CREDENTIALS)
 *                   .addSavableFields(id1, id2))
 *      .build();
 *      .build();
 * </pre>
 * </pre>
 *
 *
 * <p>Similarly, there might be cases where the user data on the service is enough to populate some
 * <p>Similarly, there might be cases where the user data on the service is enough to populate some
 * fields but not all, and the service would still be interested on saving the other fields. In this
 * fields but not all, and the service would still be interested on saving the other fields. In this
 * scenario, the service could populate the response with both {@link Dataset}s and {@code
 * scenario, the service could populate the response with both {@link Dataset}s and
 * savableIds}:
 * {@link SaveInfo}:
 *
 *
 * <pre class="prettyprint">
 * <pre class="prettyprint">
 *   new FillResponse.Builder()
 *   new FillResponse.Builder()
@@ -90,7 +90,8 @@ import java.util.ArrayList;
 *          .setTextFieldValue(id3, "742 Evergreen Terrace")  // street
 *          .setTextFieldValue(id3, "742 Evergreen Terrace")  // street
 *          .setTextFieldValue(id4, "Springfield")            // city
 *          .setTextFieldValue(id4, "Springfield")            // city
 *          .build())
 *          .build())
 *       .addSavableFields(id5, id6) // state and zipcode
 *       .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_INFO_TYPE_ADDRESS)
 *                   .addSavableFields(id5, id6)) // state and zipcode
 *       .build();
 *       .build();
 *
 *
 * </pre>
 * </pre>
@@ -140,9 +141,11 @@ import java.util.ArrayList;
 * </pre>
 * </pre>
 *
 *
 * <p>The service could require user authentication at the {@link FillResponse} or the
 * <p>The service could require user authentication at the {@link FillResponse} or the
 * {@link Dataset} level, prior to auto-filling an activity - see {@link FillResponse.Builder
 * {@link Dataset} level, prior to auto-filling an activity - see
 * #setAuthentication(IntentSender)} and {@link Dataset.Builder#setAuthentication(IntentSender)}.
 * {@link FillResponse.Builder#setAuthentication(IntentSender, RemoteViews)} and
 * It is recommended that you encrypt only the sensitive data but leave the labels unencrypted
 * {@link Dataset.Builder#setAuthentication(IntentSender)}.
 *
 * <p>It is recommended that you encrypt only the sensitive data but leave the labels unencrypted
 * which would allow you to provide a dataset presentation views with labels and if the user
 * which would allow you to provide a dataset presentation views with labels and if the user
 * chooses one of them challenge the user to authenticate. For example, if the user has a
 * chooses one of them challenge the user to authenticate. For example, if the user has a
 * home and a work address the Home and Work labels could be stored unencrypted as they don't
 * home and a work address the Home and Work labels could be stored unencrypted as they don't
@@ -158,14 +161,45 @@ import java.util.ArrayList;
public final class FillResponse implements Parcelable {
public final class FillResponse implements Parcelable {


    private final ArrayList<Dataset> mDatasets;
    private final ArrayList<Dataset> mDatasets;
    private final ArraySet<AutoFillId> mSavableIds;
    private final SaveInfo mSaveInfo;
    private final Bundle mExtras;
    private final Bundle mExtras;
    private final RemoteViews mPresentation;
    private final RemoteViews mPresentation;
    private final IntentSender mAuthentication;
    private final IntentSender mAuthentication;


    private FillResponse(@NonNull Builder builder) {
    private FillResponse(@NonNull Builder builder) {
        mDatasets = builder.mDatasets;
        mDatasets = builder.mDatasets;
        mSavableIds = builder.mSavableIds;

        if (false) {
            // TODO(b/33197203, 35727295): this is how mSaveInfo will be set once we don't support
            // FillResponse.setSavableIds()
            mSaveInfo = builder.mSaveInfo;
            if (mSaveInfo != null) {
                mSaveInfo.addSavableIds(mDatasets);
                if (mSaveInfo.getSavableIds() == null) {
                    throw new IllegalArgumentException(
                            "need to provide at least one savable id on SaveInfo");
                }
            }
        } else {
            // Temporary workaround to support FillResponse.setSavableIds()
            SaveInfo saveInfo = builder.mSaveInfoBuilder != null ? builder.mSaveInfoBuilder.build()
                    : builder.mSaveInfo;

            // 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();
            }
            if (saveInfo != null) {
                saveInfo.addSavableIds(mDatasets);
                if (saveInfo.getSavableIds() == null) {
                    throw new IllegalArgumentException(
                            "need to provide at least one savable id on SaveInfo");
                }
            }
            mSaveInfo = saveInfo;
        }

        mExtras = builder.mExtras;
        mExtras = builder.mExtras;
        mPresentation = builder.mPresentation;
        mPresentation = builder.mPresentation;
        mAuthentication = builder.mAuthentication;
        mAuthentication = builder.mAuthentication;
@@ -182,8 +216,8 @@ public final class FillResponse implements Parcelable {
    }
    }


    /** @hide */
    /** @hide */
    public @Nullable ArraySet<AutoFillId> getSavableIds() {
    public @Nullable SaveInfo getSaveInfo() {
        return mSavableIds;
        return mSaveInfo;
    }
    }


    /** @hide */
    /** @hide */
@@ -202,7 +236,10 @@ public final class FillResponse implements Parcelable {
     */
     */
    public static final class Builder {
    public static final class Builder {
        private ArrayList<Dataset> mDatasets;
        private ArrayList<Dataset> mDatasets;
        private ArraySet<AutoFillId> mSavableIds;
        // TODO(b/33197203, 35727295): temporary builder use by deprecated addSavableIds() method,
        // should be removed once that method is gone
        private SaveInfo.Builder mSaveInfoBuilder;
        private SaveInfo mSaveInfo;
        private Bundle mExtras;
        private Bundle mExtras;
        private RemoteViews mPresentation;
        private RemoteViews mPresentation;
        private IntentSender mAuthentication;
        private IntentSender mAuthentication;
@@ -276,41 +313,37 @@ public final class FillResponse implements Parcelable {
            if (!mDatasets.add(dataset)) {
            if (!mDatasets.add(dataset)) {
                return this;
                return this;
            }
            }
            if (dataset.getFieldIds() != null) {
            return this;
                final int fieldCount = dataset.getFieldIds().size();
                for (int i = 0; i < fieldCount; i++) {
                    final AutoFillId id = dataset.getFieldIds().get(i);
                    if (mSavableIds == null) {
                        mSavableIds = new ArraySet<>();
        }
        }
                    mSavableIds.add(id);

        /** @hide */
        // TODO(b/33197203, 35727295): remove when not used by clients
        public @NonNull Builder addSavableFields(@Nullable AutoFillId... ids) {
            throwIfDestroyed();
            if (mSaveInfo != null) {
                throw new IllegalStateException("setSaveInfo() already called");
            }
            }
            if (mSaveInfoBuilder == null) {
                mSaveInfoBuilder = new SaveInfo.Builder(SaveInfo.SAVE_UI_TYPE_GENERIC);
            }
            }
            mSaveInfoBuilder.addSavableIds(ids);

            return this;
            return this;
        }
        }


        /**
        /**
         * Adds ids of additional fields that the service would be interested to save (through
         * Sets the {@link SaveInfo} associated with this response.
         * {@link AutoFillService#onSaveRequest(
         * android.app.assist.AssistStructure, Bundle, SaveCallback)})
         * but were not indirectly set through {@link #addDataset(Dataset)}.
         *
         *
         * @param ids The savable ids.
         * <p>See {@link FillResponse} for more info.
         * @return This builder.
         *
         *
         * @see FillResponse
         * @return This builder.
         */
         */
        public @NonNull Builder addSavableFields(@Nullable AutoFillId... ids) {
        public @NonNull Builder setSaveInfo(@NonNull SaveInfo saveInfo) {
            throwIfDestroyed();
            throwIfDestroyed();
            if (ids == null) {
            if (mSaveInfoBuilder != null) {
                return this;
                throw new IllegalStateException("addSavableFields() already called");
            }
            for (AutoFillId id : ids) {
                if (mSavableIds == null) {
                    mSavableIds = new ArraySet<>();
                }
                mSavableIds.add(id);
            }
            }
            mSaveInfo = saveInfo;
            return this;
            return this;
        }
        }


@@ -340,9 +373,11 @@ public final class FillResponse implements Parcelable {
         */
         */
        public FillResponse build() {
        public FillResponse build() {
            throwIfDestroyed();
            throwIfDestroyed();
            if (mAuthentication == null && mDatasets == null && mSavableIds == null) {

                throw new IllegalArgumentException("need to provide at least one"
            if (mAuthentication == null && mDatasets == null && mSaveInfoBuilder == null
                        + " data set or savable ids or an authentication with a presentation");
                    && mSaveInfo == null) {
                throw new IllegalArgumentException("need to provide at least one DataSet or a "
                        + "SaveInfo or an authentication with a presentation");
            }
            }
            mDestroyed = true;
            mDestroyed = true;
            return new FillResponse(this);
            return new FillResponse(this);
@@ -361,9 +396,10 @@ public final class FillResponse implements Parcelable {
    @Override
    @Override
    public String toString() {
    public String toString() {
        if (!DEBUG) return super.toString();
        if (!DEBUG) return super.toString();

        return new StringBuilder(
        return new StringBuilder(
                "FillResponse: [datasets=").append(mDatasets)
                "FillResponse: [datasets=").append(mDatasets)
                .append(", savableIds=").append(mSavableIds)
                .append(", saveInfo=").append(mSaveInfo)
                .append(", hasExtras=").append(mExtras != null)
                .append(", hasExtras=").append(mExtras != null)
                .append(", hasPresentation=").append(mPresentation != null)
                .append(", hasPresentation=").append(mPresentation != null)
                .append(", hasAuthentication=").append(mAuthentication != null)
                .append(", hasAuthentication=").append(mAuthentication != null)
@@ -382,7 +418,7 @@ public final class FillResponse implements Parcelable {
    @Override
    @Override
    public void writeToParcel(Parcel parcel, int flags) {
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeTypedArrayList(mDatasets, flags);
        parcel.writeTypedArrayList(mDatasets, flags);
        parcel.writeTypedArraySet(mSavableIds, flags);
        parcel.writeParcelable(mSaveInfo, flags);
        parcel.writeParcelable(mExtras, flags);
        parcel.writeParcelable(mExtras, flags);
        parcel.writeParcelable(mAuthentication, flags);
        parcel.writeParcelable(mAuthentication, flags);
        parcel.writeParcelable(mPresentation, flags);
        parcel.writeParcelable(mPresentation, flags);
@@ -401,11 +437,7 @@ public final class FillResponse implements Parcelable {
            for (int i = 0; i < datasetCount; i++) {
            for (int i = 0; i < datasetCount; i++) {
                builder.addDataset(datasets.get(i));
                builder.addDataset(datasets.get(i));
            }
            }
            final ArraySet<AutoFillId> fillIds = parcel.readTypedArraySet(null);
            builder.setSaveInfo(parcel.readParcelable(null));
            final int fillIdCount = (fillIds != null) ? fillIds.size() : 0;
            for (int i = 0; i < fillIdCount; i++) {
                builder.addSavableFields(fillIds.valueAt(i));
            }
            builder.setExtras(parcel.readParcelable(null));
            builder.setExtras(parcel.readParcelable(null));
            builder.setAuthentication(parcel.readParcelable(null),
            builder.setAuthentication(parcel.readParcelable(null),
                    parcel.readParcelable(null));
                    parcel.readParcelable(null));
+19 −0
Original line number Original line Diff line number Diff line
/**
 * Copyright (c) 2017, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.service.autofill;

parcelable SaveInfo;
Loading