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

Commit 50776863 authored by Svetoslav Ganov's avatar Svetoslav Ganov
Browse files

Taking into account data change for AbsListView when prefetching node infos.

We are prefetching accessibility node infos to minimize the number of IPC
calls when an accessibility service introspects the screen. It is however,
possible that the view we are prefetching is a child of an AbsListView whose
adapter changed its data but the AbsListView still did not perform a layout
pass to sync its children with the new adapter state. This may lead to an
exeption when trying to query for the state of a child's position. If the
data of the adapter is changed and the layout pass still not performed,
we return null for the AbsLIstView's children. When the layout pass
completes we already notify the accessibliity layer so it will be able to
refetch the children of the AbsListView.

bug:8433433

Change-Id: I56313c721aef3848b15fad50027d068ba1d291f7
parent 154bb559
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -4928,6 +4928,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * @see AccessibilityNodeInfo
     */
    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
        if (mAccessibilityDelegate != null) {
            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
        } else {
            return createAccessibilityNodeInfoInternal();
        }
    }
    /**
     * @see #createAccessibilityNodeInfo()
     */
    AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
        if (provider != null) {
            return provider.createAccessibilityNodeInfo(View.NO_ID);
@@ -18690,6 +18701,33 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
            return null;
        }
        /**
         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
         * This method is responsible for obtaining an accessibility node info from a
         * pool of reusable instances and calling
         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
         * view to initialize the former.
         * <p>
         * <strong>Note:</strong> The client is responsible for recycling the obtained
         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
         * creation.
         * </p>
         * <p>
         * The default implementation behaves as
         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
         * the case of no accessibility delegate been set.
         * </p>
         * @return A populated {@link AccessibilityNodeInfo}.
         *
         * @see AccessibilityNodeInfo
         *
         * @hide
         */
        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
            return host.createAccessibilityNodeInfoInternal();
        }
    }
    private class MatchIdPredicate implements Predicate<View> {
+12 −0
Original line number Diff line number Diff line
@@ -2212,6 +2212,18 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
    }

    class ListItemAccessibilityDelegate extends AccessibilityDelegate {
        @Override
        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
            // If the data changed the children are invalid since the data model changed.
            // Hence, we pretend they do not exist. After a layout the children will sync
            // with the model at which point we notify that the accessibility state changed,
            // so a service will be able to re-fetch the views.
            if (mDataChanged) {
                return null;
            }
            return super.createAccessibilityNodeInfo(host);
        }

        @Override
        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
            super.onInitializeAccessibilityNodeInfo(host, info);