use of android.view.accessibility.AccessibilityNodeInfo in project android_frameworks_base by DirtyUnicorns.
the class ExploreByTouchHelper method createNodeForHost.
/**
* Constructs and returns an {@link AccessibilityNodeInfo} for the
* host view populated with its virtual descendants.
*
* @return An {@link AccessibilityNodeInfo} for the parent node.
*/
private AccessibilityNodeInfo createNodeForHost() {
final AccessibilityNodeInfo node = AccessibilityNodeInfo.obtain(mView);
mView.onInitializeAccessibilityNodeInfo(node);
final int realNodeCount = node.getChildCount();
// Allow the client to populate the host node.
onPopulateNodeForHost(node);
// Add the virtual descendants.
if (mTempArray == null) {
mTempArray = new IntArray();
} else {
mTempArray.clear();
}
final IntArray virtualViewIds = mTempArray;
getVisibleVirtualViews(virtualViewIds);
if (realNodeCount > 0 && virtualViewIds.size() > 0) {
throw new RuntimeException("Views cannot have both real and virtual children");
}
final int N = virtualViewIds.size();
for (int i = 0; i < N; i++) {
node.addChild(mView, virtualViewIds.get(i));
}
return node;
}
use of android.view.accessibility.AccessibilityNodeInfo in project android_frameworks_base by DirtyUnicorns.
the class ExploreByTouchHelper method createNodeForChild.
/**
* Constructs and returns an {@link AccessibilityNodeInfo} for the
* specified item. Automatically manages accessibility focus actions.
* <p>
* Allows the implementing class to specify most node properties, but
* overrides the following:
* <ul>
* <li>{@link AccessibilityNodeInfo#setPackageName}
* <li>{@link AccessibilityNodeInfo#setClassName}
* <li>{@link AccessibilityNodeInfo#setParent(View)}
* <li>{@link AccessibilityNodeInfo#setSource(View, int)}
* <li>{@link AccessibilityNodeInfo#setVisibleToUser}
* <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)}
* </ul>
* <p>
* Uses the bounds of the parent view and the parent-relative bounding
* rectangle specified by
* {@link AccessibilityNodeInfo#getBoundsInParent} to automatically
* update the following properties:
* <ul>
* <li>{@link AccessibilityNodeInfo#setVisibleToUser}
* <li>{@link AccessibilityNodeInfo#setBoundsInParent}
* </ul>
*
* @param virtualViewId The virtual view id for item for which to construct
* a node.
* @return An {@link AccessibilityNodeInfo} for the specified item.
*/
private AccessibilityNodeInfo createNodeForChild(int virtualViewId) {
ensureTempRects();
final Rect tempParentRect = mTempParentRect;
final int[] tempGlobalRect = mTempGlobalRect;
final Rect tempScreenRect = mTempScreenRect;
final AccessibilityNodeInfo node = AccessibilityNodeInfo.obtain();
// Ensure the client has good defaults.
node.setEnabled(true);
node.setClassName(DEFAULT_CLASS_NAME);
node.setBoundsInParent(INVALID_PARENT_BOUNDS);
// Allow the client to populate the node.
onPopulateNodeForVirtualView(virtualViewId, node);
// Make sure the developer is following the rules.
if ((node.getText() == null) && (node.getContentDescription() == null)) {
throw new RuntimeException("Callbacks must add text or a content description in " + "populateNodeForVirtualViewId()");
}
node.getBoundsInParent(tempParentRect);
if (tempParentRect.equals(INVALID_PARENT_BOUNDS)) {
throw new RuntimeException("Callbacks must set parent bounds in " + "populateNodeForVirtualViewId()");
}
final int actions = node.getActions();
if ((actions & AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) != 0) {
throw new RuntimeException("Callbacks must not add ACTION_ACCESSIBILITY_FOCUS in " + "populateNodeForVirtualViewId()");
}
if ((actions & AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS) != 0) {
throw new RuntimeException("Callbacks must not add ACTION_CLEAR_ACCESSIBILITY_FOCUS in " + "populateNodeForVirtualViewId()");
}
// Don't allow the client to override these properties.
node.setPackageName(mView.getContext().getPackageName());
node.setSource(mView, virtualViewId);
node.setParent(mView);
// Manage internal accessibility focus state.
if (mFocusedVirtualViewId == virtualViewId) {
node.setAccessibilityFocused(true);
node.addAction(AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
} else {
node.setAccessibilityFocused(false);
node.addAction(AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS);
}
// Set the visibility based on the parent bound.
if (intersectVisibleToUser(tempParentRect)) {
node.setVisibleToUser(true);
node.setBoundsInParent(tempParentRect);
}
// Calculate screen-relative bound.
mView.getLocationOnScreen(tempGlobalRect);
final int offsetX = tempGlobalRect[0];
final int offsetY = tempGlobalRect[1];
tempScreenRect.set(tempParentRect);
tempScreenRect.offset(offsetX, offsetY);
node.setBoundsInScreen(tempScreenRect);
return node;
}
use of android.view.accessibility.AccessibilityNodeInfo in project android_frameworks_base by DirtyUnicorns.
the class TextView method onInitializeAccessibilityNodeInfoInternal.
/** @hide */
@Override
public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfoInternal(info);
final boolean isPassword = hasPasswordTransformationMethod();
info.setPassword(isPassword);
info.setText(getTextForAccessibility());
if (mBufferType == BufferType.EDITABLE) {
info.setEditable(true);
if (isEnabled()) {
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SET_TEXT);
}
}
if (mEditor != null) {
info.setInputType(mEditor.mInputType);
if (mEditor.mError != null) {
info.setContentInvalid(true);
info.setError(mEditor.mError);
}
}
if (!TextUtils.isEmpty(mText)) {
info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
}
if (isFocused()) {
if (canCopy()) {
info.addAction(AccessibilityNodeInfo.ACTION_COPY);
}
if (canPaste()) {
info.addAction(AccessibilityNodeInfo.ACTION_PASTE);
}
if (canCut()) {
info.addAction(AccessibilityNodeInfo.ACTION_CUT);
}
if (canShare()) {
info.addAction(new AccessibilityNodeInfo.AccessibilityAction(ACCESSIBILITY_ACTION_SHARE, getResources().getString(com.android.internal.R.string.share)));
}
if (canProcessText()) {
// also implies mEditor is not null.
mEditor.mProcessTextIntentActionsHandler.onInitializeAccessibilityNodeInfo(info);
}
}
// Check for known input filter types.
final int numFilters = mFilters.length;
for (int i = 0; i < numFilters; i++) {
final InputFilter filter = mFilters[i];
if (filter instanceof InputFilter.LengthFilter) {
info.setMaxTextLength(((InputFilter.LengthFilter) filter).getMax());
}
}
if (!isSingleLine()) {
info.setMultiLine(true);
}
}
use of android.view.accessibility.AccessibilityNodeInfo in project android_frameworks_base by AOSPA.
the class QueryController method findNodePatternRecursive.
private AccessibilityNodeInfo findNodePatternRecursive(UiSelector subSelector, AccessibilityNodeInfo fromNode, int index, UiSelector originalPattern) {
if (subSelector.isMatchFor(fromNode, index)) {
if (subSelector.isLeaf()) {
if (mPatternIndexer == 0) {
if (DEBUG)
Log.d(LOG_TAG, formatLog(String.format("%s", subSelector.dumpToString(false))));
return fromNode;
} else {
if (DEBUG)
Log.d(LOG_TAG, formatLog(String.format("%s", subSelector.dumpToString(false))));
//count the pattern matched
mPatternCounter++;
//decrement until zero for the instance requested
mPatternIndexer--;
// At a leaf selector within a group and still not instance matched
// then reset the selector to continue search from current position
// in the accessibility tree for the next pattern match up until the
// pattern index hits 0.
subSelector = originalPattern;
// starting over with next pattern search so reset to parent level
mLogIndent = mLogParentIndent;
}
} else {
if (DEBUG)
Log.d(LOG_TAG, formatLog(String.format("%s", subSelector.dumpToString(false))));
if (subSelector.hasChildSelector()) {
// next selector
mLogIndent++;
subSelector = subSelector.getChildSelector();
if (subSelector == null) {
Log.e(LOG_TAG, "Error: A child selector without content");
return null;
}
} else if (subSelector.hasParentSelector()) {
// next selector
mLogIndent++;
subSelector = subSelector.getParentSelector();
if (subSelector == null) {
Log.e(LOG_TAG, "Error: A parent selector without content");
return null;
}
fromNode = fromNode.getParent();
if (fromNode == null)
return null;
}
}
}
int childCount = fromNode.getChildCount();
boolean hasNullChild = false;
for (int i = 0; i < childCount; i++) {
AccessibilityNodeInfo childNode = fromNode.getChild(i);
if (childNode == null) {
Log.w(LOG_TAG, String.format("AccessibilityNodeInfo returned a null child (%d of %d)", i, childCount));
if (!hasNullChild) {
Log.w(LOG_TAG, String.format("parent = %s", fromNode.toString()));
}
hasNullChild = true;
continue;
}
if (!childNode.isVisibleToUser()) {
if (DEBUG)
Log.d(LOG_TAG, String.format("Skipping invisible child: %s", childNode.toString()));
continue;
}
AccessibilityNodeInfo retNode = findNodePatternRecursive(subSelector, childNode, i, originalPattern);
if (retNode != null) {
return retNode;
}
}
return null;
}
use of android.view.accessibility.AccessibilityNodeInfo in project android_frameworks_base by AOSPA.
the class QueryController method findAccessibilityNodeInfo.
protected AccessibilityNodeInfo findAccessibilityNodeInfo(UiSelector selector, boolean isCounting) {
mUiAutomatorBridge.waitForIdle();
initializeNewSearch();
if (DEBUG)
Log.d(LOG_TAG, "Searching: " + selector);
synchronized (mLock) {
AccessibilityNodeInfo rootNode = getRootNode();
if (rootNode == null) {
Log.e(LOG_TAG, "Cannot proceed when root node is null. Aborted search");
return null;
}
// Copy so that we don't modify the original's sub selectors
UiSelector uiSelector = new UiSelector(selector);
return translateCompoundSelector(uiSelector, rootNode, isCounting);
}
}
Aggregations