Java Code Examples for android.view.accessibility.AccessibilityNodeInfo#recycle()

The following examples show how to use android.view.accessibility.AccessibilityNodeInfo#recycle() . 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: TreeDebugNavigationMode.java    From brailleback with Apache License 2.0 6 votes vote down vote up
private AccessibilityNodeInfo getLastDescendantDfs(
    AccessibilityNodeInfo from) {
    AccessibilityNodeInfo lastChild = getLastChild(from);
    if (lastChild == null) {
        return null;
    }
    while (true) {
        AccessibilityNodeInfo lastGrandChild = getLastChild(lastChild);
        if (lastGrandChild != null) {
            lastChild.recycle();
            lastChild = lastGrandChild;
        } else {
            break;
        }
    }
    return lastChild;
}
 
Example 2
Source File: AccessibilityNodeInfoRef.java    From oversec with GNU General Public License v3.0 6 votes vote down vote up
/**
 * Traverses to the first child of this node if any, returning
 * {@code true} on success.
 */
public boolean firstChild() {
    if (mNode == null) {
        return false;
    }
    int childCount = mNode.getChildCount();
    for (int i = 0; i < childCount; ++i) {
        AccessibilityNodeInfo newNode = mNode.getChild(i);
        if (newNode == null) {
            return false;
        }
        if (AccessibilityNodeInfoUtils.isVisibleOrLegacy(newNode)) {
            reset(newNode);
            return true;
        }
        newNode.recycle();
    }
    return false;
}
 
Example 3
Source File: AccessibilityNodeInfoUtils.java    From oversec with GNU General Public License v3.0 6 votes vote down vote up
private static AccessibilityNodeInfo refreshFromChild(
        AccessibilityNodeInfo node) {
    if (node.getChildCount() > 0) {
        AccessibilityNodeInfo firstChild = node.getChild(0);
        if (firstChild != null) {
            AccessibilityNodeInfo parent = firstChild.getParent();
            firstChild.recycle();
            if (node.equals(parent)) {
                return parent;
            } else {
                recycleNodes(parent);
            }
        }
    }
    return null;
}
 
Example 4
Source File: UiTree.java    From AutoInteraction-Library with Apache License 2.0 6 votes vote down vote up
public static AccessibilityNodeInfo getRootAccessibilityNodeInfo(@NonNull AccessibilityNodeInfo accessibilityNodeInfo) throws MyException {
    if (null == accessibilityNodeInfo) {
        throw new NullPointerException("accessibilityNodeInfo");
    }
    AccessibilityNodeInfo current = null;
    try {
        current = accessibilityNodeInfo;
        while (true) {
            AccessibilityNodeInfo parent = current.getParent();
            if (null == parent) {
                return current;
            }
            current = parent;
        }
    } catch (Exception e) {
        if (null != current) {
            current.recycle();
        }
        throw new MyException(e);
    }
}
 
Example 5
Source File: WindowManager.java    From talkback with Apache License 2.0 6 votes vote down vote up
/** Gets the window whose anchor equals the given node. */
public @Nullable AccessibilityWindowInfo getAnchoredWindow(
    @Nullable AccessibilityNodeInfoCompat targetAnchor) {
  if (!BuildVersionUtils.isAtLeastN() || targetAnchor == null) {
    return null;
  }

  int windowCount = mWindows.size();
  for (int i = 0; i < windowCount; ++i) {
    AccessibilityWindowInfo window = mWindows.get(i);
    if (window != null) {
      AccessibilityNodeInfo anchor = window.getAnchor();
      if (anchor != null) {
        try {
          if (anchor.equals(targetAnchor.unwrap())) {
            return window;
          }
        } finally {
          anchor.recycle();
        }
      }
    }
  }

  return null;
}
 
Example 6
Source File: WechatAccService.java    From RedEnvelopeAssistant with MIT License 6 votes vote down vote up
public void handleLuckyMoneyReceivePage(AccessibilityNodeInfo node) {
	if (node == null)
		return;
	LogUtil.d("handleLuckyMoneyReceivePage");
	AccessibilityNodeInfo nodeDetail = RedEnvelopeHelper.getWechatRedEnvelopeOpenDetailNode(node);
	LogUtil.d("nodeDetail="+nodeDetail);
	if (nodeDetail != null) {// the red envelope already opened
								// 红包已经被打开
		if (SettingHelper.getREAutoMode())
			ActivityHelper.goHome(this);
	} else {
		AccessibilityNodeInfo nodeOpen = RedEnvelopeHelper.getWechatRedEnvelopeOpenNode(node);
		LogUtil.d("nodeOpen="+nodeOpen);
		if (nodeOpen != null) {
			nodeOpen.performAction(AccessibilityNodeInfo.ACTION_CLICK);
			nodeOpen.recycle();
		} else {// this page is loading red envelope data, no action

		}
	}
}
 
Example 7
Source File: OversecAccessibilityService.java    From oversec with GNU General Public License v3.0 6 votes vote down vote up
public synchronized void performActionOnFocusedNode(PerformFocusedNodeAction action) {
    AccessibilityNodeInfo focusedNode = null;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        focusedNode = findFocus(AccessibilityNodeInfo.FOCUS_INPUT);
    }
    //In case we're dealing with a webView, findFocus won't work and just remove the top frame,
    //so check if the focused node makes sense and if not, fall back to findFocus_PreLollipop
    if (focusedNode == null || !mTree.isAEditText(focusedNode)) {
        focusedNode = findFocus_PreLollipop();
    }
    if (focusedNode == null) {
        action.performActionWhenNothingFocused();
    } else {
        action.performAction(focusedNode);
        focusedNode.recycle();
    }
}
 
Example 8
Source File: AccessibilityNodeInfoRef.java    From oversec with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Traverses to the next sibling of this node within its parent, returning
 * {@code true} on success.
 */
public boolean nextSibling() {
    if (mNode == null) {
        return false;
    }
    AccessibilityNodeInfo parent = mNode.getParent();
    if (parent == null) {
        return false;
    }
    try {
        int childCount = parent.getChildCount();
        int childNumber = getChildNumber(parent);
        if (childNumber < 0) {
            return false;
        }
        for (int i = childNumber + 1; i < childCount; ++i) {
            AccessibilityNodeInfo newNode =
                    parent.getChild(i);
            if (newNode == null) {
                return false;
            }
            if (AccessibilityNodeInfoUtils.isVisibleOrLegacy(newNode)) {
                reset(newNode);
                return true;
            }
            newNode.recycle();
        }
    } finally {
        parent.recycle();
    }
    return false;
}
 
Example 9
Source File: AccessibilityNodeInfoRef.java    From oversec with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Traverses to the previous sibling of this node within its parent,
 * returning {@code true} on success.
 */
public boolean previousSibling() {
    if (mNode == null) {
        return false;
    }
    AccessibilityNodeInfo parent = mNode.getParent();
    if (parent == null) {
        return false;
    }
    try {
        int childNumber = getChildNumber(parent);
        for (int i = childNumber - 1; i >= 0; --i) {
            AccessibilityNodeInfo newNode = parent.getChild(i);
            if (newNode == null) {
                return false;
            }
            if (AccessibilityNodeInfoUtils.isVisibleOrLegacy(newNode)) {
                reset(newNode);
                return true;
            }
            newNode.recycle();
        }
    } finally {
        parent.recycle();
    }
    return false;
}
 
Example 10
Source File: CustomLabelManager.java    From brailleback with Apache License 2.0 5 votes vote down vote up
/**
 * Creates a {@link Label} and persists it to the label database, and
 * refreshes the label cache.
 * <p>
 * NOTE: This method will not attempt to recycle {@code node}.
 *
 * @param node The node to label
 * @param userLabel The label provided for the node by the user
 */
public void addLabel(AccessibilityNodeInfo node, String userLabel) {
    if (node == null) {
        throw new IllegalArgumentException("Attempted to add a label for a null node.");
    }

    final AccessibilityNodeInfo internalNodeCopy = AccessibilityNodeInfo.obtain(node);
    addLabel(internalNodeCopy.getViewIdResourceName(), userLabel);
    internalNodeCopy.recycle();
}
 
Example 11
Source File: AccessibilityNode.java    From talkback with Apache License 2.0 5 votes vote down vote up
private final void recycle(AccessibilityNodeInfo node, String caller) {
  try {
    node.recycle();
  } catch (IllegalStateException e) {
    logOrThrow(
        e,
        "Caught IllegalStateException from accessibility framework with %s trying to recycle"
            + " node %s",
        caller,
        node);
  }
}
 
Example 12
Source File: CustomActionsPopup.java    From LaunchEnr with GNU General Public License v3.0 5 votes vote down vote up
private List<AccessibilityAction> getActionList() {
    if (mIcon == null || !(mIcon.getTag() instanceof ItemInfo)) {
        return Collections.EMPTY_LIST;
    }

    AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
    mDelegate.addSupportedActions(mIcon, info, true);
    List<AccessibilityAction> result = new ArrayList<>(info.getActionList());
    info.recycle();
    return result;
}
 
Example 13
Source File: OversecAccessibilityService.java    From oversec with GNU General Public License v3.0 5 votes vote down vote up
private void scrapeCompleteSubtree_MAIN(Tree.TreeNode treeNode, AccessibilityNodeInfo node, PerformNodeAction nodeAction) {
    checkHandlerThread();

    node.refresh();

    checkFocusedNode_PreLollipop(node);

    if (!node.isVisibleToUser()) {
        return;
    }

    int cc = node.getChildCount();

    for (int i = 0; i < cc; i++) {
        AccessibilityNodeInfo child = node.getChild(i);


        if (child != null) {
            Tree.TreeNode childTreeNode = mTree.put(child);
            treeNode.addChild(childTreeNode);
            if (nodeAction != null) {
                nodeAction.onNodeScanned(child);
            }
            scrapeCompleteSubtree_MAIN(childTreeNode, child, nodeAction);
            child.recycle();
        } else {
            Ln.d("SKRAPE: warning, couldn't get a child!");
            //TODO: one reason for this might be a too large binder transaction -> maybe at least give some feedback to the user
        }
    }

}
 
Example 14
Source File: FocusFinder.java    From talkback with Apache License 2.0 5 votes vote down vote up
public static @Nullable AccessibilityNodeInfoCompat getFocusedNode(
    AccessibilityService service, boolean fallbackOnRoot) {
  AccessibilityNodeInfo root = service.getRootInActiveWindow();
  AccessibilityNodeInfo focused = null;

  try {
    AccessibilityNodeInfo ret = null;
    if (root != null) {
      focused = root.findFocus(AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
      if (focused != null && focused.isVisibleToUser()) {
        ret = focused;
        focused = null;
      } else if (fallbackOnRoot) {
        ret = root;
        root = null;
      }
    } else {
      LogUtils.e(TAG, "No current window root");
    }

    if (ret != null) {
      return AccessibilityNodeInfoUtils.toCompat(ret);
    }
  } finally {
    if (root != null) {
      root.recycle();
    }

    if (focused != null) {
      focused.recycle();
    }
  }

  return null;
}
 
Example 15
Source File: EventFilter.java    From talkback with Apache License 2.0 5 votes vote down vote up
private boolean isValidScrollEvent(AccessibilityEvent event) {
  AccessibilityNodeInfo source = event.getSource();
  if (source == null) {
    return true; // Cannot check source validity, so assume that it's scrollable.
  }

  boolean valid =
      source.isScrollable() || event.getMaxScrollX() != -1 || event.getMaxScrollY() != -1;
  source.recycle();
  return valid;
}
 
Example 16
Source File: TreeDebugNavigationMode.java    From brailleback with Apache License 2.0 5 votes vote down vote up
private AccessibilityNodeInfo getNextSibling(
    AccessibilityNodeInfo from) {
    AccessibilityNodeInfo parent = from.getParent();
    if (parent == null) {
        return null;
    }
    AccessibilityNodeInfo cur = null;
    try {
        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount - 1; ++i) {
            cur = parent.getChild(i);
            if (cur == null) {
                return null;
            }
            if (cur.equals(from)) {
                return parent.getChild(i + 1);
            }
            if (cur != null) {
                cur.recycle();
                cur = null;
            }
        }
    } finally {
        parent.recycle();
        if (cur != null) {
            cur.recycle();
        }
    }
    return null;
}
 
Example 17
Source File: OversecAccessibilityService.java    From oversec with GNU General Public License v3.0 4 votes vote down vote up
private void handleScrapeAll_MAIN(String reason, PerformNodeAction nodeAction) {
        checkHandlerThread();

        mTree.clear();
        AccessibilityNodeInfo rootNode = null;
        try {
            rootNode = getRootInActiveWindow();
        } catch (Exception ex) {
            Ln.e(ex);
            return;
        }
        try {
            if (rootNode != null) {

                //fail-fast if this is not a package we're interested in
                CharSequence csPackageName = rootNode.getPackageName();
                if (csPackageName == null) return;
                String aPackageName = rootNode.getPackageName().toString();
                boolean ours = mCore.getDb().isShowDecryptOverlay(aPackageName);
                if (!ours) {
                    mCore.onAcsScrapeCompleted(aPackageName, null);
                    return;
                }

                findFocusedNodePreLollipop_startTransaction();
                if (LoggingConfig.INSTANCE.getLOG()) {
                    Ln.d("SKRAPE: FULL SCAN, root=%s", rootNode.hashCode());
                }

                mTree.addRootNode(rootNode);

                scrapeSubtree_MAIN(rootNode, "handleScrapeAll_MAIN-> " + reason, nodeAction);

                rootNode.recycle();

                findFocusedNodePreLollipop_commitTransaction();

                publishChanges_MAIN();


            } else {
                Ln.w("SKRAPE: getRootInActiveWindow returned null node!");
                clearFocusedNode_PreLollipop();
                //TODO: one reason for this might be a too large binder transaction -> maybe at least give some feedback to the user
                //TODO: or somehow scrape sub-nodes first in order to have separate smalle transactions?#
//            How to Prevent MAX binder transaction / max parcel overflow, Could happen when getting a list node with many immediate GPG text views (the listnode prefetches its children, and if all of them have a long pgp encoded text, this may just be too much for a single binder transaction)
//            size is 1 mb, let's say 50 nodes gives 20 k per node,   worst case every character is encoded with 4 bytes gives 5 k text!!!  -> might just be enough for pgp
//                    >hmmm, prefetching descendants works recursively, but will always fetch max. 50 nodes,
//            -> hopefully not needed but there's noreal way around it!other than using reflection to get the child node's IDs and then manually doing refresh

            }

        } finally {
            if (nodeAction != null) {
                nodeAction.onScrapeComplete();
            }
        }

    }
 
Example 18
Source File: AccessibilityNodeInfoDumper.java    From android-uiconductor with Apache License 2.0 4 votes vote down vote up
private static void dumpNodeRec(
    AccessibilityNodeInfo node,
    XmlSerializer serializer,
    int index,
    int width,
    int height,
    boolean withClassName)
    throws IOException {
  serializer.startTag("", withClassName ? safeTagString(node.getClassName()) : "node");

  if (!nafExcludedClass(node) && !nafCheck(node)) {
    serializer.attribute("", "NAF", Boolean.toString(true));
  }
  serializer.attribute("", "index", Integer.toString(index));
  final String text;
  if (node.getRangeInfo() == null) {
    text = safeCharSeqToString(node.getText());
  } else {
    text = Float.toString(node.getRangeInfo().getCurrent());
  }
  serializer.attribute("", "text", text);
  serializer.attribute("", "class", safeCharSeqToString(node.getClassName()));
  serializer.attribute("", "package", safeCharSeqToString(node.getPackageName()));
  serializer.attribute("", "content-desc", safeCharSeqToString(node.getContentDescription()));
  serializer.attribute("", "checkable", Boolean.toString(node.isCheckable()));
  serializer.attribute("", "checked", Boolean.toString(node.isChecked()));
  serializer.attribute("", "clickable", Boolean.toString(node.isClickable()));
  serializer.attribute("", "enabled", Boolean.toString(node.isEnabled()));
  serializer.attribute("", "focusable", Boolean.toString(node.isFocusable()));
  serializer.attribute("", "focused", Boolean.toString(node.isFocused()));
  serializer.attribute("", "scrollable", Boolean.toString(node.isScrollable()));
  serializer.attribute("", "long-clickable", Boolean.toString(node.isLongClickable()));
  serializer.attribute("", "password", Boolean.toString(node.isPassword()));
  serializer.attribute("", "selected", Boolean.toString(node.isSelected()));

  /** True if the device is >= API 18 */
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
    serializer.attribute(
        "", "bounds", getVisibleBoundsInScreen(node, width, height).toShortString());
    serializer.attribute("", "resource-id", safeCharSeqToString(node.getViewIdResourceName()));
  }

  int count = node.getChildCount();
  for (int i = 0; i < count; i++) {
    AccessibilityNodeInfo child = node.getChild(i);
    if (child != null) {
      if (child.isVisibleToUser()) {
        dumpNodeRec(child, serializer, i, width, height, withClassName);
        child.recycle();
      } else {
        Log.i(TAG, String.format("Skipping invisible child: %s", child.toString()));
      }
    } else {
      Log.i(TAG, String.format("Null child %d/%d, parent: %s", i, count, node.toString()));
    }
  }
  serializer.endTag("", withClassName ? safeTagString(node.getClassName()) : "node");
}
 
Example 19
Source File: ByMatcher.java    From JsDroidCmd with Mozilla Public License 2.0 4 votes vote down vote up
/**
 * Traverses the {@link AccessibilityNodeInfo} hierarchy starting at {@code node}, and returns
 * a list of nodes which match the {@code selector} criteria. <br />
 * <strong>Note:</strong> The caller must release each {@link AccessibilityNodeInfo} instance
 * by calling {@link AccessibilityNodeInfo#recycle()} to avoid leaking resources.
 *
 * @param node The root of the {@link AccessibilityNodeInfo} subtree we are currently searching.
 * @param index The index of this node underneath its parent.
 * @param depth The distance between {@code node} and the root node.
 * @param partialMatches The current list of {@link PartialMatch}es that need to be updated.
 * @return A {@link List} of {@link AccessibilityNodeInfo}s that meet the search criteria.
 */
private List<AccessibilityNodeInfo> findMatches(AccessibilityNodeInfo node,
        int index, int depth, SinglyLinkedList<PartialMatch> partialMatches) {

    List<AccessibilityNodeInfo> ret = new ArrayList<AccessibilityNodeInfo>();

    // Don't bother searching the subtree if it is not visible
    if (!node.isVisibleToUser()) {
        return ret;
    }

    // Update partial matches
    for (PartialMatch partialMatch : partialMatches) {
        partialMatches = partialMatch.update(node, index, depth, partialMatches);
    }

    // Create a new match, if necessary
    PartialMatch currentMatch = PartialMatch.accept(node, mSelector, index, depth);
    if (currentMatch != null) {
        partialMatches = SinglyLinkedList.prepend(currentMatch, partialMatches);
    }

    // For each child
    int numChildren = node.getChildCount();
    boolean hasNullChild = false;
    for (int i = 0; i < numChildren; i++) {
        AccessibilityNodeInfo child = node.getChild(i);
        if (child == null) {
            if (!hasNullChild) {
                Log.w(TAG, String.format("Node returned null child: %s", node.toString()));
            }
            hasNullChild = true;
            Log.w(TAG, String.format("Skipping null child (%s of %s)", i, numChildren));
            continue;
        }

        // Add any matches found under the child subtree
        ret.addAll(findMatches(child, i, depth + 1, partialMatches));

        // We're done with the child
        child.recycle();

        // Return early if we sound a match and shortCircuit is true
        if (!ret.isEmpty() && mShortCircuit) {
            return ret;
        }
    }

    // Finalize match, if necessary
    if (currentMatch != null && currentMatch.finalizeMatch()) {
        ret.add(AccessibilityNodeInfo.obtain(node));
    }

    return ret;
}
 
Example 20
Source File: WindowHierarchyElementAndroid.java    From Accessibility-Test-Framework-for-Android with Apache License 2.0 4 votes vote down vote up
private WindowHierarchyElementAndroid construct(
    int id,
    @Nullable WindowHierarchyElementAndroid parent,
    AccessibilityWindowInfo fromWindow,
    Map<ViewHierarchyElementAndroid, AccessibilityNodeInfo> elementToNodeInfoMap) {
  // Bookkeeping
  this.parentId = (parent != null) ? parent.getId() : null;

  // Window properties
  this.windowId = fromWindow.getId();
  this.layer = fromWindow.getLayer();
  this.type = fromWindow.getType();
  this.focused = fromWindow.isFocused();
  this.accessibilityFocused = fromWindow.isAccessibilityFocused();
  this.active = fromWindow.isActive();

  android.graphics.Rect tempRect = new android.graphics.Rect();
  fromWindow.getBoundsInScreen(tempRect);
  this.boundsInScreen = new Rect(tempRect.left, tempRect.top, tempRect.right, tempRect.bottom);

  // Build the window's view hierarchy
  AccessibilityNodeInfo rootInfo = fromWindow.getRoot();
  this.viewHierarchyElements = new ArrayList<>(); // The ultimate size is unknown
  if (rootInfo != null) {
    buildViewHierarchy(
        rootInfo, viewHierarchyElements, null /* no parent */, elementToNodeInfoMap);
    rootInfo.recycle();
  } else {
    // This could occur in the case where the application state changes between the time that
    // the AccessibilityWindowInfo object is obtained and when its root AccessibilityNodeInfo is
    // extracted.
    LogUtils.w(TAG, "Constructed WindowHierarchyElement with no valid root.");
  }
  return new WindowHierarchyElementAndroid(
      id,
      parentId,
      childIds,
      windowId,
      layer,
      type,
      focused,
      accessibilityFocused,
      active,
      boundsInScreen,
      viewHierarchyElements);
}