diff options
| -rw-r--r-- | core/java/android/service/autofill/FillRequest.java | 29 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 4 | ||||
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 15 | ||||
| -rw-r--r-- | core/java/android/view/autofill/AutofillManager.java | 83 |
4 files changed, 122 insertions, 9 deletions
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java index 43bd4102ffb5..f820f0389f0d 100644 --- a/core/java/android/service/autofill/FillRequest.java +++ b/core/java/android/service/autofill/FillRequest.java @@ -98,6 +98,12 @@ public final class FillRequest implements Parcelable { // The flag value 0x20 has been defined in AutofillManager. + /** + * Indicates the request is coming from the activity just started. + * @hide + */ + public static final @RequestFlags int FLAG_ACTIVITY_START = 0x40; + /** @hide */ public static final int INVALID_REQUEST_ID = Integer.MIN_VALUE; @@ -160,13 +166,13 @@ public final class FillRequest implements Parcelable { - // Code below generated by codegen v1.0.15. + // 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/service/autofill/FillRequest.java + // $ codegen $ANDROID_BUILD_TOP/./frameworks/base/core/java/android/service/autofill/FillRequest.java // // To exclude the generated code from IntelliJ auto-formatting enable (one-time): // Settings > Editor > Code Style > Formatter Control @@ -178,7 +184,8 @@ public final class FillRequest implements Parcelable { FLAG_MANUAL_REQUEST, FLAG_COMPATIBILITY_MODE_REQUEST, FLAG_PASSWORD_INPUT_TYPE, - FLAG_VIEW_NOT_FOCUSED + FLAG_VIEW_NOT_FOCUSED, + FLAG_ACTIVITY_START }) @Retention(RetentionPolicy.SOURCE) @DataClass.Generated.Member @@ -202,6 +209,8 @@ public final class FillRequest implements Parcelable { return "FLAG_PASSWORD_INPUT_TYPE"; case FLAG_VIEW_NOT_FOCUSED: return "FLAG_VIEW_NOT_FOCUSED"; + case FLAG_ACTIVITY_START: + return "FLAG_ACTIVITY_START"; default: return Integer.toHexString(value); } } @@ -264,7 +273,8 @@ public final class FillRequest implements Parcelable { FLAG_MANUAL_REQUEST | FLAG_COMPATIBILITY_MODE_REQUEST | FLAG_PASSWORD_INPUT_TYPE - | FLAG_VIEW_NOT_FOCUSED); + | FLAG_VIEW_NOT_FOCUSED + | FLAG_ACTIVITY_START); this.mInlineSuggestionsRequest = inlineSuggestionsRequest; onConstructed(); @@ -384,7 +394,7 @@ public final class FillRequest implements Parcelable { byte flg = in.readByte(); int id = in.readInt(); List<FillContext> fillContexts = new ArrayList<>(); - in.readParcelableList(fillContexts, FillContext.class.getClassLoader(), android.service.autofill.FillContext.class); + in.readParcelableList(fillContexts, FillContext.class.getClassLoader()); Bundle clientState = (flg & 0x4) == 0 ? null : in.readBundle(); int flags = in.readInt(); InlineSuggestionsRequest inlineSuggestionsRequest = (flg & 0x10) == 0 ? null : (InlineSuggestionsRequest) in.readTypedObject(InlineSuggestionsRequest.CREATOR); @@ -401,7 +411,8 @@ public final class FillRequest implements Parcelable { FLAG_MANUAL_REQUEST | FLAG_COMPATIBILITY_MODE_REQUEST | FLAG_PASSWORD_INPUT_TYPE - | FLAG_VIEW_NOT_FOCUSED); + | FLAG_VIEW_NOT_FOCUSED + | FLAG_ACTIVITY_START); this.mInlineSuggestionsRequest = inlineSuggestionsRequest; onConstructed(); @@ -422,10 +433,10 @@ public final class FillRequest implements Parcelable { }; @DataClass.Generated( - time = 1589280816805L, - codegenVersion = "1.0.15", + time = 1643052544776L, + 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 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 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_ACTIVITY_START\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 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/view/View.java b/core/java/android/view/View.java index 75592730067a..4ff7e2297ea0 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -8178,9 +8178,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // to User. Ideally View should handle the event when isVisibleToUser() // becomes true where it should issue notifyViewEntered(). afm.notifyViewEntered(this); + } else { + afm.enableFillRequestActivityStarted(); } } else if (!enter && !isFocused()) { afm.notifyViewExited(this); + } else if (enter) { + afm.enableFillRequestActivityStarted(); } } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 1496a4a7c6b3..b1b1d0ca0daf 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -563,6 +563,8 @@ public final class ViewRootImpl implements ViewParent, @Nullable int mContentCaptureEnabled = CONTENT_CAPTURE_ENABLED_NOT_CHECKED; boolean mPerformContentCapture; + boolean mPerformAutoFill; + boolean mReportNextDraw; /** @@ -841,6 +843,7 @@ public final class ViewRootImpl implements ViewParent, mPreviousTransparentRegion = new Region(); mFirst = true; // true for the first time the view is added mPerformContentCapture = true; // also true for the first time the view is added + mPerformAutoFill = true; mAdded = false; mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this, context); @@ -4352,6 +4355,18 @@ public final class ViewRootImpl implements ViewParent, if (mPerformContentCapture) { performContentCaptureInitialReport(); } + + if (mPerformAutoFill) { + notifyEnterForAutoFillIfNeeded(); + } + } + + private void notifyEnterForAutoFillIfNeeded() { + mPerformAutoFill = false; + final AutofillManager afm = getAutofillManager(); + if (afm != null) { + afm.notifyViewEnteredForActivityStarted(mView); + } } /** diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index bb13c1e78964..ac984dacdef7 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -16,6 +16,7 @@ package android.view.autofill; +import static android.service.autofill.FillRequest.FLAG_ACTIVITY_START; import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST; import static android.service.autofill.FillRequest.FLAG_PASSWORD_INPUT_TYPE; import static android.service.autofill.FillRequest.FLAG_VIEW_NOT_FOCUSED; @@ -538,6 +539,8 @@ public final class AutofillManager { */ public static final int NO_SESSION = Integer.MAX_VALUE; + private static final boolean HAS_FILL_DIALOG_UI_FEATURE = false; + private final IAutoFillManager mService; private final Object mLock = new Object(); @@ -629,6 +632,29 @@ public final class AutofillManager { @GuardedBy("mLock") @Nullable private Executor mRequestCallbackExecutor; + /** + * Indicates whether there are any fields that need to do a fill request + * after the activity starts. + * + * Note: This field will be set to true multiple times if there are many + * autofillable views. So needs to check mIsFillRequested at the same time to + * avoid re-trigger autofill. + */ + private boolean mRequireAutofill; + + /** + * Indicates whether there is already a field to do a fill request after + * the activity started. + * + * Autofill will automatically trigger a fill request after activity + * start if there is any field is autofillable. But if there is a field that + * triggered autofill, it is unnecessary to trigger again through + * AutofillManager#notifyViewEnteredForActivityStarted. + */ + private boolean mIsFillRequested; + + @Nullable private List<AutofillId> mFillDialogTriggerIds; + /** @hide */ public interface AutofillClient { /** @@ -766,6 +792,8 @@ public final class AutofillManager { mContext = Objects.requireNonNull(context, "context cannot be null"); mService = service; mOptions = context.getAutofillOptions(); + mIsFillRequested = false; + mRequireAutofill = false; if (mOptions != null) { sDebug = (mOptions.loggingLevel & FLAG_ADD_CLIENT_DEBUG) != 0; @@ -1042,6 +1070,39 @@ public final class AutofillManager { notifyViewEntered(view, 0); } + /** + * The view is autofillable, marked to perform a fill request after layout if + * the field does not trigger a fill request. + * + * @hide + */ + public void enableFillRequestActivityStarted() { + mRequireAutofill = true; + } + + private boolean hasFillDialogUiFeature() { + return HAS_FILL_DIALOG_UI_FEATURE; + } + + /** + * Notify autofill to do a fill request while the activity started. + * + * @hide + */ + public void notifyViewEnteredForActivityStarted(@NonNull View view) { + if (!hasAutofillFeature() || !hasFillDialogUiFeature()) { + return; + } + + if (!mRequireAutofill || mIsFillRequested) { + return; + } + + int flags = FLAG_ACTIVITY_START; + flags |= FLAG_VIEW_NOT_FOCUSED; + notifyViewEntered(view, flags); + } + @GuardedBy("mLock") private boolean shouldIgnoreViewEnteredLocked(@NonNull AutofillId id, int flags) { if (isDisabledByServiceLocked()) { @@ -1082,6 +1143,7 @@ public final class AutofillManager { } AutofillCallback callback; synchronized (mLock) { + mIsFillRequested = true; callback = notifyViewEnteredLocked(view, flags); } @@ -2026,6 +2088,8 @@ public final class AutofillManager { mFillableIds = null; mSaveTriggerId = null; mIdShownFillUi = null; + mIsFillRequested = false; + mRequireAutofill = false; if (resetEnteredIds) { mEnteredIds = null; } @@ -3032,6 +3096,25 @@ public final class AutofillManager { } /** + * Checks the id of autofill whether supported the fill dialog. + * + * @hide + */ + public boolean isShowFillDialog(AutofillId id) { + if (!hasFillDialogUiFeature() || mFillDialogTriggerIds == null) { + return false; + } + final int size = mFillDialogTriggerIds.size(); + for (int i = 0; i < size; i++) { + AutofillId fillId = mFillDialogTriggerIds.get(i); + if (fillId.equalsIgnoreSession(id)) { + return true; + } + } + return false; + } + + /** * Implementation of the accessibility based compatibility. */ private final class CompatibilityBridge implements AccessibilityManager.AccessibilityPolicy { |