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

Commit 8b2816fa authored by Phil Weaver's avatar Phil Weaver Committed by android-build-merger
Browse files

Merge "Separate a11y and autofill view ids" into oc-dev

am: c91290a6

Change-Id: Ib4566c2f0e32477d5f9eb6510edc140c2b66e0a4
parents 8097485c c91290a6
Loading
Loading
Loading
Loading
+17 −18
Original line number Diff line number Diff line
@@ -719,7 +719,7 @@ public class Activity extends ContextThemeWrapper
    public static final int FINISH_TASK_WITH_ACTIVITY = 2;

    static final String FRAGMENTS_TAG = "android:fragments";
    private static final String LAST_ACCESSIBILITY_ID = "android:lastAccessibilityId";
    private static final String LAST_AUTOFILL_ID = "android:lastAutofillId";

    private static final String AUTOFILL_RESET_NEEDED = "@android:autofillResetNeeded";
    private static final String WINDOW_HIERARCHY_TAG = "android:viewHierarchyState";
@@ -853,8 +853,8 @@ public class Activity extends ContextThemeWrapper

    private boolean mAutoFillResetNeeded;

    /** The last accessibility id that was returned from {@link #getNextAccessibilityId()} */
    private int mLastAccessibilityId = View.LAST_APP_ACCESSIBILITY_ID;
    /** The last autofill id that was returned from {@link #getNextAutofillId()} */
    private int mLastAutofillId = View.LAST_APP_AUTOFILL_ID;

    private AutofillPopupWindow mAutofillPopupWindow;

@@ -999,7 +999,7 @@ public class Activity extends ContextThemeWrapper
        }
        if (savedInstanceState != null) {
            mAutoFillResetNeeded = savedInstanceState.getBoolean(AUTOFILL_RESET_NEEDED, false);
            mLastAccessibilityId = savedInstanceState.getInt(LAST_ACCESSIBILITY_ID, View.NO_ID);
            mLastAutofillId = savedInstanceState.getInt(LAST_AUTOFILL_ID, View.NO_ID);

            if (mAutoFillResetNeeded) {
                getAutofillManager().onCreate(savedInstanceState);
@@ -1348,24 +1348,23 @@ public class Activity extends ContextThemeWrapper
    }

    /**
     * Gets the next accessibility ID.
     * Gets the next autofill ID.
     *
     * <p>All IDs will be bigger than {@link View#LAST_APP_ACCESSIBILITY_ID}. All IDs returned
     * <p>All IDs will be bigger than {@link View#LAST_APP_AUTOFILL_ID}. All IDs returned
     * will be unique.
     *
     * @return A ID that is unique in the activity
     *
     * {@hide}
     */
    @Override
    public int getNextAccessibilityId() {
        if (mLastAccessibilityId == Integer.MAX_VALUE - 1) {
            mLastAccessibilityId = View.LAST_APP_ACCESSIBILITY_ID;
    public int getNextAutofillId() {
        if (mLastAutofillId == Integer.MAX_VALUE - 1) {
            mLastAutofillId = View.LAST_APP_AUTOFILL_ID;
        }

        mLastAccessibilityId++;
        mLastAutofillId++;

        return mLastAccessibilityId;
        return mLastAutofillId;
    }

    /**
@@ -1563,7 +1562,7 @@ public class Activity extends ContextThemeWrapper
    protected void onSaveInstanceState(Bundle outState) {
        outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());

        outState.putInt(LAST_ACCESSIBILITY_ID, mLastAccessibilityId);
        outState.putInt(LAST_AUTOFILL_ID, mLastAutofillId);
        Parcelable p = mFragments.saveAllState();
        if (p != null) {
            outState.putParcelable(FRAGMENTS_TAG, p);
@@ -7455,7 +7454,7 @@ public class Activity extends ContextThemeWrapper

    /** @hide */
    @Override
    @NonNull public View[] findViewsByAccessibilityIdTraversal(@NonNull int[] viewIds) {
    @NonNull public View[] findViewsByAutofillIdTraversal(@NonNull int[] viewIds) {
        final View[] views = new View[viewIds.length];
        final ArrayList<ViewRootImpl> roots =
                WindowManagerGlobal.getInstance().getRootViews(getActivityToken());
@@ -7466,7 +7465,7 @@ public class Activity extends ContextThemeWrapper
            if (rootView != null) {
                for (int viewNum = 0; viewNum < viewIds.length; viewNum++) {
                    if (views[viewNum] == null) {
                        views[viewNum] = rootView.findViewByAccessibilityIdTraversal(
                        views[viewNum] = rootView.findViewByAutofillIdTraversal(
                                viewIds[viewNum]);
                    }
                }
@@ -7478,14 +7477,14 @@ public class Activity extends ContextThemeWrapper

    /** @hide */
    @Override
    @Nullable public View findViewByAccessibilityIdTraversal(int viewId) {
    @Nullable public View findViewByAutofillIdTraversal(int viewId) {
        final ArrayList<ViewRootImpl> roots =
                WindowManagerGlobal.getInstance().getRootViews(getActivityToken());
        for (int rootNum = 0; rootNum < roots.size(); rootNum++) {
            final View rootView = roots.get(rootNum).getView();

            if (rootView != null) {
                final View view = rootView.findViewByAccessibilityIdTraversal(viewId);
                final View view = rootView.findViewByAutofillIdTraversal(viewId);
                if (view != null) {
                    return view;
                }
@@ -7499,7 +7498,7 @@ public class Activity extends ContextThemeWrapper
    @Override
    @NonNull public boolean[] getViewVisibility(@NonNull int[] viewIds) {
        final boolean[] isVisible = new boolean[viewIds.length];
        final View views[] = findViewsByAccessibilityIdTraversal(viewIds);
        final View views[] = findViewsByAutofillIdTraversal(viewIds);

        for (int i = 0; i < viewIds.length; i++) {
            View view = views[i];
+9 −9
Original line number Diff line number Diff line
@@ -488,27 +488,27 @@ public abstract class Context {
     */
    public abstract Context getApplicationContext();

    /** Non-activity related accessibility ids are unique in the app */
    private static int sLastAccessibilityId = View.NO_ID;
    /** Non-activity related autofill ids are unique in the app */
    private static int sLastAutofillId = View.NO_ID;

    /**
     * Gets the next accessibility ID.
     * Gets the next autofill ID.
     *
     * <p>All IDs will be smaller or the same as {@link View#LAST_APP_ACCESSIBILITY_ID}. All IDs
     * <p>All IDs will be smaller or the same as {@link View#LAST_APP_AUTOFILL_ID}. All IDs
     * returned will be unique.
     *
     * @return A ID that is unique in the process
     *
     * {@hide}
     */
    public int getNextAccessibilityId() {
        if (sLastAccessibilityId == View.LAST_APP_ACCESSIBILITY_ID - 1) {
            sLastAccessibilityId = View.NO_ID;
    public int getNextAutofillId() {
        if (sLastAutofillId == View.LAST_APP_AUTOFILL_ID - 1) {
            sLastAutofillId = View.NO_ID;
        }

        sLastAccessibilityId++;
        sLastAutofillId++;

        return sLastAccessibilityId;
        return sLastAutofillId;
    }

    /**
+2 −3
Original line number Diff line number Diff line
@@ -956,8 +956,7 @@ public class ContextWrapper extends Context {
    /**
     * @hide
     */
    @Override
    public int getNextAccessibilityId() {
        return mBase.getNextAccessibilityId();
    public int getNextAutofillId() {
        return mBase.getNextAutofillId();
    }
}
+63 −24
Original line number Diff line number Diff line
@@ -802,7 +802,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     *
     * {@hide}
     */
    public static final int LAST_APP_ACCESSIBILITY_ID = Integer.MAX_VALUE / 2;
    public static final int LAST_APP_AUTOFILL_ID = Integer.MAX_VALUE / 2;
    /**
     * Attribute to find the autofilled highlight
@@ -2044,6 +2044,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    private SparseArray<Object> mKeyedTags;
    /**
     * The next available accessibility id.
     */
    private static int sNextAccessibilityViewId;
    /**
     * The animation currently associated with this view.
     * @hide
@@ -2086,16 +2091,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    @ViewDebug.ExportedProperty(resolveId = true)
    int mID = NO_ID;
    /** The ID of this view for accessibility and autofill purposes.
    /** The ID of this view for autofill purposes.
     * <ul>
     *     <li>== {@link #NO_ID}: ID has not been assigned yet
     *     <li>&le; {@link #LAST_APP_ACCESSIBILITY_ID}: View is not part of a activity. The ID is
     *     <li>&le; {@link #LAST_APP_AUTOFILL_ID}: View is not part of a activity. The ID is
     *                                                  unique in the process. This might change
     *                                                  over activity lifecycle events.
     *     <li>&gt; {@link #LAST_APP_ACCESSIBILITY_ID}: View is part of a activity. The ID is
     *     <li>&gt; {@link #LAST_APP_AUTOFILL_ID}: View is part of a activity. The ID is
     *                                                  unique in the activity. This stays the same
     *                                                  over activity lifecycle events.
     */
    private int mAutofillViewId = NO_ID;
    // ID for accessibility purposes. This ID must be unique for every window
    private int mAccessibilityViewId = NO_ID;
    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
@@ -7723,7 +7731,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        if (mAutofillId == null) {
            // The autofill id needs to be unique, but its value doesn't matter,
            // so it's better to reuse the accessibility id to save space.
            mAutofillId = new AutofillId(getAccessibilityViewId());
            mAutofillId = new AutofillId(getAutofillViewId());
        }
        return mAutofillId;
    }
@@ -7956,7 +7964,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    private boolean isAutofillable() {
        return getAutofillType() != AUTOFILL_TYPE_NONE && isImportantForAutofill()
                && getAccessibilityViewId() > LAST_APP_ACCESSIBILITY_ID;
                && getAutofillViewId() > LAST_APP_AUTOFILL_ID;
    }
    private void populateVirtualStructure(ViewStructure structure,
@@ -8474,11 +8482,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    public int getAccessibilityViewId() {
        if (mAccessibilityViewId == NO_ID) {
            mAccessibilityViewId = mContext.getNextAccessibilityId();
            mAccessibilityViewId = sNextAccessibilityViewId++;
        }
        return mAccessibilityViewId;
    }
    /**
     * Gets the unique identifier of this view on the screen for autofill purposes.
     *
     * @return The view autofill id.
     *
     * @hide
     */
    public int getAutofillViewId() {
        if (mAutofillViewId == NO_ID) {
            mAutofillViewId = mContext.getNextAutofillId();
        }
        return mAutofillViewId;
    }
    /**
     * Gets the unique identifier of the window in which this View reseides.
     *
@@ -12117,7 +12139,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        if (isAutofillable()) {
            AutofillManager afm = getAutofillManager();
            if (afm != null && getAccessibilityViewId() > LAST_APP_ACCESSIBILITY_ID) {
            if (afm != null && getAutofillViewId() > LAST_APP_AUTOFILL_ID) {
                if (mVisibilityChangeForAutofillHandler != null) {
                    mVisibilityChangeForAutofillHandler.removeMessages(0);
                }
@@ -17547,16 +17569,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     *
     * @return Returns a Parcelable object containing the view's current dynamic
     *         state, or null if there is nothing interesting to save.
     * @see #onRestoreInstanceState(android.os.Parcelable)
     * @see #saveHierarchyState(android.util.SparseArray)
     * @see #dispatchSaveInstanceState(android.util.SparseArray)
     * @see #onRestoreInstanceState(Parcelable)
     * @see #saveHierarchyState(SparseArray)
     * @see #dispatchSaveInstanceState(SparseArray)
     * @see #setSaveEnabled(boolean)
     */
    @CallSuper
    @Nullable protected Parcelable onSaveInstanceState() {
        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
        if (mStartActivityRequestWho != null || isAutofilled()
                || mAccessibilityViewId > LAST_APP_ACCESSIBILITY_ID) {
                || mAutofillViewId > LAST_APP_AUTOFILL_ID) {
            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
            if (mStartActivityRequestWho != null) {
@@ -17567,13 +17589,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
            }
            if (mAccessibilityViewId > LAST_APP_ACCESSIBILITY_ID) {
                state.mSavedData |= BaseSavedState.ACCESSIBILITY_ID;
            if (mAutofillViewId > LAST_APP_AUTOFILL_ID) {
                state.mSavedData |= BaseSavedState.AUTOFILL_ID;
            }
            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
            state.mIsAutofilled = isAutofilled();
            state.mAccessibilityViewId = mAccessibilityViewId;
            state.mAutofillViewId = mAutofillViewId;
            return state;
        }
        return BaseSavedState.EMPTY_STATE;
@@ -17651,8 +17673,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
                setAutofilled(baseState.mIsAutofilled);
            }
            if ((baseState.mSavedData & BaseSavedState.ACCESSIBILITY_ID) != 0) {
                mAccessibilityViewId = baseState.mAccessibilityViewId;
            if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) {
                mAutofillViewId = baseState.mAutofillViewId;
            }
        }
    }
@@ -21488,11 +21510,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    }
    /**
     * Performs the traversal to find a view by its unuque and stable accessibility id.
     * Performs the traversal to find a view by its unique and stable accessibility id.
     *
     * <strong>Note:</strong>This method does not stop at the root namespace
     * boundary since the user can touch the screen at an arbitrary location
     * potentially crossing the root namespace bounday which will send an
     * potentially crossing the root namespace boundary which will send an
     * accessibility event to accessibility services and they should be able
     * to obtain the event source. Also accessibility ids are guaranteed to be
     * unique in the window.
@@ -21508,6 +21530,23 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        return null;
    }
    /**
     * Performs the traversal to find a view by its autofill id.
     *
     * <strong>Note:</strong>This method does not stop at the root namespace
     * boundary.
     *
     * @param autofillId The autofill id.
     * @return The found view.
     * @hide
     */
    public <T extends View> T findViewByAutofillIdTraversal(int autofillId) {
        if (getAutofillViewId() == autofillId) {
            return (T) this;
        }
        return null;
    }
    /**
     * Look for a child view with the given tag.  If this view has the given
     * tag, return this view.
@@ -24974,13 +25013,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    public static class BaseSavedState extends AbsSavedState {
        static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
        static final int IS_AUTOFILLED = 0b10;
        static final int ACCESSIBILITY_ID = 0b100;
        static final int AUTOFILL_ID = 0b100;
        // Flags that describe what data in this state is valid
        int mSavedData;
        String mStartActivityRequestWhoSaved;
        boolean mIsAutofilled;
        int mAccessibilityViewId;
        int mAutofillViewId;
        /**
         * Constructor used when reading from a parcel. Reads the state of the superclass.
@@ -25003,7 +25042,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            mSavedData = source.readInt();
            mStartActivityRequestWhoSaved = source.readString();
            mIsAutofilled = source.readBoolean();
            mAccessibilityViewId = source.readInt();
            mAutofillViewId = source.readInt();
        }
        /**
@@ -25022,7 +25061,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            out.writeInt(mSavedData);
            out.writeString(mStartActivityRequestWhoSaved);
            out.writeBoolean(mIsAutofilled);
            out.writeInt(mAccessibilityViewId);
            out.writeInt(mAutofillViewId);
        }
        public static final Parcelable.Creator<BaseSavedState> CREATOR
+21 −0
Original line number Diff line number Diff line
@@ -1361,6 +1361,27 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
        return null;
    }

    /** @hide */
    @Override
    public View findViewByAutofillIdTraversal(int autofillId) {
        View foundView = super.findViewByAutofillIdTraversal(autofillId);
        if (foundView != null) {
            return foundView;
        }

        final int childrenCount = mChildrenCount;
        final View[] children = mChildren;
        for (int i = 0; i < childrenCount; i++) {
            View child = children[i];
            foundView = child.findViewByAutofillIdTraversal(autofillId);
            if (foundView != null) {
                return foundView;
            }
        }

        return null;
    }

    @Override
    public void dispatchWindowFocusChanged(boolean hasFocus) {
        super.dispatchWindowFocusChanged(hasFocus);
Loading