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

Commit ee39d54a authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Initial implementation of the new Save APIs."

parents cabb6386 979013d0
Loading
Loading
Loading
Loading
+63 −0
Original line number Original line Diff line number Diff line
@@ -36908,6 +36908,30 @@ package android.service.autofill {
    field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
    field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
  }
  }
  public final class CharSequenceTransformation 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.CharSequenceTransformation> CREATOR;
  }
  public static class CharSequenceTransformation.Builder {
    ctor public CharSequenceTransformation.Builder();
    method public android.service.autofill.CharSequenceTransformation.Builder addField(android.view.autofill.AutofillId, java.lang.String, java.lang.String);
    method public android.service.autofill.CharSequenceTransformation build();
  }
  public final class CustomDescription 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.CustomDescription> CREATOR;
  }
  public static class CustomDescription.Builder {
    ctor public CustomDescription.Builder(android.widget.RemoteViews);
    method public android.service.autofill.CustomDescription.Builder addChild(int, android.service.autofill.Transformation);
    method public android.service.autofill.CustomDescription build();
  }
  public final class Dataset implements android.os.Parcelable {
  public final class Dataset implements android.os.Parcelable {
    method public int describeContents();
    method public int describeContents();
    method public void writeToParcel(android.os.Parcel, int);
    method public void writeToParcel(android.os.Parcel, int);
@@ -36981,6 +37005,25 @@ package android.service.autofill {
    method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
    method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
  }
  }
  public final class ImageTransformation 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.ImageTransformation> CREATOR;
  }
  public static class ImageTransformation.Builder {
    ctor public ImageTransformation.Builder(android.view.autofill.AutofillId);
    method public android.service.autofill.ImageTransformation.Builder addOption(java.lang.String, int);
    method public android.service.autofill.ImageTransformation build();
  }
  public final class LuhnChecksumValidator implements android.os.Parcelable {
    ctor public LuhnChecksumValidator(android.view.autofill.AutofillId...);
    method public int describeContents();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator<android.service.autofill.LuhnChecksumValidator> CREATOR;
  }
  public final class SaveCallback {
  public final class SaveCallback {
    method public void onFailure(java.lang.CharSequence);
    method public void onFailure(java.lang.CharSequence);
    method public void onSuccess();
    method public void onSuccess();
@@ -37004,10 +37047,12 @@ package android.service.autofill {
  public static final class SaveInfo.Builder {
  public static final class SaveInfo.Builder {
    ctor public SaveInfo.Builder(int, android.view.autofill.AutofillId[]);
    ctor public SaveInfo.Builder(int, android.view.autofill.AutofillId[]);
    method public android.service.autofill.SaveInfo build();
    method public android.service.autofill.SaveInfo build();
    method public android.service.autofill.SaveInfo.Builder setCustomDescription(android.service.autofill.CustomDescription);
    method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
    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 setFlags(int);
    method public android.service.autofill.SaveInfo.Builder setNegativeAction(int, 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[]);
    method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
    method public android.service.autofill.SaveInfo.Builder setValidator(android.service.autofill.Validator);
  }
  }
  public final class SaveRequest implements android.os.Parcelable {
  public final class SaveRequest implements android.os.Parcelable {
@@ -37018,6 +37063,24 @@ package android.service.autofill {
    field public static final android.os.Parcelable.Creator<android.service.autofill.SaveRequest> CREATOR;
    field public static final android.os.Parcelable.Creator<android.service.autofill.SaveRequest> CREATOR;
  }
  }
  public final class SimpleRegexValidator implements android.os.Parcelable {
    ctor public SimpleRegexValidator(android.view.autofill.AutofillId, java.lang.String);
    method public int describeContents();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator<android.service.autofill.SimpleRegexValidator> CREATOR;
  }
  public abstract interface Transformation {
  }
  public abstract interface Validator {
  }
  public final class Validators {
    method public static android.service.autofill.Validator and(android.service.autofill.Validator...);
    method public static android.service.autofill.Validator or(android.service.autofill.Validator...);
  }
}
}
package android.service.carrier {
package android.service.carrier {
+63 −0
Original line number Original line Diff line number Diff line
@@ -39985,6 +39985,30 @@ package android.service.autofill {
    field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
    field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
  }
  }
  public final class CharSequenceTransformation 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.CharSequenceTransformation> CREATOR;
  }
  public static class CharSequenceTransformation.Builder {
    ctor public CharSequenceTransformation.Builder();
    method public android.service.autofill.CharSequenceTransformation.Builder addField(android.view.autofill.AutofillId, java.lang.String, java.lang.String);
    method public android.service.autofill.CharSequenceTransformation build();
  }
  public final class CustomDescription 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.CustomDescription> CREATOR;
  }
  public static class CustomDescription.Builder {
    ctor public CustomDescription.Builder(android.widget.RemoteViews);
    method public android.service.autofill.CustomDescription.Builder addChild(int, android.service.autofill.Transformation);
    method public android.service.autofill.CustomDescription build();
  }
  public final class Dataset implements android.os.Parcelable {
  public final class Dataset implements android.os.Parcelable {
    method public int describeContents();
    method public int describeContents();
    method public void writeToParcel(android.os.Parcel, int);
    method public void writeToParcel(android.os.Parcel, int);
@@ -40058,6 +40082,25 @@ package android.service.autofill {
    method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
    method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
  }
  }
  public final class ImageTransformation 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.ImageTransformation> CREATOR;
  }
  public static class ImageTransformation.Builder {
    ctor public ImageTransformation.Builder(android.view.autofill.AutofillId);
    method public android.service.autofill.ImageTransformation.Builder addOption(java.lang.String, int);
    method public android.service.autofill.ImageTransformation build();
  }
  public final class LuhnChecksumValidator implements android.os.Parcelable {
    ctor public LuhnChecksumValidator(android.view.autofill.AutofillId...);
    method public int describeContents();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator<android.service.autofill.LuhnChecksumValidator> CREATOR;
  }
  public final class SaveCallback {
  public final class SaveCallback {
    method public void onFailure(java.lang.CharSequence);
    method public void onFailure(java.lang.CharSequence);
    method public void onSuccess();
    method public void onSuccess();
@@ -40081,10 +40124,12 @@ package android.service.autofill {
  public static final class SaveInfo.Builder {
  public static final class SaveInfo.Builder {
    ctor public SaveInfo.Builder(int, android.view.autofill.AutofillId[]);
    ctor public SaveInfo.Builder(int, android.view.autofill.AutofillId[]);
    method public android.service.autofill.SaveInfo build();
    method public android.service.autofill.SaveInfo build();
    method public android.service.autofill.SaveInfo.Builder setCustomDescription(android.service.autofill.CustomDescription);
    method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
    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 setFlags(int);
    method public android.service.autofill.SaveInfo.Builder setNegativeAction(int, 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[]);
    method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
    method public android.service.autofill.SaveInfo.Builder setValidator(android.service.autofill.Validator);
  }
  }
  public final class SaveRequest implements android.os.Parcelable {
  public final class SaveRequest implements android.os.Parcelable {
@@ -40095,6 +40140,24 @@ package android.service.autofill {
    field public static final android.os.Parcelable.Creator<android.service.autofill.SaveRequest> CREATOR;
    field public static final android.os.Parcelable.Creator<android.service.autofill.SaveRequest> CREATOR;
  }
  }
  public final class SimpleRegexValidator implements android.os.Parcelable {
    ctor public SimpleRegexValidator(android.view.autofill.AutofillId, java.lang.String);
    method public int describeContents();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator<android.service.autofill.SimpleRegexValidator> CREATOR;
  }
  public abstract interface Transformation {
  }
  public abstract interface Validator {
  }
  public final class Validators {
    method public static android.service.autofill.Validator and(android.service.autofill.Validator...);
    method public static android.service.autofill.Validator or(android.service.autofill.Validator...);
  }
}
}
package android.service.carrier {
package android.service.carrier {
+63 −0
Original line number Original line Diff line number Diff line
@@ -37080,6 +37080,30 @@ package android.service.autofill {
    field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
    field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
  }
  }
  public final class CharSequenceTransformation 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.CharSequenceTransformation> CREATOR;
  }
  public static class CharSequenceTransformation.Builder {
    ctor public CharSequenceTransformation.Builder();
    method public android.service.autofill.CharSequenceTransformation.Builder addField(android.view.autofill.AutofillId, java.lang.String, java.lang.String);
    method public android.service.autofill.CharSequenceTransformation build();
  }
  public final class CustomDescription 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.CustomDescription> CREATOR;
  }
  public static class CustomDescription.Builder {
    ctor public CustomDescription.Builder(android.widget.RemoteViews);
    method public android.service.autofill.CustomDescription.Builder addChild(int, android.service.autofill.Transformation);
    method public android.service.autofill.CustomDescription build();
  }
  public final class Dataset implements android.os.Parcelable {
  public final class Dataset implements android.os.Parcelable {
    method public int describeContents();
    method public int describeContents();
    method public void writeToParcel(android.os.Parcel, int);
    method public void writeToParcel(android.os.Parcel, int);
@@ -37153,6 +37177,25 @@ package android.service.autofill {
    method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
    method public android.service.autofill.FillResponse.Builder setSaveInfo(android.service.autofill.SaveInfo);
  }
  }
  public final class ImageTransformation 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.ImageTransformation> CREATOR;
  }
  public static class ImageTransformation.Builder {
    ctor public ImageTransformation.Builder(android.view.autofill.AutofillId);
    method public android.service.autofill.ImageTransformation.Builder addOption(java.lang.String, int);
    method public android.service.autofill.ImageTransformation build();
  }
  public final class LuhnChecksumValidator implements android.os.Parcelable {
    ctor public LuhnChecksumValidator(android.view.autofill.AutofillId...);
    method public int describeContents();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator<android.service.autofill.LuhnChecksumValidator> CREATOR;
  }
  public final class SaveCallback {
  public final class SaveCallback {
    method public void onFailure(java.lang.CharSequence);
    method public void onFailure(java.lang.CharSequence);
    method public void onSuccess();
    method public void onSuccess();
@@ -37176,10 +37219,12 @@ package android.service.autofill {
  public static final class SaveInfo.Builder {
  public static final class SaveInfo.Builder {
    ctor public SaveInfo.Builder(int, android.view.autofill.AutofillId[]);
    ctor public SaveInfo.Builder(int, android.view.autofill.AutofillId[]);
    method public android.service.autofill.SaveInfo build();
    method public android.service.autofill.SaveInfo build();
    method public android.service.autofill.SaveInfo.Builder setCustomDescription(android.service.autofill.CustomDescription);
    method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
    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 setFlags(int);
    method public android.service.autofill.SaveInfo.Builder setNegativeAction(int, 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[]);
    method public android.service.autofill.SaveInfo.Builder setOptionalIds(android.view.autofill.AutofillId[]);
    method public android.service.autofill.SaveInfo.Builder setValidator(android.service.autofill.Validator);
  }
  }
  public final class SaveRequest implements android.os.Parcelable {
  public final class SaveRequest implements android.os.Parcelable {
@@ -37190,6 +37235,24 @@ package android.service.autofill {
    field public static final android.os.Parcelable.Creator<android.service.autofill.SaveRequest> CREATOR;
    field public static final android.os.Parcelable.Creator<android.service.autofill.SaveRequest> CREATOR;
  }
  }
  public final class SimpleRegexValidator implements android.os.Parcelable {
    ctor public SimpleRegexValidator(android.view.autofill.AutofillId, java.lang.String);
    method public int describeContents();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator<android.service.autofill.SimpleRegexValidator> CREATOR;
  }
  public abstract interface Transformation {
  }
  public abstract interface Validator {
  }
  public final class Validators {
    method public static android.service.autofill.Validator and(android.service.autofill.Validator...);
    method public static android.service.autofill.Validator or(android.service.autofill.Validator...);
  }
}
}
package android.service.carrier {
package android.service.carrier {
+202 −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;

import static android.view.autofill.Helper.sDebug;

import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;
import android.view.autofill.AutofillId;
import android.widget.RemoteViews;
import android.widget.TextView;

import com.android.internal.util.Preconditions;

/**
 * Replaces a {@link TextView} child of a {@link CustomDescription} with the contents of one or
 * more regular expressions (regexs).
 *
 * <p>When it contains more than one field, the fields that match their regex are added to the
 * overall transformation result.
 *
 * <p>For example, a transformation to mask a credit card number contained in just one field would
 * be:
 *
 * <pre class="prettyprint">
 * new CharSequenceTransformation.Builder()
 *   .addField(ccNumberId, "^.*(\\d\\d\\d\\d)$", "...$1")
 *   .build();
 * </pre>
 *
 * <p>But a tranformation that generates a {@code Exp: MM / YYYY} credit expiration date from two
 * fields (month and year) would be:
 *
 * <pre class="prettyprint">
 * new CharSequenceTransformation.Builder()
 *   .addField(ccExpMonthId, "^(\\d\\d)$", "Exp: $1")
 *   .addField(ccExpYearId, "^(\\d\\d\\d\\d)$", " / $1");
 * </pre>
 */
//TODO(b/62534917): add unit tests
public final class CharSequenceTransformation extends InternalTransformation implements Parcelable {
    private static final String TAG = "CharSequenceTransformation";
    private final ArrayMap<AutofillId, Pair<String, String>> mFields;

    private CharSequenceTransformation(Builder builder) {
        mFields = builder.mFields;
    }

    /** @hide */
    @Override
    public void apply(@NonNull ValueFinder finder, @NonNull RemoteViews parentTemplate,
            int childViewId) {
        final StringBuilder converted = new StringBuilder();
        final int size = mFields.size();
        if (sDebug) Log.d(TAG, size + " multiple fields on id " + childViewId);
        for (int i = 0; i < size; i++) {
            final AutofillId id = mFields.keyAt(i);
            final Pair<String, String> regex = mFields.valueAt(i);
            final String value = finder.findByAutofillId(id);
            if (value == null) {
                Log.w(TAG, "No value for id " + id);
                return;
            }
            final String convertedValue = value.replaceAll(regex.first, regex.second);
            converted.append(convertedValue);
        }
        parentTemplate.setCharSequence(childViewId, "setText", converted);
    }

    /**
     * Builder for {@link CharSequenceTransformation} objects.
     */
    public static class Builder {
        private ArrayMap<AutofillId, Pair<String, String>> mFields;
        private boolean mDestroyed;

        //TODO(b/62534917): add constructor that takes a field so we force it to have at least one
        // (and then remove the check for empty from build())

        /**
         * Adds the transformed contents of a field to the overall result of this transformation.
         *
         * @param id id of the screen field.
         * @param regex regular expression with groups (delimited by {@code (} and {@code (}) that
         * are used to substitute parts of the value.
         * @param subst the string that substitutes the matched regex, using {@code $} for
         * group substitution ({@code $1} for 1st group match, {@code $2} for 2nd, etc).
         *
         * @return this builder.
         */
        public Builder addField(@NonNull AutofillId id, @NonNull String regex,
                @NonNull String subst) {
            //TODO(b/62534917): throw exception if regex /subts are invalid
            throwIfDestroyed();
            Preconditions.checkNotNull(id);
            Preconditions.checkNotNull(regex);
            Preconditions.checkNotNull(subst);
            if (mFields == null) {
                mFields = new ArrayMap<>();
            }
            mFields.put(id, new Pair<>(regex, subst));
            return this;
        }

        /**
         * Creates a new {@link CharSequenceTransformation} instance.
         *
         * @throws IllegalStateException if no call to {@link #addField(AutofillId, String, String)}
         * was made.
         */
        public CharSequenceTransformation build() {
            throwIfDestroyed();
            Preconditions.checkState(mFields != null && !mFields.isEmpty(),
                    "Must add at least one field");
            mDestroyed = true;
            return new CharSequenceTransformation(this);
        }

        private void throwIfDestroyed() {
            Preconditions.checkState(!mDestroyed, "Already called build()");
        }
    }

    /////////////////////////////////////
    // Object "contract" methods. //
    /////////////////////////////////////
    @Override
    public String toString() {
        if (!sDebug) return super.toString();

        return "MultipleViewsCharSequenceTransformation: [fields=" + mFields + "]";
    }

    /////////////////////////////////////
    // Parcelable "contract" methods. //
    /////////////////////////////////////
    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        final int size = mFields.size();
        final AutofillId[] ids = new AutofillId[size];
        final String[] regexs = new String[size];
        final String[] substs = new String[size];
        Pair<String, String> pair;
        for (int i = 0; i < size; i++) {
            ids[i] = mFields.keyAt(i);
            pair = mFields.valueAt(i);
            regexs[i] = pair.first;
            substs[i] = pair.second;
        }
        parcel.writeParcelableArray(ids, flags);
        parcel.writeStringArray(regexs);
        parcel.writeStringArray(substs);
    }

    public static final Parcelable.Creator<CharSequenceTransformation> CREATOR =
            new Parcelable.Creator<CharSequenceTransformation>() {
        @Override
        public CharSequenceTransformation createFromParcel(Parcel parcel) {
            // Always go through the builder to ensure the data ingested by
            // the system obeys the contract of the builder to avoid attacks
            // using specially crafted parcels.
            final CharSequenceTransformation.Builder builder =
                    new CharSequenceTransformation.Builder();
            final AutofillId[] ids = parcel.readParcelableArray(null, AutofillId.class);
            final String[] regexs = parcel.createStringArray();
            final String[] substs = parcel.createStringArray();
            final int size = ids.length;
            for (int i = 0; i < size; i++) {
                builder.addField(ids[i], regexs[i], substs[i]);
            }
            return builder.build();
        }

        @Override
        public CharSequenceTransformation[] newArray(int size) {
            return new CharSequenceTransformation[size];
        }
    };
}
+218 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading