Merge "Add API for virtual view is ready to user"
diff --git a/core/api/current.txt b/core/api/current.txt
index 9e4c958..f50d3ca 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -54248,6 +54248,7 @@
     method public void notifyViewExited(@NonNull android.view.View, int);
     method public void notifyViewVisibilityChanged(@NonNull android.view.View, boolean);
     method public void notifyViewVisibilityChanged(@NonNull android.view.View, int, boolean);
+    method public void notifyVirtualViewsReady(@NonNull android.view.View, @NonNull android.util.SparseArray<android.view.autofill.VirtualViewFillInfo>);
     method public void registerCallback(@Nullable android.view.autofill.AutofillManager.AutofillCallback);
     method public void requestAutofill(@NonNull android.view.View);
     method public void requestAutofill(@NonNull android.view.View, int, @NonNull android.graphics.Rect);
@@ -54294,6 +54295,16 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.view.autofill.AutofillValue> CREATOR;
   }
 
+  public final class VirtualViewFillInfo {
+    method @Nullable public String[] getAutofillHints();
+  }
+
+  public static final class VirtualViewFillInfo.Builder {
+    ctor public VirtualViewFillInfo.Builder();
+    method @NonNull public android.view.autofill.VirtualViewFillInfo build();
+    method @NonNull public android.view.autofill.VirtualViewFillInfo.Builder setAutofillHints(@NonNull java.lang.String...);
+  }
+
 }
 
 package android.view.contentcapture {
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 2ad01ed..b5764c5 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -1235,6 +1235,42 @@
     }
 
     /**
+     * Called when the virtual views are ready to the user for autofill.
+     *
+     * This method is used to notify autofill system the views are ready to the user. And then
+     * Autofill can do initialization if needed before the user starts to input. For example, do
+     * a pre-fill request for the
+     * <a href="/reference/android/service/autofill/Dataset.html#FillDialogUI">fill dialog</a>.
+     *
+     * @param view the host view that holds a virtual view hierarchy.
+     * @param infos extra information for the virtual views. The key is virtual id which represents
+     *             the virtual view in the host view.
+     *
+     * @throws IllegalArgumentException if the {@code infos} was empty
+     */
+    public void notifyVirtualViewsReady(
+            @NonNull View view, @NonNull SparseArray<VirtualViewFillInfo> infos) {
+        Objects.requireNonNull(infos);
+        if (infos.size() == 0) {
+            throw new IllegalArgumentException("No VirtualViewInfo found");
+        }
+        if (AutofillFeatureFlags.isFillDialogDisabledForCredentialManager()
+                && view.isCredential()) {
+            if (sDebug) {
+                Log.d(TAG, "Ignoring Fill Dialog request since important for credMan:"
+                        + view.getAutofillId().toString());
+            }
+            return;
+        }
+        for (int i = 0; i < infos.size(); i++) {
+            final VirtualViewFillInfo info = infos.valueAt(i);
+            final int virtualId = infos.indexOfKey(i);
+            notifyViewReadyInner(getAutofillId(view, virtualId),
+                    (info == null) ? null : info.getAutofillHints());
+        }
+    }
+
+    /**
      * The {@link AutofillFeatureFlags#DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED} is {@code true} or
      * the view have the allowed autofill hints, performs a fill request to know there is any field
      * supported fill dialog.
@@ -1245,9 +1281,6 @@
         if (sDebug) {
             Log.d(TAG, "notifyViewEnteredForFillDialog:" + v.getAutofillId());
         }
-        if (!hasAutofillFeature()) {
-            return;
-        }
         if (AutofillFeatureFlags.isFillDialogDisabledForCredentialManager()
                 && v.isCredential()) {
             if (sDebug) {
@@ -1256,6 +1289,13 @@
             }
             return;
         }
+        notifyViewReadyInner(v.getAutofillId(), v.getAutofillHints());
+    }
+
+    private void notifyViewReadyInner(AutofillId id, String[] autofillHints) {
+        if (!hasAutofillFeature()) {
+            return;
+        }
 
         synchronized (mLock) {
             if (mTrackedViews != null) {
@@ -1263,7 +1303,7 @@
                 // different pages but in the same Activity. We need to reset the
                 // mIsFillRequested flag to allow asking for a new FillRequest when
                 // user switches to other page
-                mTrackedViews.checkViewState(v.getAutofillId());
+                mTrackedViews.checkViewState(id);
             }
         }
 
@@ -1273,9 +1313,9 @@
         }
 
         if (mIsFillDialogEnabled
-                || ArrayUtils.containsAny(v.getAutofillHints(), mFillDialogEnabledHints)) {
+                || ArrayUtils.containsAny(autofillHints, mFillDialogEnabledHints)) {
             if (sDebug) {
-                Log.d(TAG, "Trigger fill request at view entered");
+                Log.d(TAG, "Trigger fill request when the view is ready.");
             }
 
             int flags = FLAG_SUPPORTS_FILL_DIALOG;
diff --git a/core/java/android/view/autofill/VirtualViewFillInfo.java b/core/java/android/view/autofill/VirtualViewFillInfo.java
new file mode 100644
index 0000000..4bec5a4
--- /dev/null
+++ b/core/java/android/view/autofill/VirtualViewFillInfo.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2023 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.view.autofill;
+
+
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.view.View;
+
+import com.android.internal.util.DataClass;
+
+
+/**
+ * Information for the virtual view to the autofill framework.
+ */
+@DataClass(genBuilder = true)
+public final class VirtualViewFillInfo {
+
+    /**
+     * Autofill hints of the virtual view.
+     *
+     * @see View#setAutofillHints(String...)
+     */
+    @Nullable
+    @SuppressLint("NullableCollection")
+    private String[] mAutofillHints;
+
+    private static String[] defaultAutofillHints() {
+        return null;
+    }
+
+
+
+    // Code below generated by codegen v1.0.23.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/view/autofill/VirtualViewFillInfo.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    @DataClass.Generated.Member
+    /* package-private */ VirtualViewFillInfo(
+            @Nullable @SuppressLint("NullableCollection") String[] autofillHints) {
+        this.mAutofillHints = autofillHints;
+        com.android.internal.util.AnnotationValidations.validate(
+                SuppressLint.class, null, mAutofillHints,
+                "value", "NullableCollection");
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * Autofill hints of the virtual view.
+     *
+     * @see View#setAutofillHints(String...)
+     */
+    @DataClass.Generated.Member
+    public @Nullable @SuppressLint("NullableCollection") String[] getAutofillHints() {
+        return mAutofillHints;
+    }
+
+    /**
+     * A builder for {@link VirtualViewFillInfo}
+     */
+    @SuppressWarnings("WeakerAccess")
+    @DataClass.Generated.Member
+    public static final class Builder {
+
+        private @Nullable @SuppressLint("NullableCollection") String[] mAutofillHints;
+
+        private long mBuilderFieldsSet = 0L;
+
+        public Builder() {
+        }
+
+        /**
+         * Autofill hints of the virtual view.
+         *
+         * @see View#setAutofillHints(String...)
+         */
+        @DataClass.Generated.Member
+        public @android.annotation.NonNull Builder setAutofillHints(@SuppressLint("NullableCollection") @android.annotation.NonNull String... value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x1;
+            mAutofillHints = value;
+            return this;
+        }
+
+        /** Builds the instance. This builder should not be touched after calling this! */
+        public @android.annotation.NonNull VirtualViewFillInfo build() {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x2; // Mark builder used
+
+            if ((mBuilderFieldsSet & 0x1) == 0) {
+                mAutofillHints = defaultAutofillHints();
+            }
+            VirtualViewFillInfo o = new VirtualViewFillInfo(
+                    mAutofillHints);
+            return o;
+        }
+
+        private void checkNotUsed() {
+            if ((mBuilderFieldsSet & 0x2) != 0) {
+                throw new IllegalStateException(
+                        "This Builder should not be reused. Use a new Builder instance instead");
+            }
+        }
+    }
+
+    @DataClass.Generated(
+            time = 1674023010954L,
+            codegenVersion = "1.0.23",
+            sourceFile = "frameworks/base/core/java/android/view/autofill/VirtualViewFillInfo.java",
+            inputSignatures = "private @android.annotation.Nullable @android.annotation.SuppressLint java.lang.String[] mAutofillHints\nprivate static  java.lang.String[] defaultAutofillHints()\nclass VirtualViewFillInfo extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}