Add Autofill PCC Detection APIs for Autofill Providers

1. List of types to send back - FillRequest list
2. Flags in SaveInfo to allow types without ids
3. Datasets now also contain optional types

Also adds framework flags to turn on this feature

Fix: 261106877
Test: ag/21089916
Change-Id: Ife466d257a024ad4eb862b2a796801f00a2d7800
diff --git a/core/api/current.txt b/core/api/current.txt
index 6166f62..66d9bfc 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -39475,6 +39475,7 @@
     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 @@
     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);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 6a4584b..e0d50f0 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2524,6 +2524,7 @@
 
   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();
@@ -3273,6 +3274,7 @@
     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";
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index e9f099a..0fa5e3e 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -120,6 +120,8 @@
     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 @@
         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 @@
         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;
@@ -922,6 +933,55 @@
         }
 
         /**
+         * 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 @@
             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 @@
                 mFieldInlinePresentations = new ArrayList<>();
                 mFieldInlineTooltipPresentations = new ArrayList<>();
                 mFieldFilters = new ArrayList<>();
+                mAutofillDatatypes = null;
             }
             mFieldIds.add(id);
             mFieldValues.add(value);
@@ -1007,9 +1094,14 @@
         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 @@
         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 @@
                     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,19 +1209,37 @@
                 builder.setContent(ids.get(0), fieldContent);
             }
             final int inlinePresentationsSize = inlinePresentations.size();
-            for (int i = 0; i < ids.size(); i++) {
-                final AutofillId id = ids.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(id, value, fieldPresentation,
-                        fieldInlinePresentation, fieldInlineTooltipPresentation, filter,
-                        fieldDialogPresentation);
+
+            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);
+                    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(id, value, fieldPresentation,
+                            fieldInlinePresentation, fieldInlineTooltipPresentation, filter,
+                            fieldDialogPresentation);
+                }
             }
             builder.setAuthentication(authentication);
             builder.setId(datasetId);
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index eb5e893..4a848dd 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -141,6 +141,19 @@
     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 @@
 
     private void onConstructed() {
         Preconditions.checkCollectionElementsNotNull(mFillContexts, "contexts");
+        Preconditions.checkCollectionElementsNotNull(mHints, "hints");
     }
 
 
@@ -269,6 +283,11 @@
      *   <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 FillRequest(
             int id,
             @NonNull List<FillContext> fillContexts,
+            @NonNull List<String> hints,
             @Nullable Bundle clientState,
             @RequestFlags int flags,
             @Nullable InlineSuggestionsRequest inlineSuggestionsRequest,
@@ -320,6 +340,9 @@
         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;
 
@@ -360,6 +383,17 @@
     }
 
     /**
+     * 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 @@
         return "FillRequest { " +
                 "id = " + mId + ", " +
                 "fillContexts = " + mFillContexts + ", " +
+                "hints = " + mHints + ", " +
                 "clientState = " + mClientState + ", " +
                 "flags = " + requestFlagsToString(mFlags) + ", " +
                 "inlineSuggestionsRequest = " + mInlineSuggestionsRequest + ", " +
@@ -447,12 +482,13 @@
         // 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 @@
         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 @@
     };
 
     @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() {}
 
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 5fe1d4f..828e466 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -308,7 +308,7 @@
      * 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 @@
         /**
          * 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);
         }
diff --git a/core/java/android/view/autofill/AutofillFeatureFlags.java b/core/java/android/view/autofill/AutofillFeatureFlags.java
index e7c610b..f3a8e85 100644
--- a/core/java/android/view/autofill/AutofillFeatureFlags.java
+++ b/core/java/android/view/autofill/AutofillFeatureFlags.java
@@ -82,6 +82,12 @@
             "autofill_dialog_enabled";
 
     /**
+     * Indicates that PCC Autofill detection feature is enabled or not.
+     */
+    public static final String DEVICE_CONFIG_AUTOFILL_PCC_FEATURE_PROVIDER_HINTS =
+            "pcc_classification_hints";
+
+    /**
      * Sets the autofill hints allowed list for the fields that can trigger the fill dialog
      * feature at Activity starting.
      *
@@ -190,9 +196,11 @@
             "autofill_inline_tooltip_first_show_delay";
 
     private static final String DIALOG_HINTS_DELIMITER = ":";
+    private static final String PCC_HINTS_DELIMITER = ",";
 
     private static final boolean DEFAULT_HAS_FILL_DIALOG_UI_FEATURE = false;
     private static final String DEFAULT_FILL_DIALOG_ENABLED_HINTS = "";
+    private static final String DEFAULT_PCC_FEATURE_PROVIDER_HINTS = "";
 
 
     // CREDENTIAL MANAGER DEFAULTS
@@ -225,6 +233,25 @@
     }
 
     /**
+     * The list of datatypes that is supported by framework
+     * detection.
+     *
+     * @hide
+     */
+    public static String[] getTypeHintsForProvider() {
+        final String typeHints = DeviceConfig.getString(
+                DeviceConfig.NAMESPACE_AUTOFILL,
+                DEVICE_CONFIG_AUTOFILL_PCC_FEATURE_PROVIDER_HINTS,
+                DEFAULT_PCC_FEATURE_PROVIDER_HINTS);
+        if (TextUtils.isEmpty(typeHints)) {
+            return new String[0];
+        }
+
+        return ArrayUtils.filter(typeHints.split(PCC_HINTS_DELIMITER), String[]::new,
+                (str) -> !TextUtils.isEmpty(str));
+    }
+
+    /**
      * Gets fill dialog enabled hints.
      *
      * @hide
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 2b529bf..a23a58d 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -117,6 +117,7 @@
 import android.util.SparseArray;
 import android.util.TimeUtils;
 import android.view.KeyEvent;
+import android.view.autofill.AutofillFeatureFlags;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillManager.AutofillCommitReason;
@@ -146,6 +147,7 @@
 import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Consumer;
 import java.util.function.Function;
@@ -564,6 +566,7 @@
                 if (mPendingInlineSuggestionsRequest.isServiceSupported()) {
                     mPendingFillRequest = new FillRequest(mPendingFillRequest.getId(),
                             mPendingFillRequest.getFillContexts(),
+                            mPendingFillRequest.getHints(),
                             mPendingFillRequest.getClientState(),
                             mPendingFillRequest.getFlags(),
                             mPendingInlineSuggestionsRequest,
@@ -672,8 +675,10 @@
 
                 final ArrayList<FillContext> contexts =
                         mergePreviousSessionLocked(/* forSave= */ false);
+                final List<String> hints = getTypeHintsForProvider();
+
                 mDelayedFillPendingIntent = createPendingIntent(requestId);
-                request = new FillRequest(requestId, contexts, mClientState, flags,
+                request = new FillRequest(requestId, contexts, hints, mClientState, flags,
                         /*inlineSuggestionsRequest=*/ null,
                         /*delayedFillIntentSender=*/ mDelayedFillPendingIntent == null
                             ? null
@@ -705,6 +710,19 @@
     }
 
     /**
+     * Get the list of valid autofill hint types from Device flags
+     * Returns empty list if PCC is off or no types available
+    */
+    private List<String> getTypeHintsForProvider() {
+        if (!AutofillFeatureFlags.isAutofillPccClassificationEnabled()) {
+            return Collections.EMPTY_LIST;
+        }
+
+        String[] typeHints = AutofillFeatureFlags.getTypeHintsForProvider();
+        return List.copyOf(Set.of(typeHints));
+    }
+
+    /**
      * Assist Data Receiver for PCC
      */
     private final class PccAssistDataReceiverImpl extends IAssistDataReceiver.Stub {