Java Code Examples for android.view.accessibility.AccessibilityNodeProvider#HOST_VIEW_ID

The following examples show how to use android.view.accessibility.AccessibilityNodeProvider#HOST_VIEW_ID . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: AccessibilityInteractionController.java    From android_9.0.0_r45 with Apache License 2.0 5 votes vote down vote up
private boolean handleClickableSpanActionUiThread(
        View view, int virtualDescendantId, Bundle arguments) {
    Parcelable span = arguments.getParcelable(ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN);
    if (!(span instanceof AccessibilityClickableSpan)) {
        return false;
    }

    // Find the original ClickableSpan if it's still on the screen
    AccessibilityNodeInfo infoWithSpan = null;
    AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider();
    if (provider != null) {
        infoWithSpan = provider.createAccessibilityNodeInfo(virtualDescendantId);
    } else if (virtualDescendantId == AccessibilityNodeProvider.HOST_VIEW_ID) {
        infoWithSpan = view.createAccessibilityNodeInfo();
    }
    if (infoWithSpan == null) {
        return false;
    }

    // Click on the corresponding span
    ClickableSpan clickableSpan = ((AccessibilityClickableSpan) span).findClickableSpan(
            infoWithSpan.getOriginalText());
    if (clickableSpan != null) {
        clickableSpan.onClick(view);
        return true;
    }
    return false;
}
 
Example 2
Source File: AccessibilityInteractionController.java    From android_9.0.0_r45 with Apache License 2.0 5 votes vote down vote up
private void prefetchPredecessorsOfVirtualNode(AccessibilityNodeInfo root,
        View providerHost, AccessibilityNodeProvider provider,
        List<AccessibilityNodeInfo> outInfos) {
    final int initialResultSize = outInfos.size();
    long parentNodeId = root.getParentNodeId();
    int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(parentNodeId);
    while (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
        if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
            return;
        }
        final int virtualDescendantId =
            AccessibilityNodeInfo.getVirtualDescendantId(parentNodeId);
        if (virtualDescendantId != AccessibilityNodeProvider.HOST_VIEW_ID
                || accessibilityViewId == providerHost.getAccessibilityViewId()) {
            final AccessibilityNodeInfo parent;
            parent = provider.createAccessibilityNodeInfo(virtualDescendantId);
            if (parent == null) {
                // Going up the parent relation we found a null predecessor,
                // so remove these disconnected nodes form the result.
                final int currentResultSize = outInfos.size();
                for (int i = currentResultSize - 1; i >= initialResultSize; i--) {
                    outInfos.remove(i);
                }
                // Couldn't obtain the parent, which means we have a
                // disconnected sub-tree. Abort prefetch immediately.
                return;
            }
            outInfos.add(parent);
            parentNodeId = parent.getParentNodeId();
            accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(
                    parentNodeId);
        } else {
            prefetchPredecessorsOfRealNode(providerHost, outInfos);
            return;
        }
    }
}
 
Example 3
Source File: AccessibilityInteractionController.java    From android_9.0.0_r45 with Apache License 2.0 5 votes vote down vote up
private void prefetchSiblingsOfVirtualNode(AccessibilityNodeInfo current, View providerHost,
        AccessibilityNodeProvider provider, List<AccessibilityNodeInfo> outInfos) {
    final long parentNodeId = current.getParentNodeId();
    final int parentAccessibilityViewId =
        AccessibilityNodeInfo.getAccessibilityViewId(parentNodeId);
    final int parentVirtualDescendantId =
        AccessibilityNodeInfo.getVirtualDescendantId(parentNodeId);
    if (parentVirtualDescendantId != AccessibilityNodeProvider.HOST_VIEW_ID
            || parentAccessibilityViewId == providerHost.getAccessibilityViewId()) {
        final AccessibilityNodeInfo parent =
                provider.createAccessibilityNodeInfo(parentVirtualDescendantId);
        if (parent != null) {
            final int childCount = parent.getChildCount();
            for (int i = 0; i < childCount; i++) {
                if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
                    return;
                }
                final long childNodeId = parent.getChildId(i);
                if (childNodeId != current.getSourceNodeId()) {
                    final int childVirtualDescendantId =
                        AccessibilityNodeInfo.getVirtualDescendantId(childNodeId);
                    AccessibilityNodeInfo child = provider.createAccessibilityNodeInfo(
                            childVirtualDescendantId);
                    if (child != null) {
                        outInfos.add(child);
                    }
                }
            }
        }
    } else {
        prefetchSiblingsOfRealNode(providerHost, outInfos);
    }
}
 
Example 4
Source File: AutofillManager.java    From android_9.0.0_r45 with Apache License 2.0 4 votes vote down vote up
private boolean isVirtualNode(int nodeId) {
    return nodeId != AccessibilityNodeProvider.HOST_VIEW_ID
            && nodeId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
}
 
Example 5
Source File: AccessibilityInteractionController.java    From android_9.0.0_r45 with Apache License 2.0 4 votes vote down vote up
/**
 * Check if this message needs to be held off while the app prepares to meet either this
 * request, or a request ahead of it.
 *
 * @param originalMessage The message to be processed
 * @param callingPid The calling process id
 * @param callingTid The calling thread id
 *
 * @return {@code true} if the message is held off and will be processed later, {@code false} if
 *         the message should be posted.
 */
private boolean holdOffMessageIfNeeded(
        Message originalMessage, int callingPid, long callingTid) {
    synchronized (mLock) {
        // If a request is already pending, queue this request for when it's finished
        if (mNumActiveRequestPreparers != 0) {
            queueMessageToHandleOncePrepared(originalMessage, callingPid, callingTid);
            return true;
        }

        // Currently the only message that can hold things off is findByA11yId with extra data.
        if (originalMessage.what
                != PrivateHandler.MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID) {
            return false;
        }
        SomeArgs originalMessageArgs = (SomeArgs) originalMessage.obj;
        Bundle requestArguments = (Bundle) originalMessageArgs.arg4;
        if (requestArguments == null) {
            return false;
        }

        // If nothing it registered for this view, nothing to do
        int accessibilityViewId = originalMessageArgs.argi1;
        final List<AccessibilityRequestPreparer> preparers =
                mA11yManager.getRequestPreparersForAccessibilityId(accessibilityViewId);
        if (preparers == null) {
            return false;
        }

        // If the bundle doesn't request the extra data, nothing to do
        final String extraDataKey = requestArguments.getString(EXTRA_DATA_REQUESTED_KEY);
        if (extraDataKey == null) {
            return false;
        }

        // Send the request to the AccessibilityRequestPreparers on the UI thread
        mNumActiveRequestPreparers = preparers.size();
        for (int i = 0; i < preparers.size(); i++) {
            final Message requestPreparerMessage = mHandler.obtainMessage(
                    PrivateHandler.MSG_PREPARE_FOR_EXTRA_DATA_REQUEST);
            final SomeArgs requestPreparerArgs = SomeArgs.obtain();
            // virtualDescendentId
            requestPreparerArgs.argi1 =
                    (originalMessageArgs.argi2 == AccessibilityNodeInfo.UNDEFINED_ITEM_ID)
                    ? AccessibilityNodeProvider.HOST_VIEW_ID : originalMessageArgs.argi2;
            requestPreparerArgs.arg1 = preparers.get(i);
            requestPreparerArgs.arg2 = extraDataKey;
            requestPreparerArgs.arg3 = requestArguments;
            Message preparationFinishedMessage = mHandler.obtainMessage(
                    PrivateHandler.MSG_APP_PREPARATION_FINISHED);
            preparationFinishedMessage.arg1 = ++mActiveRequestPreparerId;
            requestPreparerArgs.arg4 = preparationFinishedMessage;

            requestPreparerMessage.obj = requestPreparerArgs;
            scheduleMessage(requestPreparerMessage, callingPid, callingTid,
                    IGNORE_REQUEST_PREPARERS);
            mHandler.obtainMessage(PrivateHandler.MSG_APP_PREPARATION_TIMEOUT);
            mHandler.sendEmptyMessageDelayed(PrivateHandler.MSG_APP_PREPARATION_TIMEOUT,
                    REQUEST_PREPARER_TIMEOUT_MS);
        }

        // Set the initial request aside
        queueMessageToHandleOncePrepared(originalMessage, callingPid, callingTid);
        return true;
    }
}
 
Example 6
Source File: AccessibilityInteractionController.java    From android_9.0.0_r45 with Apache License 2.0 4 votes vote down vote up
private void findAccessibilityNodeInfosByTextUiThread(Message message) {
    final int flags = message.arg1;

    SomeArgs args = (SomeArgs) message.obj;
    final String text = (String) args.arg1;
    final IAccessibilityInteractionConnectionCallback callback =
        (IAccessibilityInteractionConnectionCallback) args.arg2;
    final MagnificationSpec spec = (MagnificationSpec) args.arg3;
    final int accessibilityViewId = args.argi1;
    final int virtualDescendantId = args.argi2;
    final int interactionId = args.argi3;
    final Region interactiveRegion = (Region) args.arg4;
    args.recycle();

    List<AccessibilityNodeInfo> infos = null;
    try {
        if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
            return;
        }
        mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
        View root = null;
        if (accessibilityViewId != AccessibilityNodeInfo.ROOT_ITEM_ID) {
            root = findViewByAccessibilityId(accessibilityViewId);
        } else {
            root = mViewRootImpl.mView;
        }
        if (root != null && isShown(root)) {
            AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider();
            if (provider != null) {
                infos = provider.findAccessibilityNodeInfosByText(text,
                        virtualDescendantId);
            } else if (virtualDescendantId == AccessibilityNodeProvider.HOST_VIEW_ID) {
                ArrayList<View> foundViews = mTempArrayList;
                foundViews.clear();
                root.findViewsWithText(foundViews, text, View.FIND_VIEWS_WITH_TEXT
                        | View.FIND_VIEWS_WITH_CONTENT_DESCRIPTION
                        | View.FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS);
                if (!foundViews.isEmpty()) {
                    infos = mTempAccessibilityNodeInfoList;
                    infos.clear();
                    final int viewCount = foundViews.size();
                    for (int i = 0; i < viewCount; i++) {
                        View foundView = foundViews.get(i);
                        if (isShown(foundView)) {
                            provider = foundView.getAccessibilityNodeProvider();
                            if (provider != null) {
                                List<AccessibilityNodeInfo> infosFromProvider =
                                    provider.findAccessibilityNodeInfosByText(text,
                                            AccessibilityNodeProvider.HOST_VIEW_ID);
                                if (infosFromProvider != null) {
                                    infos.addAll(infosFromProvider);
                                }
                            } else  {
                                infos.add(foundView.createAccessibilityNodeInfo());
                            }
                        }
                    }
                }
            }
        }
    } finally {
        updateInfosForViewportAndReturnFindNodeResult(
                infos, callback, interactionId, spec, interactiveRegion);
    }
}
 
Example 7
Source File: AccessibilityInteractionController.java    From android_9.0.0_r45 with Apache License 2.0 4 votes vote down vote up
private void performAccessibilityActionUiThread(Message message) {
    final int flags = message.arg1;
    final int accessibilityViewId = message.arg2;

    SomeArgs args = (SomeArgs) message.obj;
    final int virtualDescendantId = args.argi1;
    final int action = args.argi2;
    final int interactionId = args.argi3;
    final IAccessibilityInteractionConnectionCallback callback =
        (IAccessibilityInteractionConnectionCallback) args.arg1;
    Bundle arguments = (Bundle) args.arg2;

    args.recycle();

    boolean succeeded = false;
    try {
        if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null ||
                mViewRootImpl.mStopped || mViewRootImpl.mPausedForTransition) {
            return;
        }
        mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
        View target = null;
        if (accessibilityViewId != AccessibilityNodeInfo.ROOT_ITEM_ID) {
            target = findViewByAccessibilityId(accessibilityViewId);
        } else {
            target = mViewRootImpl.mView;
        }
        if (target != null && isShown(target)) {
            if (action == R.id.accessibilityActionClickOnClickableSpan) {
                // Handle this hidden action separately
                succeeded = handleClickableSpanActionUiThread(
                        target, virtualDescendantId, arguments);
            } else {
                AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
                if (provider != null) {
                    succeeded = provider.performAction(virtualDescendantId, action,
                            arguments);
                } else if (virtualDescendantId == AccessibilityNodeProvider.HOST_VIEW_ID) {
                    succeeded = target.performAccessibilityAction(action, arguments);
                }
            }
        }
    } finally {
        try {
            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
            callback.setPerformAccessibilityActionResult(succeeded, interactionId);
        } catch (RemoteException re) {
            /* ignore - the other side will time out */
        }
    }
}