2 * Copyright (C) 2011 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package android.view.accessibility;
19 import android.accessibilityservice.AccessibilityService;
20 import android.accessibilityservice.AccessibilityServiceInfo;
21 import android.annotation.Nullable;
22 import android.graphics.Rect;
23 import android.os.Bundle;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 import android.text.InputType;
27 import android.text.TextUtils;
28 import android.util.ArraySet;
29 import android.util.LongArray;
30 import android.util.Pools.SynchronizedPool;
31 import android.view.View;
33 import com.android.internal.R;
35 import java.util.ArrayList;
36 import java.util.Collections;
37 import java.util.List;
40 * This class represents a node of the window content as well as actions that
41 * can be requested from its source. From the point of view of an
42 * {@link android.accessibilityservice.AccessibilityService} a window's content is
43 * presented as a tree of accessibility node infos, which may or may not map one-to-one
44 * to the view hierarchy. In other words, a custom view is free to report itself as
45 * a tree of accessibility node info.
48 * Once an accessibility node info is delivered to an accessibility service it is
49 * made immutable and calling a state mutation method generates an error.
52 * Please refer to {@link android.accessibilityservice.AccessibilityService} for
53 * details about how to obtain a handle to window content as a tree of accessibility
54 * node info as well as details about the security model.
56 * <div class="special reference">
57 * <h3>Developer Guides</h3>
58 * <p>For more information about making applications accessible, read the
59 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
60 * developer guide.</p>
63 * @see android.accessibilityservice.AccessibilityService
64 * @see AccessibilityEvent
65 * @see AccessibilityManager
67 public class AccessibilityNodeInfo implements Parcelable {
69 private static final boolean DEBUG = false;
72 public static final int UNDEFINED_CONNECTION_ID = -1;
75 public static final int UNDEFINED_SELECTION_INDEX = -1;
78 public static final int UNDEFINED_ITEM_ID = Integer.MAX_VALUE;
81 public static final long ROOT_NODE_ID = makeNodeId(UNDEFINED_ITEM_ID, UNDEFINED_ITEM_ID);
84 public static final int ACTIVE_WINDOW_ID = UNDEFINED_ITEM_ID;
87 public static final int ANY_WINDOW_ID = -2;
90 public static final int FLAG_PREFETCH_PREDECESSORS = 0x00000001;
93 public static final int FLAG_PREFETCH_SIBLINGS = 0x00000002;
96 public static final int FLAG_PREFETCH_DESCENDANTS = 0x00000004;
99 public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x00000008;
102 public static final int FLAG_REPORT_VIEW_IDS = 0x00000010;
107 * Action that gives input focus to the node.
109 public static final int ACTION_FOCUS = 0x00000001;
112 * Action that clears input focus of the node.
114 public static final int ACTION_CLEAR_FOCUS = 0x00000002;
117 * Action that selects the node.
119 public static final int ACTION_SELECT = 0x00000004;
122 * Action that deselects the node.
124 public static final int ACTION_CLEAR_SELECTION = 0x00000008;
127 * Action that clicks on the node info.
129 * See {@link AccessibilityAction#ACTION_CLICK}
131 public static final int ACTION_CLICK = 0x00000010;
134 * Action that long clicks on the node.
136 public static final int ACTION_LONG_CLICK = 0x00000020;
139 * Action that gives accessibility focus to the node.
141 public static final int ACTION_ACCESSIBILITY_FOCUS = 0x00000040;
144 * Action that clears accessibility focus of the node.
146 public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 0x00000080;
149 * Action that requests to go to the next entity in this node's text
150 * at a given movement granularity. For example, move to the next character,
153 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
154 * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
155 * <strong>Example:</strong> Move to the previous character and do not extend selection.
157 * Bundle arguments = new Bundle();
158 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
159 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
160 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
162 * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
166 * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
167 * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
169 * @see #setMovementGranularities(int)
170 * @see #getMovementGranularities()
172 * @see #MOVEMENT_GRANULARITY_CHARACTER
173 * @see #MOVEMENT_GRANULARITY_WORD
174 * @see #MOVEMENT_GRANULARITY_LINE
175 * @see #MOVEMENT_GRANULARITY_PARAGRAPH
176 * @see #MOVEMENT_GRANULARITY_PAGE
178 public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 0x00000100;
181 * Action that requests to go to the previous entity in this node's text
182 * at a given movement granularity. For example, move to the next character,
185 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
186 * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
187 * <strong>Example:</strong> Move to the next character and do not extend selection.
189 * Bundle arguments = new Bundle();
190 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
191 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
192 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
194 * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
199 * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
200 * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
202 * @see #setMovementGranularities(int)
203 * @see #getMovementGranularities()
205 * @see #MOVEMENT_GRANULARITY_CHARACTER
206 * @see #MOVEMENT_GRANULARITY_WORD
207 * @see #MOVEMENT_GRANULARITY_LINE
208 * @see #MOVEMENT_GRANULARITY_PARAGRAPH
209 * @see #MOVEMENT_GRANULARITY_PAGE
211 public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 0x00000200;
214 * Action to move to the next HTML element of a given type. For example, move
215 * to the BUTTON, INPUT, TABLE, etc.
217 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
218 * <strong>Example:</strong>
220 * Bundle arguments = new Bundle();
221 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
222 * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, arguments);
226 public static final int ACTION_NEXT_HTML_ELEMENT = 0x00000400;
229 * Action to move to the previous HTML element of a given type. For example, move
230 * to the BUTTON, INPUT, TABLE, etc.
232 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
233 * <strong>Example:</strong>
235 * Bundle arguments = new Bundle();
236 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
237 * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT, arguments);
241 public static final int ACTION_PREVIOUS_HTML_ELEMENT = 0x00000800;
244 * Action to scroll the node content forward.
246 public static final int ACTION_SCROLL_FORWARD = 0x00001000;
249 * Action to scroll the node content backward.
251 public static final int ACTION_SCROLL_BACKWARD = 0x00002000;
254 * Action to copy the current selection to the clipboard.
256 public static final int ACTION_COPY = 0x00004000;
259 * Action to paste the current clipboard content.
261 public static final int ACTION_PASTE = 0x00008000;
264 * Action to cut the current selection and place it to the clipboard.
266 public static final int ACTION_CUT = 0x00010000;
269 * Action to set the selection. Performing this action with no arguments
270 * clears the selection.
272 * <strong>Arguments:</strong>
273 * {@link #ACTION_ARGUMENT_SELECTION_START_INT},
274 * {@link #ACTION_ARGUMENT_SELECTION_END_INT}<br>
275 * <strong>Example:</strong>
277 * Bundle arguments = new Bundle();
278 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1);
279 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 2);
280 * info.performAction(AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments);
284 * @see #ACTION_ARGUMENT_SELECTION_START_INT
285 * @see #ACTION_ARGUMENT_SELECTION_END_INT
287 public static final int ACTION_SET_SELECTION = 0x00020000;
290 * Action to expand an expandable node.
292 public static final int ACTION_EXPAND = 0x00040000;
295 * Action to collapse an expandable node.
297 public static final int ACTION_COLLAPSE = 0x00080000;
300 * Action to dismiss a dismissable node.
302 public static final int ACTION_DISMISS = 0x00100000;
305 * Action that sets the text of the node. Performing the action without argument, using <code>
306 * null</code> or empty {@link CharSequence} will clear the text. This action will also put the
307 * cursor at the end of text.
309 * <strong>Arguments:</strong>
310 * {@link #ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br>
311 * <strong>Example:</strong>
313 * Bundle arguments = new Bundle();
314 * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
316 * info.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
319 public static final int ACTION_SET_TEXT = 0x00200000;
321 private static final int LAST_LEGACY_STANDARD_ACTION = ACTION_SET_TEXT;
324 * Mask to see if the value is larger than the largest ACTION_ constant
326 private static final int ACTION_TYPE_MASK = 0xFF000000;
331 * Argument for which movement granularity to be used when traversing the node text.
333 * <strong>Type:</strong> int<br>
334 * <strong>Actions:</strong>
336 * <li>{@link AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY}</li>
337 * <li>{@link AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}</li>
341 * @see AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
342 * @see AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
344 public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT =
345 "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
348 * Argument for which HTML element to get moving to the next/previous HTML element.
350 * <strong>Type:</strong> String<br>
351 * <strong>Actions:</strong>
353 * <li>{@link AccessibilityAction#ACTION_NEXT_HTML_ELEMENT}</li>
354 * <li>{@link AccessibilityAction#ACTION_PREVIOUS_HTML_ELEMENT}</li>
358 * @see AccessibilityAction#ACTION_NEXT_HTML_ELEMENT
359 * @see AccessibilityAction#ACTION_PREVIOUS_HTML_ELEMENT
361 public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING =
362 "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
365 * Argument for whether when moving at granularity to extend the selection
366 * or to move it otherwise.
368 * <strong>Type:</strong> boolean<br>
369 * <strong>Actions:</strong>
371 * <li>{@link AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY}</li>
372 * <li>{@link AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}</li>
375 * @see AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
376 * @see AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
378 public static final String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN =
379 "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
382 * Argument for specifying the selection start.
384 * <strong>Type:</strong> int<br>
385 * <strong>Actions:</strong>
387 * <li>{@link AccessibilityAction#ACTION_SET_SELECTION}</li>
390 * @see AccessibilityAction#ACTION_SET_SELECTION
392 public static final String ACTION_ARGUMENT_SELECTION_START_INT =
393 "ACTION_ARGUMENT_SELECTION_START_INT";
396 * Argument for specifying the selection end.
398 * <strong>Type:</strong> int<br>
399 * <strong>Actions:</strong>
401 * <li>{@link AccessibilityAction#ACTION_SET_SELECTION}</li>
404 * @see AccessibilityAction#ACTION_SET_SELECTION
406 public static final String ACTION_ARGUMENT_SELECTION_END_INT =
407 "ACTION_ARGUMENT_SELECTION_END_INT";
410 * Argument for specifying the text content to set.
412 * <strong>Type:</strong> CharSequence<br>
413 * <strong>Actions:</strong>
415 * <li>{@link AccessibilityAction#ACTION_SET_TEXT}</li>
418 * @see AccessibilityAction#ACTION_SET_TEXT
420 public static final String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE =
421 "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE";
424 * Argument for specifying the collection row to make visible on screen.
426 * <strong>Type:</strong> int<br>
427 * <strong>Actions:</strong>
429 * <li>{@link AccessibilityAction#ACTION_SCROLL_TO_POSITION}</li>
432 * @see AccessibilityAction#ACTION_SCROLL_TO_POSITION
434 public static final String ACTION_ARGUMENT_ROW_INT =
435 "android.view.accessibility.action.ARGUMENT_ROW_INT";
438 * Argument for specifying the collection column to make visible on screen.
440 * <strong>Type:</strong> int<br>
441 * <strong>Actions:</strong>
443 * <li>{@link AccessibilityAction#ACTION_SCROLL_TO_POSITION}</li>
446 * @see AccessibilityAction#ACTION_SCROLL_TO_POSITION
448 public static final String ACTION_ARGUMENT_COLUMN_INT =
449 "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
452 * Argument for specifying the progress value to set.
454 * <strong>Type:</strong> float<br>
455 * <strong>Actions:</strong>
457 * <li>{@link AccessibilityAction#ACTION_SET_PROGRESS}</li>
460 * @see AccessibilityAction#ACTION_SET_PROGRESS
462 public static final String ACTION_ARGUMENT_PROGRESS_VALUE =
463 "android.view.accessibility.action.ARGUMENT_PROGRESS_VALUE";
470 public static final int FOCUS_INPUT = 1;
473 * The accessibility focus.
475 public static final int FOCUS_ACCESSIBILITY = 2;
477 // Movement granularities
480 * Movement granularity bit for traversing the text of a node by character.
482 public static final int MOVEMENT_GRANULARITY_CHARACTER = 0x00000001;
485 * Movement granularity bit for traversing the text of a node by word.
487 public static final int MOVEMENT_GRANULARITY_WORD = 0x00000002;
490 * Movement granularity bit for traversing the text of a node by line.
492 public static final int MOVEMENT_GRANULARITY_LINE = 0x00000004;
495 * Movement granularity bit for traversing the text of a node by paragraph.
497 public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 0x00000008;
500 * Movement granularity bit for traversing the text of a node by page.
502 public static final int MOVEMENT_GRANULARITY_PAGE = 0x00000010;
504 // Boolean attributes.
506 private static final int BOOLEAN_PROPERTY_CHECKABLE = 0x00000001;
508 private static final int BOOLEAN_PROPERTY_CHECKED = 0x00000002;
510 private static final int BOOLEAN_PROPERTY_FOCUSABLE = 0x00000004;
512 private static final int BOOLEAN_PROPERTY_FOCUSED = 0x00000008;
514 private static final int BOOLEAN_PROPERTY_SELECTED = 0x00000010;
516 private static final int BOOLEAN_PROPERTY_CLICKABLE = 0x00000020;
518 private static final int BOOLEAN_PROPERTY_LONG_CLICKABLE = 0x00000040;
520 private static final int BOOLEAN_PROPERTY_ENABLED = 0x00000080;
522 private static final int BOOLEAN_PROPERTY_PASSWORD = 0x00000100;
524 private static final int BOOLEAN_PROPERTY_SCROLLABLE = 0x00000200;
526 private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED = 0x00000400;
528 private static final int BOOLEAN_PROPERTY_VISIBLE_TO_USER = 0x00000800;
530 private static final int BOOLEAN_PROPERTY_EDITABLE = 0x00001000;
532 private static final int BOOLEAN_PROPERTY_OPENS_POPUP = 0x00002000;
534 private static final int BOOLEAN_PROPERTY_DISMISSABLE = 0x00004000;
536 private static final int BOOLEAN_PROPERTY_MULTI_LINE = 0x00008000;
538 private static final int BOOLEAN_PROPERTY_CONTENT_INVALID = 0x00010000;
540 private static final int BOOLEAN_PROPERTY_CONTEXT_CLICKABLE = 0x00020000;
542 private static final int BOOLEAN_PROPERTY_IMPORTANCE = 0x0040000;
545 * Bits that provide the id of a virtual descendant of a view.
547 private static final long VIRTUAL_DESCENDANT_ID_MASK = 0xffffffff00000000L;
550 * Bit shift of {@link #VIRTUAL_DESCENDANT_ID_MASK} to get to the id for a
551 * virtual descendant of a view. Such a descendant does not exist in the view
552 * hierarchy and is only reported via the accessibility APIs.
554 private static final int VIRTUAL_DESCENDANT_ID_SHIFT = 32;
557 * Gets the accessibility view id which identifies a View in the view three.
559 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}.
560 * @return The accessibility view id part of the node id.
564 public static int getAccessibilityViewId(long accessibilityNodeId) {
565 return (int) accessibilityNodeId;
569 * Gets the virtual descendant id which identifies an imaginary view in a
572 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}.
573 * @return The virtual view id part of the node id.
577 public static int getVirtualDescendantId(long accessibilityNodeId) {
578 return (int) ((accessibilityNodeId & VIRTUAL_DESCENDANT_ID_MASK)
579 >> VIRTUAL_DESCENDANT_ID_SHIFT);
583 * Makes a node id by shifting the <code>virtualDescendantId</code>
584 * by {@link #VIRTUAL_DESCENDANT_ID_SHIFT} and taking
585 * the bitwise or with the <code>accessibilityViewId</code>.
587 * @param accessibilityViewId A View accessibility id.
588 * @param virtualDescendantId A virtual descendant id.
589 * @return The node id.
593 public static long makeNodeId(int accessibilityViewId, int virtualDescendantId) {
594 // We changed the value for undefined node to positive due to wrong
595 // global id composition (two 32-bin ints into one 64-bit long) but
596 // the value used for the host node provider view has id -1 so we
598 if (virtualDescendantId == AccessibilityNodeProvider.HOST_VIEW_ID) {
599 virtualDescendantId = UNDEFINED_ITEM_ID;
601 return (((long) virtualDescendantId) << VIRTUAL_DESCENDANT_ID_SHIFT) | accessibilityViewId;
605 private static final int MAX_POOL_SIZE = 50;
606 private static final SynchronizedPool<AccessibilityNodeInfo> sPool =
607 new SynchronizedPool<>(MAX_POOL_SIZE);
609 private boolean mSealed;
612 private int mWindowId = UNDEFINED_ITEM_ID;
613 private long mSourceNodeId = ROOT_NODE_ID;
614 private long mParentNodeId = ROOT_NODE_ID;
615 private long mLabelForId = ROOT_NODE_ID;
616 private long mLabeledById = ROOT_NODE_ID;
617 private long mTraversalBefore = ROOT_NODE_ID;
618 private long mTraversalAfter = ROOT_NODE_ID;
620 private int mBooleanProperties;
621 private final Rect mBoundsInParent = new Rect();
622 private final Rect mBoundsInScreen = new Rect();
623 private int mDrawingOrderInParent;
625 private CharSequence mPackageName;
626 private CharSequence mClassName;
627 private CharSequence mText;
628 private CharSequence mError;
629 private CharSequence mContentDescription;
630 private String mViewIdResourceName;
632 private LongArray mChildNodeIds;
633 private ArrayList<AccessibilityAction> mActions;
635 private int mMaxTextLength = -1;
636 private int mMovementGranularities;
638 private int mTextSelectionStart = UNDEFINED_SELECTION_INDEX;
639 private int mTextSelectionEnd = UNDEFINED_SELECTION_INDEX;
640 private int mInputType = InputType.TYPE_NULL;
641 private int mLiveRegion = View.ACCESSIBILITY_LIVE_REGION_NONE;
643 private Bundle mExtras;
645 private int mConnectionId = UNDEFINED_CONNECTION_ID;
647 private RangeInfo mRangeInfo;
648 private CollectionInfo mCollectionInfo;
649 private CollectionItemInfo mCollectionItemInfo;
652 * Hide constructor from clients.
654 private AccessibilityNodeInfo() {
661 * <strong>Note:</strong> Cannot be called from an
662 * {@link android.accessibilityservice.AccessibilityService}.
663 * This class is made immutable before being delivered to an AccessibilityService.
666 * @param source The info source.
668 public void setSource(View source) {
669 setSource(source, UNDEFINED_ITEM_ID);
673 * Sets the source to be a virtual descendant of the given <code>root</code>.
674 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
675 * is set as the source.
677 * A virtual descendant is an imaginary View that is reported as a part of the view
678 * hierarchy for accessibility purposes. This enables custom views that draw complex
679 * content to report themselves as a tree of virtual views, thus conveying their
683 * <strong>Note:</strong> Cannot be called from an
684 * {@link android.accessibilityservice.AccessibilityService}.
685 * This class is made immutable before being delivered to an AccessibilityService.
688 * @param root The root of the virtual subtree.
689 * @param virtualDescendantId The id of the virtual descendant.
691 public void setSource(View root, int virtualDescendantId) {
693 mWindowId = (root != null) ? root.getAccessibilityWindowId() : UNDEFINED_ITEM_ID;
694 final int rootAccessibilityViewId =
695 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
696 mSourceNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
700 * Find the view that has the specified focus type. The search starts from
701 * the view represented by this node info.
703 * @param focus The focus to find. One of {@link #FOCUS_INPUT} or
704 * {@link #FOCUS_ACCESSIBILITY}.
705 * @return The node info of the focused view or null.
708 * @see #FOCUS_ACCESSIBILITY
710 public AccessibilityNodeInfo findFocus(int focus) {
712 enforceValidFocusType(focus);
713 if (!canPerformRequestOverConnection(mSourceNodeId)) {
716 return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId, mWindowId,
717 mSourceNodeId, focus);
721 * Searches for the nearest view in the specified direction that can take
724 * @param direction The direction. Can be one of:
725 * {@link View#FOCUS_DOWN},
726 * {@link View#FOCUS_UP},
727 * {@link View#FOCUS_LEFT},
728 * {@link View#FOCUS_RIGHT},
729 * {@link View#FOCUS_FORWARD},
730 * {@link View#FOCUS_BACKWARD}.
732 * @return The node info for the view that can take accessibility focus.
734 public AccessibilityNodeInfo focusSearch(int direction) {
736 enforceValidFocusDirection(direction);
737 if (!canPerformRequestOverConnection(mSourceNodeId)) {
740 return AccessibilityInteractionClient.getInstance().focusSearch(mConnectionId, mWindowId,
741 mSourceNodeId, direction);
745 * Gets the id of the window from which the info comes from.
747 * @return The window id.
749 public int getWindowId() {
754 * Refreshes this info with the latest state of the view it represents.
756 * <strong>Note:</strong> If this method returns false this info is obsolete
757 * since it represents a view that is no longer in the view tree and should
761 * @param bypassCache Whether to bypass the cache.
762 * @return Whether the refresh succeeded.
766 public boolean refresh(boolean bypassCache) {
768 if (!canPerformRequestOverConnection(mSourceNodeId)) {
771 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
772 AccessibilityNodeInfo refreshedInfo = client.findAccessibilityNodeInfoByAccessibilityId(
773 mConnectionId, mWindowId, mSourceNodeId, bypassCache, 0);
774 if (refreshedInfo == null) {
778 refreshedInfo.recycle();
783 * Refreshes this info with the latest state of the view it represents.
785 * <strong>Note:</strong> If this method returns false this info is obsolete
786 * since it represents a view that is no longer in the view tree and should
789 * @return Whether the refresh succeeded.
791 public boolean refresh() {
792 return refresh(true);
796 * Returns the array containing the IDs of this node's children.
800 public LongArray getChildNodeIds() {
801 return mChildNodeIds;
805 * Returns the id of the child at the specified index.
807 * @throws IndexOutOfBoundsException when index < 0 || index >=
811 public long getChildId(int index) {
812 if (mChildNodeIds == null) {
813 throw new IndexOutOfBoundsException();
815 return mChildNodeIds.get(index);
819 * Gets the number of children.
821 * @return The child count.
823 public int getChildCount() {
824 return mChildNodeIds == null ? 0 : mChildNodeIds.size();
828 * Get the child at given index.
830 * <strong>Note:</strong> It is a client responsibility to recycle the
831 * received info by calling {@link AccessibilityNodeInfo#recycle()}
832 * to avoid creating of multiple instances.
835 * @param index The child index.
836 * @return The child node.
838 * @throws IllegalStateException If called outside of an AccessibilityService.
841 public AccessibilityNodeInfo getChild(int index) {
843 if (mChildNodeIds == null) {
846 if (!canPerformRequestOverConnection(mSourceNodeId)) {
849 final long childId = mChildNodeIds.get(index);
850 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
851 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId,
852 childId, false, FLAG_PREFETCH_DESCENDANTS);
858 * <strong>Note:</strong> Cannot be called from an
859 * {@link android.accessibilityservice.AccessibilityService}.
860 * This class is made immutable before being delivered to an AccessibilityService.
863 * @param child The child.
865 * @throws IllegalStateException If called from an AccessibilityService.
867 public void addChild(View child) {
868 addChildInternal(child, UNDEFINED_ITEM_ID, true);
872 * Unchecked version of {@link #addChild(View)} that does not verify
873 * uniqueness. For framework use only.
877 public void addChildUnchecked(View child) {
878 addChildInternal(child, UNDEFINED_ITEM_ID, false);
882 * Removes a child. If the child was not previously added to the node,
883 * calling this method has no effect.
885 * <strong>Note:</strong> Cannot be called from an
886 * {@link android.accessibilityservice.AccessibilityService}.
887 * This class is made immutable before being delivered to an AccessibilityService.
890 * @param child The child.
891 * @return true if the child was present
893 * @throws IllegalStateException If called from an AccessibilityService.
895 public boolean removeChild(View child) {
896 return removeChild(child, UNDEFINED_ITEM_ID);
900 * Adds a virtual child which is a descendant of the given <code>root</code>.
901 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
902 * is added as a child.
904 * A virtual descendant is an imaginary View that is reported as a part of the view
905 * hierarchy for accessibility purposes. This enables custom views that draw complex
906 * content to report them selves as a tree of virtual views, thus conveying their
910 * @param root The root of the virtual subtree.
911 * @param virtualDescendantId The id of the virtual child.
913 public void addChild(View root, int virtualDescendantId) {
914 addChildInternal(root, virtualDescendantId, true);
917 private void addChildInternal(View root, int virtualDescendantId, boolean checked) {
919 if (mChildNodeIds == null) {
920 mChildNodeIds = new LongArray();
922 final int rootAccessibilityViewId =
923 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
924 final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
925 // If we're checking uniqueness and the ID already exists, abort.
926 if (checked && mChildNodeIds.indexOf(childNodeId) >= 0) {
929 mChildNodeIds.add(childNodeId);
933 * Removes a virtual child which is a descendant of the given
934 * <code>root</code>. If the child was not previously added to the node,
935 * calling this method has no effect.
937 * @param root The root of the virtual subtree.
938 * @param virtualDescendantId The id of the virtual child.
939 * @return true if the child was present
940 * @see #addChild(View, int)
942 public boolean removeChild(View root, int virtualDescendantId) {
944 final LongArray childIds = mChildNodeIds;
945 if (childIds == null) {
948 final int rootAccessibilityViewId =
949 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
950 final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
951 final int index = childIds.indexOf(childNodeId);
955 childIds.remove(index);
960 * Gets the actions that can be performed on the node.
962 public List<AccessibilityAction> getActionList() {
963 if (mActions == null) {
964 return Collections.emptyList();
971 * Gets the actions that can be performed on the node.
973 * @return The bit mask of with actions.
975 * @see AccessibilityNodeInfo#ACTION_FOCUS
976 * @see AccessibilityNodeInfo#ACTION_CLEAR_FOCUS
977 * @see AccessibilityNodeInfo#ACTION_SELECT
978 * @see AccessibilityNodeInfo#ACTION_CLEAR_SELECTION
979 * @see AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS
980 * @see AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS
981 * @see AccessibilityNodeInfo#ACTION_CLICK
982 * @see AccessibilityNodeInfo#ACTION_LONG_CLICK
983 * @see AccessibilityNodeInfo#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
984 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
985 * @see AccessibilityNodeInfo#ACTION_NEXT_HTML_ELEMENT
986 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_HTML_ELEMENT
987 * @see AccessibilityNodeInfo#ACTION_SCROLL_FORWARD
988 * @see AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD
990 * @deprecated Use {@link #getActionList()}.
993 public int getActions() {
996 if (mActions == null) {
1000 final int actionSize = mActions.size();
1001 for (int i = 0; i < actionSize; i++) {
1002 int actionId = mActions.get(i).getId();
1003 if (actionId <= LAST_LEGACY_STANDARD_ACTION) {
1004 returnValue |= actionId;
1012 * Adds an action that can be performed on the node.
1014 * To add a standard action use the static constants on {@link AccessibilityAction}.
1015 * To add a custom action create a new {@link AccessibilityAction} by passing in a
1016 * resource id from your application as the action id and an optional label that
1017 * describes the action. To override one of the standard actions use as the action
1018 * id of a standard action id such as {@link #ACTION_CLICK} and an optional label that
1019 * describes the action.
1022 * <strong>Note:</strong> Cannot be called from an
1023 * {@link android.accessibilityservice.AccessibilityService}.
1024 * This class is made immutable before being delivered to an AccessibilityService.
1027 * @param action The action.
1029 * @throws IllegalStateException If called from an AccessibilityService.
1031 public void addAction(AccessibilityAction action) {
1034 addActionUnchecked(action);
1037 private void addActionUnchecked(AccessibilityAction action) {
1038 if (action == null) {
1042 if (mActions == null) {
1043 mActions = new ArrayList<>();
1046 mActions.remove(action);
1047 mActions.add(action);
1051 * Adds an action that can be performed on the node.
1053 * <strong>Note:</strong> Cannot be called from an
1054 * {@link android.accessibilityservice.AccessibilityService}.
1055 * This class is made immutable before being delivered to an AccessibilityService.
1058 * @param action The action.
1060 * @throws IllegalStateException If called from an AccessibilityService.
1061 * @throws IllegalArgumentException If the argument is not one of the standard actions.
1063 * @deprecated This has been deprecated for {@link #addAction(AccessibilityAction)}
1066 public void addAction(int action) {
1069 if ((action & ACTION_TYPE_MASK) != 0) {
1070 throw new IllegalArgumentException("Action is not a combination of the standard " +
1071 "actions: " + action);
1074 addLegacyStandardActions(action);
1078 * Removes an action that can be performed on the node. If the action was
1079 * not already added to the node, calling this method has no effect.
1081 * <strong>Note:</strong> Cannot be called from an
1082 * {@link android.accessibilityservice.AccessibilityService}.
1083 * This class is made immutable before being delivered to an AccessibilityService.
1086 * @param action The action to be removed.
1088 * @throws IllegalStateException If called from an AccessibilityService.
1089 * @deprecated Use {@link #removeAction(AccessibilityAction)}
1092 public void removeAction(int action) {
1095 removeAction(getActionSingleton(action));
1099 * Removes an action that can be performed on the node. If the action was
1100 * not already added to the node, calling this method has no effect.
1102 * <strong>Note:</strong> Cannot be called from an
1103 * {@link android.accessibilityservice.AccessibilityService}.
1104 * This class is made immutable before being delivered to an AccessibilityService.
1107 * @param action The action to be removed.
1108 * @return The action removed from the list of actions.
1110 * @throws IllegalStateException If called from an AccessibilityService.
1112 public boolean removeAction(AccessibilityAction action) {
1115 if (mActions == null || action == null) {
1119 return mActions.remove(action);
1123 * Gets the node before which this one is visited during traversal. A screen-reader
1124 * must visit the content of this node before the content of the one it precedes.
1126 * @return The succeeding node if such or <code>null</code>.
1128 * @see #setTraversalBefore(android.view.View)
1129 * @see #setTraversalBefore(android.view.View, int)
1131 public AccessibilityNodeInfo getTraversalBefore() {
1133 return getNodeForAccessibilityId(mTraversalBefore);
1137 * Sets the view before whose node this one should be visited during traversal. A
1138 * screen-reader must visit the content of this node before the content of the one
1141 * <strong>Note:</strong> Cannot be called from an
1142 * {@link android.accessibilityservice.AccessibilityService}.
1143 * This class is made immutable before being delivered to an AccessibilityService.
1146 * @param view The view providing the preceding node.
1148 * @see #getTraversalBefore()
1150 public void setTraversalBefore(View view) {
1151 setTraversalBefore(view, UNDEFINED_ITEM_ID);
1155 * Sets the node before which this one is visited during traversal. A screen-reader
1156 * must visit the content of this node before the content of the one it precedes.
1157 * The successor is a virtual descendant of the given <code>root</code>. If
1158 * <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root is set
1161 * A virtual descendant is an imaginary View that is reported as a part of the view
1162 * hierarchy for accessibility purposes. This enables custom views that draw complex
1163 * content to report them selves as a tree of virtual views, thus conveying their
1164 * logical structure.
1167 * <strong>Note:</strong> Cannot be called from an
1168 * {@link android.accessibilityservice.AccessibilityService}.
1169 * This class is made immutable before being delivered to an AccessibilityService.
1172 * @param root The root of the virtual subtree.
1173 * @param virtualDescendantId The id of the virtual descendant.
1175 public void setTraversalBefore(View root, int virtualDescendantId) {
1177 final int rootAccessibilityViewId = (root != null)
1178 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
1179 mTraversalBefore = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1183 * Gets the node after which this one is visited in accessibility traversal.
1184 * A screen-reader must visit the content of the other node before the content
1187 * @return The succeeding node if such or <code>null</code>.
1189 * @see #setTraversalAfter(android.view.View)
1190 * @see #setTraversalAfter(android.view.View, int)
1192 public AccessibilityNodeInfo getTraversalAfter() {
1194 return getNodeForAccessibilityId(mTraversalAfter);
1198 * Sets the view whose node is visited after this one in accessibility traversal.
1199 * A screen-reader must visit the content of the other node before the content
1202 * <strong>Note:</strong> Cannot be called from an
1203 * {@link android.accessibilityservice.AccessibilityService}.
1204 * This class is made immutable before being delivered to an AccessibilityService.
1207 * @param view The previous view.
1209 * @see #getTraversalAfter()
1211 public void setTraversalAfter(View view) {
1212 setTraversalAfter(view, UNDEFINED_ITEM_ID);
1216 * Sets the node after which this one is visited in accessibility traversal.
1217 * A screen-reader must visit the content of the other node before the content
1218 * of this one. If <code>virtualDescendantId</code> equals to {@link View#NO_ID}
1219 * the root is set as the predecessor.
1221 * A virtual descendant is an imaginary View that is reported as a part of the view
1222 * hierarchy for accessibility purposes. This enables custom views that draw complex
1223 * content to report them selves as a tree of virtual views, thus conveying their
1224 * logical structure.
1227 * <strong>Note:</strong> Cannot be called from an
1228 * {@link android.accessibilityservice.AccessibilityService}.
1229 * This class is made immutable before being delivered to an AccessibilityService.
1232 * @param root The root of the virtual subtree.
1233 * @param virtualDescendantId The id of the virtual descendant.
1235 public void setTraversalAfter(View root, int virtualDescendantId) {
1237 final int rootAccessibilityViewId = (root != null)
1238 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
1239 mTraversalAfter = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1243 * Sets the maximum text length, or -1 for no limit.
1245 * Typically used to indicate that an editable text field has a limit on
1246 * the number of characters entered.
1248 * <strong>Note:</strong> Cannot be called from an
1249 * {@link android.accessibilityservice.AccessibilityService}.
1250 * This class is made immutable before being delivered to an AccessibilityService.
1252 * @param max The maximum text length.
1253 * @see #getMaxTextLength()
1255 * @throws IllegalStateException If called from an AccessibilityService.
1257 public void setMaxTextLength(int max) {
1259 mMaxTextLength = max;
1263 * Returns the maximum text length for this node.
1265 * @return The maximum text length, or -1 for no limit.
1266 * @see #setMaxTextLength(int)
1268 public int getMaxTextLength() {
1269 return mMaxTextLength;
1273 * Sets the movement granularities for traversing the text of this node.
1275 * <strong>Note:</strong> Cannot be called from an
1276 * {@link android.accessibilityservice.AccessibilityService}.
1277 * This class is made immutable before being delivered to an AccessibilityService.
1280 * @param granularities The bit mask with granularities.
1282 * @throws IllegalStateException If called from an AccessibilityService.
1284 public void setMovementGranularities(int granularities) {
1286 mMovementGranularities = granularities;
1290 * Gets the movement granularities for traversing the text of this node.
1292 * @return The bit mask with granularities.
1294 public int getMovementGranularities() {
1295 return mMovementGranularities;
1299 * Performs an action on the node.
1301 * <strong>Note:</strong> An action can be performed only if the request is made
1302 * from an {@link android.accessibilityservice.AccessibilityService}.
1305 * @param action The action to perform.
1306 * @return True if the action was performed.
1308 * @throws IllegalStateException If called outside of an AccessibilityService.
1310 public boolean performAction(int action) {
1312 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1315 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1316 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
1321 * Performs an action on the node.
1323 * <strong>Note:</strong> An action can be performed only if the request is made
1324 * from an {@link android.accessibilityservice.AccessibilityService}.
1327 * @param action The action to perform.
1328 * @param arguments A bundle with additional arguments.
1329 * @return True if the action was performed.
1331 * @throws IllegalStateException If called outside of an AccessibilityService.
1333 public boolean performAction(int action, Bundle arguments) {
1335 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1338 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1339 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
1344 * Finds {@link AccessibilityNodeInfo}s by text. The match is case
1345 * insensitive containment. The search is relative to this info i.e.
1346 * this info is the root of the traversed tree.
1349 * <strong>Note:</strong> It is a client responsibility to recycle the
1350 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1351 * to avoid creating of multiple instances.
1354 * @param text The searched text.
1355 * @return A list of node info.
1357 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text) {
1359 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1360 return Collections.emptyList();
1362 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1363 return client.findAccessibilityNodeInfosByText(mConnectionId, mWindowId, mSourceNodeId,
1368 * Finds {@link AccessibilityNodeInfo}s by the fully qualified view id's resource
1369 * name where a fully qualified id is of the from "package:id/id_resource_name".
1370 * For example, if the target application's package is "foo.bar" and the id
1371 * resource name is "baz", the fully qualified resource id is "foo.bar:id/baz".
1374 * <strong>Note:</strong> It is a client responsibility to recycle the
1375 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1376 * to avoid creating of multiple instances.
1379 * <strong>Note:</strong> The primary usage of this API is for UI test automation
1380 * and in order to report the fully qualified view id if an {@link AccessibilityNodeInfo}
1381 * the client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
1382 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
1385 * @param viewId The fully qualified resource name of the view id to find.
1386 * @return A list of node info.
1388 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId(String viewId) {
1390 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1391 return Collections.emptyList();
1393 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1394 return client.findAccessibilityNodeInfosByViewId(mConnectionId, mWindowId, mSourceNodeId,
1399 * Gets the window to which this node belongs.
1401 * @return The window.
1403 * @see android.accessibilityservice.AccessibilityService#getWindows()
1405 public AccessibilityWindowInfo getWindow() {
1407 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1410 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1411 return client.getWindow(mConnectionId, mWindowId);
1417 * <strong>Note:</strong> It is a client responsibility to recycle the
1418 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1419 * to avoid creating of multiple instances.
1422 * @return The parent.
1424 public AccessibilityNodeInfo getParent() {
1426 return getNodeForAccessibilityId(mParentNodeId);
1430 * @return The parent node id.
1434 public long getParentNodeId() {
1435 return mParentNodeId;
1441 * <strong>Note:</strong> Cannot be called from an
1442 * {@link android.accessibilityservice.AccessibilityService}.
1443 * This class is made immutable before being delivered to an AccessibilityService.
1446 * @param parent The parent.
1448 * @throws IllegalStateException If called from an AccessibilityService.
1450 public void setParent(View parent) {
1451 setParent(parent, UNDEFINED_ITEM_ID);
1455 * Sets the parent to be a virtual descendant of the given <code>root</code>.
1456 * If <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root
1457 * is set as the parent.
1459 * A virtual descendant is an imaginary View that is reported as a part of the view
1460 * hierarchy for accessibility purposes. This enables custom views that draw complex
1461 * content to report them selves as a tree of virtual views, thus conveying their
1462 * logical structure.
1465 * <strong>Note:</strong> Cannot be called from an
1466 * {@link android.accessibilityservice.AccessibilityService}.
1467 * This class is made immutable before being delivered to an AccessibilityService.
1470 * @param root The root of the virtual subtree.
1471 * @param virtualDescendantId The id of the virtual descendant.
1473 public void setParent(View root, int virtualDescendantId) {
1475 final int rootAccessibilityViewId =
1476 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
1477 mParentNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1481 * Gets the node bounds in parent coordinates.
1483 * @param outBounds The output node bounds.
1485 public void getBoundsInParent(Rect outBounds) {
1486 outBounds.set(mBoundsInParent.left, mBoundsInParent.top,
1487 mBoundsInParent.right, mBoundsInParent.bottom);
1491 * Sets the node bounds in parent coordinates.
1493 * <strong>Note:</strong> Cannot be called from an
1494 * {@link android.accessibilityservice.AccessibilityService}.
1495 * This class is made immutable before being delivered to an AccessibilityService.
1498 * @param bounds The node bounds.
1500 * @throws IllegalStateException If called from an AccessibilityService.
1502 public void setBoundsInParent(Rect bounds) {
1504 mBoundsInParent.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
1508 * Gets the node bounds in screen coordinates.
1510 * @param outBounds The output node bounds.
1512 public void getBoundsInScreen(Rect outBounds) {
1513 outBounds.set(mBoundsInScreen.left, mBoundsInScreen.top,
1514 mBoundsInScreen.right, mBoundsInScreen.bottom);
1518 * Returns the actual rect containing the node bounds in screen coordinates.
1520 * @hide Not safe to expose outside the framework.
1522 public Rect getBoundsInScreen() {
1523 return mBoundsInScreen;
1527 * Sets the node bounds in screen coordinates.
1529 * <strong>Note:</strong> Cannot be called from an
1530 * {@link android.accessibilityservice.AccessibilityService}.
1531 * This class is made immutable before being delivered to an AccessibilityService.
1534 * @param bounds The node bounds.
1536 * @throws IllegalStateException If called from an AccessibilityService.
1538 public void setBoundsInScreen(Rect bounds) {
1540 mBoundsInScreen.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
1544 * Gets whether this node is checkable.
1546 * @return True if the node is checkable.
1548 public boolean isCheckable() {
1549 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE);
1553 * Sets whether this node is checkable.
1555 * <strong>Note:</strong> Cannot be called from an
1556 * {@link android.accessibilityservice.AccessibilityService}.
1557 * This class is made immutable before being delivered to an AccessibilityService.
1560 * @param checkable True if the node is checkable.
1562 * @throws IllegalStateException If called from an AccessibilityService.
1564 public void setCheckable(boolean checkable) {
1565 setBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE, checkable);
1569 * Gets whether this node is checked.
1571 * @return True if the node is checked.
1573 public boolean isChecked() {
1574 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKED);
1578 * Sets whether this node is checked.
1580 * <strong>Note:</strong> Cannot be called from an
1581 * {@link android.accessibilityservice.AccessibilityService}.
1582 * This class is made immutable before being delivered to an AccessibilityService.
1585 * @param checked True if the node is checked.
1587 * @throws IllegalStateException If called from an AccessibilityService.
1589 public void setChecked(boolean checked) {
1590 setBooleanProperty(BOOLEAN_PROPERTY_CHECKED, checked);
1594 * Gets whether this node is focusable.
1596 * @return True if the node is focusable.
1598 public boolean isFocusable() {
1599 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE);
1603 * Sets whether this node is focusable.
1605 * <strong>Note:</strong> Cannot be called from an
1606 * {@link android.accessibilityservice.AccessibilityService}.
1607 * This class is made immutable before being delivered to an AccessibilityService.
1610 * @param focusable True if the node is focusable.
1612 * @throws IllegalStateException If called from an AccessibilityService.
1614 public void setFocusable(boolean focusable) {
1615 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE, focusable);
1619 * Gets whether this node is focused.
1621 * @return True if the node is focused.
1623 public boolean isFocused() {
1624 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSED);
1628 * Sets whether this node is focused.
1630 * <strong>Note:</strong> Cannot be called from an
1631 * {@link android.accessibilityservice.AccessibilityService}.
1632 * This class is made immutable before being delivered to an AccessibilityService.
1635 * @param focused True if the node is focused.
1637 * @throws IllegalStateException If called from an AccessibilityService.
1639 public void setFocused(boolean focused) {
1640 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSED, focused);
1644 * Gets whether this node is visible to the user.
1646 * @return Whether the node is visible to the user.
1648 public boolean isVisibleToUser() {
1649 return getBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER);
1653 * Sets whether this node is visible to the user.
1655 * <strong>Note:</strong> Cannot be called from an
1656 * {@link android.accessibilityservice.AccessibilityService}.
1657 * This class is made immutable before being delivered to an AccessibilityService.
1660 * @param visibleToUser Whether the node is visible to the user.
1662 * @throws IllegalStateException If called from an AccessibilityService.
1664 public void setVisibleToUser(boolean visibleToUser) {
1665 setBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER, visibleToUser);
1669 * Gets whether this node is accessibility focused.
1671 * @return True if the node is accessibility focused.
1673 public boolean isAccessibilityFocused() {
1674 return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED);
1678 * Sets whether this node is accessibility focused.
1680 * <strong>Note:</strong> Cannot be called from an
1681 * {@link android.accessibilityservice.AccessibilityService}.
1682 * This class is made immutable before being delivered to an AccessibilityService.
1685 * @param focused True if the node is accessibility focused.
1687 * @throws IllegalStateException If called from an AccessibilityService.
1689 public void setAccessibilityFocused(boolean focused) {
1690 setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED, focused);
1694 * Gets whether this node is selected.
1696 * @return True if the node is selected.
1698 public boolean isSelected() {
1699 return getBooleanProperty(BOOLEAN_PROPERTY_SELECTED);
1703 * Sets whether this node is selected.
1705 * <strong>Note:</strong> Cannot be called from an
1706 * {@link android.accessibilityservice.AccessibilityService}.
1707 * This class is made immutable before being delivered to an AccessibilityService.
1710 * @param selected True if the node is selected.
1712 * @throws IllegalStateException If called from an AccessibilityService.
1714 public void setSelected(boolean selected) {
1715 setBooleanProperty(BOOLEAN_PROPERTY_SELECTED, selected);
1719 * Gets whether this node is clickable.
1721 * @return True if the node is clickable.
1723 public boolean isClickable() {
1724 return getBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE);
1728 * Sets whether this node is clickable.
1730 * <strong>Note:</strong> Cannot be called from an
1731 * {@link android.accessibilityservice.AccessibilityService}.
1732 * This class is made immutable before being delivered to an AccessibilityService.
1735 * @param clickable True if the node is clickable.
1737 * @throws IllegalStateException If called from an AccessibilityService.
1739 public void setClickable(boolean clickable) {
1740 setBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE, clickable);
1744 * Gets whether this node is long clickable.
1746 * @return True if the node is long clickable.
1748 public boolean isLongClickable() {
1749 return getBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE);
1753 * Sets whether this node is long clickable.
1755 * <strong>Note:</strong> Cannot be called from an
1756 * {@link android.accessibilityservice.AccessibilityService}.
1757 * This class is made immutable before being delivered to an AccessibilityService.
1760 * @param longClickable True if the node is long clickable.
1762 * @throws IllegalStateException If called from an AccessibilityService.
1764 public void setLongClickable(boolean longClickable) {
1765 setBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE, longClickable);
1769 * Gets whether this node is enabled.
1771 * @return True if the node is enabled.
1773 public boolean isEnabled() {
1774 return getBooleanProperty(BOOLEAN_PROPERTY_ENABLED);
1778 * Sets whether this node is enabled.
1780 * <strong>Note:</strong> Cannot be called from an
1781 * {@link android.accessibilityservice.AccessibilityService}.
1782 * This class is made immutable before being delivered to an AccessibilityService.
1785 * @param enabled True if the node is enabled.
1787 * @throws IllegalStateException If called from an AccessibilityService.
1789 public void setEnabled(boolean enabled) {
1790 setBooleanProperty(BOOLEAN_PROPERTY_ENABLED, enabled);
1794 * Gets whether this node is a password.
1796 * @return True if the node is a password.
1798 public boolean isPassword() {
1799 return getBooleanProperty(BOOLEAN_PROPERTY_PASSWORD);
1803 * Sets whether this node is a password.
1805 * <strong>Note:</strong> Cannot be called from an
1806 * {@link android.accessibilityservice.AccessibilityService}.
1807 * This class is made immutable before being delivered to an AccessibilityService.
1810 * @param password True if the node is a password.
1812 * @throws IllegalStateException If called from an AccessibilityService.
1814 public void setPassword(boolean password) {
1815 setBooleanProperty(BOOLEAN_PROPERTY_PASSWORD, password);
1819 * Gets if the node is scrollable.
1821 * @return True if the node is scrollable, false otherwise.
1823 public boolean isScrollable() {
1824 return getBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE);
1828 * Sets if the node is scrollable.
1830 * <strong>Note:</strong> Cannot be called from an
1831 * {@link android.accessibilityservice.AccessibilityService}.
1832 * This class is made immutable before being delivered to an AccessibilityService.
1835 * @param scrollable True if the node is scrollable, false otherwise.
1837 * @throws IllegalStateException If called from an AccessibilityService.
1839 public void setScrollable(boolean scrollable) {
1840 setBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE, scrollable);
1844 * Gets if the node is editable.
1846 * @return True if the node is editable, false otherwise.
1848 public boolean isEditable() {
1849 return getBooleanProperty(BOOLEAN_PROPERTY_EDITABLE);
1853 * Sets whether this node is editable.
1855 * <strong>Note:</strong> Cannot be called from an
1856 * {@link android.accessibilityservice.AccessibilityService}.
1857 * This class is made immutable before being delivered to an AccessibilityService.
1860 * @param editable True if the node is editable.
1862 * @throws IllegalStateException If called from an AccessibilityService.
1864 public void setEditable(boolean editable) {
1865 setBooleanProperty(BOOLEAN_PROPERTY_EDITABLE, editable);
1869 * Get the drawing order of the view corresponding it this node.
1871 * Drawing order is determined only within the node's parent, so this index is only relative
1874 * In some cases, the drawing order is essentially simultaneous, so it is possible for two
1875 * siblings to return the same value. It is also possible that values will be skipped.
1877 * @return The drawing position of the view corresponding to this node relative to its siblings.
1879 public int getDrawingOrder() {
1880 return mDrawingOrderInParent;
1884 * Set the drawing order of the view corresponding it this node.
1887 * <strong>Note:</strong> Cannot be called from an
1888 * {@link android.accessibilityservice.AccessibilityService}.
1889 * This class is made immutable before being delivered to an AccessibilityService.
1891 * @param drawingOrderInParent
1892 * @throws IllegalStateException If called from an AccessibilityService.
1894 public void setDrawingOrder(int drawingOrderInParent) {
1896 mDrawingOrderInParent = drawingOrderInParent;
1900 * Gets the collection info if the node is a collection. A collection
1901 * child is always a collection item.
1903 * @return The collection info.
1905 public CollectionInfo getCollectionInfo() {
1906 return mCollectionInfo;
1910 * Sets the collection info if the node is a collection. A collection
1911 * child is always a collection item.
1913 * <strong>Note:</strong> Cannot be called from an
1914 * {@link android.accessibilityservice.AccessibilityService}.
1915 * This class is made immutable before being delivered to an AccessibilityService.
1918 * @param collectionInfo The collection info.
1920 public void setCollectionInfo(CollectionInfo collectionInfo) {
1922 mCollectionInfo = collectionInfo;
1926 * Gets the collection item info if the node is a collection item. A collection
1927 * item is always a child of a collection.
1929 * @return The collection item info.
1931 public CollectionItemInfo getCollectionItemInfo() {
1932 return mCollectionItemInfo;
1936 * Sets the collection item info if the node is a collection item. A collection
1937 * item is always a child of a collection.
1939 * <strong>Note:</strong> Cannot be called from an
1940 * {@link android.accessibilityservice.AccessibilityService}.
1941 * This class is made immutable before being delivered to an AccessibilityService.
1944 public void setCollectionItemInfo(CollectionItemInfo collectionItemInfo) {
1946 mCollectionItemInfo = collectionItemInfo;
1950 * Gets the range info if this node is a range.
1952 * @return The range.
1954 public RangeInfo getRangeInfo() {
1959 * Sets the range info if this node is a range.
1961 * <strong>Note:</strong> Cannot be called from an
1962 * {@link android.accessibilityservice.AccessibilityService}.
1963 * This class is made immutable before being delivered to an AccessibilityService.
1966 * @param rangeInfo The range info.
1968 public void setRangeInfo(RangeInfo rangeInfo) {
1970 mRangeInfo = rangeInfo;
1974 * Gets if the content of this node is invalid. For example,
1975 * a date is not well-formed.
1977 * @return If the node content is invalid.
1979 public boolean isContentInvalid() {
1980 return getBooleanProperty(BOOLEAN_PROPERTY_CONTENT_INVALID);
1984 * Sets if the content of this node is invalid. For example,
1985 * a date is not well-formed.
1987 * <strong>Note:</strong> Cannot be called from an
1988 * {@link android.accessibilityservice.AccessibilityService}.
1989 * This class is made immutable before being delivered to an AccessibilityService.
1992 * @param contentInvalid If the node content is invalid.
1994 public void setContentInvalid(boolean contentInvalid) {
1995 setBooleanProperty(BOOLEAN_PROPERTY_CONTENT_INVALID, contentInvalid);
1999 * Gets whether this node is context clickable.
2001 * @return True if the node is context clickable.
2003 public boolean isContextClickable() {
2004 return getBooleanProperty(BOOLEAN_PROPERTY_CONTEXT_CLICKABLE);
2008 * Sets whether this node is context clickable.
2010 * <strong>Note:</strong> Cannot be called from an
2011 * {@link android.accessibilityservice.AccessibilityService}. This class is made immutable
2012 * before being delivered to an AccessibilityService.
2015 * @param contextClickable True if the node is context clickable.
2016 * @throws IllegalStateException If called from an AccessibilityService.
2018 public void setContextClickable(boolean contextClickable) {
2019 setBooleanProperty(BOOLEAN_PROPERTY_CONTEXT_CLICKABLE, contextClickable);
2023 * Gets the node's live region mode.
2025 * A live region is a node that contains information that is important for
2026 * the user and when it changes the user should be notified. For example,
2027 * in a login screen with a TextView that displays an "incorrect password"
2028 * notification, that view should be marked as a live region with mode
2029 * {@link View#ACCESSIBILITY_LIVE_REGION_POLITE}.
2031 * It is the responsibility of the accessibility service to monitor
2032 * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} events indicating
2033 * changes to live region nodes and their children.
2035 * @return The live region mode, or
2036 * {@link View#ACCESSIBILITY_LIVE_REGION_NONE} if the view is not a
2038 * @see android.view.View#getAccessibilityLiveRegion()
2040 public int getLiveRegion() {
2045 * Sets the node's live region mode.
2047 * <strong>Note:</strong> Cannot be called from an
2048 * {@link android.accessibilityservice.AccessibilityService}. This class is
2049 * made immutable before being delivered to an AccessibilityService.
2051 * @param mode The live region mode, or
2052 * {@link View#ACCESSIBILITY_LIVE_REGION_NONE} if the view is not a
2054 * @see android.view.View#setAccessibilityLiveRegion(int)
2056 public void setLiveRegion(int mode) {
2062 * Gets if the node is a multi line editable text.
2064 * @return True if the node is multi line.
2066 public boolean isMultiLine() {
2067 return getBooleanProperty(BOOLEAN_PROPERTY_MULTI_LINE);
2071 * Sets if the node is a multi line editable text.
2073 * <strong>Note:</strong> Cannot be called from an
2074 * {@link android.accessibilityservice.AccessibilityService}.
2075 * This class is made immutable before being delivered to an AccessibilityService.
2078 * @param multiLine True if the node is multi line.
2080 public void setMultiLine(boolean multiLine) {
2081 setBooleanProperty(BOOLEAN_PROPERTY_MULTI_LINE, multiLine);
2085 * Gets if this node opens a popup or a dialog.
2087 * @return If the the node opens a popup.
2089 public boolean canOpenPopup() {
2090 return getBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP);
2094 * Sets if this node opens a popup or a dialog.
2096 * <strong>Note:</strong> Cannot be called from an
2097 * {@link android.accessibilityservice.AccessibilityService}.
2098 * This class is made immutable before being delivered to an AccessibilityService.
2101 * @param opensPopup If the the node opens a popup.
2103 public void setCanOpenPopup(boolean opensPopup) {
2105 setBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP, opensPopup);
2109 * Gets if the node can be dismissed.
2111 * @return If the node can be dismissed.
2113 public boolean isDismissable() {
2114 return getBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE);
2118 * Sets if the node can be dismissed.
2120 * <strong>Note:</strong> Cannot be called from an
2121 * {@link android.accessibilityservice.AccessibilityService}.
2122 * This class is made immutable before being delivered to an AccessibilityService.
2125 * @param dismissable If the node can be dismissed.
2127 public void setDismissable(boolean dismissable) {
2128 setBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE, dismissable);
2132 * Returns whether the node originates from a view considered important for accessibility.
2134 * @return {@code true} if the node originates from a view considered important for
2135 * accessibility, {@code false} otherwise
2137 * @see View#isImportantForAccessibility()
2139 public boolean isImportantForAccessibility() {
2140 return getBooleanProperty(BOOLEAN_PROPERTY_IMPORTANCE);
2144 * Sets whether the node is considered important for accessibility.
2146 * <strong>Note:</strong> Cannot be called from an
2147 * {@link android.accessibilityservice.AccessibilityService}.
2148 * This class is made immutable before being delivered to an AccessibilityService.
2151 * @param important {@code true} if the node is considered important for accessibility,
2152 * {@code false} otherwise
2154 public void setImportantForAccessibility(boolean important) {
2155 setBooleanProperty(BOOLEAN_PROPERTY_IMPORTANCE, important);
2159 * Gets the package this node comes from.
2161 * @return The package name.
2163 public CharSequence getPackageName() {
2164 return mPackageName;
2168 * Sets the package this node comes from.
2170 * <strong>Note:</strong> Cannot be called from an
2171 * {@link android.accessibilityservice.AccessibilityService}.
2172 * This class is made immutable before being delivered to an AccessibilityService.
2175 * @param packageName The package name.
2177 * @throws IllegalStateException If called from an AccessibilityService.
2179 public void setPackageName(CharSequence packageName) {
2181 mPackageName = packageName;
2185 * Gets the class this node comes from.
2187 * @return The class name.
2189 public CharSequence getClassName() {
2194 * Sets the class this node comes from.
2196 * <strong>Note:</strong> Cannot be called from an
2197 * {@link android.accessibilityservice.AccessibilityService}.
2198 * This class is made immutable before being delivered to an AccessibilityService.
2201 * @param className The class name.
2203 * @throws IllegalStateException If called from an AccessibilityService.
2205 public void setClassName(CharSequence className) {
2207 mClassName = className;
2211 * Gets the text of this node.
2215 public CharSequence getText() {
2220 * Sets the text of this node.
2222 * <strong>Note:</strong> Cannot be called from an
2223 * {@link android.accessibilityservice.AccessibilityService}.
2224 * This class is made immutable before being delivered to an AccessibilityService.
2227 * @param text The text.
2229 * @throws IllegalStateException If called from an AccessibilityService.
2231 public void setText(CharSequence text) {
2237 * Sets the error text of this node.
2239 * <strong>Note:</strong> Cannot be called from an
2240 * {@link android.accessibilityservice.AccessibilityService}.
2241 * This class is made immutable before being delivered to an AccessibilityService.
2244 * @param error The error text.
2246 * @throws IllegalStateException If called from an AccessibilityService.
2248 public void setError(CharSequence error) {
2254 * Gets the error text of this node.
2256 * @return The error text.
2258 public CharSequence getError() {
2263 * Gets the content description of this node.
2265 * @return The content description.
2267 public CharSequence getContentDescription() {
2268 return mContentDescription;
2272 * Sets the content description of this node.
2274 * <strong>Note:</strong> Cannot be called from an
2275 * {@link android.accessibilityservice.AccessibilityService}.
2276 * This class is made immutable before being delivered to an AccessibilityService.
2279 * @param contentDescription The content description.
2281 * @throws IllegalStateException If called from an AccessibilityService.
2283 public void setContentDescription(CharSequence contentDescription) {
2285 mContentDescription = contentDescription;
2289 * Sets the view for which the view represented by this info serves as a
2290 * label for accessibility purposes.
2292 * @param labeled The view for which this info serves as a label.
2294 public void setLabelFor(View labeled) {
2295 setLabelFor(labeled, UNDEFINED_ITEM_ID);
2299 * Sets the view for which the view represented by this info serves as a
2300 * label for accessibility purposes. If <code>virtualDescendantId</code>
2301 * is {@link View#NO_ID} the root is set as the labeled.
2303 * A virtual descendant is an imaginary View that is reported as a part of the view
2304 * hierarchy for accessibility purposes. This enables custom views that draw complex
2305 * content to report themselves as a tree of virtual views, thus conveying their
2306 * logical structure.
2309 * <strong>Note:</strong> Cannot be called from an
2310 * {@link android.accessibilityservice.AccessibilityService}.
2311 * This class is made immutable before being delivered to an AccessibilityService.
2314 * @param root The root whose virtual descendant serves as a label.
2315 * @param virtualDescendantId The id of the virtual descendant.
2317 public void setLabelFor(View root, int virtualDescendantId) {
2319 final int rootAccessibilityViewId = (root != null)
2320 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
2321 mLabelForId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
2325 * Gets the node info for which the view represented by this info serves as
2326 * a label for accessibility purposes.
2328 * <strong>Note:</strong> It is a client responsibility to recycle the
2329 * received info by calling {@link AccessibilityNodeInfo#recycle()}
2330 * to avoid creating of multiple instances.
2333 * @return The labeled info.
2335 public AccessibilityNodeInfo getLabelFor() {
2337 return getNodeForAccessibilityId(mLabelForId);
2341 * Sets the view which serves as the label of the view represented by
2342 * this info for accessibility purposes.
2344 * @param label The view that labels this node's source.
2346 public void setLabeledBy(View label) {
2347 setLabeledBy(label, UNDEFINED_ITEM_ID);
2351 * Sets the view which serves as the label of the view represented by
2352 * this info for accessibility purposes. If <code>virtualDescendantId</code>
2353 * is {@link View#NO_ID} the root is set as the label.
2355 * A virtual descendant is an imaginary View that is reported as a part of the view
2356 * hierarchy for accessibility purposes. This enables custom views that draw complex
2357 * content to report themselves as a tree of virtual views, thus conveying their
2358 * logical structure.
2361 * <strong>Note:</strong> Cannot be called from an
2362 * {@link android.accessibilityservice.AccessibilityService}.
2363 * This class is made immutable before being delivered to an AccessibilityService.
2366 * @param root The root whose virtual descendant labels this node's source.
2367 * @param virtualDescendantId The id of the virtual descendant.
2369 public void setLabeledBy(View root, int virtualDescendantId) {
2371 final int rootAccessibilityViewId = (root != null)
2372 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
2373 mLabeledById = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
2377 * Gets the node info which serves as the label of the view represented by
2378 * this info for accessibility purposes.
2380 * <strong>Note:</strong> It is a client responsibility to recycle the
2381 * received info by calling {@link AccessibilityNodeInfo#recycle()}
2382 * to avoid creating of multiple instances.
2385 * @return The label.
2387 public AccessibilityNodeInfo getLabeledBy() {
2389 return getNodeForAccessibilityId(mLabeledById);
2393 * Sets the fully qualified resource name of the source view's id.
2396 * <strong>Note:</strong> Cannot be called from an
2397 * {@link android.accessibilityservice.AccessibilityService}.
2398 * This class is made immutable before being delivered to an AccessibilityService.
2401 * @param viewIdResName The id resource name.
2403 public void setViewIdResourceName(String viewIdResName) {
2405 mViewIdResourceName = viewIdResName;
2409 * Gets the fully qualified resource name of the source view's id.
2412 * <strong>Note:</strong> The primary usage of this API is for UI test automation
2413 * and in order to report the source view id of an {@link AccessibilityNodeInfo} the
2414 * client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
2415 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
2418 * @return The id resource name.
2420 public String getViewIdResourceName() {
2421 return mViewIdResourceName;
2425 * Gets the text selection start or the cursor position.
2427 * If no text is selected, both this method and
2428 * {@link AccessibilityNodeInfo#getTextSelectionEnd()} return the same value:
2429 * the current location of the cursor.
2432 * @return The text selection start, the cursor location if there is no selection, or -1 if
2433 * there is no text selection and no cursor.
2435 public int getTextSelectionStart() {
2436 return mTextSelectionStart;
2440 * Gets the text selection end if text is selected.
2442 * If no text is selected, both this method and
2443 * {@link AccessibilityNodeInfo#getTextSelectionStart()} return the same value:
2444 * the current location of the cursor.
2447 * @return The text selection end, the cursor location if there is no selection, or -1 if
2448 * there is no text selection and no cursor.
2450 public int getTextSelectionEnd() {
2451 return mTextSelectionEnd;
2455 * Sets the text selection start and end.
2457 * <strong>Note:</strong> Cannot be called from an
2458 * {@link android.accessibilityservice.AccessibilityService}.
2459 * This class is made immutable before being delivered to an AccessibilityService.
2462 * @param start The text selection start.
2463 * @param end The text selection end.
2465 * @throws IllegalStateException If called from an AccessibilityService.
2467 public void setTextSelection(int start, int end) {
2469 mTextSelectionStart = start;
2470 mTextSelectionEnd = end;
2474 * Gets the input type of the source as defined by {@link InputType}.
2476 * @return The input type.
2478 public int getInputType() {
2483 * Sets the input type of the source as defined by {@link InputType}.
2485 * <strong>Note:</strong> Cannot be called from an
2486 * {@link android.accessibilityservice.AccessibilityService}.
2487 * This class is made immutable before being delivered to an
2488 * AccessibilityService.
2491 * @param inputType The input type.
2493 * @throws IllegalStateException If called from an AccessibilityService.
2495 public void setInputType(int inputType) {
2497 mInputType = inputType;
2501 * Gets an optional bundle with extra data. The bundle
2502 * is lazily created and never <code>null</code>.
2504 * <strong>Note:</strong> It is recommended to use the package
2505 * name of your application as a prefix for the keys to avoid
2506 * collisions which may confuse an accessibility service if the
2507 * same key has different meaning when emitted from different
2511 * @return The bundle.
2513 public Bundle getExtras() {
2514 if (mExtras == null) {
2515 mExtras = new Bundle();
2521 * Gets the value of a boolean property.
2523 * @param property The property.
2524 * @return The value.
2526 private boolean getBooleanProperty(int property) {
2527 return (mBooleanProperties & property) != 0;
2531 * Sets a boolean property.
2533 * @param property The property.
2534 * @param value The value.
2536 * @throws IllegalStateException If called from an AccessibilityService.
2538 private void setBooleanProperty(int property, boolean value) {
2541 mBooleanProperties |= property;
2543 mBooleanProperties &= ~property;
2548 * Sets the unique id of the IAccessibilityServiceConnection over which
2549 * this instance can send requests to the system.
2551 * @param connectionId The connection id.
2555 public void setConnectionId(int connectionId) {
2557 mConnectionId = connectionId;
2564 public int describeContents() {
2569 * Gets the id of the source node.
2575 public long getSourceNodeId() {
2576 return mSourceNodeId;
2580 * Sets if this instance is sealed.
2582 * @param sealed Whether is sealed.
2586 public void setSealed(boolean sealed) {
2591 * Gets if this instance is sealed.
2593 * @return Whether is sealed.
2597 public boolean isSealed() {
2602 * Enforces that this instance is sealed.
2604 * @throws IllegalStateException If this instance is not sealed.
2608 protected void enforceSealed() {
2610 throw new IllegalStateException("Cannot perform this "
2611 + "action on a not sealed instance.");
2615 private void enforceValidFocusDirection(int direction) {
2616 switch (direction) {
2617 case View.FOCUS_DOWN:
2619 case View.FOCUS_LEFT:
2620 case View.FOCUS_RIGHT:
2621 case View.FOCUS_FORWARD:
2622 case View.FOCUS_BACKWARD:
2625 throw new IllegalArgumentException("Unknown direction: " + direction);
2629 private void enforceValidFocusType(int focusType) {
2630 switch (focusType) {
2632 case FOCUS_ACCESSIBILITY:
2635 throw new IllegalArgumentException("Unknown focus type: " + focusType);
2640 * Enforces that this instance is not sealed.
2642 * @throws IllegalStateException If this instance is sealed.
2646 protected void enforceNotSealed() {
2648 throw new IllegalStateException("Cannot perform this "
2649 + "action on a sealed instance.");
2654 * Returns a cached instance if such is available otherwise a new one
2655 * and sets the source.
2657 * @param source The source view.
2658 * @return An instance.
2660 * @see #setSource(View)
2662 public static AccessibilityNodeInfo obtain(View source) {
2663 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
2664 info.setSource(source);
2669 * Returns a cached instance if such is available otherwise a new one
2670 * and sets the source.
2672 * @param root The root of the virtual subtree.
2673 * @param virtualDescendantId The id of the virtual descendant.
2674 * @return An instance.
2676 * @see #setSource(View, int)
2678 public static AccessibilityNodeInfo obtain(View root, int virtualDescendantId) {
2679 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
2680 info.setSource(root, virtualDescendantId);
2685 * Returns a cached instance if such is available otherwise a new one.
2687 * @return An instance.
2689 public static AccessibilityNodeInfo obtain() {
2690 AccessibilityNodeInfo info = sPool.acquire();
2691 return (info != null) ? info : new AccessibilityNodeInfo();
2695 * Returns a cached instance if such is available or a new one is
2696 * create. The returned instance is initialized from the given
2697 * <code>info</code>.
2699 * @param info The other info.
2700 * @return An instance.
2702 public static AccessibilityNodeInfo obtain(AccessibilityNodeInfo info) {
2703 AccessibilityNodeInfo infoClone = AccessibilityNodeInfo.obtain();
2704 infoClone.init(info);
2709 * Return an instance back to be reused.
2711 * <strong>Note:</strong> You must not touch the object after calling this function.
2713 * @throws IllegalStateException If the info is already recycled.
2715 public void recycle() {
2717 sPool.release(this);
2723 * <strong>Note:</strong> After the instance is written to a parcel it
2724 * is recycled. You must not touch the object after calling this function.
2728 public void writeToParcel(Parcel parcel, int flags) {
2729 parcel.writeInt(isSealed() ? 1 : 0);
2730 parcel.writeLong(mSourceNodeId);
2731 parcel.writeInt(mWindowId);
2732 parcel.writeLong(mParentNodeId);
2733 parcel.writeLong(mLabelForId);
2734 parcel.writeLong(mLabeledById);
2735 parcel.writeLong(mTraversalBefore);
2736 parcel.writeLong(mTraversalAfter);
2738 parcel.writeInt(mConnectionId);
2740 final LongArray childIds = mChildNodeIds;
2741 if (childIds == null) {
2744 final int childIdsSize = childIds.size();
2745 parcel.writeInt(childIdsSize);
2746 for (int i = 0; i < childIdsSize; i++) {
2747 parcel.writeLong(childIds.get(i));
2751 parcel.writeInt(mBoundsInParent.top);
2752 parcel.writeInt(mBoundsInParent.bottom);
2753 parcel.writeInt(mBoundsInParent.left);
2754 parcel.writeInt(mBoundsInParent.right);
2756 parcel.writeInt(mBoundsInScreen.top);
2757 parcel.writeInt(mBoundsInScreen.bottom);
2758 parcel.writeInt(mBoundsInScreen.left);
2759 parcel.writeInt(mBoundsInScreen.right);
2761 if (mActions != null && !mActions.isEmpty()) {
2762 final int actionCount = mActions.size();
2763 parcel.writeInt(actionCount);
2765 int defaultLegacyStandardActions = 0;
2766 for (int i = 0; i < actionCount; i++) {
2767 AccessibilityAction action = mActions.get(i);
2768 if (isDefaultLegacyStandardAction(action)) {
2769 defaultLegacyStandardActions |= action.getId();
2772 parcel.writeInt(defaultLegacyStandardActions);
2774 for (int i = 0; i < actionCount; i++) {
2775 AccessibilityAction action = mActions.get(i);
2776 if (!isDefaultLegacyStandardAction(action)) {
2777 parcel.writeInt(action.getId());
2778 parcel.writeCharSequence(action.getLabel());
2785 parcel.writeInt(mMaxTextLength);
2786 parcel.writeInt(mMovementGranularities);
2787 parcel.writeInt(mBooleanProperties);
2789 parcel.writeCharSequence(mPackageName);
2790 parcel.writeCharSequence(mClassName);
2791 parcel.writeCharSequence(mText);
2792 parcel.writeCharSequence(mError);
2793 parcel.writeCharSequence(mContentDescription);
2794 parcel.writeString(mViewIdResourceName);
2796 parcel.writeInt(mTextSelectionStart);
2797 parcel.writeInt(mTextSelectionEnd);
2798 parcel.writeInt(mInputType);
2799 parcel.writeInt(mLiveRegion);
2800 parcel.writeInt(mDrawingOrderInParent);
2802 if (mExtras != null) {
2804 parcel.writeBundle(mExtras);
2809 if (mRangeInfo != null) {
2811 parcel.writeInt(mRangeInfo.getType());
2812 parcel.writeFloat(mRangeInfo.getMin());
2813 parcel.writeFloat(mRangeInfo.getMax());
2814 parcel.writeFloat(mRangeInfo.getCurrent());
2819 if (mCollectionInfo != null) {
2821 parcel.writeInt(mCollectionInfo.getRowCount());
2822 parcel.writeInt(mCollectionInfo.getColumnCount());
2823 parcel.writeInt(mCollectionInfo.isHierarchical() ? 1 : 0);
2824 parcel.writeInt(mCollectionInfo.getSelectionMode());
2829 if (mCollectionItemInfo != null) {
2831 parcel.writeInt(mCollectionItemInfo.getRowIndex());
2832 parcel.writeInt(mCollectionItemInfo.getRowSpan());
2833 parcel.writeInt(mCollectionItemInfo.getColumnIndex());
2834 parcel.writeInt(mCollectionItemInfo.getColumnSpan());
2835 parcel.writeInt(mCollectionItemInfo.isHeading() ? 1 : 0);
2836 parcel.writeInt(mCollectionItemInfo.isSelected() ? 1 : 0);
2841 // Since instances of this class are fetched via synchronous i.e. blocking
2842 // calls in IPCs we always recycle as soon as the instance is marshaled.
2847 * Initializes this instance from another one.
2849 * @param other The other instance.
2851 private void init(AccessibilityNodeInfo other) {
2852 mSealed = other.mSealed;
2853 mSourceNodeId = other.mSourceNodeId;
2854 mParentNodeId = other.mParentNodeId;
2855 mLabelForId = other.mLabelForId;
2856 mLabeledById = other.mLabeledById;
2857 mTraversalBefore = other.mTraversalBefore;
2858 mTraversalAfter = other.mTraversalAfter;
2859 mWindowId = other.mWindowId;
2860 mConnectionId = other.mConnectionId;
2861 mBoundsInParent.set(other.mBoundsInParent);
2862 mBoundsInScreen.set(other.mBoundsInScreen);
2863 mPackageName = other.mPackageName;
2864 mClassName = other.mClassName;
2865 mText = other.mText;
2866 mError = other.mError;
2867 mContentDescription = other.mContentDescription;
2868 mViewIdResourceName = other.mViewIdResourceName;
2870 final ArrayList<AccessibilityAction> otherActions = other.mActions;
2871 if (otherActions != null && otherActions.size() > 0) {
2872 if (mActions == null) {
2873 mActions = new ArrayList(otherActions);
2876 mActions.addAll(other.mActions);
2880 mBooleanProperties = other.mBooleanProperties;
2881 mMaxTextLength = other.mMaxTextLength;
2882 mMovementGranularities = other.mMovementGranularities;
2884 final LongArray otherChildNodeIds = other.mChildNodeIds;
2885 if (otherChildNodeIds != null && otherChildNodeIds.size() > 0) {
2886 if (mChildNodeIds == null) {
2887 mChildNodeIds = otherChildNodeIds.clone();
2889 mChildNodeIds.clear();
2890 mChildNodeIds.addAll(otherChildNodeIds);
2894 mTextSelectionStart = other.mTextSelectionStart;
2895 mTextSelectionEnd = other.mTextSelectionEnd;
2896 mInputType = other.mInputType;
2897 mLiveRegion = other.mLiveRegion;
2898 mDrawingOrderInParent = other.mDrawingOrderInParent;
2899 if (other.mExtras != null) {
2900 mExtras = new Bundle(other.mExtras);
2904 mRangeInfo = (other.mRangeInfo != null)
2905 ? RangeInfo.obtain(other.mRangeInfo) : null;
2906 mCollectionInfo = (other.mCollectionInfo != null)
2907 ? CollectionInfo.obtain(other.mCollectionInfo) : null;
2908 mCollectionItemInfo = (other.mCollectionItemInfo != null)
2909 ? CollectionItemInfo.obtain(other.mCollectionItemInfo) : null;
2913 * Creates a new instance from a {@link Parcel}.
2915 * @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}.
2917 private void initFromParcel(Parcel parcel) {
2918 final boolean sealed = (parcel.readInt() == 1);
2919 mSourceNodeId = parcel.readLong();
2920 mWindowId = parcel.readInt();
2921 mParentNodeId = parcel.readLong();
2922 mLabelForId = parcel.readLong();
2923 mLabeledById = parcel.readLong();
2924 mTraversalBefore = parcel.readLong();
2925 mTraversalAfter = parcel.readLong();
2927 mConnectionId = parcel.readInt();
2929 final int childrenSize = parcel.readInt();
2930 if (childrenSize <= 0) {
2931 mChildNodeIds = null;
2933 mChildNodeIds = new LongArray(childrenSize);
2934 for (int i = 0; i < childrenSize; i++) {
2935 final long childId = parcel.readLong();
2936 mChildNodeIds.add(childId);
2940 mBoundsInParent.top = parcel.readInt();
2941 mBoundsInParent.bottom = parcel.readInt();
2942 mBoundsInParent.left = parcel.readInt();
2943 mBoundsInParent.right = parcel.readInt();
2945 mBoundsInScreen.top = parcel.readInt();
2946 mBoundsInScreen.bottom = parcel.readInt();
2947 mBoundsInScreen.left = parcel.readInt();
2948 mBoundsInScreen.right = parcel.readInt();
2950 final int actionCount = parcel.readInt();
2951 if (actionCount > 0) {
2952 final int legacyStandardActions = parcel.readInt();
2953 addLegacyStandardActions(legacyStandardActions);
2954 final int nonLegacyActionCount = actionCount - Integer.bitCount(legacyStandardActions);
2955 for (int i = 0; i < nonLegacyActionCount; i++) {
2956 final AccessibilityAction action = new AccessibilityAction(
2957 parcel.readInt(), parcel.readCharSequence());
2958 addActionUnchecked(action);
2962 mMaxTextLength = parcel.readInt();
2963 mMovementGranularities = parcel.readInt();
2964 mBooleanProperties = parcel.readInt();
2966 mPackageName = parcel.readCharSequence();
2967 mClassName = parcel.readCharSequence();
2968 mText = parcel.readCharSequence();
2969 mError = parcel.readCharSequence();
2970 mContentDescription = parcel.readCharSequence();
2971 mViewIdResourceName = parcel.readString();
2973 mTextSelectionStart = parcel.readInt();
2974 mTextSelectionEnd = parcel.readInt();
2976 mInputType = parcel.readInt();
2977 mLiveRegion = parcel.readInt();
2978 mDrawingOrderInParent = parcel.readInt();
2980 if (parcel.readInt() == 1) {
2981 mExtras = parcel.readBundle();
2986 if (parcel.readInt() == 1) {
2987 mRangeInfo = RangeInfo.obtain(
2991 parcel.readFloat());
2994 if (parcel.readInt() == 1) {
2995 mCollectionInfo = CollectionInfo.obtain(
2998 parcel.readInt() == 1,
3002 if (parcel.readInt() == 1) {
3003 mCollectionItemInfo = CollectionItemInfo.obtain(
3008 parcel.readInt() == 1,
3009 parcel.readInt() == 1);
3016 * Clears the state of this instance.
3018 private void clear() {
3020 mSourceNodeId = ROOT_NODE_ID;
3021 mParentNodeId = ROOT_NODE_ID;
3022 mLabelForId = ROOT_NODE_ID;
3023 mLabeledById = ROOT_NODE_ID;
3024 mTraversalBefore = ROOT_NODE_ID;
3025 mTraversalAfter = ROOT_NODE_ID;
3026 mWindowId = UNDEFINED_ITEM_ID;
3027 mConnectionId = UNDEFINED_CONNECTION_ID;
3028 mMaxTextLength = -1;
3029 mMovementGranularities = 0;
3030 if (mChildNodeIds != null) {
3031 mChildNodeIds.clear();
3033 mBoundsInParent.set(0, 0, 0, 0);
3034 mBoundsInScreen.set(0, 0, 0, 0);
3035 mBooleanProperties = 0;
3036 mDrawingOrderInParent = 0;
3037 mPackageName = null;
3041 mContentDescription = null;
3042 mViewIdResourceName = null;
3043 if (mActions != null) {
3046 mTextSelectionStart = UNDEFINED_SELECTION_INDEX;
3047 mTextSelectionEnd = UNDEFINED_SELECTION_INDEX;
3048 mInputType = InputType.TYPE_NULL;
3049 mLiveRegion = View.ACCESSIBILITY_LIVE_REGION_NONE;
3051 if (mRangeInfo != null) {
3052 mRangeInfo.recycle();
3055 if (mCollectionInfo != null) {
3056 mCollectionInfo.recycle();
3057 mCollectionInfo = null;
3059 if (mCollectionItemInfo != null) {
3060 mCollectionItemInfo.recycle();
3061 mCollectionItemInfo = null;
3065 private static boolean isDefaultLegacyStandardAction(AccessibilityAction action) {
3066 return (action.getId() <= LAST_LEGACY_STANDARD_ACTION
3067 && TextUtils.isEmpty(action.getLabel()));
3070 private static AccessibilityAction getActionSingleton(int actionId) {
3071 final int actions = AccessibilityAction.sStandardActions.size();
3072 for (int i = 0; i < actions; i++) {
3073 AccessibilityAction currentAction = AccessibilityAction.sStandardActions.valueAt(i);
3074 if (actionId == currentAction.getId()) {
3075 return currentAction;
3082 private void addLegacyStandardActions(int actionMask) {
3083 int remainingIds = actionMask;
3084 while (remainingIds > 0) {
3085 final int id = 1 << Integer.numberOfTrailingZeros(remainingIds);
3086 remainingIds &= ~id;
3087 AccessibilityAction action = getActionSingleton(id);
3093 * Gets the human readable action symbolic name.
3095 * @param action The action.
3096 * @return The symbolic name.
3098 private static String getActionSymbolicName(int action) {
3101 return "ACTION_FOCUS";
3102 case ACTION_CLEAR_FOCUS:
3103 return "ACTION_CLEAR_FOCUS";
3105 return "ACTION_SELECT";
3106 case ACTION_CLEAR_SELECTION:
3107 return "ACTION_CLEAR_SELECTION";
3109 return "ACTION_CLICK";
3110 case ACTION_LONG_CLICK:
3111 return "ACTION_LONG_CLICK";
3112 case ACTION_ACCESSIBILITY_FOCUS:
3113 return "ACTION_ACCESSIBILITY_FOCUS";
3114 case ACTION_CLEAR_ACCESSIBILITY_FOCUS:
3115 return "ACTION_CLEAR_ACCESSIBILITY_FOCUS";
3116 case ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
3117 return "ACTION_NEXT_AT_MOVEMENT_GRANULARITY";
3118 case ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY:
3119 return "ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY";
3120 case ACTION_NEXT_HTML_ELEMENT:
3121 return "ACTION_NEXT_HTML_ELEMENT";
3122 case ACTION_PREVIOUS_HTML_ELEMENT:
3123 return "ACTION_PREVIOUS_HTML_ELEMENT";
3124 case ACTION_SCROLL_FORWARD:
3125 return "ACTION_SCROLL_FORWARD";
3126 case ACTION_SCROLL_BACKWARD:
3127 return "ACTION_SCROLL_BACKWARD";
3129 return "ACTION_CUT";
3131 return "ACTION_COPY";
3133 return "ACTION_PASTE";
3134 case ACTION_SET_SELECTION:
3135 return "ACTION_SET_SELECTION";
3137 return "ACTION_EXPAND";
3138 case ACTION_COLLAPSE:
3139 return "ACTION_COLLAPSE";
3140 case ACTION_DISMISS:
3141 return "ACTION_DISMISS";
3142 case ACTION_SET_TEXT:
3143 return "ACTION_SET_TEXT";
3144 case R.id.accessibilityActionShowOnScreen:
3145 return "ACTION_SHOW_ON_SCREEN";
3146 case R.id.accessibilityActionScrollToPosition:
3147 return "ACTION_SCROLL_TO_POSITION";
3148 case R.id.accessibilityActionScrollUp:
3149 return "ACTION_SCROLL_UP";
3150 case R.id.accessibilityActionScrollLeft:
3151 return "ACTION_SCROLL_LEFT";
3152 case R.id.accessibilityActionScrollDown:
3153 return "ACTION_SCROLL_DOWN";
3154 case R.id.accessibilityActionScrollRight:
3155 return "ACTION_SCROLL_RIGHT";
3156 case R.id.accessibilityActionSetProgress:
3157 return "ACTION_SET_PROGRESS";
3158 case R.id.accessibilityActionContextClick:
3159 return "ACTION_CONTEXT_CLICK";
3161 return "ACTION_UNKNOWN";
3166 * Gets the human readable movement granularity symbolic name.
3168 * @param granularity The granularity.
3169 * @return The symbolic name.
3171 private static String getMovementGranularitySymbolicName(int granularity) {
3172 switch (granularity) {
3173 case MOVEMENT_GRANULARITY_CHARACTER:
3174 return "MOVEMENT_GRANULARITY_CHARACTER";
3175 case MOVEMENT_GRANULARITY_WORD:
3176 return "MOVEMENT_GRANULARITY_WORD";
3177 case MOVEMENT_GRANULARITY_LINE:
3178 return "MOVEMENT_GRANULARITY_LINE";
3179 case MOVEMENT_GRANULARITY_PARAGRAPH:
3180 return "MOVEMENT_GRANULARITY_PARAGRAPH";
3181 case MOVEMENT_GRANULARITY_PAGE:
3182 return "MOVEMENT_GRANULARITY_PAGE";
3184 throw new IllegalArgumentException("Unknown movement granularity: " + granularity);
3188 private boolean canPerformRequestOverConnection(long accessibilityNodeId) {
3189 return (mWindowId != UNDEFINED_ITEM_ID
3190 && getAccessibilityViewId(accessibilityNodeId) != UNDEFINED_ITEM_ID
3191 && mConnectionId != UNDEFINED_CONNECTION_ID);
3195 public boolean equals(Object object) {
3196 if (this == object) {
3199 if (object == null) {
3202 if (getClass() != object.getClass()) {
3205 AccessibilityNodeInfo other = (AccessibilityNodeInfo) object;
3206 if (mSourceNodeId != other.mSourceNodeId) {
3209 if (mWindowId != other.mWindowId) {
3216 public int hashCode() {
3217 final int prime = 31;
3219 result = prime * result + getAccessibilityViewId(mSourceNodeId);
3220 result = prime * result + getVirtualDescendantId(mSourceNodeId);
3221 result = prime * result + mWindowId;
3226 public String toString() {
3227 StringBuilder builder = new StringBuilder();
3228 builder.append(super.toString());
3231 builder.append("; sourceNodeId: " + mSourceNodeId);
3232 builder.append("; accessibilityViewId: " + getAccessibilityViewId(mSourceNodeId));
3233 builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId));
3234 builder.append("; mParentNodeId: " + mParentNodeId);
3235 builder.append("; traversalBefore: ").append(mTraversalBefore);
3236 builder.append("; traversalAfter: ").append(mTraversalAfter);
3238 int granularities = mMovementGranularities;
3239 builder.append("; MovementGranularities: [");
3240 while (granularities != 0) {
3241 final int granularity = 1 << Integer.numberOfTrailingZeros(granularities);
3242 granularities &= ~granularity;
3243 builder.append(getMovementGranularitySymbolicName(granularity));
3244 if (granularities != 0) {
3245 builder.append(", ");
3248 builder.append("]");
3250 builder.append("; childAccessibilityIds: [");
3251 final LongArray childIds = mChildNodeIds;
3252 if (childIds != null) {
3253 for (int i = 0, count = childIds.size(); i < count; i++) {
3254 builder.append(childIds.get(i));
3255 if (i < count - 1) {
3256 builder.append(", ");
3260 builder.append("]");
3263 builder.append("; boundsInParent: " + mBoundsInParent);
3264 builder.append("; boundsInScreen: " + mBoundsInScreen);
3266 builder.append("; packageName: ").append(mPackageName);
3267 builder.append("; className: ").append(mClassName);
3268 builder.append("; text: ").append(mText);
3269 builder.append("; error: ").append(mError);
3270 builder.append("; maxTextLength: ").append(mMaxTextLength);
3271 builder.append("; contentDescription: ").append(mContentDescription);
3272 builder.append("; viewIdResName: ").append(mViewIdResourceName);
3274 builder.append("; checkable: ").append(isCheckable());
3275 builder.append("; checked: ").append(isChecked());
3276 builder.append("; focusable: ").append(isFocusable());
3277 builder.append("; focused: ").append(isFocused());
3278 builder.append("; selected: ").append(isSelected());
3279 builder.append("; clickable: ").append(isClickable());
3280 builder.append("; longClickable: ").append(isLongClickable());
3281 builder.append("; contextClickable: ").append(isContextClickable());
3282 builder.append("; enabled: ").append(isEnabled());
3283 builder.append("; password: ").append(isPassword());
3284 builder.append("; scrollable: ").append(isScrollable());
3285 builder.append("; actions: ").append(mActions);
3287 return builder.toString();
3290 private AccessibilityNodeInfo getNodeForAccessibilityId(long accessibilityId) {
3291 if (!canPerformRequestOverConnection(accessibilityId)) {
3294 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
3295 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
3296 mWindowId, accessibilityId, false, FLAG_PREFETCH_PREDECESSORS
3297 | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
3301 * A class defining an action that can be performed on an {@link AccessibilityNodeInfo}.
3302 * Each action has a unique id that is mandatory and optional data.
3304 * There are three categories of actions:
3306 * <li><strong>Standard actions</strong> - These are actions that are reported and
3307 * handled by the standard UI widgets in the platform. For each standard action
3308 * there is a static constant defined in this class, e.g. {@link #ACTION_FOCUS}.
3310 * <li><strong>Custom actions action</strong> - These are actions that are reported
3311 * and handled by custom widgets. i.e. ones that are not part of the UI toolkit. For
3312 * example, an application may define a custom action for clearing the user history.
3314 * <li><strong>Overriden standard actions</strong> - These are actions that override
3315 * standard actions to customize them. For example, an app may add a label to the
3316 * standard {@link #ACTION_CLICK} action to announce that this action clears browsing history.
3320 * Actions are typically added to an {@link AccessibilityNodeInfo} by using
3321 * {@link AccessibilityNodeInfo#addAction(AccessibilityAction)} within
3322 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} and are performed
3323 * within {@link View#performAccessibilityAction(int, Bundle)}.
3326 * <strong>Note:</strong> Views which support these actions should invoke
3327 * {@link View#setImportantForAccessibility(int)} with
3328 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_YES} to ensure an {@link AccessibilityService}
3329 * can discover the set of supported actions.
3332 public static final class AccessibilityAction {
3335 * Action that gives input focus to the node.
3337 public static final AccessibilityAction ACTION_FOCUS =
3338 new AccessibilityAction(
3339 AccessibilityNodeInfo.ACTION_FOCUS, null);
3342 * Action that clears input focus of the node.
3344 public static final AccessibilityAction ACTION_CLEAR_FOCUS =
3345 new AccessibilityAction(
3346 AccessibilityNodeInfo.ACTION_CLEAR_FOCUS, null);
3349 * Action that selects the node.
3351 public static final AccessibilityAction ACTION_SELECT =
3352 new AccessibilityAction(
3353 AccessibilityNodeInfo.ACTION_SELECT, null);
3356 * Action that deselects the node.
3358 public static final AccessibilityAction ACTION_CLEAR_SELECTION =
3359 new AccessibilityAction(
3360 AccessibilityNodeInfo.ACTION_CLEAR_SELECTION, null);
3363 * Action that clicks on the node info.
3365 public static final AccessibilityAction ACTION_CLICK =
3366 new AccessibilityAction(
3367 AccessibilityNodeInfo.ACTION_CLICK, null);
3370 * Action that long clicks on the node.
3372 public static final AccessibilityAction ACTION_LONG_CLICK =
3373 new AccessibilityAction(
3374 AccessibilityNodeInfo.ACTION_LONG_CLICK, null);
3377 * Action that gives accessibility focus to the node.
3379 public static final AccessibilityAction ACTION_ACCESSIBILITY_FOCUS =
3380 new AccessibilityAction(
3381 AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
3384 * Action that clears accessibility focus of the node.
3386 public static final AccessibilityAction ACTION_CLEAR_ACCESSIBILITY_FOCUS =
3387 new AccessibilityAction(
3388 AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
3391 * Action that requests to go to the next entity in this node's text
3392 * at a given movement granularity. For example, move to the next character,
3395 * <strong>Arguments:</strong>
3396 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3397 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT},
3398 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3399 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
3400 * <strong>Example:</strong> Move to the previous character and do not extend selection.
3402 * Bundle arguments = new Bundle();
3403 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
3404 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
3405 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
3407 * info.performAction(AccessibilityAction.ACTION_NEXT_AT_MOVEMENT_GRANULARITY.getId(),
3412 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3413 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3414 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3415 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3417 * @see AccessibilityNodeInfo#setMovementGranularities(int)
3418 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3419 * @see AccessibilityNodeInfo#getMovementGranularities()
3420 * AccessibilityNodeInfo.getMovementGranularities()
3422 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_CHARACTER
3423 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
3424 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_WORD
3425 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
3426 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_LINE
3427 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
3428 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PARAGRAPH
3429 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
3430 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PAGE
3431 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE
3433 public static final AccessibilityAction ACTION_NEXT_AT_MOVEMENT_GRANULARITY =
3434 new AccessibilityAction(
3435 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, null);
3438 * Action that requests to go to the previous entity in this node's text
3439 * at a given movement granularity. For example, move to the next character,
3442 * <strong>Arguments:</strong>
3443 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3444 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT},
3445 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3446 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
3447 * <strong>Example:</strong> Move to the next character and do not extend selection.
3449 * Bundle arguments = new Bundle();
3450 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
3451 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
3452 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
3454 * info.performAction(AccessibilityAction.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY.getId(),
3459 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3460 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3461 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3462 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3464 * @see AccessibilityNodeInfo#setMovementGranularities(int)
3465 * AccessibilityNodeInfo.setMovementGranularities(int)
3466 * @see AccessibilityNodeInfo#getMovementGranularities()
3467 * AccessibilityNodeInfo.getMovementGranularities()
3469 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_CHARACTER
3470 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
3471 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_WORD
3472 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
3473 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_LINE
3474 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
3475 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PARAGRAPH
3476 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
3477 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PAGE
3478 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE
3480 public static final AccessibilityAction ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY =
3481 new AccessibilityAction(
3482 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, null);
3485 * Action to move to the next HTML element of a given type. For example, move
3486 * to the BUTTON, INPUT, TABLE, etc.
3488 * <strong>Arguments:</strong>
3489 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_HTML_ELEMENT_STRING
3490 * AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
3491 * <strong>Example:</strong>
3493 * Bundle arguments = new Bundle();
3494 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
3495 * info.performAction(AccessibilityAction.ACTION_NEXT_HTML_ELEMENT.getId(), arguments);
3499 public static final AccessibilityAction ACTION_NEXT_HTML_ELEMENT =
3500 new AccessibilityAction(
3501 AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, null);
3504 * Action to move to the previous HTML element of a given type. For example, move
3505 * to the BUTTON, INPUT, TABLE, etc.
3507 * <strong>Arguments:</strong>
3508 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_HTML_ELEMENT_STRING
3509 * AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
3510 * <strong>Example:</strong>
3512 * Bundle arguments = new Bundle();
3513 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
3514 * info.performAction(AccessibilityAction.ACTION_PREVIOUS_HTML_ELEMENT.getId(), arguments);
3518 public static final AccessibilityAction ACTION_PREVIOUS_HTML_ELEMENT =
3519 new AccessibilityAction(
3520 AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT, null);
3523 * Action to scroll the node content forward.
3525 public static final AccessibilityAction ACTION_SCROLL_FORWARD =
3526 new AccessibilityAction(
3527 AccessibilityNodeInfo.ACTION_SCROLL_FORWARD, null);
3530 * Action to scroll the node content backward.
3532 public static final AccessibilityAction ACTION_SCROLL_BACKWARD =
3533 new AccessibilityAction(
3534 AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD, null);
3537 * Action to copy the current selection to the clipboard.
3539 public static final AccessibilityAction ACTION_COPY =
3540 new AccessibilityAction(
3541 AccessibilityNodeInfo.ACTION_COPY, null);
3544 * Action to paste the current clipboard content.
3546 public static final AccessibilityAction ACTION_PASTE =
3547 new AccessibilityAction(
3548 AccessibilityNodeInfo.ACTION_PASTE, null);
3551 * Action to cut the current selection and place it to the clipboard.
3553 public static final AccessibilityAction ACTION_CUT =
3554 new AccessibilityAction(
3555 AccessibilityNodeInfo.ACTION_CUT, null);
3558 * Action to set the selection. Performing this action with no arguments
3559 * clears the selection.
3561 * <strong>Arguments:</strong>
3562 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_START_INT
3563 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT},
3564 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_END_INT
3565 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT}<br>
3566 * <strong>Example:</strong>
3568 * Bundle arguments = new Bundle();
3569 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1);
3570 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 2);
3571 * info.performAction(AccessibilityAction.ACTION_SET_SELECTION.getId(), arguments);
3575 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_START_INT
3576 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT
3577 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_END_INT
3578 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT
3580 public static final AccessibilityAction ACTION_SET_SELECTION =
3581 new AccessibilityAction(
3582 AccessibilityNodeInfo.ACTION_SET_SELECTION, null);
3585 * Action to expand an expandable node.
3587 public static final AccessibilityAction ACTION_EXPAND =
3588 new AccessibilityAction(
3589 AccessibilityNodeInfo.ACTION_EXPAND, null);
3592 * Action to collapse an expandable node.
3594 public static final AccessibilityAction ACTION_COLLAPSE =
3595 new AccessibilityAction(
3596 AccessibilityNodeInfo.ACTION_COLLAPSE, null);
3599 * Action to dismiss a dismissable node.
3601 public static final AccessibilityAction ACTION_DISMISS =
3602 new AccessibilityAction(
3603 AccessibilityNodeInfo.ACTION_DISMISS, null);
3606 * Action that sets the text of the node. Performing the action without argument,
3607 * using <code> null</code> or empty {@link CharSequence} will clear the text. This
3608 * action will also put the cursor at the end of text.
3610 * <strong>Arguments:</strong>
3611 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE
3612 * AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br>
3613 * <strong>Example:</strong>
3615 * Bundle arguments = new Bundle();
3616 * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
3618 * info.performAction(AccessibilityAction.ACTION_SET_TEXT.getId(), arguments);
3621 public static final AccessibilityAction ACTION_SET_TEXT =
3622 new AccessibilityAction(
3623 AccessibilityNodeInfo.ACTION_SET_TEXT, null);
3626 * Action that requests the node make its bounding rectangle visible
3627 * on the screen, scrolling if necessary just enough.
3629 * @see View#requestRectangleOnScreen(Rect)
3631 public static final AccessibilityAction ACTION_SHOW_ON_SCREEN =
3632 new AccessibilityAction(R.id.accessibilityActionShowOnScreen, null);
3635 * Action that scrolls the node to make the specified collection
3636 * position visible on screen.
3638 * <strong>Arguments:</strong>
3640 * <li>{@link AccessibilityNodeInfo#ACTION_ARGUMENT_ROW_INT}</li>
3641 * <li>{@link AccessibilityNodeInfo#ACTION_ARGUMENT_COLUMN_INT}</li>
3644 * @see AccessibilityNodeInfo#getCollectionInfo()
3646 public static final AccessibilityAction ACTION_SCROLL_TO_POSITION =
3647 new AccessibilityAction(R.id.accessibilityActionScrollToPosition, null);
3650 * Action to scroll the node content up.
3652 public static final AccessibilityAction ACTION_SCROLL_UP =
3653 new AccessibilityAction(R.id.accessibilityActionScrollUp, null);
3656 * Action to scroll the node content left.
3658 public static final AccessibilityAction ACTION_SCROLL_LEFT =
3659 new AccessibilityAction(R.id.accessibilityActionScrollLeft, null);
3662 * Action to scroll the node content down.
3664 public static final AccessibilityAction ACTION_SCROLL_DOWN =
3665 new AccessibilityAction(R.id.accessibilityActionScrollDown, null);
3668 * Action to scroll the node content right.
3670 public static final AccessibilityAction ACTION_SCROLL_RIGHT =
3671 new AccessibilityAction(R.id.accessibilityActionScrollRight, null);
3674 * Action that context clicks the node.
3676 public static final AccessibilityAction ACTION_CONTEXT_CLICK =
3677 new AccessibilityAction(R.id.accessibilityActionContextClick, null);
3680 * Action that sets progress between {@link RangeInfo#getMin() RangeInfo.getMin()} and
3681 * {@link RangeInfo#getMax() RangeInfo.getMax()}. It should use the same value type as
3682 * {@link RangeInfo#getType() RangeInfo.getType()}
3684 * <strong>Arguments:</strong>
3685 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_PROGRESS_VALUE}
3689 public static final AccessibilityAction ACTION_SET_PROGRESS =
3690 new AccessibilityAction(R.id.accessibilityActionSetProgress, null);
3692 private static final ArraySet<AccessibilityAction> sStandardActions = new ArraySet<>();
3694 sStandardActions.add(ACTION_FOCUS);
3695 sStandardActions.add(ACTION_CLEAR_FOCUS);
3696 sStandardActions.add(ACTION_SELECT);
3697 sStandardActions.add(ACTION_CLEAR_SELECTION);
3698 sStandardActions.add(ACTION_CLICK);
3699 sStandardActions.add(ACTION_LONG_CLICK);
3700 sStandardActions.add(ACTION_ACCESSIBILITY_FOCUS);
3701 sStandardActions.add(ACTION_CLEAR_ACCESSIBILITY_FOCUS);
3702 sStandardActions.add(ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
3703 sStandardActions.add(ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
3704 sStandardActions.add(ACTION_NEXT_HTML_ELEMENT);
3705 sStandardActions.add(ACTION_PREVIOUS_HTML_ELEMENT);
3706 sStandardActions.add(ACTION_SCROLL_FORWARD);
3707 sStandardActions.add(ACTION_SCROLL_BACKWARD);
3708 sStandardActions.add(ACTION_COPY);
3709 sStandardActions.add(ACTION_PASTE);
3710 sStandardActions.add(ACTION_CUT);
3711 sStandardActions.add(ACTION_SET_SELECTION);
3712 sStandardActions.add(ACTION_EXPAND);
3713 sStandardActions.add(ACTION_COLLAPSE);
3714 sStandardActions.add(ACTION_DISMISS);
3715 sStandardActions.add(ACTION_SET_TEXT);
3716 sStandardActions.add(ACTION_SHOW_ON_SCREEN);
3717 sStandardActions.add(ACTION_SCROLL_TO_POSITION);
3718 sStandardActions.add(ACTION_SCROLL_UP);
3719 sStandardActions.add(ACTION_SCROLL_LEFT);
3720 sStandardActions.add(ACTION_SCROLL_DOWN);
3721 sStandardActions.add(ACTION_SCROLL_RIGHT);
3722 sStandardActions.add(ACTION_SET_PROGRESS);
3723 sStandardActions.add(ACTION_CONTEXT_CLICK);
3726 private final int mActionId;
3727 private final CharSequence mLabel;
3730 * Creates a new AccessibilityAction. For adding a standard action without a specific label,
3731 * use the static constants.
3733 * You can also override the description for one the standard actions. Below is an example
3734 * how to override the standard click action by adding a custom label:
3736 * AccessibilityAction action = new AccessibilityAction(
3737 * AccessibilityAction.ACTION_ACTION_CLICK, getLocalizedLabel());
3738 * node.addAction(action);
3741 * @param actionId The id for this action. This should either be one of the
3742 * standard actions or a specific action for your app. In that case it is
3743 * required to use a resource identifier.
3744 * @param label The label for the new AccessibilityAction.
3746 public AccessibilityAction(int actionId, @Nullable CharSequence label) {
3747 if ((actionId & ACTION_TYPE_MASK) == 0 && Integer.bitCount(actionId) != 1) {
3748 throw new IllegalArgumentException("Invalid standard action id");
3751 mActionId = actionId;
3756 * Gets the id for this action.
3758 * @return The action id.
3760 public int getId() {
3765 * Gets the label for this action. Its purpose is to describe the
3768 * @return The label.
3770 public CharSequence getLabel() {
3775 public int hashCode() {
3780 public boolean equals(Object other) {
3781 if (other == null) {
3785 if (other == this) {
3789 if (getClass() != other.getClass()) {
3793 return mActionId == ((AccessibilityAction)other).mActionId;
3797 public String toString() {
3798 return "AccessibilityAction: " + getActionSymbolicName(mActionId) + " - " + mLabel;
3803 * Class with information if a node is a range. Use
3804 * {@link RangeInfo#obtain(int, float, float, float)} to get an instance.
3806 public static final class RangeInfo {
3807 private static final int MAX_POOL_SIZE = 10;
3809 /** Range type: integer. */
3810 public static final int RANGE_TYPE_INT = 0;
3811 /** Range type: float. */
3812 public static final int RANGE_TYPE_FLOAT = 1;
3813 /** Range type: percent with values from zero to one.*/
3814 public static final int RANGE_TYPE_PERCENT = 2;
3816 private static final SynchronizedPool<RangeInfo> sPool =
3817 new SynchronizedPool<AccessibilityNodeInfo.RangeInfo>(MAX_POOL_SIZE);
3822 private float mCurrent;
3825 * Obtains a pooled instance that is a clone of another one.
3827 * @param other The instance to clone.
3831 public static RangeInfo obtain(RangeInfo other) {
3832 return obtain(other.mType, other.mMin, other.mMax, other.mCurrent);
3836 * Obtains a pooled instance.
3838 * @param type The type of the range.
3839 * @param min The min value.
3840 * @param max The max value.
3841 * @param current The current value.
3843 public static RangeInfo obtain(int type, float min, float max, float current) {
3844 RangeInfo info = sPool.acquire();
3846 return new RangeInfo(type, min, max, current);
3852 info.mCurrent = current;
3857 * Creates a new range.
3859 * @param type The type of the range.
3860 * @param min The min value.
3861 * @param max The max value.
3862 * @param current The current value.
3864 private RangeInfo(int type, float min, float max, float current) {
3872 * Gets the range type.
3874 * @return The range type.
3876 * @see #RANGE_TYPE_INT
3877 * @see #RANGE_TYPE_FLOAT
3878 * @see #RANGE_TYPE_PERCENT
3880 public int getType() {
3885 * Gets the min value.
3887 * @return The min value.
3889 public float getMin() {
3894 * Gets the max value.
3896 * @return The max value.
3898 public float getMax() {
3903 * Gets the current value.
3905 * @return The current value.
3907 public float getCurrent() {
3912 * Recycles this instance.
3916 sPool.release(this);
3919 private void clear() {
3928 * Class with information if a node is a collection. Use
3929 * {@link CollectionInfo#obtain(int, int, boolean)} to get an instance.
3931 * A collection of items has rows and columns and may be hierarchical.
3932 * For example, a horizontal list is a collection with one column, as
3933 * many rows as the list items, and is not hierarchical; A table is a
3934 * collection with several rows, several columns, and is not hierarchical;
3935 * A vertical tree is a hierarchical collection with one column and
3936 * as many rows as the first level children.
3939 public static final class CollectionInfo {
3940 /** Selection mode where items are not selectable. */
3941 public static final int SELECTION_MODE_NONE = 0;
3943 /** Selection mode where a single item may be selected. */
3944 public static final int SELECTION_MODE_SINGLE = 1;
3946 /** Selection mode where multiple items may be selected. */
3947 public static final int SELECTION_MODE_MULTIPLE = 2;
3949 private static final int MAX_POOL_SIZE = 20;
3951 private static final SynchronizedPool<CollectionInfo> sPool =
3952 new SynchronizedPool<>(MAX_POOL_SIZE);
3954 private int mRowCount;
3955 private int mColumnCount;
3956 private boolean mHierarchical;
3957 private int mSelectionMode;
3960 * Obtains a pooled instance that is a clone of another one.
3962 * @param other The instance to clone.
3965 public static CollectionInfo obtain(CollectionInfo other) {
3966 return CollectionInfo.obtain(other.mRowCount, other.mColumnCount, other.mHierarchical,
3967 other.mSelectionMode);
3971 * Obtains a pooled instance.
3973 * @param rowCount The number of rows.
3974 * @param columnCount The number of columns.
3975 * @param hierarchical Whether the collection is hierarchical.
3977 public static CollectionInfo obtain(int rowCount, int columnCount,
3978 boolean hierarchical) {
3979 return obtain(rowCount, columnCount, hierarchical, SELECTION_MODE_NONE);
3983 * Obtains a pooled instance.
3985 * @param rowCount The number of rows.
3986 * @param columnCount The number of columns.
3987 * @param hierarchical Whether the collection is hierarchical.
3988 * @param selectionMode The collection's selection mode, one of:
3990 * <li>{@link #SELECTION_MODE_NONE}
3991 * <li>{@link #SELECTION_MODE_SINGLE}
3992 * <li>{@link #SELECTION_MODE_MULTIPLE}
3995 public static CollectionInfo obtain(int rowCount, int columnCount,
3996 boolean hierarchical, int selectionMode) {
3997 final CollectionInfo info = sPool.acquire();
3999 return new CollectionInfo(rowCount, columnCount, hierarchical, selectionMode);
4002 info.mRowCount = rowCount;
4003 info.mColumnCount = columnCount;
4004 info.mHierarchical = hierarchical;
4005 info.mSelectionMode = selectionMode;
4010 * Creates a new instance.
4012 * @param rowCount The number of rows.
4013 * @param columnCount The number of columns.
4014 * @param hierarchical Whether the collection is hierarchical.
4015 * @param selectionMode The collection's selection mode.
4017 private CollectionInfo(int rowCount, int columnCount, boolean hierarchical,
4018 int selectionMode) {
4019 mRowCount = rowCount;
4020 mColumnCount = columnCount;
4021 mHierarchical = hierarchical;
4022 mSelectionMode = selectionMode;
4026 * Gets the number of rows.
4028 * @return The row count.
4030 public int getRowCount() {
4035 * Gets the number of columns.
4037 * @return The column count.
4039 public int getColumnCount() {
4040 return mColumnCount;
4044 * Gets if the collection is a hierarchically ordered.
4046 * @return Whether the collection is hierarchical.
4048 public boolean isHierarchical() {
4049 return mHierarchical;
4053 * Gets the collection's selection mode.
4055 * @return The collection's selection mode, one of:
4057 * <li>{@link #SELECTION_MODE_NONE}
4058 * <li>{@link #SELECTION_MODE_SINGLE}
4059 * <li>{@link #SELECTION_MODE_MULTIPLE}
4062 public int getSelectionMode() {
4063 return mSelectionMode;
4067 * Recycles this instance.
4071 sPool.release(this);
4074 private void clear() {
4077 mHierarchical = false;
4078 mSelectionMode = SELECTION_MODE_NONE;
4083 * Class with information if a node is a collection item. Use
4084 * {@link CollectionItemInfo#obtain(int, int, int, int, boolean)}
4085 * to get an instance.
4087 * A collection item is contained in a collection, it starts at
4088 * a given row and column in the collection, and spans one or
4089 * more rows and columns. For example, a header of two related
4090 * table columns starts at the first row and the first column,
4091 * spans one row and two columns.
4094 public static final class CollectionItemInfo {
4095 private static final int MAX_POOL_SIZE = 20;
4097 private static final SynchronizedPool<CollectionItemInfo> sPool =
4098 new SynchronizedPool<>(MAX_POOL_SIZE);
4101 * Obtains a pooled instance that is a clone of another one.
4103 * @param other The instance to clone.
4106 public static CollectionItemInfo obtain(CollectionItemInfo other) {
4107 return CollectionItemInfo.obtain(other.mRowIndex, other.mRowSpan, other.mColumnIndex,
4108 other.mColumnSpan, other.mHeading, other.mSelected);
4112 * Obtains a pooled instance.
4114 * @param rowIndex The row index at which the item is located.
4115 * @param rowSpan The number of rows the item spans.
4116 * @param columnIndex The column index at which the item is located.
4117 * @param columnSpan The number of columns the item spans.
4118 * @param heading Whether the item is a heading.
4120 public static CollectionItemInfo obtain(int rowIndex, int rowSpan,
4121 int columnIndex, int columnSpan, boolean heading) {
4122 return obtain(rowIndex, rowSpan, columnIndex, columnSpan, heading, false);
4126 * Obtains a pooled instance.
4128 * @param rowIndex The row index at which the item is located.
4129 * @param rowSpan The number of rows the item spans.
4130 * @param columnIndex The column index at which the item is located.
4131 * @param columnSpan The number of columns the item spans.
4132 * @param heading Whether the item is a heading.
4133 * @param selected Whether the item is selected.
4135 public static CollectionItemInfo obtain(int rowIndex, int rowSpan,
4136 int columnIndex, int columnSpan, boolean heading, boolean selected) {
4137 final CollectionItemInfo info = sPool.acquire();
4139 return new CollectionItemInfo(
4140 rowIndex, rowSpan, columnIndex, columnSpan, heading, selected);
4143 info.mRowIndex = rowIndex;
4144 info.mRowSpan = rowSpan;
4145 info.mColumnIndex = columnIndex;
4146 info.mColumnSpan = columnSpan;
4147 info.mHeading = heading;
4148 info.mSelected = selected;
4152 private boolean mHeading;
4153 private int mColumnIndex;
4154 private int mRowIndex;
4155 private int mColumnSpan;
4156 private int mRowSpan;
4157 private boolean mSelected;
4160 * Creates a new instance.
4162 * @param rowIndex The row index at which the item is located.
4163 * @param rowSpan The number of rows the item spans.
4164 * @param columnIndex The column index at which the item is located.
4165 * @param columnSpan The number of columns the item spans.
4166 * @param heading Whether the item is a heading.
4168 private CollectionItemInfo(int rowIndex, int rowSpan, int columnIndex, int columnSpan,
4169 boolean heading, boolean selected) {
4170 mRowIndex = rowIndex;
4172 mColumnIndex = columnIndex;
4173 mColumnSpan = columnSpan;
4175 mSelected = selected;
4179 * Gets the column index at which the item is located.
4181 * @return The column index.
4183 public int getColumnIndex() {
4184 return mColumnIndex;
4188 * Gets the row index at which the item is located.
4190 * @return The row index.
4192 public int getRowIndex() {
4197 * Gets the number of columns the item spans.
4199 * @return The column span.
4201 public int getColumnSpan() {
4206 * Gets the number of rows the item spans.
4208 * @return The row span.
4210 public int getRowSpan() {
4215 * Gets if the collection item is a heading. For example, section
4216 * heading, table header, etc.
4218 * @return If the item is a heading.
4220 public boolean isHeading() {
4225 * Gets if the collection item is selected.
4227 * @return If the item is selected.
4229 public boolean isSelected() {
4234 * Recycles this instance.
4238 sPool.release(this);
4241 private void clear() {
4252 * @see android.os.Parcelable.Creator
4254 public static final Parcelable.Creator<AccessibilityNodeInfo> CREATOR =
4255 new Parcelable.Creator<AccessibilityNodeInfo>() {
4257 public AccessibilityNodeInfo createFromParcel(Parcel parcel) {
4258 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
4259 info.initFromParcel(parcel);
4264 public AccessibilityNodeInfo[] newArray(int size) {
4265 return new AccessibilityNodeInfo[size];