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

Commit 41797aa7 authored by Feng Cao's avatar Feng Cao
Browse files

Pass focused field's ViewNode information in the augmented autofill request

* Only regular view's viewnode info is produced. Virtual view is not
  support yet, for efficiency reasons.

Test: manual
Test: atest android.autofillservice.cts.inline
Test: atest android.autofillservice.cts.augmented
Bug: 141703532
Change-Id: Ib9aa75ebf8504d674513bd0e6528460ba9db2c34
parent 1a4243b4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -9211,6 +9211,7 @@ package android.service.autofill.augmented {
    method @NonNull public android.content.ComponentName getActivityComponent();
    method @NonNull public android.view.autofill.AutofillId getFocusedId();
    method @NonNull public android.view.autofill.AutofillValue getFocusedValue();
    method @Nullable public android.app.assist.AssistStructure.ViewNode getFocusedViewNode();
    method @Nullable public android.view.inputmethod.InlineSuggestionsRequest getInlineSuggestionsRequest();
    method @Nullable public android.service.autofill.augmented.PresentationParams getPresentationParams();
    method public int getTaskId();
+2 −0
Original line number Diff line number Diff line
@@ -1702,6 +1702,7 @@ package android.service.autofill.augmented {
    method @NonNull public android.content.ComponentName getActivityComponent();
    method @NonNull public android.view.autofill.AutofillId getFocusedId();
    method @NonNull public android.view.autofill.AutofillValue getFocusedValue();
    method @Nullable public android.app.assist.AssistStructure.ViewNode getFocusedViewNode();
    method @Nullable public android.view.inputmethod.InlineSuggestionsRequest getInlineSuggestionsRequest();
    method @Nullable public android.service.autofill.augmented.PresentationParams getPresentationParams();
    method public int getTaskId();
@@ -2187,6 +2188,7 @@ package android.view.autofill {
    ctor public AutofillId(int, int);
    ctor public AutofillId(@NonNull android.view.autofill.AutofillId, long, int);
    method public boolean equalsIgnoreSession(@Nullable android.view.autofill.AutofillId);
    method public boolean isNonVirtual();
    method @NonNull public static android.view.autofill.AutofillId withoutSession(@NonNull android.view.autofill.AutofillId);
  }

+5 −0
Original line number Diff line number Diff line
@@ -17,3 +17,8 @@
package android.app.assist;

parcelable AssistStructure;

/**
 * {@hide}
 */
parcelable AssistStructure.ViewNodeParcelable;
+142 −31
Original line number Diff line number Diff line
@@ -271,7 +271,8 @@ public class AssistStructure implements Parcelable {
                    + ", views=" + mNumWrittenViews
                    + ", level=" + (mCurViewStackPos+levelAdj));
            out.writeInt(VALIDATE_VIEW_TOKEN);
            int flags = child.writeSelfToParcel(out, pwriter, mSanitizeOnWrite, mTmpMatrix);
            int flags = child.writeSelfToParcel(out, pwriter, mSanitizeOnWrite,
                    mTmpMatrix, /*willWriteChildren=*/true);
            mNumWrittenViews++;
            // If the child has children, push it on the stack to write them next.
            if ((flags&ViewNode.FLAGS_HAS_CHILDREN) != 0) {
@@ -724,11 +725,51 @@ public class AssistStructure implements Parcelable {
        public ViewNode() {
        }

        ViewNode(@NonNull Parcel in) {
            initializeFromParcelWithoutChildren(in, /*preader=*/null, /*tmpMatrix=*/null);
        }

        ViewNode(ParcelTransferReader reader, int nestingLevel) {
            final Parcel in = reader.readParcel(VALIDATE_VIEW_TOKEN, nestingLevel);
            reader.mNumReadViews++;
            final PooledStringReader preader = reader.mStringReader;
            mClassName = preader.readString();
            initializeFromParcelWithoutChildren(in, Objects.requireNonNull(reader.mStringReader),
                    Objects.requireNonNull(reader.mTmpMatrix));
            if ((mFlags & FLAGS_HAS_CHILDREN) != 0) {
                final int numChildren = in.readInt();
                if (DEBUG_PARCEL_TREE || DEBUG_PARCEL_CHILDREN) {
                    Log.d(TAG,
                            "Preparing to read " + numChildren
                                    + " children: @ #" + reader.mNumReadViews
                                    + ", level " + nestingLevel);
                }
                mChildren = new ViewNode[numChildren];
                for (int i = 0; i < numChildren; i++) {
                    mChildren[i] = new ViewNode(reader, nestingLevel + 1);
                }
            }
        }

        private static void writeString(@NonNull Parcel out, @Nullable PooledStringWriter pwriter,
                @Nullable String str) {
            if (pwriter != null) {
                pwriter.writeString(str);
            } else {
                out.writeString(str);
            }
        }

        @Nullable
        private static String readString(@NonNull Parcel in, @Nullable PooledStringReader preader) {
            if (preader != null) {
                return preader.readString();
            }
            return in.readString();
        }

        // This does not read the child nodes.
        void initializeFromParcelWithoutChildren(Parcel in, @Nullable PooledStringReader preader,
                @Nullable float[] tmpMatrix) {
            mClassName = readString(in, preader);
            mFlags = in.readInt();
            final int flags = mFlags;
            mAutofillFlags = in.readInt();
@@ -736,10 +777,10 @@ public class AssistStructure implements Parcelable {
            if ((flags&FLAGS_HAS_ID) != 0) {
                mId = in.readInt();
                if (mId != View.NO_ID) {
                    mIdEntry = preader.readString();
                    mIdEntry = readString(in, preader);
                    if (mIdEntry != null) {
                        mIdType = preader.readString();
                        mIdPackage = preader.readString();
                        mIdType = readString(in, preader);
                        mIdPackage = readString(in, preader);
                    }
                }
            }
@@ -784,10 +825,10 @@ public class AssistStructure implements Parcelable {
                    mMaxLength = in.readInt();
                }
                if ((autofillFlags & AUTOFILL_FLAGS_HAS_TEXT_ID_ENTRY) != 0) {
                    mTextIdEntry = preader.readString();
                    mTextIdEntry = readString(in, preader);
                }
                if ((autofillFlags & AUTOFILL_FLAGS_HAS_HINT_ID_ENTRY) != 0) {
                    mHintIdEntry = preader.readString();
                    mHintIdEntry = readString(in, preader);
                }
            }
            if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
@@ -809,8 +850,11 @@ public class AssistStructure implements Parcelable {
            }
            if ((flags&FLAGS_HAS_MATRIX) != 0) {
                mMatrix = new Matrix();
                in.readFloatArray(reader.mTmpMatrix);
                mMatrix.setValues(reader.mTmpMatrix);
                if (tmpMatrix == null) {
                    tmpMatrix = new float[9];
                }
                in.readFloatArray(tmpMatrix);
                mMatrix.setValues(tmpMatrix);
            }
            if ((flags&FLAGS_HAS_ELEVATION) != 0) {
                mElevation = in.readFloat();
@@ -839,21 +883,16 @@ public class AssistStructure implements Parcelable {
            if ((flags&FLAGS_HAS_EXTRAS) != 0) {
                mExtras = in.readBundle();
            }
            if ((flags&FLAGS_HAS_CHILDREN) != 0) {
                final int NCHILDREN = in.readInt();
                if (DEBUG_PARCEL_TREE || DEBUG_PARCEL_CHILDREN) Log.d(TAG,
                        "Preparing to read " + NCHILDREN
                                + " children: @ #" + reader.mNumReadViews
                                + ", level " + nestingLevel);
                mChildren = new ViewNode[NCHILDREN];
                for (int i=0; i<NCHILDREN; i++) {
                    mChildren[i] = new ViewNode(reader, nestingLevel + 1);
                }
            }
        }

        int writeSelfToParcel(Parcel out, PooledStringWriter pwriter, boolean sanitizeOnWrite,
                float[] tmpMatrix) {
        /**
         * This does not write the child nodes.
         *
         * @param willWriteChildren whether child nodes will be written to the parcel or not after
         *                          calling this method.
         */
        int writeSelfToParcel(@NonNull Parcel out, @Nullable PooledStringWriter pwriter,
                boolean sanitizeOnWrite, @Nullable float[] tmpMatrix, boolean willWriteChildren) {
            // Guard used to skip non-sanitized data when writing for autofill.
            boolean writeSensitive = true;

@@ -903,7 +942,7 @@ public class AssistStructure implements Parcelable {
            if (mExtras != null) {
                flags |= FLAGS_HAS_EXTRAS;
            }
            if (mChildren != null) {
            if (mChildren != null && willWriteChildren) {
                flags |= FLAGS_HAS_CHILDREN;
            }
            if (mAutofillId != null) {
@@ -946,7 +985,7 @@ public class AssistStructure implements Parcelable {
                autofillFlags |= AUTOFILL_FLAGS_HAS_HINT_ID_ENTRY;
            }

            pwriter.writeString(mClassName);
            writeString(out, pwriter, mClassName);

            int writtenFlags = flags;
            if (autofillFlags != 0 && (mSanitized || !sanitizeOnWrite)) {
@@ -966,10 +1005,10 @@ public class AssistStructure implements Parcelable {
            if ((flags&FLAGS_HAS_ID) != 0) {
                out.writeInt(mId);
                if (mId != View.NO_ID) {
                    pwriter.writeString(mIdEntry);
                    writeString(out, pwriter, mIdEntry);
                    if (mIdEntry != null) {
                        pwriter.writeString(mIdType);
                        pwriter.writeString(mIdPackage);
                        writeString(out, pwriter, mIdType);
                        writeString(out, pwriter, mIdPackage);
                    }
                }
            }
@@ -1020,10 +1059,10 @@ public class AssistStructure implements Parcelable {
                    out.writeInt(mMaxLength);
                }
                if ((autofillFlags & AUTOFILL_FLAGS_HAS_TEXT_ID_ENTRY) != 0) {
                    pwriter.writeString(mTextIdEntry);
                    writeString(out, pwriter, mTextIdEntry);
                }
                if ((autofillFlags & AUTOFILL_FLAGS_HAS_HINT_ID_ENTRY) != 0) {
                    pwriter.writeString(mHintIdEntry);
                    writeString(out, pwriter, mHintIdEntry);
                }
            }
            if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
@@ -1040,6 +1079,9 @@ public class AssistStructure implements Parcelable {
                out.writeInt(mScrollY);
            }
            if ((flags&FLAGS_HAS_MATRIX) != 0) {
                if (tmpMatrix == null) {
                    tmpMatrix = new float[9];
                }
                mMatrix.getValues(tmpMatrix);
                out.writeFloatArray(tmpMatrix);
            }
@@ -1694,6 +1736,57 @@ public class AssistStructure implements Parcelable {
        }
    }

    /**
     * A parcelable wrapper class around {@link ViewNode}.
     *
     * <p>This class, when parceled and unparceled, does not carry the child nodes.
     *
     * @hide
     */
    public static final class ViewNodeParcelable implements Parcelable {

        @NonNull
        private final ViewNode mViewNode;

        public ViewNodeParcelable(@NonNull ViewNode viewNode) {
            mViewNode = viewNode;
        }

        public ViewNodeParcelable(@NonNull Parcel in) {
            mViewNode = new ViewNode(in);
        }

        @NonNull
        public ViewNode getViewNode() {
            return mViewNode;
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(@NonNull Parcel parcel, int flags) {
            mViewNode.writeSelfToParcel(parcel, /*pwriter=*/null, /*sanitizeOnWrite=*/false,
                    /*tmpMatrix*/null, /*willWriteChildren=*/ false);
        }

        @NonNull
        public static final Parcelable.Creator<ViewNodeParcelable> CREATOR =
                new Parcelable.Creator<ViewNodeParcelable>() {
                    @Override
                    public ViewNodeParcelable createFromParcel(@NonNull Parcel in) {
                        return new ViewNodeParcelable(in);
                    }

                    @Override
                    public ViewNodeParcelable[] newArray(int size) {
                        return new ViewNodeParcelable[size];
                    }
                };
    }

    /**
     * POJO used to override some autofill-related values when the node is parcelized.
     *
@@ -1704,17 +1797,35 @@ public class AssistStructure implements Parcelable {
        public AutofillValue value;
    }

    static class ViewNodeBuilder extends ViewStructure {
    /**
     * @hide
     */
    public static class ViewNodeBuilder extends ViewStructure {
        final AssistStructure mAssist;
        final ViewNode mNode;
        final boolean mAsync;

        /**
         * Used to instantiate a builder for a stand-alone {@link ViewNode} which is not associated
         * to a properly created {@link AssistStructure}.
         */
        public ViewNodeBuilder() {
            mAssist = new AssistStructure();
            mNode = new ViewNode();
            mAsync = false;
        }

        ViewNodeBuilder(AssistStructure assist, ViewNode node, boolean async) {
            mAssist = assist;
            mNode = node;
            mAsync = async;
        }

        @NonNull
        public ViewNode getViewNode() {
            return mNode;
        }

        @Override
        public void setId(int id, String packageName, String typeName, String entryName) {
            mNode.mId = id;
+24 −0
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.Service;
import android.app.assist.AssistStructure.ViewNode;
import android.app.assist.AssistStructure.ViewNodeParcelable;
import android.content.ComponentName;
import android.content.Intent;
import android.graphics.Rect;
@@ -415,6 +417,8 @@ public abstract class AugmentedAutofillService extends Service {
        @GuardedBy("mLock")
        private AutofillValue mFocusedValue;
        @GuardedBy("mLock")
        private ViewNode mFocusedViewNode;
        @GuardedBy("mLock")
        private IFillCallback mCallback;

        /**
@@ -532,6 +536,7 @@ public abstract class AugmentedAutofillService extends Service {
            synchronized (mLock) {
                mFocusedId = focusedId;
                mFocusedValue = focusedValue;
                mFocusedViewNode = null;
                if (mCallback != null) {
                    try {
                        if (!mCallback.isCompleted()) {
@@ -570,6 +575,25 @@ public abstract class AugmentedAutofillService extends Service {
            }
        }

        @Nullable
        public ViewNode getFocusedViewNode() {
            synchronized (mLock) {
                if (mFocusedViewNode == null) {
                    try {
                        final ViewNodeParcelable viewNodeParcelable = mClient.getViewNodeParcelable(
                                mFocusedId);
                        if (viewNodeParcelable != null) {
                            mFocusedViewNode = viewNodeParcelable.getViewNode();
                        }
                    } catch (RemoteException e) {
                        Log.e(TAG, "Error getting the ViewNode of the focused view: " + e);
                        return null;
                    }
                }
                return mFocusedViewNode;
            }
        }

        void logEvent(@ReportEvent int event) {
            if (sVerbose) Log.v(TAG, "returnAndLogResult(): " + event);
            long duration = -1;
Loading