diff --git a/core/api/current.txt b/core/api/current.txt index 0ad7d80ea508d..16d56077e7e84 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -54194,6 +54194,7 @@ package android.view.autofill { 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); 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); @@ -54240,6 +54241,16 @@ package android.view.autofill { field @NonNull public static final android.os.Parcelable.Creator 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 58e7a70b155c1..756952319b355 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -1087,6 +1087,42 @@ public final class AutofillManager { notifyViewEntered(view, 0); } + /** + * 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 + * fill dialog. + * + * @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 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 @@ -1098,9 +1134,6 @@ public final class AutofillManager { if (sDebug) { Log.d(TAG, "notifyViewEnteredForFillDialog:" + v.getAutofillId()); } - if (!hasAutofillFeature()) { - return; - } if (AutofillFeatureFlags.isFillDialogDisabledForCredentialManager() && v.isCredential()) { if (sDebug) { @@ -1109,6 +1142,13 @@ public final class AutofillManager { } return; } + notifyViewReadyInner(v.getAutofillId(), v.getAutofillHints()); + } + + private void notifyViewReadyInner(AutofillId id, String[] autofillHints) { + if (!hasAutofillFeature()) { + return; + } synchronized (mLock) { if (mTrackedViews != null) { @@ -1116,7 +1156,7 @@ public final class AutofillManager { // 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); } } @@ -1126,9 +1166,9 @@ public final class AutofillManager { } 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 0000000000000..4bec5a4a0960f --- /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 + +}