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

Commit b482a249 authored by TYM Tsai's avatar TYM Tsai Committed by Ahaan Ugale
Browse files

Notify Autofill while activity started

After activity started, if there is any field that is autofillable,
notify autofill to do a fill request to get ids that require a
special prompt UI.

Bug: 210926084
Test: Manual
Change-Id: Ia1058de63affc98065eeeb4808d4c3f8bae22d03
parent 523f1f5f
Loading
Loading
Loading
Loading
+20 −9
Original line number Diff line number Diff line
@@ -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() {}

+4 −0
Original line number Diff line number Diff line
@@ -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();
                }
            }
        }
+15 −0
Original line number Diff line number Diff line
@@ -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);
        }
    }

    /**
+83 −0
Original line number Diff line number Diff line
@@ -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;
        }
@@ -3031,6 +3095,25 @@ public final class AutofillManager {
        client.autofillClientRunOnUiThread(runnable);
    }

    /**
     * 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.
     */