Search in sources :

Example 6 with AccessibilityNodeProvider

use of android.view.accessibility.AccessibilityNodeProvider in project android_frameworks_base by ResurrectionRemix.

the class ViewRootImpl method requestSendAccessibilityEvent.

@Override
public boolean requestSendAccessibilityEvent(View child, AccessibilityEvent event) {
    if (mView == null || mStopped || mPausedForTransition) {
        return false;
    }
    // Intercept accessibility focus events fired by virtual nodes to keep
    // track of accessibility focus position in such nodes.
    final int eventType = event.getEventType();
    switch(eventType) {
        case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED:
            {
                final long sourceNodeId = event.getSourceNodeId();
                final int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(sourceNodeId);
                View source = mView.findViewByAccessibilityId(accessibilityViewId);
                if (source != null) {
                    AccessibilityNodeProvider provider = source.getAccessibilityNodeProvider();
                    if (provider != null) {
                        final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId(sourceNodeId);
                        final AccessibilityNodeInfo node;
                        if (virtualNodeId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
                            node = provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
                        } else {
                            node = provider.createAccessibilityNodeInfo(virtualNodeId);
                        }
                        setAccessibilityFocus(source, node);
                    }
                }
            }
            break;
        case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED:
            {
                final long sourceNodeId = event.getSourceNodeId();
                final int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(sourceNodeId);
                View source = mView.findViewByAccessibilityId(accessibilityViewId);
                if (source != null) {
                    AccessibilityNodeProvider provider = source.getAccessibilityNodeProvider();
                    if (provider != null) {
                        setAccessibilityFocus(null, null);
                    }
                }
            }
            break;
        case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
            {
                handleWindowContentChangedEvent(event);
            }
            break;
    }
    mAccessibilityManager.sendAccessibilityEvent(event);
    return true;
}
Also used : AccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo) AccessibilityNodeProvider(android.view.accessibility.AccessibilityNodeProvider) Point(android.graphics.Point)

Example 7 with AccessibilityNodeProvider

use of android.view.accessibility.AccessibilityNodeProvider in project android_frameworks_base by ResurrectionRemix.

the class View method onProvideVirtualStructure.

/**
     * Called when assist structure is being retrieved from a view as part of
     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
     * generate additional virtual structure under this view.  The defaullt implementation
     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
     * view's virtual accessibility nodes, if any.  You can override this for a more
     * optimal implementation providing this data.
     */
public void onProvideVirtualStructure(ViewStructure structure) {
    AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
    if (provider != null) {
        AccessibilityNodeInfo info = createAccessibilityNodeInfo();
        structure.setChildCount(1);
        ViewStructure root = structure.newChild(0);
        populateVirtualStructure(root, provider, info);
        info.recycle();
    }
}
Also used : AccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo) AccessibilityNodeProvider(android.view.accessibility.AccessibilityNodeProvider)

Example 8 with AccessibilityNodeProvider

use of android.view.accessibility.AccessibilityNodeProvider in project android_frameworks_base by DirtyUnicorns.

the class ListView method layoutChildren.

@Override
protected void layoutChildren() {
    final boolean blockLayoutRequests = mBlockLayoutRequests;
    if (blockLayoutRequests) {
        return;
    }
    mBlockLayoutRequests = true;
    try {
        super.layoutChildren();
        invalidate();
        if (mAdapter == null) {
            resetList();
            invokeOnItemScrollListener();
            return;
        }
        final int childrenTop = mListPadding.top;
        final int childrenBottom = mBottom - mTop - mListPadding.bottom;
        final int childCount = getChildCount();
        int index = 0;
        int delta = 0;
        View sel;
        View oldSel = null;
        View oldFirst = null;
        View newSel = null;
        // Remember stuff we will need down below
        switch(mLayoutMode) {
            case LAYOUT_SET_SELECTION:
                index = mNextSelectedPosition - mFirstPosition;
                if (index >= 0 && index < childCount) {
                    newSel = getChildAt(index);
                }
                break;
            case LAYOUT_FORCE_TOP:
            case LAYOUT_FORCE_BOTTOM:
            case LAYOUT_SPECIFIC:
            case LAYOUT_SYNC:
                break;
            case LAYOUT_MOVE_SELECTION:
            default:
                // Remember the previously selected view
                index = mSelectedPosition - mFirstPosition;
                if (index >= 0 && index < childCount) {
                    oldSel = getChildAt(index);
                }
                // Remember the previous first child
                oldFirst = getChildAt(0);
                if (mNextSelectedPosition >= 0) {
                    delta = mNextSelectedPosition - mSelectedPosition;
                }
                // Caution: newSel might be null
                newSel = getChildAt(index + delta);
        }
        boolean dataChanged = mDataChanged;
        if (dataChanged) {
            handleDataChanged();
        }
        // and calling it a day
        if (mItemCount == 0) {
            resetList();
            invokeOnItemScrollListener();
            return;
        } else if (mItemCount != mAdapter.getCount()) {
            throw new IllegalStateException("The content of the adapter has changed but " + "ListView did not receive a notification. Make sure the content of " + "your adapter is not modified from a background thread, but only from " + "the UI thread. Make sure your adapter calls notifyDataSetChanged() " + "when its content changes. [in ListView(" + getId() + ", " + getClass() + ") with Adapter(" + mAdapter.getClass() + ")]");
        }
        setSelectedPositionInt(mNextSelectedPosition);
        AccessibilityNodeInfo accessibilityFocusLayoutRestoreNode = null;
        View accessibilityFocusLayoutRestoreView = null;
        int accessibilityFocusPosition = INVALID_POSITION;
        // Remember which child, if any, had accessibility focus. This must
        // occur before recycling any views, since that will clear
        // accessibility focus.
        final ViewRootImpl viewRootImpl = getViewRootImpl();
        if (viewRootImpl != null) {
            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
            if (focusHost != null) {
                final View focusChild = getAccessibilityFocusedChild(focusHost);
                if (focusChild != null) {
                    if (!dataChanged || isDirectChildHeaderOrFooter(focusChild) || focusChild.hasTransientState() || mAdapterHasStableIds) {
                        // The views won't be changing, so try to maintain
                        // focus on the current host and virtual view.
                        accessibilityFocusLayoutRestoreView = focusHost;
                        accessibilityFocusLayoutRestoreNode = viewRootImpl.getAccessibilityFocusedVirtualView();
                    }
                    // If all else fails, maintain focus at the same
                    // position.
                    accessibilityFocusPosition = getPositionForView(focusChild);
                }
            }
        }
        View focusLayoutRestoreDirectChild = null;
        View focusLayoutRestoreView = null;
        // Take focus back to us temporarily to avoid the eventual call to
        // clear focus when removing the focused child below from messing
        // things up when ViewAncestor assigns focus back to someone else.
        final View focusedChild = getFocusedChild();
        if (focusedChild != null) {
            // header or footer.
            if (!dataChanged || isDirectChildHeaderOrFooter(focusedChild) || focusedChild.hasTransientState() || mAdapterHasStableIds) {
                focusLayoutRestoreDirectChild = focusedChild;
                // Remember the specific view that had focus.
                focusLayoutRestoreView = findFocus();
                if (focusLayoutRestoreView != null) {
                    // Tell it we are going to mess with it.
                    focusLayoutRestoreView.dispatchStartTemporaryDetach();
                }
            }
            requestFocus();
        }
        // Pull all children into the RecycleBin.
        // These views will be reused if possible
        final int firstPosition = mFirstPosition;
        final RecycleBin recycleBin = mRecycler;
        if (dataChanged) {
            for (int i = 0; i < childCount; i++) {
                recycleBin.addScrapView(getChildAt(i), firstPosition + i);
            }
        } else {
            recycleBin.fillActiveViews(childCount, firstPosition);
        }
        // Clear out old views
        detachAllViewsFromParent();
        recycleBin.removeSkippedScrap();
        switch(mLayoutMode) {
            case LAYOUT_SET_SELECTION:
                if (newSel != null) {
                    sel = fillFromSelection(newSel.getTop(), childrenTop, childrenBottom);
                } else {
                    sel = fillFromMiddle(childrenTop, childrenBottom);
                }
                break;
            case LAYOUT_SYNC:
                sel = fillSpecific(mSyncPosition, mSpecificTop);
                break;
            case LAYOUT_FORCE_BOTTOM:
                sel = fillUp(mItemCount - 1, childrenBottom);
                adjustViewsUpOrDown();
                break;
            case LAYOUT_FORCE_TOP:
                mFirstPosition = 0;
                sel = fillFromTop(childrenTop);
                adjustViewsUpOrDown();
                break;
            case LAYOUT_SPECIFIC:
                final int selectedPosition = reconcileSelectedPosition();
                sel = fillSpecific(selectedPosition, mSpecificTop);
                /**
                 * When ListView is resized, FocusSelector requests an async selection for the
                 * previously focused item to make sure it is still visible. If the item is not
                 * selectable, it won't regain focus so instead we call FocusSelector
                 * to directly request focus on the view after it is visible.
                 */
                if (sel == null && mFocusSelector != null) {
                    final Runnable focusRunnable = mFocusSelector.setupFocusIfValid(selectedPosition);
                    if (focusRunnable != null) {
                        post(focusRunnable);
                    }
                }
                break;
            case LAYOUT_MOVE_SELECTION:
                sel = moveSelection(oldSel, newSel, delta, childrenTop, childrenBottom);
                break;
            default:
                if (childCount == 0) {
                    if (!mStackFromBottom) {
                        final int position = lookForSelectablePosition(0, true);
                        setSelectedPositionInt(position);
                        sel = fillFromTop(childrenTop);
                    } else {
                        final int position = lookForSelectablePosition(mItemCount - 1, false);
                        setSelectedPositionInt(position);
                        sel = fillUp(mItemCount - 1, childrenBottom);
                    }
                } else {
                    if (mSelectedPosition >= 0 && mSelectedPosition < mItemCount) {
                        sel = fillSpecific(mSelectedPosition, oldSel == null ? childrenTop : oldSel.getTop());
                    } else if (mFirstPosition < mItemCount) {
                        sel = fillSpecific(mFirstPosition, oldFirst == null ? childrenTop : oldFirst.getTop());
                    } else {
                        sel = fillSpecific(0, childrenTop);
                    }
                }
                break;
        }
        // Flush any cached views that did not get reused above
        recycleBin.scrapActiveViews();
        // remove any header/footer that has been temp detached and not re-attached
        removeUnusedFixedViews(mHeaderViewInfos);
        removeUnusedFixedViews(mFooterViewInfos);
        if (sel != null) {
            // focusable.
            if (mItemsCanFocus && hasFocus() && !sel.hasFocus()) {
                final boolean focusWasTaken = (sel == focusLayoutRestoreDirectChild && focusLayoutRestoreView != null && focusLayoutRestoreView.requestFocus()) || sel.requestFocus();
                if (!focusWasTaken) {
                    // Selected item didn't take focus, but we still want to
                    // make sure something else outside of the selected view
                    // has focus.
                    final View focused = getFocusedChild();
                    if (focused != null) {
                        focused.clearFocus();
                    }
                    positionSelector(INVALID_POSITION, sel);
                } else {
                    sel.setSelected(false);
                    mSelectorRect.setEmpty();
                }
            } else {
                positionSelector(INVALID_POSITION, sel);
            }
            mSelectedTop = sel.getTop();
        } else {
            final boolean inTouchMode = mTouchMode == TOUCH_MODE_TAP || mTouchMode == TOUCH_MODE_DONE_WAITING;
            if (inTouchMode) {
                // If the user's finger is down, select the motion position.
                final View child = getChildAt(mMotionPosition - mFirstPosition);
                if (child != null) {
                    positionSelector(mMotionPosition, child);
                }
            } else if (mSelectorPosition != INVALID_POSITION) {
                // If we had previously positioned the selector somewhere,
                // put it back there. It might not match up with the data,
                // but it's transitioning out so it's not a big deal.
                final View child = getChildAt(mSelectorPosition - mFirstPosition);
                if (child != null) {
                    positionSelector(mSelectorPosition, child);
                }
            } else {
                // Otherwise, clear selection.
                mSelectedTop = 0;
                mSelectorRect.setEmpty();
            }
            // restore focus (i.e. something focusable in touch mode).
            if (hasFocus() && focusLayoutRestoreView != null) {
                focusLayoutRestoreView.requestFocus();
            }
        }
        // Attempt to restore accessibility focus, if necessary.
        if (viewRootImpl != null) {
            final View newAccessibilityFocusedView = viewRootImpl.getAccessibilityFocusedHost();
            if (newAccessibilityFocusedView == null) {
                if (accessibilityFocusLayoutRestoreView != null && accessibilityFocusLayoutRestoreView.isAttachedToWindow()) {
                    final AccessibilityNodeProvider provider = accessibilityFocusLayoutRestoreView.getAccessibilityNodeProvider();
                    if (accessibilityFocusLayoutRestoreNode != null && provider != null) {
                        final int virtualViewId = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityFocusLayoutRestoreNode.getSourceNodeId());
                        provider.performAction(virtualViewId, AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
                    } else {
                        accessibilityFocusLayoutRestoreView.requestAccessibilityFocus();
                    }
                } else if (accessibilityFocusPosition != INVALID_POSITION) {
                    // Bound the position within the visible children.
                    final int position = MathUtils.constrain(accessibilityFocusPosition - mFirstPosition, 0, getChildCount() - 1);
                    final View restoreView = getChildAt(position);
                    if (restoreView != null) {
                        restoreView.requestAccessibilityFocus();
                    }
                }
            }
        }
        // our view hierarchy.
        if (focusLayoutRestoreView != null && focusLayoutRestoreView.getWindowToken() != null) {
            focusLayoutRestoreView.dispatchFinishTemporaryDetach();
        }
        mLayoutMode = LAYOUT_NORMAL;
        mDataChanged = false;
        if (mPositionScrollAfterLayout != null) {
            post(mPositionScrollAfterLayout);
            mPositionScrollAfterLayout = null;
        }
        mNeedSync = false;
        setNextSelectedPositionInt(mSelectedPosition);
        updateScrollIndicators();
        if (mItemCount > 0) {
            checkSelectionChanged();
        }
        invokeOnItemScrollListener();
    } finally {
        if (mFocusSelector != null) {
            mFocusSelector.onLayoutComplete();
        }
        if (!blockLayoutRequests) {
            mBlockLayoutRequests = false;
        }
    }
}
Also used : ViewRootImpl(android.view.ViewRootImpl) AccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo) RemoteView(android.widget.RemoteViews.RemoteView) View(android.view.View) AccessibilityNodeProvider(android.view.accessibility.AccessibilityNodeProvider) Paint(android.graphics.Paint)

Example 9 with AccessibilityNodeProvider

use of android.view.accessibility.AccessibilityNodeProvider in project android_frameworks_base by DirtyUnicorns.

the class GridView method layoutChildren.

@Override
protected void layoutChildren() {
    final boolean blockLayoutRequests = mBlockLayoutRequests;
    if (!blockLayoutRequests) {
        mBlockLayoutRequests = true;
    }
    try {
        super.layoutChildren();
        invalidate();
        if (mAdapter == null) {
            resetList();
            invokeOnItemScrollListener();
            return;
        }
        final int childrenTop = mListPadding.top;
        final int childrenBottom = mBottom - mTop - mListPadding.bottom;
        int childCount = getChildCount();
        int index;
        int delta = 0;
        View sel;
        View oldSel = null;
        View oldFirst = null;
        View newSel = null;
        // Remember stuff we will need down below
        switch(mLayoutMode) {
            case LAYOUT_SET_SELECTION:
                index = mNextSelectedPosition - mFirstPosition;
                if (index >= 0 && index < childCount) {
                    newSel = getChildAt(index);
                }
                break;
            case LAYOUT_FORCE_TOP:
            case LAYOUT_FORCE_BOTTOM:
            case LAYOUT_SPECIFIC:
            case LAYOUT_SYNC:
                break;
            case LAYOUT_MOVE_SELECTION:
                if (mNextSelectedPosition >= 0) {
                    delta = mNextSelectedPosition - mSelectedPosition;
                }
                break;
            default:
                // Remember the previously selected view
                index = mSelectedPosition - mFirstPosition;
                if (index >= 0 && index < childCount) {
                    oldSel = getChildAt(index);
                }
                // Remember the previous first child
                oldFirst = getChildAt(0);
        }
        boolean dataChanged = mDataChanged;
        if (dataChanged) {
            handleDataChanged();
        }
        // and calling it a day
        if (mItemCount == 0) {
            resetList();
            invokeOnItemScrollListener();
            return;
        }
        setSelectedPositionInt(mNextSelectedPosition);
        AccessibilityNodeInfo accessibilityFocusLayoutRestoreNode = null;
        View accessibilityFocusLayoutRestoreView = null;
        int accessibilityFocusPosition = INVALID_POSITION;
        // Remember which child, if any, had accessibility focus. This must
        // occur before recycling any views, since that will clear
        // accessibility focus.
        final ViewRootImpl viewRootImpl = getViewRootImpl();
        if (viewRootImpl != null) {
            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
            if (focusHost != null) {
                final View focusChild = getAccessibilityFocusedChild(focusHost);
                if (focusChild != null) {
                    if (!dataChanged || focusChild.hasTransientState() || mAdapterHasStableIds) {
                        // The views won't be changing, so try to maintain
                        // focus on the current host and virtual view.
                        accessibilityFocusLayoutRestoreView = focusHost;
                        accessibilityFocusLayoutRestoreNode = viewRootImpl.getAccessibilityFocusedVirtualView();
                    }
                    // Try to maintain focus at the same position.
                    accessibilityFocusPosition = getPositionForView(focusChild);
                }
            }
        }
        // Pull all children into the RecycleBin.
        // These views will be reused if possible
        final int firstPosition = mFirstPosition;
        final RecycleBin recycleBin = mRecycler;
        if (dataChanged) {
            for (int i = 0; i < childCount; i++) {
                recycleBin.addScrapView(getChildAt(i), firstPosition + i);
            }
        } else {
            recycleBin.fillActiveViews(childCount, firstPosition);
        }
        // Clear out old views
        detachAllViewsFromParent();
        recycleBin.removeSkippedScrap();
        switch(mLayoutMode) {
            case LAYOUT_SET_SELECTION:
                if (newSel != null) {
                    sel = fillFromSelection(newSel.getTop(), childrenTop, childrenBottom);
                } else {
                    sel = fillSelection(childrenTop, childrenBottom);
                }
                break;
            case LAYOUT_FORCE_TOP:
                mFirstPosition = 0;
                sel = fillFromTop(childrenTop);
                adjustViewsUpOrDown();
                break;
            case LAYOUT_FORCE_BOTTOM:
                sel = fillUp(mItemCount - 1, childrenBottom);
                adjustViewsUpOrDown();
                break;
            case LAYOUT_SPECIFIC:
                sel = fillSpecific(mSelectedPosition, mSpecificTop);
                break;
            case LAYOUT_SYNC:
                sel = fillSpecific(mSyncPosition, mSpecificTop);
                break;
            case LAYOUT_MOVE_SELECTION:
                // Move the selection relative to its old position
                sel = moveSelection(delta, childrenTop, childrenBottom);
                break;
            default:
                if (childCount == 0) {
                    if (!mStackFromBottom) {
                        setSelectedPositionInt(mAdapter == null || isInTouchMode() ? INVALID_POSITION : 0);
                        sel = fillFromTop(childrenTop);
                    } else {
                        final int last = mItemCount - 1;
                        setSelectedPositionInt(mAdapter == null || isInTouchMode() ? INVALID_POSITION : last);
                        sel = fillFromBottom(last, childrenBottom);
                    }
                } else {
                    if (mSelectedPosition >= 0 && mSelectedPosition < mItemCount) {
                        sel = fillSpecific(mSelectedPosition, oldSel == null ? childrenTop : oldSel.getTop());
                    } else if (mFirstPosition < mItemCount) {
                        sel = fillSpecific(mFirstPosition, oldFirst == null ? childrenTop : oldFirst.getTop());
                    } else {
                        sel = fillSpecific(0, childrenTop);
                    }
                }
                break;
        }
        // Flush any cached views that did not get reused above
        recycleBin.scrapActiveViews();
        if (sel != null) {
            positionSelector(INVALID_POSITION, sel);
            mSelectedTop = sel.getTop();
        } else {
            final boolean inTouchMode = mTouchMode > TOUCH_MODE_DOWN && mTouchMode < TOUCH_MODE_SCROLL;
            if (inTouchMode) {
                // If the user's finger is down, select the motion position.
                final View child = getChildAt(mMotionPosition - mFirstPosition);
                if (child != null) {
                    positionSelector(mMotionPosition, child);
                }
            } else if (mSelectedPosition != INVALID_POSITION) {
                // If we had previously positioned the selector somewhere,
                // put it back there. It might not match up with the data,
                // but it's transitioning out so it's not a big deal.
                final View child = getChildAt(mSelectorPosition - mFirstPosition);
                if (child != null) {
                    positionSelector(mSelectorPosition, child);
                }
            } else {
                // Otherwise, clear selection.
                mSelectedTop = 0;
                mSelectorRect.setEmpty();
            }
        }
        // Attempt to restore accessibility focus, if necessary.
        if (viewRootImpl != null) {
            final View newAccessibilityFocusedView = viewRootImpl.getAccessibilityFocusedHost();
            if (newAccessibilityFocusedView == null) {
                if (accessibilityFocusLayoutRestoreView != null && accessibilityFocusLayoutRestoreView.isAttachedToWindow()) {
                    final AccessibilityNodeProvider provider = accessibilityFocusLayoutRestoreView.getAccessibilityNodeProvider();
                    if (accessibilityFocusLayoutRestoreNode != null && provider != null) {
                        final int virtualViewId = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityFocusLayoutRestoreNode.getSourceNodeId());
                        provider.performAction(virtualViewId, AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
                    } else {
                        accessibilityFocusLayoutRestoreView.requestAccessibilityFocus();
                    }
                } else if (accessibilityFocusPosition != INVALID_POSITION) {
                    // Bound the position within the visible children.
                    final int position = MathUtils.constrain(accessibilityFocusPosition - mFirstPosition, 0, getChildCount() - 1);
                    final View restoreView = getChildAt(position);
                    if (restoreView != null) {
                        restoreView.requestAccessibilityFocus();
                    }
                }
            }
        }
        mLayoutMode = LAYOUT_NORMAL;
        mDataChanged = false;
        if (mPositionScrollAfterLayout != null) {
            post(mPositionScrollAfterLayout);
            mPositionScrollAfterLayout = null;
        }
        mNeedSync = false;
        setNextSelectedPositionInt(mSelectedPosition);
        updateScrollIndicators();
        if (mItemCount > 0) {
            checkSelectionChanged();
        }
        invokeOnItemScrollListener();
    } finally {
        if (!blockLayoutRequests) {
            mBlockLayoutRequests = false;
        }
    }
}
Also used : ViewRootImpl(android.view.ViewRootImpl) AccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo) RemoteView(android.widget.RemoteViews.RemoteView) View(android.view.View) AccessibilityNodeProvider(android.view.accessibility.AccessibilityNodeProvider)

Example 10 with AccessibilityNodeProvider

use of android.view.accessibility.AccessibilityNodeProvider in project android_frameworks_base by DirtyUnicorns.

the class AccessibilityInteractionController method findFocusUiThread.

private void findFocusUiThread(Message message) {
    final int flags = message.arg1;
    final int focusType = message.arg2;
    SomeArgs args = (SomeArgs) message.obj;
    final int interactionId = args.argi1;
    final int accessibilityViewId = args.argi2;
    final int virtualDescendantId = args.argi3;
    final IAccessibilityInteractionConnectionCallback callback = (IAccessibilityInteractionConnectionCallback) args.arg1;
    final MagnificationSpec spec = (MagnificationSpec) args.arg2;
    final Region interactiveRegion = (Region) args.arg3;
    args.recycle();
    AccessibilityNodeInfo focused = null;
    try {
        if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
            return;
        }
        mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
        View root = null;
        if (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
            root = findViewByAccessibilityId(accessibilityViewId);
        } else {
            root = mViewRootImpl.mView;
        }
        if (root != null && isShown(root)) {
            switch(focusType) {
                case AccessibilityNodeInfo.FOCUS_ACCESSIBILITY:
                    {
                        View host = mViewRootImpl.mAccessibilityFocusedHost;
                        // of the root from which to start the search, then the search failed.
                        if (host == null || !ViewRootImpl.isViewDescendantOf(host, root)) {
                            break;
                        }
                        // The focused view not shown, we failed.
                        if (!isShown(host)) {
                            break;
                        }
                        // If the host has a provider ask this provider to search for the
                        // focus instead fetching all provider nodes to do the search here.
                        AccessibilityNodeProvider provider = host.getAccessibilityNodeProvider();
                        if (provider != null) {
                            if (mViewRootImpl.mAccessibilityFocusedVirtualView != null) {
                                focused = AccessibilityNodeInfo.obtain(mViewRootImpl.mAccessibilityFocusedVirtualView);
                            }
                        } else if (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
                            focused = host.createAccessibilityNodeInfo();
                        }
                    }
                    break;
                case AccessibilityNodeInfo.FOCUS_INPUT:
                    {
                        View target = root.findFocus();
                        if (target == null || !isShown(target)) {
                            break;
                        }
                        AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
                        if (provider != null) {
                            focused = provider.findFocus(focusType);
                        }
                        if (focused == null) {
                            focused = target.createAccessibilityNodeInfo();
                        }
                    }
                    break;
                default:
                    throw new IllegalArgumentException("Unknown focus type: " + focusType);
            }
        }
    } finally {
        try {
            mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
            applyAppScaleAndMagnificationSpecIfNeeded(focused, spec);
            // system process and obtained from a pool when read from parcel.
            if (spec != null && android.os.Process.myPid() != Binder.getCallingPid()) {
                spec.recycle();
            }
            adjustIsVisibleToUserIfNeeded(focused, interactiveRegion);
            callback.setFindAccessibilityNodeInfoResult(focused, interactionId);
        } catch (RemoteException re) {
        /* ignore - the other side will time out */
        }
        // the system process and instantiated  when read from parcel.
        if (interactiveRegion != null && android.os.Process.myPid() == Binder.getCallingPid()) {
            interactiveRegion.recycle();
        }
    }
}
Also used : IAccessibilityInteractionConnectionCallback(android.view.accessibility.IAccessibilityInteractionConnectionCallback) SomeArgs(com.android.internal.os.SomeArgs) AccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo) Region(android.graphics.Region) RemoteException(android.os.RemoteException) AccessibilityNodeProvider(android.view.accessibility.AccessibilityNodeProvider) Point(android.graphics.Point)

Aggregations

AccessibilityNodeProvider (android.view.accessibility.AccessibilityNodeProvider)63 AccessibilityNodeInfo (android.view.accessibility.AccessibilityNodeInfo)45 Point (android.graphics.Point)36 RemoteException (android.os.RemoteException)18 IAccessibilityInteractionConnectionCallback (android.view.accessibility.IAccessibilityInteractionConnectionCallback)18 SomeArgs (com.android.internal.os.SomeArgs)18 View (android.view.View)11 ViewRootImpl (android.view.ViewRootImpl)11 RemoteView (android.widget.RemoteViews.RemoteView)11 Paint (android.graphics.Paint)10 Region (android.graphics.Region)10 Rect (android.graphics.Rect)7 AccessibilityManager (android.view.accessibility.AccessibilityManager)7 Bundle (android.os.Bundle)6 ArrayList (java.util.ArrayList)6 List (java.util.List)6 AttachInfo (android.view.View.AttachInfo)5 LinkedList (java.util.LinkedList)5 Drawable (android.graphics.drawable.Drawable)2