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

Commit e349a753 authored by Tim Yu's avatar Tim Yu Committed by Android (Google) Code Review
Browse files

Merge "Add Autofill PCC Detection APIs for Autofill Providers"

parents a93d9526 b3cc8890
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -39475,6 +39475,7 @@ package android.service.autofill {
    method @NonNull public android.service.autofill.Dataset build();
    method @NonNull public android.service.autofill.Dataset.Builder setAuthentication(@Nullable android.content.IntentSender);
    method @NonNull public android.service.autofill.Dataset.Builder setField(@NonNull android.view.autofill.AutofillId, @Nullable android.service.autofill.Field);
    method @NonNull public android.service.autofill.Dataset.Builder setField(@NonNull String, @NonNull android.service.autofill.Field);
    method @NonNull public android.service.autofill.Dataset.Builder setId(@Nullable String);
    method @Deprecated @NonNull public android.service.autofill.Dataset.Builder setInlinePresentation(@NonNull android.service.autofill.InlinePresentation);
    method @Deprecated @NonNull public android.service.autofill.Dataset.Builder setInlinePresentation(@NonNull android.service.autofill.InlinePresentation, @NonNull android.service.autofill.InlinePresentation);
@@ -39583,6 +39584,7 @@ package android.service.autofill {
    method @Nullable public android.content.IntentSender getDelayedFillIntentSender();
    method @NonNull public java.util.List<android.service.autofill.FillContext> getFillContexts();
    method public int getFlags();
    method @NonNull public java.util.List<java.lang.String> getHints();
    method public int getId();
    method @Nullable public android.view.inputmethod.InlineSuggestionsRequest getInlineSuggestionsRequest();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
+2 −0
Original line number Diff line number Diff line
@@ -2529,6 +2529,7 @@ package android.service.autofill {

  public final class Dataset implements android.os.Parcelable {
    method @Nullable public android.content.IntentSender getAuthentication();
    method @Nullable public java.util.ArrayList<java.lang.String> getAutofillDatatypes();
    method @Nullable public android.content.ClipData getFieldContent();
    method @Nullable public java.util.ArrayList<android.view.autofill.AutofillId> getFieldIds();
    method @Nullable public java.util.ArrayList<android.view.autofill.AutofillValue> getFieldValues();
@@ -3278,6 +3279,7 @@ package android.view.autofill {
    field public static final String DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_IGNORE_VIEWS = "autofill_credential_manager_ignore_views";
    field public static final String DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED = "autofill_dialog_enabled";
    field public static final String DEVICE_CONFIG_AUTOFILL_PCC_CLASSIFICATION_ENABLED = "pcc_classification_enabled";
    field public static final String DEVICE_CONFIG_AUTOFILL_PCC_FEATURE_PROVIDER_HINTS = "pcc_classification_hints";
    field public static final String DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES = "smart_suggestion_supported_modes";
    field public static final String DEVICE_CONFIG_NON_AUTOFILLABLE_IME_ACTION_IDS = "non_autofillable_ime_action_ids";
    field public static final String DEVICE_CONFIG_PACKAGE_DENYLIST_FOR_UNIMPORTANT_VIEW = "package_deny_list_for_unimportant_view";
+127 −14
Original line number Diff line number Diff line
@@ -120,6 +120,8 @@ public final class Dataset implements Parcelable {
    private final ArrayList<InlinePresentation> mFieldInlinePresentations;
    private final ArrayList<InlinePresentation> mFieldInlineTooltipPresentations;
    private final ArrayList<DatasetFieldFilter> mFieldFilters;
    private final ArrayList<String> mAutofillDatatypes;

    @Nullable private final ClipData mFieldContent;
    private final RemoteViews mPresentation;
    private final RemoteViews mDialogPresentation;
@@ -143,6 +145,14 @@ public final class Dataset implements Parcelable {
        mInlineTooltipPresentation = builder.mInlineTooltipPresentation;
        mAuthentication = builder.mAuthentication;
        mId = builder.mId;
        mAutofillDatatypes = builder.mAutofillDatatypes;
    }

    /** @hide */
    @TestApi
    @SuppressLint({"ConcreteCollection", "NullableCollection"})
    public @Nullable ArrayList<String> getAutofillDatatypes() {
        return mAutofillDatatypes;
    }

    /** @hide */
@@ -293,6 +303,7 @@ public final class Dataset implements Parcelable {
        private ArrayList<InlinePresentation> mFieldInlinePresentations;
        private ArrayList<InlinePresentation> mFieldInlineTooltipPresentations;
        private ArrayList<DatasetFieldFilter> mFieldFilters;
        private ArrayList<String> mAutofillDatatypes;
        @Nullable private ClipData mFieldContent;
        private RemoteViews mPresentation;
        private RemoteViews mDialogPresentation;
@@ -921,6 +932,55 @@ public final class Dataset implements Parcelable {
            return this;
        }

        /**
         * Adds a field to this Dataset with a specific type and no
         * AutofillId. This is used to send back Field information
         * when Autofilling with platform detections is on.
         * Platform detections are on when receiving a populated list from
         * FillRequest#getHints().
         *
         * Populate every field/type known for this user for this app.
         *
         * For example, if getHints() contains "username" and "password",
         * a new Dataset should be created that calls this method twice,
         * one for the username, then another for the password (assuming
         * the only one credential pair is found for the user). If a user
         * has two credential pairs, then two Datasets should be created,
         * and so on.
         *
         * Using this will remove any data populated with
         * setField(@NonNull AutofillId id, @Nullable Field field).
         *
         * @param hint An autofill hint returned from {@link
         *         FillRequest#getHints()}.
         *
         * @param field the fill information about the field.
         *
         * @throws IllegalStateException if {@link #build()} was already called
         * or this builder also contains AutofillId information
         *
         * @return this builder.
         */
        public @NonNull Dataset.Builder setField(
                @NonNull String hint, @NonNull Field field) {
            throwIfDestroyed();

            final DatasetFieldFilter filter = field.getDatasetFieldFilter();
            final Presentations presentations = field.getPresentations();
            if (presentations == null) {
                setLifeTheUniverseAndEverything(hint, field.getValue(), null, null, null,
                        filter, null);
            } else {
                setLifeTheUniverseAndEverything(hint, field.getValue(),
                        presentations.getMenuPresentation(),
                        presentations.getInlinePresentation(),
                        presentations.getInlineTooltipPresentation(), filter,
                        presentations.getDialogPresentation());
            }

            return this;
        }

        /**
         * Sets the value of a field with an <a href="#Filtering">explicit filter</a>, and using an
         * {@link InlinePresentation} to visualize it as an inline suggestion.
@@ -958,6 +1018,32 @@ public final class Dataset implements Parcelable {
            return this;
        }

        private void setLifeTheUniverseAndEverything(String datatype,
                @Nullable AutofillValue value,
                @Nullable RemoteViews presentation,
                @Nullable InlinePresentation inlinePresentation,
                @Nullable InlinePresentation tooltip,
                @Nullable DatasetFieldFilter filter,
                @Nullable RemoteViews dialogPresentation) {
            if (mAutofillDatatypes == null) {
                mFieldValues = new ArrayList<>();
                mFieldPresentations = new ArrayList<>();
                mFieldDialogPresentations = new ArrayList<>();
                mFieldInlinePresentations = new ArrayList<>();
                mFieldInlineTooltipPresentations = new ArrayList<>();
                mFieldFilters = new ArrayList<>();
                mAutofillDatatypes = new ArrayList<>();
                mFieldIds = null;
            }
            mFieldValues.add(value);
            mFieldPresentations.add(presentation);
            mFieldDialogPresentations.add(dialogPresentation);
            mFieldInlinePresentations.add(inlinePresentation);
            mFieldInlineTooltipPresentations.add(tooltip);
            mFieldFilters.add(filter);
            mAutofillDatatypes.add(datatype);
        }

        private void setLifeTheUniverseAndEverything(@NonNull AutofillId id,
                @Nullable AutofillValue value, @Nullable RemoteViews presentation,
                @Nullable InlinePresentation inlinePresentation,
@@ -984,6 +1070,7 @@ public final class Dataset implements Parcelable {
                mFieldInlinePresentations = new ArrayList<>();
                mFieldInlineTooltipPresentations = new ArrayList<>();
                mFieldFilters = new ArrayList<>();
                mAutofillDatatypes = null;
            }
            mFieldIds.add(id);
            mFieldValues.add(value);
@@ -1007,9 +1094,14 @@ public final class Dataset implements Parcelable {
        public @NonNull Dataset build() {
            throwIfDestroyed();
            mDestroyed = true;
            if (mFieldIds == null) {
            if (mFieldIds == null && mAutofillDatatypes == null) {
                throw new IllegalStateException("at least one value must be set");
            }
            if (mFieldIds != null && mAutofillDatatypes != null) {
                if (mFieldIds.size() > 0 && mAutofillDatatypes.size() > 0) {
                    throw new IllegalStateException("both field and datatype were populated");
                }
            }
            if (mFieldContent != null) {
                if (mFieldIds.size() > 1) {
                    throw new IllegalStateException(
@@ -1051,6 +1143,7 @@ public final class Dataset implements Parcelable {
        parcel.writeTypedList(mFieldInlinePresentations, flags);
        parcel.writeTypedList(mFieldInlineTooltipPresentations, flags);
        parcel.writeTypedList(mFieldFilters, flags);
        parcel.writeStringList(mAutofillDatatypes);
        parcel.writeParcelable(mFieldContent, flags);
        parcel.writeParcelable(mAuthentication, flags);
        parcel.writeString(mId);
@@ -1081,6 +1174,8 @@ public final class Dataset implements Parcelable {
                    parcel.createTypedArrayList(InlinePresentation.CREATOR);
            final ArrayList<DatasetFieldFilter> filters =
                    parcel.createTypedArrayList(DatasetFieldFilter.CREATOR);
            final ArrayList<String> datatypes =
                    parcel.createStringArrayList();
            final ClipData fieldContent = parcel.readParcelable(null,
                    android.content.ClipData.class);
            final IntentSender authentication = parcel.readParcelable(null,
@@ -1114,6 +1209,23 @@ public final class Dataset implements Parcelable {
                builder.setContent(ids.get(0), fieldContent);
            }
            final int inlinePresentationsSize = inlinePresentations.size();

            if (ids.size() == 0 && datatypes.size() > 0) {
                for (int i = 0; i < ids.size(); i++) {
                    final String datatype = datatypes.get(i);
                    final AutofillValue value = values.get(i);
                    final RemoteViews fieldPresentation = presentations.get(i);
                    final RemoteViews fieldDialogPresentation = dialogPresentations.get(i);
                    final InlinePresentation fieldInlinePresentation =
                            i < inlinePresentationsSize ? inlinePresentations.get(i) : null;
                    final InlinePresentation fieldInlineTooltipPresentation =
                            i < inlinePresentationsSize ? inlineTooltipPresentations.get(i) : null;
                    final DatasetFieldFilter filter = filters.get(i);
                    builder.setLifeTheUniverseAndEverything(
                            datatype, value, fieldPresentation, fieldInlinePresentation,
                            fieldInlineTooltipPresentation, filter, fieldDialogPresentation);
                }
            } else {
                for (int i = 0; i < ids.size(); i++) {
                    final AutofillId id = ids.get(i);
                    final AutofillValue value = values.get(i);
@@ -1128,6 +1240,7 @@ public final class Dataset implements Parcelable {
                            fieldInlinePresentation, fieldInlineTooltipPresentation, filter,
                            fieldDialogPresentation);
                }
            }
            builder.setAuthentication(authentication);
            builder.setId(datasetId);
            return builder.build();
+49 −8
Original line number Diff line number Diff line
@@ -140,6 +140,19 @@ public final class FillRequest implements Parcelable {
     */
    private final @NonNull List<FillContext> mFillContexts;

    /**
     * Sends a list of datatypes for the Autofill Provider.
     *
     * If this is populated, Autofill Provider should return data
     * for the autofill hints requested here,
     * even though the Autofill Provider may not have detected these types.
     * The hints would be part of HintConstants:
     * https://developer.android.com/reference/androidx/autofill/HintConstants
     *
     * This is populated if the platform's field detection is enabled.
     */
    private final @NonNull List<String> mHints;

    /**
     * Gets the latest client state bundle set by the service in a
     * {@link FillResponse.Builder#setClientState(Bundle) fill response}.
@@ -196,6 +209,7 @@ public final class FillRequest implements Parcelable {

    private void onConstructed() {
        Preconditions.checkCollectionElementsNotNull(mFillContexts, "contexts");
        Preconditions.checkCollectionElementsNotNull(mHints, "hints");
    }


@@ -269,6 +283,11 @@ public final class FillRequest implements Parcelable {
     *   <p><b>Note:</b> Starting on Android {@link android.os.Build.VERSION_CODES#Q}, it could also
     *   include contexts from requests whose {@link SaveInfo} had the
     *   {@link SaveInfo#FLAG_DELAY_SAVE} flag.
     * @param hints
     *   Autofill Provider should return data for the autofill hints requested here,
     *   even though the Autofill Provider may not have detected these types.
     *   The hints would be part of HintConstants:
     *   https://developer.android.com/reference/androidx/autofill/HintConstants
     * @param clientState
     *   Gets the latest client state bundle set by the service in a
     *   {@link FillResponse.Builder#setClientState(Bundle) fill response}.
@@ -312,6 +331,7 @@ public final class FillRequest implements Parcelable {
    public FillRequest(
            int id,
            @NonNull List<FillContext> fillContexts,
            @NonNull List<String> hints,
            @Nullable Bundle clientState,
            @RequestFlags int flags,
            @Nullable InlineSuggestionsRequest inlineSuggestionsRequest,
@@ -320,6 +340,9 @@ public final class FillRequest implements Parcelable {
        this.mFillContexts = fillContexts;
        com.android.internal.util.AnnotationValidations.validate(
                NonNull.class, null, mFillContexts);
        this.mHints = hints;
        com.android.internal.util.AnnotationValidations.validate(
                NonNull.class, null, mHints);
        this.mClientState = clientState;
        this.mFlags = flags;

@@ -359,6 +382,17 @@ public final class FillRequest implements Parcelable {
        return mFillContexts;
    }

    /**
     * Autofill Provider should return data for the autofill hints requested here,
     * even though the Autofill Provider may not have detected these types.
     * The hints would be part of HintConstants:
     * https://developer.android.com/reference/androidx/autofill/HintConstants
     */
    @DataClass.Generated.Member
    public @NonNull List<String> getHints() {
        return mHints;
    }

    /**
     * Gets the latest client state bundle set by the service in a
     * {@link FillResponse.Builder#setClientState(Bundle) fill response}.
@@ -433,6 +467,7 @@ public final class FillRequest implements Parcelable {
        return "FillRequest { " +
                "id = " + mId + ", " +
                "fillContexts = " + mFillContexts + ", " +
                "hints = " + mHints + ", " +
                "clientState = " + mClientState + ", " +
                "flags = " + requestFlagsToString(mFlags) + ", " +
                "inlineSuggestionsRequest = " + mInlineSuggestionsRequest + ", " +
@@ -447,12 +482,13 @@ public final class FillRequest implements Parcelable {
        // void parcelFieldName(Parcel dest, int flags) { ... }

        byte flg = 0;
        if (mClientState != null) flg |= 0x4;
        if (mInlineSuggestionsRequest != null) flg |= 0x10;
        if (mDelayedFillIntentSender != null) flg |= 0x20;
        if (mClientState != null) flg |= 0x8;
        if (mInlineSuggestionsRequest != null) flg |= 0x20;
        if (mDelayedFillIntentSender != null) flg |= 0x40;
        dest.writeByte(flg);
        dest.writeInt(mId);
        dest.writeParcelableList(mFillContexts, flags);
        dest.writeStringList(mHints);
        if (mClientState != null) dest.writeBundle(mClientState);
        dest.writeInt(mFlags);
        if (mInlineSuggestionsRequest != null) dest.writeTypedObject(mInlineSuggestionsRequest, flags);
@@ -474,15 +510,20 @@ public final class FillRequest implements Parcelable {
        int id = in.readInt();
        List<FillContext> fillContexts = new ArrayList<>();
        in.readParcelableList(fillContexts, FillContext.class.getClassLoader());
        Bundle clientState = (flg & 0x4) == 0 ? null : in.readBundle();
        List<String> hints = new ArrayList<>();
        in.readStringList(hints);
        Bundle clientState = (flg & 0x8) == 0 ? null : in.readBundle();
        int flags = in.readInt();
        InlineSuggestionsRequest inlineSuggestionsRequest = (flg & 0x10) == 0 ? null : (InlineSuggestionsRequest) in.readTypedObject(InlineSuggestionsRequest.CREATOR);
        IntentSender delayedFillIntentSender = (flg & 0x20) == 0 ? null : (IntentSender) in.readTypedObject(IntentSender.CREATOR);
        InlineSuggestionsRequest inlineSuggestionsRequest = (flg & 0x20) == 0 ? null : (InlineSuggestionsRequest) in.readTypedObject(InlineSuggestionsRequest.CREATOR);
        IntentSender delayedFillIntentSender = (flg & 0x40) == 0 ? null : (IntentSender) in.readTypedObject(IntentSender.CREATOR);

        this.mId = id;
        this.mFillContexts = fillContexts;
        com.android.internal.util.AnnotationValidations.validate(
                NonNull.class, null, mFillContexts);
        this.mHints = hints;
        com.android.internal.util.AnnotationValidations.validate(
                NonNull.class, null, mHints);
        this.mClientState = clientState;
        this.mFlags = flags;

@@ -517,10 +558,10 @@ public final class FillRequest implements Parcelable {
    };

    @DataClass.Generated(
            time = 1675460688829L,
            time = 1675711417112L,
            codegenVersion = "1.0.23",
            sourceFile = "frameworks/base/core/java/android/service/autofill/FillRequest.java",
            inputSignatures = "public static final @android.service.autofill.FillRequest.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PASSWORD_INPUT_TYPE\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_VIEW_NOT_FOCUSED\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_SUPPORTS_FILL_DIALOG\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_IME_SHOWING\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_RESET_FILL_DIALOG_STATE\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PCC_DETECTION\npublic static final  int INVALID_REQUEST_ID\nprivate final  int mId\nprivate final @android.annotation.NonNull java.util.List<android.service.autofill.FillContext> mFillContexts\nprivate final @android.annotation.Nullable android.os.Bundle mClientState\nprivate final @android.service.autofill.FillRequest.RequestFlags int mFlags\nprivate final @android.annotation.Nullable android.view.inputmethod.InlineSuggestionsRequest mInlineSuggestionsRequest\nprivate final @android.annotation.Nullable android.content.IntentSender mDelayedFillIntentSender\nprivate  void onConstructed()\nclass FillRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)")
            inputSignatures = "public static final @android.service.autofill.FillRequest.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PASSWORD_INPUT_TYPE\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_VIEW_NOT_FOCUSED\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_SUPPORTS_FILL_DIALOG\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_IME_SHOWING\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_RESET_FILL_DIALOG_STATE\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PCC_DETECTION\npublic static final  int INVALID_REQUEST_ID\nprivate final  int mId\nprivate final @android.annotation.NonNull java.util.List<android.service.autofill.FillContext> mFillContexts\nprivate final @android.annotation.NonNull java.util.List<java.lang.String> mHints\nprivate final @android.annotation.Nullable android.os.Bundle mClientState\nprivate final @android.service.autofill.FillRequest.RequestFlags int mFlags\nprivate final @android.annotation.Nullable android.view.inputmethod.InlineSuggestionsRequest mInlineSuggestionsRequest\nprivate final @android.annotation.Nullable android.content.IntentSender mDelayedFillIntentSender\nprivate  void onConstructed()\nclass FillRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)")
    @Deprecated
    private void __metadata() {}

+4 −8
Original line number Diff line number Diff line
@@ -308,7 +308,7 @@ public final class SaveInfo implements Parcelable {
     * username field, another for password).
     */
    // TODO(b/113281366): improve documentation: add example, document relationship with other
    // flagss, etc...
    // flags, etc...
    public static final int FLAG_DELAY_SAVE = 0x4;

    /** @hide */
@@ -777,17 +777,13 @@ public final class SaveInfo implements Parcelable {
        /**
         * Builds a new {@link SaveInfo} instance.
         *
         * @throws IllegalStateException if no
         * {@link #Builder(int, AutofillId[]) required ids},
         * If no {@link #Builder(int, AutofillId[]) required ids},
         * or {@link #setOptionalIds(AutofillId[]) optional ids}, or {@link #FLAG_DELAY_SAVE}
         * were set
         * were set, Save Dialog will only be triggered if platform detection is enabled, which
         * is indicated when {@link FillRequest.getHints()} is not empty.
         */
        public SaveInfo build() {
            throwIfDestroyed();
            Preconditions.checkState(
                    !ArrayUtils.isEmpty(mRequiredIds) || !ArrayUtils.isEmpty(mOptionalIds)
                            || (mFlags & FLAG_DELAY_SAVE) != 0,
                    "must have at least one required or optional id or FLAG_DELAYED_SAVE");
            mDestroyed = true;
            return new SaveInfo(this);
        }
Loading