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

Commit 1c06dab6 authored by Sally Yuen's avatar Sally Yuen Committed by Automerger Merge Worker
Browse files

Merge "Service requests can interrupt node prefetching" into sc-dev am: 515057f7

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13776283

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I5d3a6930697d0fa91a88b2700379e30a25d5a3c7
parents 0bb7e428 515057f7
Loading
Loading
Loading
Loading
+221 −130
Original line number Original line Diff line number Diff line
@@ -86,6 +86,12 @@ public final class AccessibilityInteractionController {
    // accessibility from hanging
    // accessibility from hanging
    private static final long REQUEST_PREPARER_TIMEOUT_MS = 500;
    private static final long REQUEST_PREPARER_TIMEOUT_MS = 500;


    // Callbacks should have the same configuration of the flags below to allow satisfying a pending
    // node request on prefetch
    private static final int FLAGS_AFFECTING_REPORTED_DATA =
            AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
            | AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;

    private final ArrayList<AccessibilityNodeInfo> mTempAccessibilityNodeInfoList =
    private final ArrayList<AccessibilityNodeInfo> mTempAccessibilityNodeInfoList =
        new ArrayList<AccessibilityNodeInfo>();
        new ArrayList<AccessibilityNodeInfo>();


@@ -113,6 +119,9 @@ public final class AccessibilityInteractionController {


    private AddNodeInfosForViewId mAddNodeInfosForViewId;
    private AddNodeInfosForViewId mAddNodeInfosForViewId;


    @GuardedBy("mLock")
    private ArrayList<Message> mPendingFindNodeByIdMessages;

    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private int mNumActiveRequestPreparers;
    private int mNumActiveRequestPreparers;
    @GuardedBy("mLock")
    @GuardedBy("mLock")
@@ -128,6 +137,7 @@ public final class AccessibilityInteractionController {
        mViewRootImpl = viewRootImpl;
        mViewRootImpl = viewRootImpl;
        mPrefetcher = new AccessibilityNodePrefetcher();
        mPrefetcher = new AccessibilityNodePrefetcher();
        mA11yManager = mViewRootImpl.mContext.getSystemService(AccessibilityManager.class);
        mA11yManager = mViewRootImpl.mContext.getSystemService(AccessibilityManager.class);
        mPendingFindNodeByIdMessages = new ArrayList<>();
    }
    }


    private void scheduleMessage(Message message, int interrogatingPid, long interrogatingTid,
    private void scheduleMessage(Message message, int interrogatingPid, long interrogatingTid,
@@ -177,7 +187,11 @@ public final class AccessibilityInteractionController {
        args.arg4 = arguments;
        args.arg4 = arguments;
        message.obj = args;
        message.obj = args;


        scheduleMessage(message, interrogatingPid, interrogatingTid, CONSIDER_REQUEST_PREPARERS);
        synchronized (mLock) {
            mPendingFindNodeByIdMessages.add(message);
            scheduleMessage(message, interrogatingPid, interrogatingTid,
                    CONSIDER_REQUEST_PREPARERS);
        }
    }
    }


    /**
    /**
@@ -315,6 +329,9 @@ public final class AccessibilityInteractionController {
    }
    }


    private void findAccessibilityNodeInfoByAccessibilityIdUiThread(Message message) {
    private void findAccessibilityNodeInfoByAccessibilityIdUiThread(Message message) {
        synchronized (mLock) {
            mPendingFindNodeByIdMessages.remove(message);
        }
        final int flags = message.arg1;
        final int flags = message.arg1;


        SomeArgs args = (SomeArgs) message.obj;
        SomeArgs args = (SomeArgs) message.obj;
@@ -329,22 +346,58 @@ public final class AccessibilityInteractionController {


        args.recycle();
        args.recycle();


        List<AccessibilityNodeInfo> infos = mTempAccessibilityNodeInfoList;
        View rootView = null;
        infos.clear();
        AccessibilityNodeInfo rootNode = null;
        try {
        try {
            if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
            if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
                return;
                return;
            }
            }
            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
            final View root = findViewByAccessibilityId(accessibilityViewId);
            rootView = findViewByAccessibilityId(accessibilityViewId);
            if (root != null && isShown(root)) {
            if (rootView != null && isShown(rootView)) {
                mPrefetcher.prefetchAccessibilityNodeInfos(
                rootNode = populateAccessibilityNodeInfoForView(
                        root, virtualDescendantId, flags, infos, arguments);
                        rootView, arguments, virtualDescendantId);
            }
            }
        } finally {
        } finally {
            updateInfosForViewportAndReturnFindNodeResult(
            updateInfoForViewportAndReturnFindNodeResult(
                    infos, callback, interactionId, spec, interactiveRegion);
                    rootNode == null ? null : AccessibilityNodeInfo.obtain(rootNode),
                    callback, interactionId, spec, interactiveRegion);
        }
        }
        ArrayList<AccessibilityNodeInfo> infos = mTempAccessibilityNodeInfoList;
        infos.clear();
        mPrefetcher.prefetchAccessibilityNodeInfos(
                rootView, rootNode == null ? null : AccessibilityNodeInfo.obtain(rootNode),
                virtualDescendantId, flags, infos);
        mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
        updateInfosForViewPort(infos, spec, interactiveRegion);
        returnPrefetchResult(interactionId, infos, callback);
        returnPendingFindAccessibilityNodeInfosInPrefetch(rootNode, infos, flags);
    }

    private AccessibilityNodeInfo populateAccessibilityNodeInfoForView(
            View view, Bundle arguments, int virtualViewId) {
        AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider();
        // Determine if we'll be populating extra data
        final String extraDataRequested = (arguments == null) ? null
                : arguments.getString(EXTRA_DATA_REQUESTED_KEY);
        AccessibilityNodeInfo root = null;
        if (provider == null) {
            root = view.createAccessibilityNodeInfo();
            if (root != null) {
                if (extraDataRequested != null) {
                    view.addExtraDataToAccessibilityNodeInfo(root, extraDataRequested, arguments);
                }
            }
        } else {
            root = provider.createAccessibilityNodeInfo(virtualViewId);
            if (root != null) {
                if (extraDataRequested != null) {
                    provider.addExtraDataToAccessibilityNodeInfo(
                            virtualViewId, root, extraDataRequested, arguments);
                }
            }
        }
        return root;
    }
    }


    public void findAccessibilityNodeInfosByViewIdClientThread(long accessibilityNodeId,
    public void findAccessibilityNodeInfosByViewIdClientThread(long accessibilityNodeId,
@@ -403,6 +456,7 @@ public final class AccessibilityInteractionController {
                mAddNodeInfosForViewId.reset();
                mAddNodeInfosForViewId.reset();
            }
            }
        } finally {
        } finally {
            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
            updateInfosForViewportAndReturnFindNodeResult(
            updateInfosForViewportAndReturnFindNodeResult(
                    infos, callback, interactionId, spec, interactiveRegion);
                    infos, callback, interactionId, spec, interactiveRegion);
        }
        }
@@ -485,6 +539,7 @@ public final class AccessibilityInteractionController {
                }
                }
            }
            }
        } finally {
        } finally {
            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
            updateInfosForViewportAndReturnFindNodeResult(
            updateInfosForViewportAndReturnFindNodeResult(
                    infos, callback, interactionId, spec, interactiveRegion);
                    infos, callback, interactionId, spec, interactiveRegion);
        }
        }
@@ -576,6 +631,7 @@ public final class AccessibilityInteractionController {
                }
                }
            }
            }
        } finally {
        } finally {
            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
            updateInfoForViewportAndReturnFindNodeResult(
            updateInfoForViewportAndReturnFindNodeResult(
                    focused, callback, interactionId, spec, interactiveRegion);
                    focused, callback, interactionId, spec, interactiveRegion);
        }
        }
@@ -630,6 +686,7 @@ public final class AccessibilityInteractionController {
                }
                }
            }
            }
        } finally {
        } finally {
            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
            updateInfoForViewportAndReturnFindNodeResult(
            updateInfoForViewportAndReturnFindNodeResult(
                    next, callback, interactionId, spec, interactiveRegion);
                    next, callback, interactionId, spec, interactiveRegion);
        }
        }
@@ -786,33 +843,6 @@ public final class AccessibilityInteractionController {
        }
        }
    }
    }


    private void applyAppScaleAndMagnificationSpecIfNeeded(List<AccessibilityNodeInfo> infos,
            MagnificationSpec spec) {
        if (infos == null) {
            return;
        }
        final float applicationScale = mViewRootImpl.mAttachInfo.mApplicationScale;
        if (shouldApplyAppScaleAndMagnificationSpec(applicationScale, spec)) {
            final int infoCount = infos.size();
            for (int i = 0; i < infoCount; i++) {
                AccessibilityNodeInfo info = infos.get(i);
                applyAppScaleAndMagnificationSpecIfNeeded(info, spec);
            }
        }
    }

    private void adjustIsVisibleToUserIfNeeded(List<AccessibilityNodeInfo> infos,
            Region interactiveRegion) {
        if (interactiveRegion == null || infos == null) {
            return;
        }
        final int infoCount = infos.size();
        for (int i = 0; i < infoCount; i++) {
            AccessibilityNodeInfo info = infos.get(i);
            adjustIsVisibleToUserIfNeeded(info, interactiveRegion);
        }
    }

    private void adjustIsVisibleToUserIfNeeded(AccessibilityNodeInfo info,
    private void adjustIsVisibleToUserIfNeeded(AccessibilityNodeInfo info,
            Region interactiveRegion) {
            Region interactiveRegion) {
        if (interactiveRegion == null || info == null) {
        if (interactiveRegion == null || info == null) {
@@ -833,17 +863,6 @@ public final class AccessibilityInteractionController {
        return false;
        return false;
    }
    }


    private void adjustBoundsInScreenIfNeeded(List<AccessibilityNodeInfo> infos) {
        if (infos == null || shouldBypassAdjustBoundsInScreen()) {
            return;
        }
        final int infoCount = infos.size();
        for (int i = 0; i < infoCount; i++) {
            final AccessibilityNodeInfo info = infos.get(i);
            adjustBoundsInScreenIfNeeded(info);
        }
    }

    private void adjustBoundsInScreenIfNeeded(AccessibilityNodeInfo info) {
    private void adjustBoundsInScreenIfNeeded(AccessibilityNodeInfo info) {
        if (info == null || shouldBypassAdjustBoundsInScreen()) {
        if (info == null || shouldBypassAdjustBoundsInScreen()) {
            return;
            return;
@@ -891,17 +910,6 @@ public final class AccessibilityInteractionController {
        return screenMatrix == null || screenMatrix.isIdentity();
        return screenMatrix == null || screenMatrix.isIdentity();
    }
    }


    private void associateLeashedParentIfNeeded(List<AccessibilityNodeInfo> infos) {
        if (infos == null || shouldBypassAssociateLeashedParent()) {
            return;
        }
        final int infoCount = infos.size();
        for (int i = 0; i < infoCount; i++) {
            final AccessibilityNodeInfo info = infos.get(i);
            associateLeashedParentIfNeeded(info);
        }
    }

    private void associateLeashedParentIfNeeded(AccessibilityNodeInfo info) {
    private void associateLeashedParentIfNeeded(AccessibilityNodeInfo info) {
        if (info == null || shouldBypassAssociateLeashedParent()) {
        if (info == null || shouldBypassAssociateLeashedParent()) {
            return;
            return;
@@ -975,18 +983,46 @@ public final class AccessibilityInteractionController {
        return (appScale != 1.0f || (spec != null && !spec.isNop()));
        return (appScale != 1.0f || (spec != null && !spec.isNop()));
    }
    }


    private void updateInfosForViewPort(List<AccessibilityNodeInfo> infos, MagnificationSpec spec,
                                        Region interactiveRegion) {
        for (int i = 0; i < infos.size(); i++) {
            updateInfoForViewPort(infos.get(i), spec, interactiveRegion);
        }
    }

    private void updateInfoForViewPort(AccessibilityNodeInfo info, MagnificationSpec spec,
                                       Region interactiveRegion) {
        associateLeashedParentIfNeeded(info);
        applyScreenMatrixIfNeeded(info);
        adjustBoundsInScreenIfNeeded(info);
        // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node,
        // then impact the visibility result, we need to adjust visibility before apply scale.
        adjustIsVisibleToUserIfNeeded(info, interactiveRegion);
        applyAppScaleAndMagnificationSpecIfNeeded(info, spec);
    }

    private void updateInfosForViewportAndReturnFindNodeResult(List<AccessibilityNodeInfo> infos,
    private void updateInfosForViewportAndReturnFindNodeResult(List<AccessibilityNodeInfo> infos,
            IAccessibilityInteractionConnectionCallback callback, int interactionId,
            IAccessibilityInteractionConnectionCallback callback, int interactionId,
            MagnificationSpec spec, Region interactiveRegion) {
            MagnificationSpec spec, Region interactiveRegion) {
        if (infos != null) {
            updateInfosForViewPort(infos, spec, interactiveRegion);
        }
        returnFindNodesResult(infos, callback, interactionId);
    }

    private void returnFindNodeResult(AccessibilityNodeInfo info,
                                      IAccessibilityInteractionConnectionCallback callback,
                                      int interactionId) {
        try {
            callback.setFindAccessibilityNodeInfoResult(info, interactionId);
        } catch (RemoteException re) {
            /* ignore - the other side will time out */
        }
    }

    private void returnFindNodesResult(List<AccessibilityNodeInfo> infos,
            IAccessibilityInteractionConnectionCallback callback, int interactionId) {
        try {
        try {
            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
            associateLeashedParentIfNeeded(infos);
            applyScreenMatrixIfNeeded(infos);
            adjustBoundsInScreenIfNeeded(infos);
            // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node,
            // then impact the visibility result, we need to adjust visibility before apply scale.
            adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
            applyAppScaleAndMagnificationSpecIfNeeded(infos, spec);
            callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
            callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
            if (infos != null) {
            if (infos != null) {
                infos.clear();
                infos.clear();
@@ -996,24 +1032,82 @@ public final class AccessibilityInteractionController {
        }
        }
    }
    }


    private void updateInfoForViewportAndReturnFindNodeResult(AccessibilityNodeInfo info,
    private void returnPendingFindAccessibilityNodeInfosInPrefetch(AccessibilityNodeInfo rootNode,
            IAccessibilityInteractionConnectionCallback callback, int interactionId,
            List<AccessibilityNodeInfo> infos, int flags) {
            MagnificationSpec spec, Region interactiveRegion) {

        AccessibilityNodeInfo satisfiedPendingRequestPrefetchedNode = null;
        IAccessibilityInteractionConnectionCallback satisfiedPendingRequestCallback = null;
        int satisfiedPendingRequestInteractionId = AccessibilityInteractionClient.NO_ID;

        synchronized (mLock) {
            for (int i = 0; i < mPendingFindNodeByIdMessages.size(); i++) {
                final Message pendingMessage = mPendingFindNodeByIdMessages.get(i);
                final int pendingFlags = pendingMessage.arg1;
                if ((pendingFlags & FLAGS_AFFECTING_REPORTED_DATA)
                        != (flags & FLAGS_AFFECTING_REPORTED_DATA)) {
                    continue;
                }
                SomeArgs args = (SomeArgs) pendingMessage.obj;
                final int accessibilityViewId = args.argi1;
                final int virtualDescendantId = args.argi2;

                satisfiedPendingRequestPrefetchedNode = nodeWithIdFromList(rootNode,
                        infos, AccessibilityNodeInfo.makeNodeId(
                                accessibilityViewId, virtualDescendantId));

                if (satisfiedPendingRequestPrefetchedNode != null) {
                    satisfiedPendingRequestCallback =
                            (IAccessibilityInteractionConnectionCallback) args.arg1;
                    satisfiedPendingRequestInteractionId = args.argi3;
                    mHandler.removeMessages(
                            PrivateHandler.MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID,
                            pendingMessage.obj);
                    args.recycle();
                    break;
                }
            }
            mPendingFindNodeByIdMessages.clear();
        }

        if (satisfiedPendingRequestPrefetchedNode != null) {
            returnFindNodeResult(
                    AccessibilityNodeInfo.obtain(satisfiedPendingRequestPrefetchedNode),
                    satisfiedPendingRequestCallback, satisfiedPendingRequestInteractionId);
        }
    }

    private AccessibilityNodeInfo nodeWithIdFromList(AccessibilityNodeInfo rootNode,
            List<AccessibilityNodeInfo> infos, long nodeId) {
        if (rootNode != null && rootNode.getSourceNodeId() == nodeId) {
            return rootNode;
        }
        for (int j = 0; j < infos.size(); j++) {
            AccessibilityNodeInfo info = infos.get(j);
            if (info.getSourceNodeId() == nodeId) {
                return info;
            }
        }
        return null;
    }

    private void returnPrefetchResult(int interactionId, List<AccessibilityNodeInfo> infos,
                                      IAccessibilityInteractionConnectionCallback callback) {
        if (infos.size() > 0) {
            try {
            try {
            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
                callback.setPrefetchAccessibilityNodeInfoResult(infos, interactionId);
            associateLeashedParentIfNeeded(info);
            applyScreenMatrixIfNeeded(info);
            adjustBoundsInScreenIfNeeded(info);
            // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node,
            // then impact the visibility result, we need to adjust visibility before apply scale.
            adjustIsVisibleToUserIfNeeded(info, interactiveRegion);
            applyAppScaleAndMagnificationSpecIfNeeded(info, spec);
            callback.setFindAccessibilityNodeInfoResult(info, interactionId);
            } catch (RemoteException re) {
            } catch (RemoteException re) {
                /* ignore - the other side will time out */
                /* ignore - other side isn't too bothered if this doesn't arrive */
            }
        }
        }
    }
    }


    private void updateInfoForViewportAndReturnFindNodeResult(AccessibilityNodeInfo info,
            IAccessibilityInteractionConnectionCallback callback, int interactionId,
            MagnificationSpec spec, Region interactiveRegion) {
        updateInfoForViewPort(info, spec, interactiveRegion);
        returnFindNodeResult(info, callback, interactionId);
    }

    private boolean handleClickableSpanActionUiThread(
    private boolean handleClickableSpanActionUiThread(
            View view, int virtualDescendantId, Bundle arguments) {
            View view, int virtualDescendantId, Bundle arguments) {
        Parcelable span = arguments.getParcelable(ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN);
        Parcelable span = arguments.getParcelable(ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN);
@@ -1054,20 +1148,13 @@ public final class AccessibilityInteractionController {


        private final ArrayList<View> mTempViewList = new ArrayList<View>();
        private final ArrayList<View> mTempViewList = new ArrayList<View>();


        public void prefetchAccessibilityNodeInfos(View view, int virtualViewId, int fetchFlags,
        public void prefetchAccessibilityNodeInfos(View view, AccessibilityNodeInfo root,
                List<AccessibilityNodeInfo> outInfos, Bundle arguments) {
                int virtualViewId, int fetchFlags, List<AccessibilityNodeInfo> outInfos) {
            if (root == null) {
                return;
            }
            AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider();
            AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider();
            // Determine if we'll be populating extra data
            final String extraDataRequested = (arguments == null) ? null
                    : arguments.getString(EXTRA_DATA_REQUESTED_KEY);
            if (provider == null) {
            if (provider == null) {
                AccessibilityNodeInfo root = view.createAccessibilityNodeInfo();
                if (root != null) {
                    if (extraDataRequested != null) {
                        view.addExtraDataToAccessibilityNodeInfo(
                                root, extraDataRequested, arguments);
                    }
                    outInfos.add(root);
                if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) {
                if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) {
                    prefetchPredecessorsOfRealNode(view, outInfos);
                    prefetchPredecessorsOfRealNode(view, outInfos);
                }
                }
@@ -1077,16 +1164,7 @@ public final class AccessibilityInteractionController {
                if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS) != 0) {
                if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS) != 0) {
                    prefetchDescendantsOfRealNode(view, outInfos);
                    prefetchDescendantsOfRealNode(view, outInfos);
                }
                }
                }
            } else {
            } else {
                final AccessibilityNodeInfo root =
                        provider.createAccessibilityNodeInfo(virtualViewId);
                if (root != null) {
                    if (extraDataRequested != null) {
                        provider.addExtraDataToAccessibilityNodeInfo(
                                virtualViewId, root, extraDataRequested, arguments);
                    }
                    outInfos.add(root);
                if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) {
                if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) {
                    prefetchPredecessorsOfVirtualNode(root, view, provider, outInfos);
                    prefetchPredecessorsOfVirtualNode(root, view, provider, outInfos);
                }
                }
@@ -1097,13 +1175,18 @@ public final class AccessibilityInteractionController {
                    prefetchDescendantsOfVirtualNode(root, provider, outInfos);
                    prefetchDescendantsOfVirtualNode(root, provider, outInfos);
                }
                }
            }
            }
            }
            if (ENFORCE_NODE_TREE_CONSISTENT) {
            if (ENFORCE_NODE_TREE_CONSISTENT) {
                enforceNodeTreeConsistent(outInfos);
                enforceNodeTreeConsistent(root, outInfos);
            }
            }
        }
        }


        private void enforceNodeTreeConsistent(List<AccessibilityNodeInfo> nodes) {
        private boolean shouldStopPrefetching(List prefetchededInfos) {
            return mHandler.hasUserInteractiveMessagesWaiting()
                    || prefetchededInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE;
        }

        private void enforceNodeTreeConsistent(
                AccessibilityNodeInfo root, List<AccessibilityNodeInfo> nodes) {
            LongSparseArray<AccessibilityNodeInfo> nodeMap =
            LongSparseArray<AccessibilityNodeInfo> nodeMap =
                    new LongSparseArray<AccessibilityNodeInfo>();
                    new LongSparseArray<AccessibilityNodeInfo>();
            final int nodeCount = nodes.size();
            final int nodeCount = nodes.size();
@@ -1114,7 +1197,6 @@ public final class AccessibilityInteractionController {


            // If the nodes are a tree it does not matter from
            // If the nodes are a tree it does not matter from
            // which node we start to search for the root.
            // which node we start to search for the root.
            AccessibilityNodeInfo root = nodeMap.valueAt(0);
            AccessibilityNodeInfo parent = root;
            AccessibilityNodeInfo parent = root;
            while (parent != null) {
            while (parent != null) {
                root = parent;
                root = parent;
@@ -1181,9 +1263,11 @@ public final class AccessibilityInteractionController {


        private void prefetchPredecessorsOfRealNode(View view,
        private void prefetchPredecessorsOfRealNode(View view,
                List<AccessibilityNodeInfo> outInfos) {
                List<AccessibilityNodeInfo> outInfos) {
            if (shouldStopPrefetching(outInfos)) {
                return;
            }
            ViewParent parent = view.getParentForAccessibility();
            ViewParent parent = view.getParentForAccessibility();
            while (parent instanceof View
            while (parent instanceof View && !shouldStopPrefetching(outInfos)) {
                    && outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
                View parentView = (View) parent;
                View parentView = (View) parent;
                AccessibilityNodeInfo info = parentView.createAccessibilityNodeInfo();
                AccessibilityNodeInfo info = parentView.createAccessibilityNodeInfo();
                if (info != null) {
                if (info != null) {
@@ -1195,6 +1279,9 @@ public final class AccessibilityInteractionController {


        private void prefetchSiblingsOfRealNode(View current,
        private void prefetchSiblingsOfRealNode(View current,
                List<AccessibilityNodeInfo> outInfos) {
                List<AccessibilityNodeInfo> outInfos) {
            if (shouldStopPrefetching(outInfos)) {
                return;
            }
            ViewParent parent = current.getParentForAccessibility();
            ViewParent parent = current.getParentForAccessibility();
            if (parent instanceof ViewGroup) {
            if (parent instanceof ViewGroup) {
                ViewGroup parentGroup = (ViewGroup) parent;
                ViewGroup parentGroup = (ViewGroup) parent;
@@ -1204,7 +1291,7 @@ public final class AccessibilityInteractionController {
                    parentGroup.addChildrenForAccessibility(children);
                    parentGroup.addChildrenForAccessibility(children);
                    final int childCount = children.size();
                    final int childCount = children.size();
                    for (int i = 0; i < childCount; i++) {
                    for (int i = 0; i < childCount; i++) {
                        if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
                        if (shouldStopPrefetching(outInfos)) {
                            return;
                            return;
                        }
                        }
                        View child = children.get(i);
                        View child = children.get(i);
@@ -1232,7 +1319,7 @@ public final class AccessibilityInteractionController {


        private void prefetchDescendantsOfRealNode(View root,
        private void prefetchDescendantsOfRealNode(View root,
                List<AccessibilityNodeInfo> outInfos) {
                List<AccessibilityNodeInfo> outInfos) {
            if (!(root instanceof ViewGroup)) {
            if (shouldStopPrefetching(outInfos) || !(root instanceof ViewGroup)) {
                return;
                return;
            }
            }
            HashMap<View, AccessibilityNodeInfo> addedChildren =
            HashMap<View, AccessibilityNodeInfo> addedChildren =
@@ -1243,7 +1330,7 @@ public final class AccessibilityInteractionController {
                root.addChildrenForAccessibility(children);
                root.addChildrenForAccessibility(children);
                final int childCount = children.size();
                final int childCount = children.size();
                for (int i = 0; i < childCount; i++) {
                for (int i = 0; i < childCount; i++) {
                    if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
                    if (shouldStopPrefetching(outInfos)) {
                        return;
                        return;
                    }
                    }
                    View child = children.get(i);
                    View child = children.get(i);
@@ -1268,7 +1355,7 @@ public final class AccessibilityInteractionController {
            } finally {
            } finally {
                children.clear();
                children.clear();
            }
            }
            if (outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
            if (!shouldStopPrefetching(outInfos)) {
                for (Map.Entry<View, AccessibilityNodeInfo> entry : addedChildren.entrySet()) {
                for (Map.Entry<View, AccessibilityNodeInfo> entry : addedChildren.entrySet()) {
                    View addedChild = entry.getKey();
                    View addedChild = entry.getKey();
                    AccessibilityNodeInfo virtualRoot = entry.getValue();
                    AccessibilityNodeInfo virtualRoot = entry.getValue();
@@ -1290,7 +1377,7 @@ public final class AccessibilityInteractionController {
            long parentNodeId = root.getParentNodeId();
            long parentNodeId = root.getParentNodeId();
            int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(parentNodeId);
            int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(parentNodeId);
            while (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
            while (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
                if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
                if (shouldStopPrefetching(outInfos)) {
                    return;
                    return;
                }
                }
                final int virtualDescendantId =
                final int virtualDescendantId =
@@ -1335,7 +1422,7 @@ public final class AccessibilityInteractionController {
                if (parent != null) {
                if (parent != null) {
                    final int childCount = parent.getChildCount();
                    final int childCount = parent.getChildCount();
                    for (int i = 0; i < childCount; i++) {
                    for (int i = 0; i < childCount; i++) {
                        if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
                        if (shouldStopPrefetching(outInfos)) {
                            return;
                            return;
                        }
                        }
                        final long childNodeId = parent.getChildId(i);
                        final long childNodeId = parent.getChildId(i);
@@ -1360,7 +1447,7 @@ public final class AccessibilityInteractionController {
            final int initialOutInfosSize = outInfos.size();
            final int initialOutInfosSize = outInfos.size();
            final int childCount = root.getChildCount();
            final int childCount = root.getChildCount();
            for (int i = 0; i < childCount; i++) {
            for (int i = 0; i < childCount; i++) {
                if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
                if (shouldStopPrefetching(outInfos)) {
                    return;
                    return;
                }
                }
                final long childNodeId = root.getChildId(i);
                final long childNodeId = root.getChildId(i);
@@ -1370,7 +1457,7 @@ public final class AccessibilityInteractionController {
                    outInfos.add(child);
                    outInfos.add(child);
                }
                }
            }
            }
            if (outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
            if (!shouldStopPrefetching(outInfos)) {
                final int addedChildCount = outInfos.size() - initialOutInfosSize;
                final int addedChildCount = outInfos.size() - initialOutInfosSize;
                for (int i = 0; i < addedChildCount; i++) {
                for (int i = 0; i < addedChildCount; i++) {
                    AccessibilityNodeInfo child = outInfos.get(initialOutInfosSize + i);
                    AccessibilityNodeInfo child = outInfos.get(initialOutInfosSize + i);
@@ -1479,6 +1566,10 @@ public final class AccessibilityInteractionController {
        boolean hasAccessibilityCallback(Message message) {
        boolean hasAccessibilityCallback(Message message) {
            return message.what < FIRST_NO_ACCESSIBILITY_CALLBACK_MSG ? true : false;
            return message.what < FIRST_NO_ACCESSIBILITY_CALLBACK_MSG ? true : false;
        }
        }

        boolean hasUserInteractiveMessagesWaiting() {
            return hasMessagesOrCallbacks();
        }
    }
    }


    private final class AddNodeInfosForViewId implements Predicate<View> {
    private final class AddNodeInfosForViewId implements Predicate<View> {
+84 −9

File changed.

Preview size limit exceeded, changes collapsed.

+9 −0
Original line number Original line Diff line number Diff line
@@ -46,6 +46,15 @@ oneway interface IAccessibilityInteractionConnectionCallback {
    void setFindAccessibilityNodeInfosResult(in List<AccessibilityNodeInfo> infos,
    void setFindAccessibilityNodeInfosResult(in List<AccessibilityNodeInfo> infos,
        int interactionId);
        int interactionId);


    /**
     * Sets the result of a prefetch request that returns {@link AccessibilityNodeInfo}s.
     *
     * @param root The {@link AccessibilityNodeInfo} for which the prefetching is based off of.
     * @param infos The result {@link AccessibilityNodeInfo}s.
     */
    void setPrefetchAccessibilityNodeInfoResult(
        in List<AccessibilityNodeInfo> infos, int interactionId);

    /**
    /**
     * Sets the result of a request to perform an accessibility action.
     * Sets the result of a request to perform an accessibility action.
     *
     *
+3 −6

File changed.

Preview size limit exceeded, changes collapsed.

+128 −93

File changed.

Preview size limit exceeded, changes collapsed.

Loading