blob: 86ed499cabc098794ef5aa0fc23829509a5baca1 [file] [log] [blame]
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17package android.view.accessibility;
18
Svetoslav Ganov80943d82013-01-02 10:25:37 -080019import android.accessibilityservice.AccessibilityServiceInfo;
Kristian Monsen74bc1942014-04-29 11:00:17 -070020import android.annotation.Nullable;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070021import android.graphics.Rect;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -070022import android.os.Bundle;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070023import android.os.Parcel;
24import android.os.Parcelable;
Svetoslav6254f482013-06-04 17:22:14 -070025import android.text.InputType;
Kristian Monsen74bc1942014-04-29 11:00:17 -070026import android.text.TextUtils;
27import android.util.ArraySet;
Alan Viverettef0aed092013-11-06 15:33:03 -080028import android.util.LongArray;
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -080029import android.util.Pools.SynchronizedPool;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070030import android.view.View;
31
Alan Viverette26c44ee2015-03-25 14:54:13 -070032import com.android.internal.R;
33
Kristian Monsen74bc1942014-04-29 11:00:17 -070034import java.util.ArrayList;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -070035import java.util.Collections;
36import java.util.List;
37
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070038/**
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070039 * This class represents a node of the window content as well as actions that
40 * can be requested from its source. From the point of view of an
41 * {@link android.accessibilityservice.AccessibilityService} a window content is
42 * presented as tree of accessibility node info which may or may not map one-to-one
43 * to the view hierarchy. In other words, a custom view is free to report itself as
44 * a tree of accessibility node info.
45 * </p>
46 * <p>
47 * Once an accessibility node info is delivered to an accessibility service it is
48 * made immutable and calling a state mutation method generates an error.
49 * </p>
50 * <p>
51 * Please refer to {@link android.accessibilityservice.AccessibilityService} for
52 * details about how to obtain a handle to window content as a tree of accessibility
53 * node info as well as familiarizing with the security model.
54 * </p>
Joe Fernandeze1302ed2012-02-06 14:30:15 -080055 * <div class="special reference">
56 * <h3>Developer Guides</h3>
57 * <p>For more information about making applications accessible, read the
58 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
59 * developer guide.</p>
60 * </div>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070061 *
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070062 * @see android.accessibilityservice.AccessibilityService
63 * @see AccessibilityEvent
64 * @see AccessibilityManager
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070065 */
66public class AccessibilityNodeInfo implements Parcelable {
67
68 private static final boolean DEBUG = false;
69
Svetoslav Ganov0d04e242012-02-21 13:46:36 -080070 /** @hide */
Svetoslav8e3feb12014-02-24 13:46:47 -080071 public static final int UNDEFINED_CONNECTION_ID = -1;
Svetoslav Ganov0d04e242012-02-21 13:46:36 -080072
73 /** @hide */
Svetoslav8e3feb12014-02-24 13:46:47 -080074 public static final int UNDEFINED_SELECTION_INDEX = -1;
Svetoslav Ganov0d04e242012-02-21 13:46:36 -080075
76 /** @hide */
Svetoslav8e3feb12014-02-24 13:46:47 -080077 public static final int UNDEFINED_ITEM_ID = Integer.MAX_VALUE;
78
79 /** @hide */
80 public static final long ROOT_NODE_ID = makeNodeId(UNDEFINED_ITEM_ID, UNDEFINED_ITEM_ID);
81
82 /** @hide */
83 public static final int ACTIVE_WINDOW_ID = UNDEFINED_ITEM_ID;
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -080084
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -080085 /** @hide */
Svetoslav1e0d4af2014-04-10 17:41:29 -070086 public static final int ANY_WINDOW_ID = -2;
87
88 /** @hide */
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -080089 public static final int FLAG_PREFETCH_PREDECESSORS = 0x00000001;
90
91 /** @hide */
92 public static final int FLAG_PREFETCH_SIBLINGS = 0x00000002;
93
94 /** @hide */
Svetoslav Ganov42138042012-03-20 11:51:39 -070095 public static final int FLAG_PREFETCH_DESCENDANTS = 0x00000004;
96
97 /** @hide */
Svetoslav Ganov80943d82013-01-02 10:25:37 -080098 public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x00000008;
99
100 /** @hide */
101 public static final int FLAG_REPORT_VIEW_IDS = 0x00000010;
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800102
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700103 // Actions.
104
105 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700106 * Action that gives input focus to the node.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700107 */
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700108 public static final int ACTION_FOCUS = 0x00000001;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700109
110 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700111 * Action that clears input focus of the node.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700112 */
Svetoslav Ganov42138042012-03-20 11:51:39 -0700113 public static final int ACTION_CLEAR_FOCUS = 0x00000002;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700114
115 /**
116 * Action that selects the node.
117 */
Svetoslav Ganov42138042012-03-20 11:51:39 -0700118 public static final int ACTION_SELECT = 0x00000004;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700119
120 /**
Kristian Monsen74bc1942014-04-29 11:00:17 -0700121 * Action that deselects the node.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700122 */
Svetoslav Ganov42138042012-03-20 11:51:39 -0700123 public static final int ACTION_CLEAR_SELECTION = 0x00000008;
124
125 /**
Svetoslav Ganov6d17a932012-04-27 19:30:38 -0700126 * Action that clicks on the node info.
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700127 */
128 public static final int ACTION_CLICK = 0x00000010;
129
130 /**
Svetoslav Ganov6d17a932012-04-27 19:30:38 -0700131 * Action that long clicks on the node.
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700132 */
133 public static final int ACTION_LONG_CLICK = 0x00000020;
134
135 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700136 * Action that gives accessibility focus to the node.
137 */
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700138 public static final int ACTION_ACCESSIBILITY_FOCUS = 0x00000040;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700139
140 /**
141 * Action that clears accessibility focus of the node.
142 */
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700143 public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 0x00000080;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700144
145 /**
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700146 * Action that requests to go to the next entity in this node's text
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700147 * at a given movement granularity. For example, move to the next character,
148 * word, etc.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700149 * <p>
Svetoslav7c512842013-01-30 23:02:08 -0800150 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
151 * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
152 * <strong>Example:</strong> Move to the previous character and do not extend selection.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700153 * <code><pre><p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700154 * Bundle arguments = new Bundle();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700155 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
156 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
Svetoslav7c512842013-01-30 23:02:08 -0800157 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
158 * false);
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700159 * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700160 * </code></pre></p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700161 * </p>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700162 *
Svetoslav7c512842013-01-30 23:02:08 -0800163 * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
164 * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
165 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700166 * @see #setMovementGranularities(int)
167 * @see #getMovementGranularities()
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700168 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700169 * @see #MOVEMENT_GRANULARITY_CHARACTER
170 * @see #MOVEMENT_GRANULARITY_WORD
171 * @see #MOVEMENT_GRANULARITY_LINE
172 * @see #MOVEMENT_GRANULARITY_PARAGRAPH
173 * @see #MOVEMENT_GRANULARITY_PAGE
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700174 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700175 public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 0x00000100;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700176
177 /**
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700178 * Action that requests to go to the previous entity in this node's text
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700179 * at a given movement granularity. For example, move to the next character,
180 * word, etc.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700181 * <p>
Svetoslav7c512842013-01-30 23:02:08 -0800182 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
183 * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
184 * <strong>Example:</strong> Move to the next character and do not extend selection.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700185 * <code><pre><p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700186 * Bundle arguments = new Bundle();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700187 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
188 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
Svetoslav7c512842013-01-30 23:02:08 -0800189 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
190 * false);
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700191 * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
192 * arguments);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700193 * </code></pre></p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700194 * </p>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700195 *
Svetoslav7c512842013-01-30 23:02:08 -0800196 * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
197 * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
198 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700199 * @see #setMovementGranularities(int)
200 * @see #getMovementGranularities()
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700201 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700202 * @see #MOVEMENT_GRANULARITY_CHARACTER
203 * @see #MOVEMENT_GRANULARITY_WORD
204 * @see #MOVEMENT_GRANULARITY_LINE
205 * @see #MOVEMENT_GRANULARITY_PARAGRAPH
206 * @see #MOVEMENT_GRANULARITY_PAGE
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700207 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700208 public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 0x00000200;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700209
210 /**
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700211 * Action to move to the next HTML element of a given type. For example, move
212 * to the BUTTON, INPUT, TABLE, etc.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700213 * <p>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700214 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
215 * <strong>Example:</strong>
216 * <code><pre><p>
217 * Bundle arguments = new Bundle();
218 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
219 * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, arguments);
220 * </code></pre></p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700221 * </p>
222 */
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700223 public static final int ACTION_NEXT_HTML_ELEMENT = 0x00000400;
224
225 /**
226 * Action to move to the previous HTML element of a given type. For example, move
227 * to the BUTTON, INPUT, TABLE, etc.
228 * <p>
229 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
230 * <strong>Example:</strong>
231 * <code><pre><p>
232 * Bundle arguments = new Bundle();
233 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
234 * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT, arguments);
235 * </code></pre></p>
236 * </p>
237 */
238 public static final int ACTION_PREVIOUS_HTML_ELEMENT = 0x00000800;
239
240 /**
Svetoslav Ganova1dc7612012-05-10 04:14:53 -0700241 * Action to scroll the node content forward.
242 */
243 public static final int ACTION_SCROLL_FORWARD = 0x00001000;
244
245 /**
246 * Action to scroll the node content backward.
247 */
248 public static final int ACTION_SCROLL_BACKWARD = 0x00002000;
249
250 /**
Svetoslav7c512842013-01-30 23:02:08 -0800251 * Action to copy the current selection to the clipboard.
252 */
253 public static final int ACTION_COPY = 0x00004000;
254
255 /**
256 * Action to paste the current clipboard content.
257 */
258 public static final int ACTION_PASTE = 0x00008000;
259
260 /**
261 * Action to cut the current selection and place it to the clipboard.
262 */
263 public static final int ACTION_CUT = 0x00010000;
264
265 /**
266 * Action to set the selection. Performing this action with no arguments
267 * clears the selection.
268 * <p>
Alan Viverette23f44322015-04-06 16:04:56 -0700269 * <strong>Arguments:</strong>
270 * {@link #ACTION_ARGUMENT_SELECTION_START_INT},
Svetoslav7c512842013-01-30 23:02:08 -0800271 * {@link #ACTION_ARGUMENT_SELECTION_END_INT}<br>
272 * <strong>Example:</strong>
273 * <code><pre><p>
274 * Bundle arguments = new Bundle();
275 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1);
276 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 2);
277 * info.performAction(AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments);
278 * </code></pre></p>
279 * </p>
280 *
281 * @see #ACTION_ARGUMENT_SELECTION_START_INT
282 * @see #ACTION_ARGUMENT_SELECTION_END_INT
283 */
284 public static final int ACTION_SET_SELECTION = 0x00020000;
285
286 /**
Svetoslav3577a282013-06-06 14:09:10 -0700287 * Action to expand an expandable node.
288 */
289 public static final int ACTION_EXPAND = 0x00040000;
290
291 /**
292 * Action to collapse an expandable node.
293 */
294 public static final int ACTION_COLLAPSE = 0x00080000;
295
296 /**
297 * Action to dismiss a dismissable node.
298 */
299 public static final int ACTION_DISMISS = 0x00100000;
300
Guang Zhu4cd353c2014-02-12 19:54:30 -0800301 /**
302 * Action that sets the text of the node. Performing the action without argument, using <code>
303 * null</code> or empty {@link CharSequence} will clear the text. This action will also put the
304 * cursor at the end of text.
305 * <p>
Alan Viverette23f44322015-04-06 16:04:56 -0700306 * <strong>Arguments:</strong>
307 * {@link #ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br>
Guang Zhu4cd353c2014-02-12 19:54:30 -0800308 * <strong>Example:</strong>
309 * <code><pre><p>
310 * Bundle arguments = new Bundle();
311 * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
312 * "android");
313 * info.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
314 * </code></pre></p>
315 */
316 public static final int ACTION_SET_TEXT = 0x00200000;
317
Kristian Monsen74bc1942014-04-29 11:00:17 -0700318 private static final int LAST_LEGACY_STANDARD_ACTION = ACTION_SET_TEXT;
319
320 /**
321 * Mask to see if the value is larger than the largest ACTION_ constant
322 */
323 private static final int ACTION_TYPE_MASK = 0xFF000000;
324
Svetoslav3577a282013-06-06 14:09:10 -0700325 // Action arguments
326
327 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700328 * Argument for which movement granularity to be used when traversing the node text.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700329 * <p>
330 * <strong>Type:</strong> int<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700331 * <strong>Actions:</strong>
332 * <ul>
333 * <li>{@link AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY}</li>
334 * <li>{@link AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}</li>
335 * </ul>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700336 * </p>
Svetoslav7c512842013-01-30 23:02:08 -0800337 *
Alan Viverette23f44322015-04-06 16:04:56 -0700338 * @see AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
339 * @see AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700340 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700341 public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT =
Svetoslav7c512842013-01-30 23:02:08 -0800342 "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700343
344 /**
345 * Argument for which HTML element to get moving to the next/previous HTML element.
346 * <p>
347 * <strong>Type:</strong> String<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700348 * <strong>Actions:</strong>
349 * <ul>
350 * <li>{@link AccessibilityAction#ACTION_NEXT_HTML_ELEMENT}</li>
351 * <li>{@link AccessibilityAction#ACTION_PREVIOUS_HTML_ELEMENT}</li>
352 * </ul>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700353 * </p>
Svetoslav7c512842013-01-30 23:02:08 -0800354 *
Alan Viverette23f44322015-04-06 16:04:56 -0700355 * @see AccessibilityAction#ACTION_NEXT_HTML_ELEMENT
356 * @see AccessibilityAction#ACTION_PREVIOUS_HTML_ELEMENT
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700357 */
358 public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING =
Svetoslav7c512842013-01-30 23:02:08 -0800359 "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
360
361 /**
362 * Argument for whether when moving at granularity to extend the selection
363 * or to move it otherwise.
364 * <p>
365 * <strong>Type:</strong> boolean<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700366 * <strong>Actions:</strong>
367 * <ul>
368 * <li>{@link AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY}</li>
369 * <li>{@link AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}</li>
370 * </ul>
Svetoslav7c512842013-01-30 23:02:08 -0800371 *
Alan Viverette23f44322015-04-06 16:04:56 -0700372 * @see AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
373 * @see AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
Svetoslav7c512842013-01-30 23:02:08 -0800374 */
375 public static final String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN =
376 "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
377
378 /**
379 * Argument for specifying the selection start.
380 * <p>
381 * <strong>Type:</strong> int<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700382 * <strong>Actions:</strong>
383 * <ul>
384 * <li>{@link AccessibilityAction#ACTION_SET_SELECTION}</li>
385 * </ul>
Svetoslav7c512842013-01-30 23:02:08 -0800386 *
Alan Viverette23f44322015-04-06 16:04:56 -0700387 * @see AccessibilityAction#ACTION_SET_SELECTION
Svetoslav7c512842013-01-30 23:02:08 -0800388 */
389 public static final String ACTION_ARGUMENT_SELECTION_START_INT =
390 "ACTION_ARGUMENT_SELECTION_START_INT";
391
392 /**
393 * Argument for specifying the selection end.
394 * <p>
395 * <strong>Type:</strong> int<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700396 * <strong>Actions:</strong>
397 * <ul>
398 * <li>{@link AccessibilityAction#ACTION_SET_SELECTION}</li>
399 * </ul>
Svetoslav7c512842013-01-30 23:02:08 -0800400 *
Alan Viverette23f44322015-04-06 16:04:56 -0700401 * @see AccessibilityAction#ACTION_SET_SELECTION
Svetoslav7c512842013-01-30 23:02:08 -0800402 */
403 public static final String ACTION_ARGUMENT_SELECTION_END_INT =
404 "ACTION_ARGUMENT_SELECTION_END_INT";
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700405
Guang Zhu4cd353c2014-02-12 19:54:30 -0800406 /**
Alan Viverette23f44322015-04-06 16:04:56 -0700407 * Argument for specifying the text content to set.
Guang Zhu4cd353c2014-02-12 19:54:30 -0800408 * <p>
409 * <strong>Type:</strong> CharSequence<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700410 * <strong>Actions:</strong>
411 * <ul>
412 * <li>{@link AccessibilityAction#ACTION_SET_TEXT}</li>
413 * </ul>
Guang Zhu4cd353c2014-02-12 19:54:30 -0800414 *
Alan Viverette23f44322015-04-06 16:04:56 -0700415 * @see AccessibilityAction#ACTION_SET_TEXT
Guang Zhu4cd353c2014-02-12 19:54:30 -0800416 */
417 public static final String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE =
418 "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE";
419
Alan Viverette23f44322015-04-06 16:04:56 -0700420 /**
421 * Argument for specifying the collection row to make visible on screen.
422 * <p>
423 * <strong>Type:</strong> int<br>
424 * <strong>Actions:</strong>
425 * <ul>
426 * <li>{@link AccessibilityAction#ACTION_SCROLL_TO_POSITION}</li>
427 * </ul>
428 *
429 * @see AccessibilityAction#ACTION_SCROLL_TO_POSITION
430 */
431 public static final String ACTION_ARGUMENT_ROW_INT =
432 "android.view.accessibility.action.ARGUMENT_ROW_INT";
433
434 /**
435 * Argument for specifying the collection column to make visible on screen.
436 * <p>
437 * <strong>Type:</strong> int<br>
438 * <strong>Actions:</strong>
439 * <ul>
440 * <li>{@link AccessibilityAction#ACTION_SCROLL_TO_POSITION}</li>
441 * </ul>
442 *
443 * @see AccessibilityAction#ACTION_SCROLL_TO_POSITION
444 */
445 public static final String ACTION_ARGUMENT_COLUMN_INT =
446 "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
447
Svetoslav3577a282013-06-06 14:09:10 -0700448 // Focus types
449
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700450 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700451 * The input focus.
452 */
453 public static final int FOCUS_INPUT = 1;
454
455 /**
456 * The accessibility focus.
457 */
458 public static final int FOCUS_ACCESSIBILITY = 2;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700459
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700460 // Movement granularities
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700461
462 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700463 * Movement granularity bit for traversing the text of a node by character.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700464 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700465 public static final int MOVEMENT_GRANULARITY_CHARACTER = 0x00000001;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700466
467 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700468 * Movement granularity bit for traversing the text of a node by word.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700469 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700470 public static final int MOVEMENT_GRANULARITY_WORD = 0x00000002;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700471
472 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700473 * Movement granularity bit for traversing the text of a node by line.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700474 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700475 public static final int MOVEMENT_GRANULARITY_LINE = 0x00000004;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700476
477 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700478 * Movement granularity bit for traversing the text of a node by paragraph.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700479 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700480 public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 0x00000008;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700481
482 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700483 * Movement granularity bit for traversing the text of a node by page.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700484 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700485 public static final int MOVEMENT_GRANULARITY_PAGE = 0x00000010;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700486
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700487 // Boolean attributes.
488
Svetoslavbcc46a02013-02-06 11:56:00 -0800489 private static final int BOOLEAN_PROPERTY_CHECKABLE = 0x00000001;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700490
Svetoslavbcc46a02013-02-06 11:56:00 -0800491 private static final int BOOLEAN_PROPERTY_CHECKED = 0x00000002;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700492
Svetoslavbcc46a02013-02-06 11:56:00 -0800493 private static final int BOOLEAN_PROPERTY_FOCUSABLE = 0x00000004;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700494
Svetoslavbcc46a02013-02-06 11:56:00 -0800495 private static final int BOOLEAN_PROPERTY_FOCUSED = 0x00000008;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700496
Svetoslavbcc46a02013-02-06 11:56:00 -0800497 private static final int BOOLEAN_PROPERTY_SELECTED = 0x00000010;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700498
Svetoslavbcc46a02013-02-06 11:56:00 -0800499 private static final int BOOLEAN_PROPERTY_CLICKABLE = 0x00000020;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700500
Svetoslavbcc46a02013-02-06 11:56:00 -0800501 private static final int BOOLEAN_PROPERTY_LONG_CLICKABLE = 0x00000040;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700502
Svetoslavbcc46a02013-02-06 11:56:00 -0800503 private static final int BOOLEAN_PROPERTY_ENABLED = 0x00000080;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700504
Svetoslavbcc46a02013-02-06 11:56:00 -0800505 private static final int BOOLEAN_PROPERTY_PASSWORD = 0x00000100;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700506
Svetoslavbcc46a02013-02-06 11:56:00 -0800507 private static final int BOOLEAN_PROPERTY_SCROLLABLE = 0x00000200;
Svetoslav Ganova0156172011-06-26 17:55:44 -0700508
Svetoslavbcc46a02013-02-06 11:56:00 -0800509 private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED = 0x00000400;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700510
Svetoslavbcc46a02013-02-06 11:56:00 -0800511 private static final int BOOLEAN_PROPERTY_VISIBLE_TO_USER = 0x00000800;
512
513 private static final int BOOLEAN_PROPERTY_EDITABLE = 0x00001000;
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -0700514
Alan Viverette77e9a282013-09-12 17:16:09 -0700515 private static final int BOOLEAN_PROPERTY_OPENS_POPUP = 0x00002000;
Svetoslav3577a282013-06-06 14:09:10 -0700516
Alan Viverette77e9a282013-09-12 17:16:09 -0700517 private static final int BOOLEAN_PROPERTY_DISMISSABLE = 0x00004000;
Svetoslav3577a282013-06-06 14:09:10 -0700518
Alan Viverette77e9a282013-09-12 17:16:09 -0700519 private static final int BOOLEAN_PROPERTY_MULTI_LINE = 0x00008000;
Svetoslav3577a282013-06-06 14:09:10 -0700520
Alan Viverette77e9a282013-09-12 17:16:09 -0700521 private static final int BOOLEAN_PROPERTY_CONTENT_INVALID = 0x00010000;
Svetoslav3577a282013-06-06 14:09:10 -0700522
Mady Mellore8608912015-06-05 09:02:55 -0700523 private static final int BOOLEAN_PROPERTY_CONTEXT_CLICKABLE = 0x00020000;
Mady Mellore82067b2015-04-30 09:58:35 -0700524
Svetoslav Ganov02107852011-10-03 17:06:56 -0700525 /**
526 * Bits that provide the id of a virtual descendant of a view.
527 */
528 private static final long VIRTUAL_DESCENDANT_ID_MASK = 0xffffffff00000000L;
529
530 /**
531 * Bit shift of {@link #VIRTUAL_DESCENDANT_ID_MASK} to get to the id for a
532 * virtual descendant of a view. Such a descendant does not exist in the view
533 * hierarchy and is only reported via the accessibility APIs.
534 */
535 private static final int VIRTUAL_DESCENDANT_ID_SHIFT = 32;
536
537 /**
538 * Gets the accessibility view id which identifies a View in the view three.
539 *
540 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}.
541 * @return The accessibility view id part of the node id.
542 *
543 * @hide
544 */
545 public static int getAccessibilityViewId(long accessibilityNodeId) {
546 return (int) accessibilityNodeId;
547 }
548
549 /**
550 * Gets the virtual descendant id which identifies an imaginary view in a
551 * containing View.
552 *
553 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}.
554 * @return The virtual view id part of the node id.
555 *
556 * @hide
557 */
558 public static int getVirtualDescendantId(long accessibilityNodeId) {
559 return (int) ((accessibilityNodeId & VIRTUAL_DESCENDANT_ID_MASK)
560 >> VIRTUAL_DESCENDANT_ID_SHIFT);
561 }
562
563 /**
564 * Makes a node id by shifting the <code>virtualDescendantId</code>
565 * by {@link #VIRTUAL_DESCENDANT_ID_SHIFT} and taking
566 * the bitwise or with the <code>accessibilityViewId</code>.
567 *
568 * @param accessibilityViewId A View accessibility id.
569 * @param virtualDescendantId A virtual descendant id.
570 * @return The node id.
571 *
572 * @hide
573 */
574 public static long makeNodeId(int accessibilityViewId, int virtualDescendantId) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800575 // We changed the value for undefined node to positive due to wrong
576 // global id composition (two 32-bin ints into one 64-bit long) but
577 // the value used for the host node provider view has id -1 so we
578 // remap it here.
579 if (virtualDescendantId == AccessibilityNodeProvider.HOST_VIEW_ID) {
580 virtualDescendantId = UNDEFINED_ITEM_ID;
581 }
Svetoslav Ganov02107852011-10-03 17:06:56 -0700582 return (((long) virtualDescendantId) << VIRTUAL_DESCENDANT_ID_SHIFT) | accessibilityViewId;
583 }
584
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700585 // Housekeeping.
586 private static final int MAX_POOL_SIZE = 50;
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -0800587 private static final SynchronizedPool<AccessibilityNodeInfo> sPool =
Alan Viverette23f44322015-04-06 16:04:56 -0700588 new SynchronizedPool<>(MAX_POOL_SIZE);
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -0800589
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700590 private boolean mSealed;
591
592 // Data.
Svetoslav8e3feb12014-02-24 13:46:47 -0800593 private int mWindowId = UNDEFINED_ITEM_ID;
Svetoslav Ganov0d04e242012-02-21 13:46:36 -0800594 private long mSourceNodeId = ROOT_NODE_ID;
595 private long mParentNodeId = ROOT_NODE_ID;
Svetoslav Ganov33aef982012-09-13 12:49:03 -0700596 private long mLabelForId = ROOT_NODE_ID;
597 private long mLabeledById = ROOT_NODE_ID;
Svetoslav6c702902014-10-09 18:40:56 -0700598 private long mTraversalBefore = ROOT_NODE_ID;
599 private long mTraversalAfter = ROOT_NODE_ID;
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800600
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700601 private int mBooleanProperties;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700602 private final Rect mBoundsInParent = new Rect();
603 private final Rect mBoundsInScreen = new Rect();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700604
605 private CharSequence mPackageName;
606 private CharSequence mClassName;
607 private CharSequence mText;
Alan Viverettefccbff52014-07-07 15:06:14 -0700608 private CharSequence mError;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700609 private CharSequence mContentDescription;
Svetoslav9fa1ee52013-04-22 12:43:03 -0700610 private String mViewIdResourceName;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700611
Alan Viverettef0aed092013-11-06 15:33:03 -0800612 private LongArray mChildNodeIds;
Kristian Monsen74bc1942014-04-29 11:00:17 -0700613 private ArrayList<AccessibilityAction> mActions;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700614
Alan Viverette029942f2014-08-12 14:55:56 -0700615 private int mMaxTextLength = -1;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700616 private int mMovementGranularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700617
Svetoslav8e3feb12014-02-24 13:46:47 -0800618 private int mTextSelectionStart = UNDEFINED_SELECTION_INDEX;
619 private int mTextSelectionEnd = UNDEFINED_SELECTION_INDEX;
Svetoslav6254f482013-06-04 17:22:14 -0700620 private int mInputType = InputType.TYPE_NULL;
Alan Viverette77e9a282013-09-12 17:16:09 -0700621 private int mLiveRegion = View.ACCESSIBILITY_LIVE_REGION_NONE;
Svetoslav6254f482013-06-04 17:22:14 -0700622
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -0700623 private Bundle mExtras;
Svetoslavbcc46a02013-02-06 11:56:00 -0800624
Svetoslav8e3feb12014-02-24 13:46:47 -0800625 private int mConnectionId = UNDEFINED_CONNECTION_ID;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700626
Svetoslav3577a282013-06-06 14:09:10 -0700627 private RangeInfo mRangeInfo;
628 private CollectionInfo mCollectionInfo;
629 private CollectionItemInfo mCollectionItemInfo;
630
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700631 /**
632 * Hide constructor from clients.
633 */
634 private AccessibilityNodeInfo() {
635 /* do nothing */
636 }
637
638 /**
639 * Sets the source.
Svetoslav Ganov02107852011-10-03 17:06:56 -0700640 * <p>
641 * <strong>Note:</strong> Cannot be called from an
642 * {@link android.accessibilityservice.AccessibilityService}.
643 * This class is made immutable before being delivered to an AccessibilityService.
644 * </p>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700645 *
646 * @param source The info source.
647 */
648 public void setSource(View source) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800649 setSource(source, UNDEFINED_ITEM_ID);
Svetoslav Ganov02107852011-10-03 17:06:56 -0700650 }
651
652 /**
653 * Sets the source to be a virtual descendant of the given <code>root</code>.
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700654 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
Svetoslav Ganov02107852011-10-03 17:06:56 -0700655 * is set as the source.
656 * <p>
657 * A virtual descendant is an imaginary View that is reported as a part of the view
658 * hierarchy for accessibility purposes. This enables custom views that draw complex
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700659 * content to report themselves as a tree of virtual views, thus conveying their
Svetoslav Ganov02107852011-10-03 17:06:56 -0700660 * logical structure.
661 * </p>
662 * <p>
663 * <strong>Note:</strong> Cannot be called from an
664 * {@link android.accessibilityservice.AccessibilityService}.
665 * This class is made immutable before being delivered to an AccessibilityService.
666 * </p>
667 *
668 * @param root The root of the virtual subtree.
669 * @param virtualDescendantId The id of the virtual descendant.
670 */
671 public void setSource(View root, int virtualDescendantId) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700672 enforceNotSealed();
Svetoslav8e3feb12014-02-24 13:46:47 -0800673 mWindowId = (root != null) ? root.getAccessibilityWindowId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700674 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -0800675 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700676 mSourceNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700677 }
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700678
Svetoslav Ganov42138042012-03-20 11:51:39 -0700679 /**
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700680 * Find the view that has the specified focus type. The search starts from
Svetoslav Ganov42138042012-03-20 11:51:39 -0700681 * the view represented by this node info.
682 *
683 * @param focus The focus to find. One of {@link #FOCUS_INPUT} or
684 * {@link #FOCUS_ACCESSIBILITY}.
685 * @return The node info of the focused view or null.
686 *
687 * @see #FOCUS_INPUT
688 * @see #FOCUS_ACCESSIBILITY
689 */
690 public AccessibilityNodeInfo findFocus(int focus) {
691 enforceSealed();
Svetoslav Ganov2ef69052012-06-04 08:55:16 -0700692 enforceValidFocusType(focus);
Svetoslav Ganov42138042012-03-20 11:51:39 -0700693 if (!canPerformRequestOverConnection(mSourceNodeId)) {
694 return null;
695 }
696 return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId, mWindowId,
697 mSourceNodeId, focus);
698 }
699
700 /**
701 * Searches for the nearest view in the specified direction that can take
702 * the input focus.
703 *
704 * @param direction The direction. Can be one of:
705 * {@link View#FOCUS_DOWN},
706 * {@link View#FOCUS_UP},
707 * {@link View#FOCUS_LEFT},
708 * {@link View#FOCUS_RIGHT},
709 * {@link View#FOCUS_FORWARD},
Svetoslav Ganov8ffe8b32012-06-15 10:31:31 -0700710 * {@link View#FOCUS_BACKWARD}.
Svetoslav Ganov42138042012-03-20 11:51:39 -0700711 *
712 * @return The node info for the view that can take accessibility focus.
713 */
714 public AccessibilityNodeInfo focusSearch(int direction) {
715 enforceSealed();
Svetoslav Ganov2ef69052012-06-04 08:55:16 -0700716 enforceValidFocusDirection(direction);
Svetoslav Ganov42138042012-03-20 11:51:39 -0700717 if (!canPerformRequestOverConnection(mSourceNodeId)) {
718 return null;
719 }
720 return AccessibilityInteractionClient.getInstance().focusSearch(mConnectionId, mWindowId,
721 mSourceNodeId, direction);
722 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700723
724 /**
725 * Gets the id of the window from which the info comes from.
726 *
727 * @return The window id.
728 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700729 public int getWindowId() {
Svetoslav Ganov02107852011-10-03 17:06:56 -0700730 return mWindowId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700731 }
732
733 /**
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800734 * Refreshes this info with the latest state of the view it represents.
735 * <p>
736 * <strong>Note:</strong> If this method returns false this info is obsolete
737 * since it represents a view that is no longer in the view tree and should
738 * be recycled.
739 * </p>
Svetoslav6254f482013-06-04 17:22:14 -0700740 *
741 * @param bypassCache Whether to bypass the cache.
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800742 * @return Whether the refresh succeeded.
Svetoslav6254f482013-06-04 17:22:14 -0700743 *
744 * @hide
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800745 */
Svetoslav6254f482013-06-04 17:22:14 -0700746 public boolean refresh(boolean bypassCache) {
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800747 enforceSealed();
748 if (!canPerformRequestOverConnection(mSourceNodeId)) {
749 return false;
750 }
751 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
752 AccessibilityNodeInfo refreshedInfo = client.findAccessibilityNodeInfoByAccessibilityId(
Svetoslav6254f482013-06-04 17:22:14 -0700753 mConnectionId, mWindowId, mSourceNodeId, bypassCache, 0);
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800754 if (refreshedInfo == null) {
755 return false;
756 }
757 init(refreshedInfo);
758 refreshedInfo.recycle();
759 return true;
760 }
761
762 /**
Svetoslav6254f482013-06-04 17:22:14 -0700763 * Refreshes this info with the latest state of the view it represents.
764 * <p>
765 * <strong>Note:</strong> If this method returns false this info is obsolete
766 * since it represents a view that is no longer in the view tree and should
767 * be recycled.
768 * </p>
769 * @return Whether the refresh succeeded.
770 */
771 public boolean refresh() {
Svetoslav5738fec2015-01-28 16:44:02 -0800772 return refresh(true);
Svetoslav6254f482013-06-04 17:22:14 -0700773 }
774
775 /**
Alan Viverettef0aed092013-11-06 15:33:03 -0800776 * Returns the array containing the IDs of this node's children.
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800777 *
778 * @hide
779 */
Alan Viverettef0aed092013-11-06 15:33:03 -0800780 public LongArray getChildNodeIds() {
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800781 return mChildNodeIds;
782 }
783
784 /**
Alan Viverettef0aed092013-11-06 15:33:03 -0800785 * Returns the id of the child at the specified index.
786 *
787 * @throws IndexOutOfBoundsException when index &lt; 0 || index &gt;=
788 * getChildCount()
789 * @hide
790 */
791 public long getChildId(int index) {
792 if (mChildNodeIds == null) {
793 throw new IndexOutOfBoundsException();
794 }
795 return mChildNodeIds.get(index);
796 }
797
798 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700799 * Gets the number of children.
800 *
801 * @return The child count.
802 */
803 public int getChildCount() {
Alan Viverettef0aed092013-11-06 15:33:03 -0800804 return mChildNodeIds == null ? 0 : mChildNodeIds.size();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700805 }
806
807 /**
808 * Get the child at given index.
809 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700810 * <strong>Note:</strong> It is a client responsibility to recycle the
811 * received info by calling {@link AccessibilityNodeInfo#recycle()}
812 * to avoid creating of multiple instances.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700813 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700814 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700815 * @param index The child index.
816 * @return The child node.
817 *
818 * @throws IllegalStateException If called outside of an AccessibilityService.
819 *
820 */
821 public AccessibilityNodeInfo getChild(int index) {
822 enforceSealed();
Alan Viverettef0aed092013-11-06 15:33:03 -0800823 if (mChildNodeIds == null) {
824 return null;
825 }
Svetoslav Ganov02107852011-10-03 17:06:56 -0700826 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700827 return null;
828 }
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800829 final long childId = mChildNodeIds.get(index);
Svetoslav Ganov8bd69612011-08-23 13:40:30 -0700830 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800831 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId,
Svetoslav6254f482013-06-04 17:22:14 -0700832 childId, false, FLAG_PREFETCH_DESCENDANTS);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700833 }
834
835 /**
836 * Adds a child.
837 * <p>
Svetoslav Ganov02107852011-10-03 17:06:56 -0700838 * <strong>Note:</strong> Cannot be called from an
839 * {@link android.accessibilityservice.AccessibilityService}.
840 * This class is made immutable before being delivered to an AccessibilityService.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700841 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700842 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700843 * @param child The child.
844 *
845 * @throws IllegalStateException If called from an AccessibilityService.
846 */
847 public void addChild(View child) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800848 addChildInternal(child, UNDEFINED_ITEM_ID, true);
Alan Viverettef0aed092013-11-06 15:33:03 -0800849 }
850
851 /**
852 * Unchecked version of {@link #addChild(View)} that does not verify
853 * uniqueness. For framework use only.
854 *
855 * @hide
856 */
857 public void addChildUnchecked(View child) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800858 addChildInternal(child, UNDEFINED_ITEM_ID, false);
Alan Viverettef0aed092013-11-06 15:33:03 -0800859 }
860
861 /**
862 * Removes a child. If the child was not previously added to the node,
863 * calling this method has no effect.
864 * <p>
865 * <strong>Note:</strong> Cannot be called from an
866 * {@link android.accessibilityservice.AccessibilityService}.
867 * This class is made immutable before being delivered to an AccessibilityService.
868 * </p>
869 *
870 * @param child The child.
871 * @return true if the child was present
872 *
873 * @throws IllegalStateException If called from an AccessibilityService.
874 */
875 public boolean removeChild(View child) {
Svetoslav8e3feb12014-02-24 13:46:47 -0800876 return removeChild(child, UNDEFINED_ITEM_ID);
Svetoslav Ganov02107852011-10-03 17:06:56 -0700877 }
878
879 /**
880 * Adds a virtual child which is a descendant of the given <code>root</code>.
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700881 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
Svetoslav Ganov02107852011-10-03 17:06:56 -0700882 * is added as a child.
883 * <p>
884 * A virtual descendant is an imaginary View that is reported as a part of the view
885 * hierarchy for accessibility purposes. This enables custom views that draw complex
886 * content to report them selves as a tree of virtual views, thus conveying their
887 * logical structure.
888 * </p>
889 *
890 * @param root The root of the virtual subtree.
891 * @param virtualDescendantId The id of the virtual child.
892 */
893 public void addChild(View root, int virtualDescendantId) {
Alan Viverettef0aed092013-11-06 15:33:03 -0800894 addChildInternal(root, virtualDescendantId, true);
895 }
896
897 private void addChildInternal(View root, int virtualDescendantId, boolean checked) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700898 enforceNotSealed();
Alan Viverettef0aed092013-11-06 15:33:03 -0800899 if (mChildNodeIds == null) {
900 mChildNodeIds = new LongArray();
901 }
Svetoslav Ganov02107852011-10-03 17:06:56 -0700902 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -0800903 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700904 final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Alan Viverettef0aed092013-11-06 15:33:03 -0800905 // If we're checking uniqueness and the ID already exists, abort.
906 if (checked && mChildNodeIds.indexOf(childNodeId) >= 0) {
907 return;
908 }
909 mChildNodeIds.add(childNodeId);
910 }
911
912 /**
913 * Removes a virtual child which is a descendant of the given
914 * <code>root</code>. If the child was not previously added to the node,
915 * calling this method has no effect.
916 *
917 * @param root The root of the virtual subtree.
918 * @param virtualDescendantId The id of the virtual child.
919 * @return true if the child was present
920 * @see #addChild(View, int)
921 */
922 public boolean removeChild(View root, int virtualDescendantId) {
923 enforceNotSealed();
924 final LongArray childIds = mChildNodeIds;
925 if (childIds == null) {
926 return false;
927 }
928 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -0800929 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Alan Viverettef0aed092013-11-06 15:33:03 -0800930 final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
931 final int index = childIds.indexOf(childNodeId);
932 if (index < 0) {
933 return false;
934 }
935 childIds.remove(index);
936 return true;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700937 }
938
939 /**
940 * Gets the actions that can be performed on the node.
Kristian Monsen74bc1942014-04-29 11:00:17 -0700941 */
942 public List<AccessibilityAction> getActionList() {
943 if (mActions == null) {
944 return Collections.emptyList();
945 }
946
947 return mActions;
948 }
949
950 /**
951 * Gets the actions that can be performed on the node.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700952 *
953 * @return The bit mask of with actions.
954 *
955 * @see AccessibilityNodeInfo#ACTION_FOCUS
956 * @see AccessibilityNodeInfo#ACTION_CLEAR_FOCUS
957 * @see AccessibilityNodeInfo#ACTION_SELECT
958 * @see AccessibilityNodeInfo#ACTION_CLEAR_SELECTION
Svetoslav Ganova1dc7612012-05-10 04:14:53 -0700959 * @see AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS
960 * @see AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS
961 * @see AccessibilityNodeInfo#ACTION_CLICK
962 * @see AccessibilityNodeInfo#ACTION_LONG_CLICK
963 * @see AccessibilityNodeInfo#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
964 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
965 * @see AccessibilityNodeInfo#ACTION_NEXT_HTML_ELEMENT
966 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_HTML_ELEMENT
967 * @see AccessibilityNodeInfo#ACTION_SCROLL_FORWARD
968 * @see AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD
Kristian Monsen74bc1942014-04-29 11:00:17 -0700969 *
970 * @deprecated Use {@link #getActionList()}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700971 */
Kristian Monsen74bc1942014-04-29 11:00:17 -0700972 @Deprecated
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700973 public int getActions() {
Kristian Monsen74bc1942014-04-29 11:00:17 -0700974 int returnValue = 0;
975
976 if (mActions == null) {
977 return returnValue;
978 }
979
980 final int actionSize = mActions.size();
981 for (int i = 0; i < actionSize; i++) {
982 int actionId = mActions.get(i).getId();
983 if (actionId <= LAST_LEGACY_STANDARD_ACTION) {
984 returnValue |= actionId;
985 }
986 }
987
988 return returnValue;
989 }
990
991 /**
992 * Adds an action that can be performed on the node.
993 * <p>
994 * To add a standard action use the static constants on {@link AccessibilityAction}.
995 * To add a custom action create a new {@link AccessibilityAction} by passing in a
996 * resource id from your application as the action id and an optional label that
997 * describes the action. To override one of the standard actions use as the action
998 * id of a standard action id such as {@link #ACTION_CLICK} and an optional label that
999 * describes the action.
1000 * </p>
1001 * <p>
1002 * <strong>Note:</strong> Cannot be called from an
1003 * {@link android.accessibilityservice.AccessibilityService}.
1004 * This class is made immutable before being delivered to an AccessibilityService.
1005 * </p>
1006 *
1007 * @param action The action.
1008 *
1009 * @throws IllegalStateException If called from an AccessibilityService.
1010 */
1011 public void addAction(AccessibilityAction action) {
1012 enforceNotSealed();
1013
Alan Viverettec921f272015-05-14 12:26:49 -07001014 addActionUnchecked(action);
1015 }
1016
1017 private void addActionUnchecked(AccessibilityAction action) {
Kristian Monsen74bc1942014-04-29 11:00:17 -07001018 if (action == null) {
1019 return;
1020 }
1021
1022 if (mActions == null) {
Alan Viverette23f44322015-04-06 16:04:56 -07001023 mActions = new ArrayList<>();
Kristian Monsen74bc1942014-04-29 11:00:17 -07001024 }
1025
1026 mActions.remove(action);
1027 mActions.add(action);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001028 }
1029
1030 /**
1031 * Adds an action that can be performed on the node.
1032 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001033 * <strong>Note:</strong> Cannot be called from an
1034 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001035 * This class is made immutable before being delivered to an AccessibilityService.
1036 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001037 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001038 * @param action The action.
1039 *
1040 * @throws IllegalStateException If called from an AccessibilityService.
Kristian Monsen74bc1942014-04-29 11:00:17 -07001041 * @throws IllegalArgumentException If the argument is not one of the standard actions.
1042 *
1043 * @deprecated This has been deprecated for {@link #addAction(AccessibilityAction)}
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001044 */
Kristian Monsen74bc1942014-04-29 11:00:17 -07001045 @Deprecated
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001046 public void addAction(int action) {
1047 enforceNotSealed();
Kristian Monsen74bc1942014-04-29 11:00:17 -07001048
Kristian Monsen8d5f3fa2014-05-20 13:16:19 -07001049 if ((action & ACTION_TYPE_MASK) != 0) {
1050 throw new IllegalArgumentException("Action is not a combination of the standard " +
1051 "actions: " + action);
Kristian Monsen74bc1942014-04-29 11:00:17 -07001052 }
1053
Kristian Monsen8d5f3fa2014-05-20 13:16:19 -07001054 addLegacyStandardActions(action);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001055 }
1056
1057 /**
Alan Viverettef0aed092013-11-06 15:33:03 -08001058 * Removes an action that can be performed on the node. If the action was
1059 * not already added to the node, calling this method has no effect.
1060 * <p>
1061 * <strong>Note:</strong> Cannot be called from an
1062 * {@link android.accessibilityservice.AccessibilityService}.
1063 * This class is made immutable before being delivered to an AccessibilityService.
1064 * </p>
1065 *
Kristian Monsen74bc1942014-04-29 11:00:17 -07001066 * @param action The action to be removed.
1067 *
1068 * @throws IllegalStateException If called from an AccessibilityService.
1069 * @deprecated Use {@link #removeAction(AccessibilityAction)}
1070 */
1071 @Deprecated
1072 public void removeAction(int action) {
1073 enforceNotSealed();
1074
1075 removeAction(getActionSingleton(action));
1076 }
1077
1078 /**
1079 * Removes an action that can be performed on the node. If the action was
1080 * not already added to the node, calling this method has no effect.
1081 * <p>
1082 * <strong>Note:</strong> Cannot be called from an
1083 * {@link android.accessibilityservice.AccessibilityService}.
1084 * This class is made immutable before being delivered to an AccessibilityService.
1085 * </p>
1086 *
1087 * @param action The action to be removed.
1088 * @return The action removed from the list of actions.
Alan Viverettef0aed092013-11-06 15:33:03 -08001089 *
1090 * @throws IllegalStateException If called from an AccessibilityService.
1091 */
Kristian Monsen74bc1942014-04-29 11:00:17 -07001092 public boolean removeAction(AccessibilityAction action) {
Alan Viverettef0aed092013-11-06 15:33:03 -08001093 enforceNotSealed();
Kristian Monsen74bc1942014-04-29 11:00:17 -07001094
1095 if (mActions == null || action == null) {
1096 return false;
1097 }
1098
1099 return mActions.remove(action);
Alan Viverettef0aed092013-11-06 15:33:03 -08001100 }
1101
1102 /**
Svetoslav6c702902014-10-09 18:40:56 -07001103 * Gets the node before which this one is visited during traversal. A screen-reader
1104 * must visit the content of this node before the content of the one it precedes.
1105 *
1106 * @return The succeeding node if such or <code>null</code>.
1107 *
1108 * @see #setTraversalBefore(android.view.View)
1109 * @see #setTraversalBefore(android.view.View, int)
1110 */
1111 public AccessibilityNodeInfo getTraversalBefore() {
1112 enforceSealed();
1113 return getNodeForAccessibilityId(mTraversalBefore);
1114 }
1115
1116 /**
1117 * Sets the view before whose node this one should be visited during traversal. A
1118 * screen-reader must visit the content of this node before the content of the one
1119 * it precedes.
1120 * <p>
1121 * <strong>Note:</strong> Cannot be called from an
1122 * {@link android.accessibilityservice.AccessibilityService}.
1123 * This class is made immutable before being delivered to an AccessibilityService.
1124 * </p>
1125 *
1126 * @param view The view providing the preceding node.
1127 *
1128 * @see #getTraversalBefore()
1129 */
1130 public void setTraversalBefore(View view) {
1131 setTraversalBefore(view, UNDEFINED_ITEM_ID);
1132 }
1133
1134 /**
1135 * Sets the node before which this one is visited during traversal. A screen-reader
1136 * must visit the content of this node before the content of the one it precedes.
1137 * The successor is a virtual descendant of the given <code>root</code>. If
1138 * <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root is set
1139 * as the successor.
1140 * <p>
1141 * A virtual descendant is an imaginary View that is reported as a part of the view
1142 * hierarchy for accessibility purposes. This enables custom views that draw complex
1143 * content to report them selves as a tree of virtual views, thus conveying their
1144 * logical structure.
1145 * </p>
1146 * <p>
1147 * <strong>Note:</strong> Cannot be called from an
1148 * {@link android.accessibilityservice.AccessibilityService}.
1149 * This class is made immutable before being delivered to an AccessibilityService.
1150 * </p>
1151 *
1152 * @param root The root of the virtual subtree.
1153 * @param virtualDescendantId The id of the virtual descendant.
1154 */
1155 public void setTraversalBefore(View root, int virtualDescendantId) {
1156 enforceNotSealed();
1157 final int rootAccessibilityViewId = (root != null)
1158 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
1159 mTraversalBefore = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1160 }
1161
1162 /**
1163 * Gets the node after which this one is visited in accessibility traversal.
1164 * A screen-reader must visit the content of the other node before the content
1165 * of this one.
1166 *
1167 * @return The succeeding node if such or <code>null</code>.
1168 *
1169 * @see #setTraversalAfter(android.view.View)
1170 * @see #setTraversalAfter(android.view.View, int)
1171 */
1172 public AccessibilityNodeInfo getTraversalAfter() {
1173 enforceSealed();
1174 return getNodeForAccessibilityId(mTraversalAfter);
1175 }
1176
1177 /**
1178 * Sets the view whose node is visited after this one in accessibility traversal.
1179 * A screen-reader must visit the content of the other node before the content
1180 * of this one.
1181 * <p>
1182 * <strong>Note:</strong> Cannot be called from an
1183 * {@link android.accessibilityservice.AccessibilityService}.
1184 * This class is made immutable before being delivered to an AccessibilityService.
1185 * </p>
1186 *
1187 * @param view The previous view.
1188 *
1189 * @see #getTraversalAfter()
1190 */
1191 public void setTraversalAfter(View view) {
1192 setTraversalAfter(view, UNDEFINED_ITEM_ID);
1193 }
1194
1195 /**
1196 * Sets the node after which this one is visited in accessibility traversal.
1197 * A screen-reader must visit the content of the other node before the content
1198 * of this one. If <code>virtualDescendantId</code> equals to {@link View#NO_ID}
1199 * the root is set as the predecessor.
1200 * <p>
1201 * A virtual descendant is an imaginary View that is reported as a part of the view
1202 * hierarchy for accessibility purposes. This enables custom views that draw complex
1203 * content to report them selves as a tree of virtual views, thus conveying their
1204 * logical structure.
1205 * </p>
1206 * <p>
1207 * <strong>Note:</strong> Cannot be called from an
1208 * {@link android.accessibilityservice.AccessibilityService}.
1209 * This class is made immutable before being delivered to an AccessibilityService.
1210 * </p>
1211 *
1212 * @param root The root of the virtual subtree.
1213 * @param virtualDescendantId The id of the virtual descendant.
1214 */
1215 public void setTraversalAfter(View root, int virtualDescendantId) {
1216 enforceNotSealed();
1217 final int rootAccessibilityViewId = (root != null)
1218 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
1219 mTraversalAfter = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1220 }
1221
1222 /**
Alan Viverette029942f2014-08-12 14:55:56 -07001223 * Sets the maximum text length, or -1 for no limit.
1224 * <p>
1225 * Typically used to indicate that an editable text field has a limit on
1226 * the number of characters entered.
1227 * <p>
1228 * <strong>Note:</strong> Cannot be called from an
1229 * {@link android.accessibilityservice.AccessibilityService}.
1230 * This class is made immutable before being delivered to an AccessibilityService.
1231 *
1232 * @param max The maximum text length.
1233 * @see #getMaxTextLength()
1234 *
1235 * @throws IllegalStateException If called from an AccessibilityService.
1236 */
1237 public void setMaxTextLength(int max) {
1238 enforceNotSealed();
1239 mMaxTextLength = max;
1240 }
1241
1242 /**
1243 * Returns the maximum text length for this node.
1244 *
1245 * @return The maximum text length, or -1 for no limit.
1246 * @see #setMaxTextLength(int)
1247 */
1248 public int getMaxTextLength() {
1249 return mMaxTextLength;
1250 }
1251
1252 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001253 * Sets the movement granularities for traversing the text of this node.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001254 * <p>
1255 * <strong>Note:</strong> Cannot be called from an
1256 * {@link android.accessibilityservice.AccessibilityService}.
1257 * This class is made immutable before being delivered to an AccessibilityService.
1258 * </p>
1259 *
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07001260 * @param granularities The bit mask with granularities.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001261 *
1262 * @throws IllegalStateException If called from an AccessibilityService.
1263 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001264 public void setMovementGranularities(int granularities) {
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001265 enforceNotSealed();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001266 mMovementGranularities = granularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001267 }
1268
1269 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001270 * Gets the movement granularities for traversing the text of this node.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001271 *
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07001272 * @return The bit mask with granularities.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001273 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001274 public int getMovementGranularities() {
1275 return mMovementGranularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001276 }
1277
1278 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001279 * Performs an action on the node.
1280 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001281 * <strong>Note:</strong> An action can be performed only if the request is made
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001282 * from an {@link android.accessibilityservice.AccessibilityService}.
1283 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001284 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001285 * @param action The action to perform.
1286 * @return True if the action was performed.
1287 *
1288 * @throws IllegalStateException If called outside of an AccessibilityService.
1289 */
1290 public boolean performAction(int action) {
1291 enforceSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -07001292 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001293 return false;
1294 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -07001295 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001296 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
1297 action, null);
1298 }
1299
1300 /**
1301 * Performs an action on the node.
1302 * <p>
1303 * <strong>Note:</strong> An action can be performed only if the request is made
1304 * from an {@link android.accessibilityservice.AccessibilityService}.
1305 * </p>
1306 *
1307 * @param action The action to perform.
1308 * @param arguments A bundle with additional arguments.
1309 * @return True if the action was performed.
1310 *
1311 * @throws IllegalStateException If called outside of an AccessibilityService.
1312 */
1313 public boolean performAction(int action, Bundle arguments) {
1314 enforceSealed();
1315 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1316 return false;
1317 }
1318 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1319 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
1320 action, arguments);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001321 }
1322
1323 /**
1324 * Finds {@link AccessibilityNodeInfo}s by text. The match is case
Svetoslav Ganov86398bd2011-06-21 17:38:43 -07001325 * insensitive containment. The search is relative to this info i.e.
1326 * this info is the root of the traversed tree.
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07001327 *
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001328 * <p>
1329 * <strong>Note:</strong> It is a client responsibility to recycle the
1330 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1331 * to avoid creating of multiple instances.
1332 * </p>
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001333 *
1334 * @param text The searched text.
1335 * @return A list of node info.
1336 */
1337 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text) {
1338 enforceSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -07001339 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganov86398bd2011-06-21 17:38:43 -07001340 return Collections.emptyList();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001341 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -07001342 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganov79311c42012-01-17 20:24:26 -08001343 return client.findAccessibilityNodeInfosByText(mConnectionId, mWindowId, mSourceNodeId,
1344 text);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001345 }
1346
1347 /**
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001348 * Finds {@link AccessibilityNodeInfo}s by the fully qualified view id's resource
1349 * name where a fully qualified id is of the from "package:id/id_resource_name".
1350 * For example, if the target application's package is "foo.bar" and the id
1351 * resource name is "baz", the fully qualified resource id is "foo.bar:id/baz".
1352 *
1353 * <p>
1354 * <strong>Note:</strong> It is a client responsibility to recycle the
1355 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1356 * to avoid creating of multiple instances.
1357 * </p>
1358 * <p>
1359 * <strong>Note:</strong> The primary usage of this API is for UI test automation
1360 * and in order to report the fully qualified view id if an {@link AccessibilityNodeInfo}
1361 * the client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
Svetoslav14ff9962013-01-29 03:21:37 -08001362 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001363 * </p>
1364 *
1365 * @param viewId The fully qualified resource name of the view id to find.
1366 * @return A list of node info.
1367 */
1368 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId(String viewId) {
1369 enforceSealed();
1370 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1371 return Collections.emptyList();
1372 }
1373 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1374 return client.findAccessibilityNodeInfosByViewId(mConnectionId, mWindowId, mSourceNodeId,
1375 viewId);
1376 }
1377
1378 /**
Svetoslav8e3feb12014-02-24 13:46:47 -08001379 * Gets the window to which this node belongs.
1380 *
1381 * @return The window.
1382 *
1383 * @see android.accessibilityservice.AccessibilityService#getWindows()
1384 */
1385 public AccessibilityWindowInfo getWindow() {
1386 enforceSealed();
1387 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1388 return null;
1389 }
1390 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1391 return client.getWindow(mConnectionId, mWindowId);
1392 }
1393
1394 /**
Svetoslav Ganov00aabf72011-07-21 11:35:03 -07001395 * Gets the parent.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001396 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001397 * <strong>Note:</strong> It is a client responsibility to recycle the
1398 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1399 * to avoid creating of multiple instances.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001400 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001401 *
Svetoslav Ganov00aabf72011-07-21 11:35:03 -07001402 * @return The parent.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001403 */
1404 public AccessibilityNodeInfo getParent() {
1405 enforceSealed();
Svetoslav6c702902014-10-09 18:40:56 -07001406 return getNodeForAccessibilityId(mParentNodeId);
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -08001407 }
1408
1409 /**
1410 * @return The parent node id.
1411 *
1412 * @hide
1413 */
1414 public long getParentNodeId() {
1415 return mParentNodeId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001416 }
1417
1418 /**
1419 * Sets the parent.
1420 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001421 * <strong>Note:</strong> Cannot be called from an
1422 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001423 * This class is made immutable before being delivered to an AccessibilityService.
1424 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001425 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001426 * @param parent The parent.
1427 *
1428 * @throws IllegalStateException If called from an AccessibilityService.
1429 */
1430 public void setParent(View parent) {
Svetoslav8e3feb12014-02-24 13:46:47 -08001431 setParent(parent, UNDEFINED_ITEM_ID);
Svetoslav Ganov02107852011-10-03 17:06:56 -07001432 }
1433
1434 /**
1435 * Sets the parent to be a virtual descendant of the given <code>root</code>.
1436 * If <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root
1437 * is set as the parent.
1438 * <p>
1439 * A virtual descendant is an imaginary View that is reported as a part of the view
1440 * hierarchy for accessibility purposes. This enables custom views that draw complex
1441 * content to report them selves as a tree of virtual views, thus conveying their
1442 * logical structure.
1443 * </p>
1444 * <p>
1445 * <strong>Note:</strong> Cannot be called from an
1446 * {@link android.accessibilityservice.AccessibilityService}.
1447 * This class is made immutable before being delivered to an AccessibilityService.
1448 * </p>
1449 *
1450 * @param root The root of the virtual subtree.
1451 * @param virtualDescendantId The id of the virtual descendant.
1452 */
1453 public void setParent(View root, int virtualDescendantId) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001454 enforceNotSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -07001455 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -08001456 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -07001457 mParentNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001458 }
1459
1460 /**
1461 * Gets the node bounds in parent coordinates.
1462 *
1463 * @param outBounds The output node bounds.
1464 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001465 public void getBoundsInParent(Rect outBounds) {
1466 outBounds.set(mBoundsInParent.left, mBoundsInParent.top,
1467 mBoundsInParent.right, mBoundsInParent.bottom);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001468 }
1469
1470 /**
1471 * Sets the node bounds in parent coordinates.
1472 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001473 * <strong>Note:</strong> Cannot be called from an
1474 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001475 * This class is made immutable before being delivered to an AccessibilityService.
1476 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001477 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001478 * @param bounds The node bounds.
1479 *
1480 * @throws IllegalStateException If called from an AccessibilityService.
1481 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001482 public void setBoundsInParent(Rect bounds) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001483 enforceNotSealed();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001484 mBoundsInParent.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
1485 }
1486
1487 /**
1488 * Gets the node bounds in screen coordinates.
1489 *
1490 * @param outBounds The output node bounds.
1491 */
1492 public void getBoundsInScreen(Rect outBounds) {
1493 outBounds.set(mBoundsInScreen.left, mBoundsInScreen.top,
1494 mBoundsInScreen.right, mBoundsInScreen.bottom);
1495 }
1496
1497 /**
Alan Viverettea7ea65e2015-05-15 11:30:21 -07001498 * Returns the actual rect containing the node bounds in screen coordinates.
1499 *
1500 * @hide Not safe to expose outside the framework.
1501 */
1502 public Rect getBoundsInScreen() {
1503 return mBoundsInScreen;
1504 }
1505
1506 /**
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001507 * Sets the node bounds in screen coordinates.
1508 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001509 * <strong>Note:</strong> Cannot be called from an
1510 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001511 * This class is made immutable before being delivered to an AccessibilityService.
1512 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001513 *
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001514 * @param bounds The node bounds.
1515 *
1516 * @throws IllegalStateException If called from an AccessibilityService.
1517 */
1518 public void setBoundsInScreen(Rect bounds) {
1519 enforceNotSealed();
1520 mBoundsInScreen.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001521 }
1522
1523 /**
1524 * Gets whether this node is checkable.
1525 *
1526 * @return True if the node is checkable.
1527 */
1528 public boolean isCheckable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001529 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001530 }
1531
1532 /**
1533 * Sets whether this node is checkable.
1534 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001535 * <strong>Note:</strong> Cannot be called from an
1536 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001537 * This class is made immutable before being delivered to an AccessibilityService.
1538 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001539 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001540 * @param checkable True if the node is checkable.
1541 *
1542 * @throws IllegalStateException If called from an AccessibilityService.
1543 */
1544 public void setCheckable(boolean checkable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001545 setBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE, checkable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001546 }
1547
1548 /**
1549 * Gets whether this node is checked.
1550 *
1551 * @return True if the node is checked.
1552 */
1553 public boolean isChecked() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001554 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001555 }
1556
1557 /**
1558 * Sets whether this node is checked.
1559 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001560 * <strong>Note:</strong> Cannot be called from an
1561 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001562 * This class is made immutable before being delivered to an AccessibilityService.
1563 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001564 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001565 * @param checked True if the node is checked.
1566 *
1567 * @throws IllegalStateException If called from an AccessibilityService.
1568 */
1569 public void setChecked(boolean checked) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001570 setBooleanProperty(BOOLEAN_PROPERTY_CHECKED, checked);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001571 }
1572
1573 /**
1574 * Gets whether this node is focusable.
1575 *
1576 * @return True if the node is focusable.
1577 */
1578 public boolean isFocusable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001579 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001580 }
1581
1582 /**
1583 * Sets whether this node is focusable.
1584 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001585 * <strong>Note:</strong> Cannot be called from an
1586 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001587 * This class is made immutable before being delivered to an AccessibilityService.
1588 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001589 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001590 * @param focusable True if the node is focusable.
1591 *
1592 * @throws IllegalStateException If called from an AccessibilityService.
1593 */
1594 public void setFocusable(boolean focusable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001595 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE, focusable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001596 }
1597
1598 /**
1599 * Gets whether this node is focused.
1600 *
1601 * @return True if the node is focused.
1602 */
1603 public boolean isFocused() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001604 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001605 }
1606
1607 /**
1608 * Sets whether this node is focused.
1609 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001610 * <strong>Note:</strong> Cannot be called from an
1611 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001612 * This class is made immutable before being delivered to an AccessibilityService.
1613 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001614 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001615 * @param focused True if the node is focused.
1616 *
1617 * @throws IllegalStateException If called from an AccessibilityService.
1618 */
1619 public void setFocused(boolean focused) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001620 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSED, focused);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001621 }
1622
1623 /**
Alan Viverette1579edc2015-04-01 13:23:06 -07001624 * Gets whether this node is visible to the user.
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001625 *
1626 * @return Whether the node is visible to the user.
1627 */
1628 public boolean isVisibleToUser() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001629 return getBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001630 }
1631
1632 /**
1633 * Sets whether this node is visible to the user.
1634 * <p>
1635 * <strong>Note:</strong> Cannot be called from an
1636 * {@link android.accessibilityservice.AccessibilityService}.
1637 * This class is made immutable before being delivered to an AccessibilityService.
1638 * </p>
1639 *
1640 * @param visibleToUser Whether the node is visible to the user.
1641 *
1642 * @throws IllegalStateException If called from an AccessibilityService.
1643 */
1644 public void setVisibleToUser(boolean visibleToUser) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001645 setBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER, visibleToUser);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001646 }
1647
1648 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -07001649 * Gets whether this node is accessibility focused.
1650 *
1651 * @return True if the node is accessibility focused.
1652 */
1653 public boolean isAccessibilityFocused() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001654 return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED);
Svetoslav Ganov42138042012-03-20 11:51:39 -07001655 }
1656
1657 /**
1658 * Sets whether this node is accessibility focused.
1659 * <p>
1660 * <strong>Note:</strong> Cannot be called from an
1661 * {@link android.accessibilityservice.AccessibilityService}.
1662 * This class is made immutable before being delivered to an AccessibilityService.
1663 * </p>
1664 *
1665 * @param focused True if the node is accessibility focused.
1666 *
1667 * @throws IllegalStateException If called from an AccessibilityService.
1668 */
1669 public void setAccessibilityFocused(boolean focused) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001670 setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED, focused);
Svetoslav Ganov42138042012-03-20 11:51:39 -07001671 }
1672
1673 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001674 * Gets whether this node is selected.
1675 *
1676 * @return True if the node is selected.
1677 */
1678 public boolean isSelected() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001679 return getBooleanProperty(BOOLEAN_PROPERTY_SELECTED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001680 }
1681
1682 /**
1683 * Sets whether this node is selected.
1684 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001685 * <strong>Note:</strong> Cannot be called from an
1686 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001687 * This class is made immutable before being delivered to an AccessibilityService.
1688 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001689 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001690 * @param selected True if the node is selected.
1691 *
1692 * @throws IllegalStateException If called from an AccessibilityService.
1693 */
1694 public void setSelected(boolean selected) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001695 setBooleanProperty(BOOLEAN_PROPERTY_SELECTED, selected);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001696 }
1697
1698 /**
1699 * Gets whether this node is clickable.
1700 *
1701 * @return True if the node is clickable.
1702 */
1703 public boolean isClickable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001704 return getBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001705 }
1706
1707 /**
1708 * Sets whether this node is clickable.
1709 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001710 * <strong>Note:</strong> Cannot be called from an
1711 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001712 * This class is made immutable before being delivered to an AccessibilityService.
1713 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001714 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001715 * @param clickable True if the node is clickable.
1716 *
1717 * @throws IllegalStateException If called from an AccessibilityService.
1718 */
1719 public void setClickable(boolean clickable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001720 setBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE, clickable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001721 }
1722
1723 /**
1724 * Gets whether this node is long clickable.
1725 *
1726 * @return True if the node is long clickable.
1727 */
1728 public boolean isLongClickable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001729 return getBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001730 }
1731
1732 /**
1733 * Sets whether this node is long clickable.
1734 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001735 * <strong>Note:</strong> Cannot be called from an
1736 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001737 * This class is made immutable before being delivered to an AccessibilityService.
1738 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001739 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001740 * @param longClickable True if the node is long clickable.
1741 *
1742 * @throws IllegalStateException If called from an AccessibilityService.
1743 */
1744 public void setLongClickable(boolean longClickable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001745 setBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE, longClickable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001746 }
1747
1748 /**
1749 * Gets whether this node is enabled.
1750 *
1751 * @return True if the node is enabled.
1752 */
1753 public boolean isEnabled() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001754 return getBooleanProperty(BOOLEAN_PROPERTY_ENABLED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001755 }
1756
1757 /**
1758 * Sets whether this node is enabled.
1759 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001760 * <strong>Note:</strong> Cannot be called from an
1761 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001762 * This class is made immutable before being delivered to an AccessibilityService.
1763 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001764 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001765 * @param enabled True if the node is enabled.
1766 *
1767 * @throws IllegalStateException If called from an AccessibilityService.
1768 */
1769 public void setEnabled(boolean enabled) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001770 setBooleanProperty(BOOLEAN_PROPERTY_ENABLED, enabled);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001771 }
1772
1773 /**
1774 * Gets whether this node is a password.
1775 *
1776 * @return True if the node is a password.
1777 */
1778 public boolean isPassword() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001779 return getBooleanProperty(BOOLEAN_PROPERTY_PASSWORD);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001780 }
1781
1782 /**
1783 * Sets whether this node is a password.
1784 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001785 * <strong>Note:</strong> Cannot be called from an
1786 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001787 * This class is made immutable before being delivered to an AccessibilityService.
1788 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001789 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001790 * @param password True if the node is a password.
1791 *
1792 * @throws IllegalStateException If called from an AccessibilityService.
1793 */
1794 public void setPassword(boolean password) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001795 setBooleanProperty(BOOLEAN_PROPERTY_PASSWORD, password);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001796 }
1797
1798 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -07001799 * Gets if the node is scrollable.
1800 *
1801 * @return True if the node is scrollable, false otherwise.
1802 */
1803 public boolean isScrollable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001804 return getBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE);
Svetoslav Ganova0156172011-06-26 17:55:44 -07001805 }
1806
1807 /**
1808 * Sets if the node is scrollable.
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001809 * <p>
1810 * <strong>Note:</strong> Cannot be called from an
1811 * {@link android.accessibilityservice.AccessibilityService}.
1812 * This class is made immutable before being delivered to an AccessibilityService.
1813 * </p>
Svetoslav Ganova0156172011-06-26 17:55:44 -07001814 *
1815 * @param scrollable True if the node is scrollable, false otherwise.
1816 *
1817 * @throws IllegalStateException If called from an AccessibilityService.
1818 */
1819 public void setScrollable(boolean scrollable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001820 setBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE, scrollable);
1821 }
1822
1823 /**
1824 * Gets if the node is editable.
1825 *
1826 * @return True if the node is editable, false otherwise.
1827 */
1828 public boolean isEditable() {
1829 return getBooleanProperty(BOOLEAN_PROPERTY_EDITABLE);
1830 }
1831
1832 /**
1833 * Sets whether this node is editable.
1834 * <p>
1835 * <strong>Note:</strong> Cannot be called from an
1836 * {@link android.accessibilityservice.AccessibilityService}.
1837 * This class is made immutable before being delivered to an AccessibilityService.
1838 * </p>
1839 *
1840 * @param editable True if the node is editable.
1841 *
1842 * @throws IllegalStateException If called from an AccessibilityService.
1843 */
1844 public void setEditable(boolean editable) {
1845 setBooleanProperty(BOOLEAN_PROPERTY_EDITABLE, editable);
Svetoslav Ganova0156172011-06-26 17:55:44 -07001846 }
1847
1848 /**
Svetoslav3577a282013-06-06 14:09:10 -07001849 * Gets the collection info if the node is a collection. A collection
1850 * child is always a collection item.
1851 *
1852 * @return The collection info.
1853 */
1854 public CollectionInfo getCollectionInfo() {
1855 return mCollectionInfo;
1856 }
1857
1858 /**
1859 * Sets the collection info if the node is a collection. A collection
1860 * child is always a collection item.
1861 * <p>
1862 * <strong>Note:</strong> Cannot be called from an
1863 * {@link android.accessibilityservice.AccessibilityService}.
1864 * This class is made immutable before being delivered to an AccessibilityService.
1865 * </p>
1866 *
1867 * @param collectionInfo The collection info.
1868 */
1869 public void setCollectionInfo(CollectionInfo collectionInfo) {
1870 enforceNotSealed();
1871 mCollectionInfo = collectionInfo;
1872 }
1873
1874 /**
1875 * Gets the collection item info if the node is a collection item. A collection
1876 * item is always a child of a collection.
1877 *
1878 * @return The collection item info.
1879 */
1880 public CollectionItemInfo getCollectionItemInfo() {
1881 return mCollectionItemInfo;
1882 }
1883
1884 /**
1885 * Sets the collection item info if the node is a collection item. A collection
1886 * item is always a child of a collection.
1887 * <p>
1888 * <strong>Note:</strong> Cannot be called from an
1889 * {@link android.accessibilityservice.AccessibilityService}.
1890 * This class is made immutable before being delivered to an AccessibilityService.
1891 * </p>
Svetoslav3577a282013-06-06 14:09:10 -07001892 */
1893 public void setCollectionItemInfo(CollectionItemInfo collectionItemInfo) {
1894 enforceNotSealed();
1895 mCollectionItemInfo = collectionItemInfo;
1896 }
1897
1898 /**
1899 * Gets the range info if this node is a range.
1900 *
1901 * @return The range.
1902 */
1903 public RangeInfo getRangeInfo() {
1904 return mRangeInfo;
1905 }
1906
1907 /**
1908 * Sets the range info if this node is a range.
1909 * <p>
1910 * <strong>Note:</strong> Cannot be called from an
1911 * {@link android.accessibilityservice.AccessibilityService}.
1912 * This class is made immutable before being delivered to an AccessibilityService.
1913 * </p>
1914 *
1915 * @param rangeInfo The range info.
1916 */
1917 public void setRangeInfo(RangeInfo rangeInfo) {
1918 enforceNotSealed();
1919 mRangeInfo = rangeInfo;
1920 }
1921
1922 /**
1923 * Gets if the content of this node is invalid. For example,
1924 * a date is not well-formed.
1925 *
1926 * @return If the node content is invalid.
1927 */
1928 public boolean isContentInvalid() {
1929 return getBooleanProperty(BOOLEAN_PROPERTY_CONTENT_INVALID);
1930 }
1931
1932 /**
1933 * Sets if the content of this node is invalid. For example,
1934 * a date is not well-formed.
1935 * <p>
1936 * <strong>Note:</strong> Cannot be called from an
1937 * {@link android.accessibilityservice.AccessibilityService}.
1938 * This class is made immutable before being delivered to an AccessibilityService.
1939 * </p>
1940 *
1941 * @param contentInvalid If the node content is invalid.
1942 */
1943 public void setContentInvalid(boolean contentInvalid) {
1944 setBooleanProperty(BOOLEAN_PROPERTY_CONTENT_INVALID, contentInvalid);
1945 }
1946
1947 /**
Mady Mellore8608912015-06-05 09:02:55 -07001948 * Gets whether this node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07001949 *
Mady Mellore8608912015-06-05 09:02:55 -07001950 * @return True if the node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07001951 */
Mady Mellore8608912015-06-05 09:02:55 -07001952 public boolean isContextClickable() {
1953 return getBooleanProperty(BOOLEAN_PROPERTY_CONTEXT_CLICKABLE);
Mady Mellore82067b2015-04-30 09:58:35 -07001954 }
1955
1956 /**
Mady Mellore8608912015-06-05 09:02:55 -07001957 * Sets whether this node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07001958 * <p>
1959 * <strong>Note:</strong> Cannot be called from an
1960 * {@link android.accessibilityservice.AccessibilityService}. This class is made immutable
1961 * before being delivered to an AccessibilityService.
1962 * </p>
1963 *
Mady Mellore8608912015-06-05 09:02:55 -07001964 * @param contextClickable True if the node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07001965 * @throws IllegalStateException If called from an AccessibilityService.
1966 */
Mady Mellore8608912015-06-05 09:02:55 -07001967 public void setContextClickable(boolean contextClickable) {
1968 setBooleanProperty(BOOLEAN_PROPERTY_CONTEXT_CLICKABLE, contextClickable);
Mady Mellore82067b2015-04-30 09:58:35 -07001969 }
1970
1971 /**
Alan Viverette77e9a282013-09-12 17:16:09 -07001972 * Gets the node's live region mode.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07001973 * <p>
Alan Viverette77e9a282013-09-12 17:16:09 -07001974 * A live region is a node that contains information that is important for
1975 * the user and when it changes the user should be notified. For example,
1976 * in a login screen with a TextView that displays an "incorrect password"
1977 * notification, that view should be marked as a live region with mode
1978 * {@link View#ACCESSIBILITY_LIVE_REGION_POLITE}.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07001979 * <p>
Alan Viverette77e9a282013-09-12 17:16:09 -07001980 * It is the responsibility of the accessibility service to monitor
1981 * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} events indicating
1982 * changes to live region nodes and their children.
Svetoslav3577a282013-06-06 14:09:10 -07001983 *
Alan Viverette77e9a282013-09-12 17:16:09 -07001984 * @return The live region mode, or
1985 * {@link View#ACCESSIBILITY_LIVE_REGION_NONE} if the view is not a
1986 * live region.
1987 * @see android.view.View#getAccessibilityLiveRegion()
Svetoslav3577a282013-06-06 14:09:10 -07001988 */
Alan Viverette77e9a282013-09-12 17:16:09 -07001989 public int getLiveRegion() {
1990 return mLiveRegion;
Svetoslav3577a282013-06-06 14:09:10 -07001991 }
1992
1993 /**
Alan Viverette77e9a282013-09-12 17:16:09 -07001994 * Sets the node's live region mode.
Svetoslav3577a282013-06-06 14:09:10 -07001995 * <p>
Alan Viverette77e9a282013-09-12 17:16:09 -07001996 * <strong>Note:</strong> Cannot be called from an
1997 * {@link android.accessibilityservice.AccessibilityService}. This class is
1998 * made immutable before being delivered to an AccessibilityService.
Svetoslav3577a282013-06-06 14:09:10 -07001999 *
Alan Viverette77e9a282013-09-12 17:16:09 -07002000 * @param mode The live region mode, or
2001 * {@link View#ACCESSIBILITY_LIVE_REGION_NONE} if the view is not a
2002 * live region.
2003 * @see android.view.View#setAccessibilityLiveRegion(int)
Svetoslav3577a282013-06-06 14:09:10 -07002004 */
Alan Viverette77e9a282013-09-12 17:16:09 -07002005 public void setLiveRegion(int mode) {
2006 enforceNotSealed();
2007 mLiveRegion = mode;
Svetoslav3577a282013-06-06 14:09:10 -07002008 }
2009
2010 /**
2011 * Gets if the node is a multi line editable text.
2012 *
2013 * @return True if the node is multi line.
2014 */
2015 public boolean isMultiLine() {
2016 return getBooleanProperty(BOOLEAN_PROPERTY_MULTI_LINE);
2017 }
2018
2019 /**
2020 * Sets if the node is a multi line editable text.
2021 * <p>
2022 * <strong>Note:</strong> Cannot be called from an
2023 * {@link android.accessibilityservice.AccessibilityService}.
2024 * This class is made immutable before being delivered to an AccessibilityService.
2025 * </p>
2026 *
2027 * @param multiLine True if the node is multi line.
2028 */
2029 public void setMultiLine(boolean multiLine) {
Svetoslav3577a282013-06-06 14:09:10 -07002030 setBooleanProperty(BOOLEAN_PROPERTY_MULTI_LINE, multiLine);
2031 }
2032
2033 /**
2034 * Gets if this node opens a popup or a dialog.
2035 *
2036 * @return If the the node opens a popup.
2037 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002038 public boolean canOpenPopup() {
Svetoslav3577a282013-06-06 14:09:10 -07002039 return getBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP);
2040 }
2041
2042 /**
2043 * Sets if this node opens a popup or a dialog.
2044 * <p>
2045 * <strong>Note:</strong> Cannot be called from an
2046 * {@link android.accessibilityservice.AccessibilityService}.
2047 * This class is made immutable before being delivered to an AccessibilityService.
2048 * </p>
2049 *
2050 * @param opensPopup If the the node opens a popup.
2051 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002052 public void setCanOpenPopup(boolean opensPopup) {
2053 enforceNotSealed();
Svetoslav3577a282013-06-06 14:09:10 -07002054 setBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP, opensPopup);
2055 }
2056
2057 /**
Svetoslav3577a282013-06-06 14:09:10 -07002058 * Gets if the node can be dismissed.
2059 *
2060 * @return If the node can be dismissed.
2061 */
2062 public boolean isDismissable() {
2063 return getBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE);
2064 }
2065
2066 /**
2067 * Sets if the node can be dismissed.
2068 * <p>
2069 * <strong>Note:</strong> Cannot be called from an
2070 * {@link android.accessibilityservice.AccessibilityService}.
2071 * This class is made immutable before being delivered to an AccessibilityService.
2072 * </p>
2073 *
2074 * @param dismissable If the node can be dismissed.
2075 */
2076 public void setDismissable(boolean dismissable) {
Svetoslav3577a282013-06-06 14:09:10 -07002077 setBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE, dismissable);
2078 }
2079
2080 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002081 * Gets the package this node comes from.
2082 *
2083 * @return The package name.
2084 */
2085 public CharSequence getPackageName() {
2086 return mPackageName;
2087 }
2088
2089 /**
2090 * Sets the package this node comes from.
2091 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002092 * <strong>Note:</strong> Cannot be called from an
2093 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002094 * This class is made immutable before being delivered to an AccessibilityService.
2095 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002096 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002097 * @param packageName The package name.
2098 *
2099 * @throws IllegalStateException If called from an AccessibilityService.
2100 */
2101 public void setPackageName(CharSequence packageName) {
2102 enforceNotSealed();
2103 mPackageName = packageName;
2104 }
2105
2106 /**
2107 * Gets the class this node comes from.
2108 *
2109 * @return The class name.
2110 */
2111 public CharSequence getClassName() {
2112 return mClassName;
2113 }
2114
2115 /**
2116 * Sets the class this node comes from.
2117 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002118 * <strong>Note:</strong> Cannot be called from an
2119 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002120 * This class is made immutable before being delivered to an AccessibilityService.
2121 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002122 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002123 * @param className The class name.
2124 *
2125 * @throws IllegalStateException If called from an AccessibilityService.
2126 */
2127 public void setClassName(CharSequence className) {
2128 enforceNotSealed();
2129 mClassName = className;
2130 }
2131
2132 /**
2133 * Gets the text of this node.
2134 *
2135 * @return The text.
2136 */
2137 public CharSequence getText() {
2138 return mText;
2139 }
2140
2141 /**
2142 * Sets the text of this node.
2143 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002144 * <strong>Note:</strong> Cannot be called from an
2145 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002146 * This class is made immutable before being delivered to an AccessibilityService.
2147 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002148 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002149 * @param text The text.
2150 *
2151 * @throws IllegalStateException If called from an AccessibilityService.
2152 */
2153 public void setText(CharSequence text) {
2154 enforceNotSealed();
2155 mText = text;
2156 }
2157
2158 /**
Alan Viverettefccbff52014-07-07 15:06:14 -07002159 * Sets the error text of this node.
2160 * <p>
2161 * <strong>Note:</strong> Cannot be called from an
2162 * {@link android.accessibilityservice.AccessibilityService}.
2163 * This class is made immutable before being delivered to an AccessibilityService.
2164 * </p>
2165 *
2166 * @param error The error text.
2167 *
2168 * @throws IllegalStateException If called from an AccessibilityService.
2169 */
2170 public void setError(CharSequence error) {
2171 enforceNotSealed();
2172 mError = error;
2173 }
2174
2175 /**
2176 * Gets the error text of this node.
2177 *
2178 * @return The error text.
2179 */
2180 public CharSequence getError() {
2181 return mError;
2182 }
2183
2184 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002185 * Gets the content description of this node.
2186 *
2187 * @return The content description.
2188 */
2189 public CharSequence getContentDescription() {
2190 return mContentDescription;
2191 }
2192
2193 /**
2194 * Sets the content description of this node.
2195 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002196 * <strong>Note:</strong> Cannot be called from an
2197 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002198 * This class is made immutable before being delivered to an AccessibilityService.
2199 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002200 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002201 * @param contentDescription The content description.
2202 *
2203 * @throws IllegalStateException If called from an AccessibilityService.
2204 */
2205 public void setContentDescription(CharSequence contentDescription) {
2206 enforceNotSealed();
2207 mContentDescription = contentDescription;
2208 }
2209
2210 /**
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002211 * Sets the view for which the view represented by this info serves as a
2212 * label for accessibility purposes.
2213 *
2214 * @param labeled The view for which this info serves as a label.
2215 */
2216 public void setLabelFor(View labeled) {
Svetoslav8e3feb12014-02-24 13:46:47 -08002217 setLabelFor(labeled, UNDEFINED_ITEM_ID);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002218 }
2219
2220 /**
2221 * Sets the view for which the view represented by this info serves as a
2222 * label for accessibility purposes. If <code>virtualDescendantId</code>
2223 * is {@link View#NO_ID} the root is set as the labeled.
2224 * <p>
2225 * A virtual descendant is an imaginary View that is reported as a part of the view
2226 * hierarchy for accessibility purposes. This enables custom views that draw complex
2227 * content to report themselves as a tree of virtual views, thus conveying their
2228 * logical structure.
2229 * </p>
2230 * <p>
2231 * <strong>Note:</strong> Cannot be called from an
2232 * {@link android.accessibilityservice.AccessibilityService}.
2233 * This class is made immutable before being delivered to an AccessibilityService.
2234 * </p>
2235 *
2236 * @param root The root whose virtual descendant serves as a label.
2237 * @param virtualDescendantId The id of the virtual descendant.
2238 */
2239 public void setLabelFor(View root, int virtualDescendantId) {
2240 enforceNotSealed();
2241 final int rootAccessibilityViewId = (root != null)
Svetoslav8e3feb12014-02-24 13:46:47 -08002242 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002243 mLabelForId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
2244 }
2245
2246 /**
2247 * Gets the node info for which the view represented by this info serves as
2248 * a label for accessibility purposes.
2249 * <p>
2250 * <strong>Note:</strong> It is a client responsibility to recycle the
2251 * received info by calling {@link AccessibilityNodeInfo#recycle()}
2252 * to avoid creating of multiple instances.
2253 * </p>
2254 *
2255 * @return The labeled info.
2256 */
2257 public AccessibilityNodeInfo getLabelFor() {
2258 enforceSealed();
Svetoslav6c702902014-10-09 18:40:56 -07002259 return getNodeForAccessibilityId(mLabelForId);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002260 }
2261
2262 /**
2263 * Sets the view which serves as the label of the view represented by
2264 * this info for accessibility purposes.
2265 *
2266 * @param label The view that labels this node's source.
2267 */
2268 public void setLabeledBy(View label) {
Svetoslav8e3feb12014-02-24 13:46:47 -08002269 setLabeledBy(label, UNDEFINED_ITEM_ID);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002270 }
2271
2272 /**
2273 * Sets the view which serves as the label of the view represented by
2274 * this info for accessibility purposes. If <code>virtualDescendantId</code>
2275 * is {@link View#NO_ID} the root is set as the label.
2276 * <p>
2277 * A virtual descendant is an imaginary View that is reported as a part of the view
2278 * hierarchy for accessibility purposes. This enables custom views that draw complex
2279 * content to report themselves as a tree of virtual views, thus conveying their
2280 * logical structure.
2281 * </p>
2282 * <p>
2283 * <strong>Note:</strong> Cannot be called from an
2284 * {@link android.accessibilityservice.AccessibilityService}.
2285 * This class is made immutable before being delivered to an AccessibilityService.
2286 * </p>
2287 *
2288 * @param root The root whose virtual descendant labels this node's source.
2289 * @param virtualDescendantId The id of the virtual descendant.
2290 */
2291 public void setLabeledBy(View root, int virtualDescendantId) {
2292 enforceNotSealed();
2293 final int rootAccessibilityViewId = (root != null)
Svetoslav8e3feb12014-02-24 13:46:47 -08002294 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002295 mLabeledById = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
2296 }
2297
2298 /**
2299 * Gets the node info which serves as the label of the view represented by
2300 * this info for accessibility purposes.
2301 * <p>
2302 * <strong>Note:</strong> It is a client responsibility to recycle the
2303 * received info by calling {@link AccessibilityNodeInfo#recycle()}
2304 * to avoid creating of multiple instances.
2305 * </p>
2306 *
2307 * @return The label.
2308 */
2309 public AccessibilityNodeInfo getLabeledBy() {
2310 enforceSealed();
Svetoslav6c702902014-10-09 18:40:56 -07002311 return getNodeForAccessibilityId(mLabeledById);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002312 }
2313
2314 /**
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002315 * Sets the fully qualified resource name of the source view's id.
2316 *
2317 * <p>
2318 * <strong>Note:</strong> Cannot be called from an
2319 * {@link android.accessibilityservice.AccessibilityService}.
2320 * This class is made immutable before being delivered to an AccessibilityService.
2321 * </p>
2322 *
Svetoslav92826452013-02-05 14:57:42 -08002323 * @param viewIdResName The id resource name.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002324 */
Svetoslav9fa1ee52013-04-22 12:43:03 -07002325 public void setViewIdResourceName(String viewIdResName) {
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002326 enforceNotSealed();
Svetoslav22431a32013-02-05 14:30:19 -08002327 mViewIdResourceName = viewIdResName;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002328 }
2329
2330 /**
2331 * Gets the fully qualified resource name of the source view's id.
2332 *
2333 * <p>
2334 * <strong>Note:</strong> The primary usage of this API is for UI test automation
2335 * and in order to report the source view id of an {@link AccessibilityNodeInfo} the
2336 * client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
Svetoslav14ff9962013-01-29 03:21:37 -08002337 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002338 * </p>
2339
2340 * @return The id resource name.
2341 */
Svetoslav9fa1ee52013-04-22 12:43:03 -07002342 public String getViewIdResourceName() {
Svetoslav22431a32013-02-05 14:30:19 -08002343 return mViewIdResourceName;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002344 }
2345
2346 /**
Svetoslavbcc46a02013-02-06 11:56:00 -08002347 * Gets the text selection start.
2348 *
2349 * @return The text selection start if there is selection or -1.
2350 */
2351 public int getTextSelectionStart() {
2352 return mTextSelectionStart;
2353 }
2354
2355 /**
2356 * Gets the text selection end.
2357 *
2358 * @return The text selection end if there is selection or -1.
2359 */
2360 public int getTextSelectionEnd() {
2361 return mTextSelectionEnd;
2362 }
2363
2364 /**
2365 * Sets the text selection start and end.
2366 * <p>
2367 * <strong>Note:</strong> Cannot be called from an
2368 * {@link android.accessibilityservice.AccessibilityService}.
2369 * This class is made immutable before being delivered to an AccessibilityService.
2370 * </p>
2371 *
2372 * @param start The text selection start.
2373 * @param end The text selection end.
2374 *
2375 * @throws IllegalStateException If called from an AccessibilityService.
2376 */
2377 public void setTextSelection(int start, int end) {
2378 enforceNotSealed();
2379 mTextSelectionStart = start;
2380 mTextSelectionEnd = end;
2381 }
2382
2383 /**
Svetoslav6254f482013-06-04 17:22:14 -07002384 * Gets the input type of the source as defined by {@link InputType}.
2385 *
2386 * @return The input type.
2387 */
2388 public int getInputType() {
2389 return mInputType;
2390 }
2391
2392 /**
2393 * Sets the input type of the source as defined by {@link InputType}.
2394 * <p>
2395 * <strong>Note:</strong> Cannot be called from an
2396 * {@link android.accessibilityservice.AccessibilityService}.
2397 * This class is made immutable before being delivered to an
2398 * AccessibilityService.
2399 * </p>
2400 *
2401 * @param inputType The input type.
2402 *
2403 * @throws IllegalStateException If called from an AccessibilityService.
2404 */
2405 public void setInputType(int inputType) {
Alan Viverettedf39cb92013-08-19 12:28:04 -07002406 enforceNotSealed();
Svetoslav6254f482013-06-04 17:22:14 -07002407 mInputType = inputType;
2408 }
2409
2410 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002411 * Gets an optional bundle with extra data. The bundle
Svetoslav6254f482013-06-04 17:22:14 -07002412 * is lazily created and never <code>null</code>.
2413 * <p>
2414 * <strong>Note:</strong> It is recommended to use the package
2415 * name of your application as a prefix for the keys to avoid
2416 * collisions which may confuse an accessibility service if the
2417 * same key has different meaning when emitted from different
2418 * applications.
2419 * </p>
2420 *
2421 * @return The bundle.
2422 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002423 public Bundle getExtras() {
2424 if (mExtras == null) {
2425 mExtras = new Bundle();
Svetoslav6254f482013-06-04 17:22:14 -07002426 }
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002427 return mExtras;
Svetoslav6254f482013-06-04 17:22:14 -07002428 }
2429
2430 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002431 * Gets the value of a boolean property.
2432 *
2433 * @param property The property.
2434 * @return The value.
2435 */
2436 private boolean getBooleanProperty(int property) {
2437 return (mBooleanProperties & property) != 0;
2438 }
2439
2440 /**
2441 * Sets a boolean property.
2442 *
2443 * @param property The property.
2444 * @param value The value.
2445 *
2446 * @throws IllegalStateException If called from an AccessibilityService.
2447 */
2448 private void setBooleanProperty(int property, boolean value) {
2449 enforceNotSealed();
2450 if (value) {
2451 mBooleanProperties |= property;
2452 } else {
2453 mBooleanProperties &= ~property;
2454 }
2455 }
2456
2457 /**
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002458 * Sets the unique id of the IAccessibilityServiceConnection over which
2459 * this instance can send requests to the system.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002460 *
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002461 * @param connectionId The connection id.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002462 *
2463 * @hide
2464 */
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002465 public void setConnectionId(int connectionId) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002466 enforceNotSealed();
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002467 mConnectionId = connectionId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002468 }
2469
2470 /**
2471 * {@inheritDoc}
2472 */
Alan Viverettef0aed092013-11-06 15:33:03 -08002473 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002474 public int describeContents() {
2475 return 0;
2476 }
2477
2478 /**
Svetoslav Ganov79311c42012-01-17 20:24:26 -08002479 * Gets the id of the source node.
2480 *
2481 * @return The id.
2482 *
2483 * @hide
2484 */
2485 public long getSourceNodeId() {
2486 return mSourceNodeId;
2487 }
2488
2489 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002490 * Sets if this instance is sealed.
2491 *
2492 * @param sealed Whether is sealed.
2493 *
2494 * @hide
2495 */
2496 public void setSealed(boolean sealed) {
2497 mSealed = sealed;
2498 }
2499
2500 /**
2501 * Gets if this instance is sealed.
2502 *
2503 * @return Whether is sealed.
2504 *
2505 * @hide
2506 */
2507 public boolean isSealed() {
2508 return mSealed;
2509 }
2510
2511 /**
2512 * Enforces that this instance is sealed.
2513 *
2514 * @throws IllegalStateException If this instance is not sealed.
2515 *
2516 * @hide
2517 */
2518 protected void enforceSealed() {
2519 if (!isSealed()) {
2520 throw new IllegalStateException("Cannot perform this "
2521 + "action on a not sealed instance.");
2522 }
2523 }
2524
Svetoslav Ganov2ef69052012-06-04 08:55:16 -07002525 private void enforceValidFocusDirection(int direction) {
2526 switch (direction) {
2527 case View.FOCUS_DOWN:
2528 case View.FOCUS_UP:
2529 case View.FOCUS_LEFT:
2530 case View.FOCUS_RIGHT:
2531 case View.FOCUS_FORWARD:
2532 case View.FOCUS_BACKWARD:
Svetoslav Ganov2ef69052012-06-04 08:55:16 -07002533 return;
2534 default:
2535 throw new IllegalArgumentException("Unknown direction: " + direction);
2536 }
2537 }
2538
2539 private void enforceValidFocusType(int focusType) {
2540 switch (focusType) {
2541 case FOCUS_INPUT:
2542 case FOCUS_ACCESSIBILITY:
2543 return;
2544 default:
2545 throw new IllegalArgumentException("Unknown focus type: " + focusType);
2546 }
2547 }
2548
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002549 /**
2550 * Enforces that this instance is not sealed.
2551 *
2552 * @throws IllegalStateException If this instance is sealed.
2553 *
2554 * @hide
2555 */
2556 protected void enforceNotSealed() {
2557 if (isSealed()) {
2558 throw new IllegalStateException("Cannot perform this "
Ken Wakasaf76a50c2012-03-09 19:56:35 +09002559 + "action on a sealed instance.");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002560 }
2561 }
2562
2563 /**
2564 * Returns a cached instance if such is available otherwise a new one
2565 * and sets the source.
2566 *
Svetoslav Ganov02107852011-10-03 17:06:56 -07002567 * @param source The source view.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002568 * @return An instance.
2569 *
2570 * @see #setSource(View)
2571 */
2572 public static AccessibilityNodeInfo obtain(View source) {
2573 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
2574 info.setSource(source);
2575 return info;
2576 }
2577
2578 /**
Svetoslav Ganov02107852011-10-03 17:06:56 -07002579 * Returns a cached instance if such is available otherwise a new one
2580 * and sets the source.
2581 *
2582 * @param root The root of the virtual subtree.
2583 * @param virtualDescendantId The id of the virtual descendant.
2584 * @return An instance.
2585 *
2586 * @see #setSource(View, int)
2587 */
2588 public static AccessibilityNodeInfo obtain(View root, int virtualDescendantId) {
2589 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
2590 info.setSource(root, virtualDescendantId);
2591 return info;
2592 }
2593
2594 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002595 * Returns a cached instance if such is available otherwise a new one.
2596 *
2597 * @return An instance.
2598 */
2599 public static AccessibilityNodeInfo obtain() {
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -08002600 AccessibilityNodeInfo info = sPool.acquire();
2601 return (info != null) ? info : new AccessibilityNodeInfo();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002602 }
2603
2604 /**
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07002605 * Returns a cached instance if such is available or a new one is
2606 * create. The returned instance is initialized from the given
2607 * <code>info</code>.
2608 *
2609 * @param info The other info.
2610 * @return An instance.
2611 */
2612 public static AccessibilityNodeInfo obtain(AccessibilityNodeInfo info) {
2613 AccessibilityNodeInfo infoClone = AccessibilityNodeInfo.obtain();
2614 infoClone.init(info);
2615 return infoClone;
2616 }
2617
2618 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002619 * Return an instance back to be reused.
2620 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002621 * <strong>Note:</strong> You must not touch the object after calling this function.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002622 *
2623 * @throws IllegalStateException If the info is already recycled.
2624 */
2625 public void recycle() {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002626 clear();
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -08002627 sPool.release(this);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002628 }
2629
2630 /**
2631 * {@inheritDoc}
2632 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002633 * <strong>Note:</strong> After the instance is written to a parcel it
2634 * is recycled. You must not touch the object after calling this function.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002635 * </p>
2636 */
Alan Viverettef0aed092013-11-06 15:33:03 -08002637 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002638 public void writeToParcel(Parcel parcel, int flags) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002639 parcel.writeInt(isSealed() ? 1 : 0);
Svetoslav Ganov02107852011-10-03 17:06:56 -07002640 parcel.writeLong(mSourceNodeId);
2641 parcel.writeInt(mWindowId);
2642 parcel.writeLong(mParentNodeId);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002643 parcel.writeLong(mLabelForId);
2644 parcel.writeLong(mLabeledById);
Svetoslav6c702902014-10-09 18:40:56 -07002645 parcel.writeLong(mTraversalBefore);
2646 parcel.writeLong(mTraversalAfter);
2647
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002648 parcel.writeInt(mConnectionId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002649
Alan Viverettef0aed092013-11-06 15:33:03 -08002650 final LongArray childIds = mChildNodeIds;
2651 if (childIds == null) {
2652 parcel.writeInt(0);
2653 } else {
2654 final int childIdsSize = childIds.size();
2655 parcel.writeInt(childIdsSize);
2656 for (int i = 0; i < childIdsSize; i++) {
2657 parcel.writeLong(childIds.get(i));
2658 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002659 }
2660
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002661 parcel.writeInt(mBoundsInParent.top);
2662 parcel.writeInt(mBoundsInParent.bottom);
2663 parcel.writeInt(mBoundsInParent.left);
2664 parcel.writeInt(mBoundsInParent.right);
2665
2666 parcel.writeInt(mBoundsInScreen.top);
2667 parcel.writeInt(mBoundsInScreen.bottom);
2668 parcel.writeInt(mBoundsInScreen.left);
2669 parcel.writeInt(mBoundsInScreen.right);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002670
Kristian Monsen74bc1942014-04-29 11:00:17 -07002671 if (mActions != null && !mActions.isEmpty()) {
2672 final int actionCount = mActions.size();
2673 parcel.writeInt(actionCount);
2674
2675 int defaultLegacyStandardActions = 0;
2676 for (int i = 0; i < actionCount; i++) {
2677 AccessibilityAction action = mActions.get(i);
2678 if (isDefaultLegacyStandardAction(action)) {
2679 defaultLegacyStandardActions |= action.getId();
2680 }
2681 }
2682 parcel.writeInt(defaultLegacyStandardActions);
2683
2684 for (int i = 0; i < actionCount; i++) {
2685 AccessibilityAction action = mActions.get(i);
2686 if (!isDefaultLegacyStandardAction(action)) {
2687 parcel.writeInt(action.getId());
2688 parcel.writeCharSequence(action.getLabel());
2689 }
2690 }
2691 } else {
2692 parcel.writeInt(0);
2693 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002694
Alan Viverette029942f2014-08-12 14:55:56 -07002695 parcel.writeInt(mMaxTextLength);
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002696 parcel.writeInt(mMovementGranularities);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002697 parcel.writeInt(mBooleanProperties);
2698
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002699 parcel.writeCharSequence(mPackageName);
2700 parcel.writeCharSequence(mClassName);
2701 parcel.writeCharSequence(mText);
Alan Viverettefccbff52014-07-07 15:06:14 -07002702 parcel.writeCharSequence(mError);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002703 parcel.writeCharSequence(mContentDescription);
Svetoslav9fa1ee52013-04-22 12:43:03 -07002704 parcel.writeString(mViewIdResourceName);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002705
Svetoslavbcc46a02013-02-06 11:56:00 -08002706 parcel.writeInt(mTextSelectionStart);
2707 parcel.writeInt(mTextSelectionEnd);
Svetoslav6254f482013-06-04 17:22:14 -07002708 parcel.writeInt(mInputType);
Alan Viverette77e9a282013-09-12 17:16:09 -07002709 parcel.writeInt(mLiveRegion);
Svetoslav6254f482013-06-04 17:22:14 -07002710
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002711 if (mExtras != null) {
Svetoslav6254f482013-06-04 17:22:14 -07002712 parcel.writeInt(1);
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002713 parcel.writeBundle(mExtras);
Svetoslav6254f482013-06-04 17:22:14 -07002714 } else {
2715 parcel.writeInt(0);
2716 }
Svetoslavbcc46a02013-02-06 11:56:00 -08002717
Svetoslav3577a282013-06-06 14:09:10 -07002718 if (mRangeInfo != null) {
2719 parcel.writeInt(1);
2720 parcel.writeInt(mRangeInfo.getType());
2721 parcel.writeFloat(mRangeInfo.getMin());
2722 parcel.writeFloat(mRangeInfo.getMax());
2723 parcel.writeFloat(mRangeInfo.getCurrent());
2724 } else {
2725 parcel.writeInt(0);
2726 }
2727
2728 if (mCollectionInfo != null) {
2729 parcel.writeInt(1);
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002730 parcel.writeInt(mCollectionInfo.getRowCount());
2731 parcel.writeInt(mCollectionInfo.getColumnCount());
Svetoslav3577a282013-06-06 14:09:10 -07002732 parcel.writeInt(mCollectionInfo.isHierarchical() ? 1 : 0);
Alan Viverette76769ae2014-02-12 16:38:10 -08002733 parcel.writeInt(mCollectionInfo.getSelectionMode());
Svetoslav3577a282013-06-06 14:09:10 -07002734 } else {
2735 parcel.writeInt(0);
2736 }
2737
2738 if (mCollectionItemInfo != null) {
2739 parcel.writeInt(1);
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002740 parcel.writeInt(mCollectionItemInfo.getRowIndex());
2741 parcel.writeInt(mCollectionItemInfo.getRowSpan());
Alan Viverettefaeac962015-06-01 09:03:27 -07002742 parcel.writeInt(mCollectionItemInfo.getColumnIndex());
2743 parcel.writeInt(mCollectionItemInfo.getColumnSpan());
Svetoslav3577a282013-06-06 14:09:10 -07002744 parcel.writeInt(mCollectionItemInfo.isHeading() ? 1 : 0);
Alan Viverette76769ae2014-02-12 16:38:10 -08002745 parcel.writeInt(mCollectionItemInfo.isSelected() ? 1 : 0);
Svetoslav3577a282013-06-06 14:09:10 -07002746 } else {
2747 parcel.writeInt(0);
2748 }
2749
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002750 // Since instances of this class are fetched via synchronous i.e. blocking
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002751 // calls in IPCs we always recycle as soon as the instance is marshaled.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002752 recycle();
2753 }
2754
2755 /**
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07002756 * Initializes this instance from another one.
2757 *
2758 * @param other The other instance.
2759 */
2760 private void init(AccessibilityNodeInfo other) {
2761 mSealed = other.mSealed;
Svetoslav Ganov02107852011-10-03 17:06:56 -07002762 mSourceNodeId = other.mSourceNodeId;
2763 mParentNodeId = other.mParentNodeId;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002764 mLabelForId = other.mLabelForId;
2765 mLabeledById = other.mLabeledById;
Svetoslav6c702902014-10-09 18:40:56 -07002766 mTraversalBefore = other.mTraversalBefore;
2767 mTraversalAfter = other.mTraversalAfter;
Svetoslav Ganov02107852011-10-03 17:06:56 -07002768 mWindowId = other.mWindowId;
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002769 mConnectionId = other.mConnectionId;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07002770 mBoundsInParent.set(other.mBoundsInParent);
2771 mBoundsInScreen.set(other.mBoundsInScreen);
2772 mPackageName = other.mPackageName;
2773 mClassName = other.mClassName;
2774 mText = other.mText;
Alan Viverettefccbff52014-07-07 15:06:14 -07002775 mError = other.mError;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07002776 mContentDescription = other.mContentDescription;
Svetoslav22431a32013-02-05 14:30:19 -08002777 mViewIdResourceName = other.mViewIdResourceName;
Kristian Monsen74bc1942014-04-29 11:00:17 -07002778
2779 final ArrayList<AccessibilityAction> otherActions = other.mActions;
2780 if (otherActions != null && otherActions.size() > 0) {
2781 if (mActions == null) {
2782 mActions = new ArrayList(otherActions);
2783 } else {
2784 mActions.clear();
2785 mActions.addAll(other.mActions);
2786 }
2787 }
2788
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07002789 mBooleanProperties = other.mBooleanProperties;
Alan Viverette029942f2014-08-12 14:55:56 -07002790 mMaxTextLength = other.mMaxTextLength;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002791 mMovementGranularities = other.mMovementGranularities;
Alan Viverettef0aed092013-11-06 15:33:03 -08002792
2793 final LongArray otherChildNodeIds = other.mChildNodeIds;
2794 if (otherChildNodeIds != null && otherChildNodeIds.size() > 0) {
2795 if (mChildNodeIds == null) {
2796 mChildNodeIds = otherChildNodeIds.clone();
2797 } else {
Svetoslav8e3feb12014-02-24 13:46:47 -08002798 mChildNodeIds.clear();
Alan Viverettef0aed092013-11-06 15:33:03 -08002799 mChildNodeIds.addAll(otherChildNodeIds);
2800 }
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002801 }
Alan Viverettef0aed092013-11-06 15:33:03 -08002802
Svetoslavbcc46a02013-02-06 11:56:00 -08002803 mTextSelectionStart = other.mTextSelectionStart;
2804 mTextSelectionEnd = other.mTextSelectionEnd;
Svetoslav6254f482013-06-04 17:22:14 -07002805 mInputType = other.mInputType;
Alan Viverette77e9a282013-09-12 17:16:09 -07002806 mLiveRegion = other.mLiveRegion;
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002807 if (other.mExtras != null && !other.mExtras.isEmpty()) {
2808 getExtras().putAll(other.mExtras);
Svetoslav6254f482013-06-04 17:22:14 -07002809 }
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07002810 mRangeInfo = (other.mRangeInfo != null)
2811 ? RangeInfo.obtain(other.mRangeInfo) : null;
2812 mCollectionInfo = (other.mCollectionInfo != null)
2813 ? CollectionInfo.obtain(other.mCollectionInfo) : null;
2814 mCollectionItemInfo = (other.mCollectionItemInfo != null)
2815 ? CollectionItemInfo.obtain(other.mCollectionItemInfo) : null;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07002816 }
2817
2818 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002819 * Creates a new instance from a {@link Parcel}.
2820 *
2821 * @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}.
2822 */
2823 private void initFromParcel(Parcel parcel) {
Maxim Bogatov2f55a3f2015-06-09 15:00:44 -07002824 final boolean sealed = (parcel.readInt() == 1);
Svetoslav Ganov02107852011-10-03 17:06:56 -07002825 mSourceNodeId = parcel.readLong();
2826 mWindowId = parcel.readInt();
2827 mParentNodeId = parcel.readLong();
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002828 mLabelForId = parcel.readLong();
2829 mLabeledById = parcel.readLong();
Svetoslav6c702902014-10-09 18:40:56 -07002830 mTraversalBefore = parcel.readLong();
2831 mTraversalAfter = parcel.readLong();
2832
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002833 mConnectionId = parcel.readInt();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002834
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002835 final int childrenSize = parcel.readInt();
Alan Viverettef0aed092013-11-06 15:33:03 -08002836 if (childrenSize <= 0) {
2837 mChildNodeIds = null;
2838 } else {
2839 mChildNodeIds = new LongArray(childrenSize);
2840 for (int i = 0; i < childrenSize; i++) {
2841 final long childId = parcel.readLong();
2842 mChildNodeIds.add(childId);
2843 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002844 }
2845
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002846 mBoundsInParent.top = parcel.readInt();
2847 mBoundsInParent.bottom = parcel.readInt();
2848 mBoundsInParent.left = parcel.readInt();
2849 mBoundsInParent.right = parcel.readInt();
2850
2851 mBoundsInScreen.top = parcel.readInt();
2852 mBoundsInScreen.bottom = parcel.readInt();
2853 mBoundsInScreen.left = parcel.readInt();
2854 mBoundsInScreen.right = parcel.readInt();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002855
Kristian Monsen74bc1942014-04-29 11:00:17 -07002856 final int actionCount = parcel.readInt();
2857 if (actionCount > 0) {
2858 final int legacyStandardActions = parcel.readInt();
2859 addLegacyStandardActions(legacyStandardActions);
2860 final int nonLegacyActionCount = actionCount - Integer.bitCount(legacyStandardActions);
2861 for (int i = 0; i < nonLegacyActionCount; i++) {
Alan Viverettec921f272015-05-14 12:26:49 -07002862 final AccessibilityAction action = new AccessibilityAction(
Kristian Monsen74bc1942014-04-29 11:00:17 -07002863 parcel.readInt(), parcel.readCharSequence());
Alan Viverettec921f272015-05-14 12:26:49 -07002864 addActionUnchecked(action);
Kristian Monsen74bc1942014-04-29 11:00:17 -07002865 }
2866 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002867
Alan Viverette029942f2014-08-12 14:55:56 -07002868 mMaxTextLength = parcel.readInt();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002869 mMovementGranularities = parcel.readInt();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002870 mBooleanProperties = parcel.readInt();
2871
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002872 mPackageName = parcel.readCharSequence();
2873 mClassName = parcel.readCharSequence();
2874 mText = parcel.readCharSequence();
Alan Viverettefccbff52014-07-07 15:06:14 -07002875 mError = parcel.readCharSequence();
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002876 mContentDescription = parcel.readCharSequence();
Svetoslav9fa1ee52013-04-22 12:43:03 -07002877 mViewIdResourceName = parcel.readString();
Svetoslavbcc46a02013-02-06 11:56:00 -08002878
2879 mTextSelectionStart = parcel.readInt();
2880 mTextSelectionEnd = parcel.readInt();
Svetoslav3577a282013-06-06 14:09:10 -07002881
Svetoslav6254f482013-06-04 17:22:14 -07002882 mInputType = parcel.readInt();
Alan Viverette77e9a282013-09-12 17:16:09 -07002883 mLiveRegion = parcel.readInt();
Svetoslav6254f482013-06-04 17:22:14 -07002884
2885 if (parcel.readInt() == 1) {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002886 getExtras().putAll(parcel.readBundle());
Svetoslav6254f482013-06-04 17:22:14 -07002887 }
Svetoslav3577a282013-06-06 14:09:10 -07002888
2889 if (parcel.readInt() == 1) {
2890 mRangeInfo = RangeInfo.obtain(
2891 parcel.readInt(),
2892 parcel.readFloat(),
2893 parcel.readFloat(),
2894 parcel.readFloat());
2895 }
2896
2897 if (parcel.readInt() == 1) {
2898 mCollectionInfo = CollectionInfo.obtain(
2899 parcel.readInt(),
2900 parcel.readInt(),
Alan Viverette76769ae2014-02-12 16:38:10 -08002901 parcel.readInt() == 1,
2902 parcel.readInt());
Svetoslav3577a282013-06-06 14:09:10 -07002903 }
2904
2905 if (parcel.readInt() == 1) {
2906 mCollectionItemInfo = CollectionItemInfo.obtain(
2907 parcel.readInt(),
2908 parcel.readInt(),
2909 parcel.readInt(),
2910 parcel.readInt(),
Alan Viverette76769ae2014-02-12 16:38:10 -08002911 parcel.readInt() == 1,
Svetoslav3577a282013-06-06 14:09:10 -07002912 parcel.readInt() == 1);
2913 }
Maxim Bogatov2f55a3f2015-06-09 15:00:44 -07002914
2915 mSealed = sealed;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002916 }
2917
2918 /**
2919 * Clears the state of this instance.
2920 */
2921 private void clear() {
2922 mSealed = false;
Svetoslav Ganov0d04e242012-02-21 13:46:36 -08002923 mSourceNodeId = ROOT_NODE_ID;
2924 mParentNodeId = ROOT_NODE_ID;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002925 mLabelForId = ROOT_NODE_ID;
2926 mLabeledById = ROOT_NODE_ID;
Svetoslav6c702902014-10-09 18:40:56 -07002927 mTraversalBefore = ROOT_NODE_ID;
2928 mTraversalAfter = ROOT_NODE_ID;
Svetoslav8e3feb12014-02-24 13:46:47 -08002929 mWindowId = UNDEFINED_ITEM_ID;
2930 mConnectionId = UNDEFINED_CONNECTION_ID;
Alan Viverette029942f2014-08-12 14:55:56 -07002931 mMaxTextLength = -1;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002932 mMovementGranularities = 0;
Alan Viverettef0aed092013-11-06 15:33:03 -08002933 if (mChildNodeIds != null) {
2934 mChildNodeIds.clear();
2935 }
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002936 mBoundsInParent.set(0, 0, 0, 0);
2937 mBoundsInScreen.set(0, 0, 0, 0);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002938 mBooleanProperties = 0;
2939 mPackageName = null;
2940 mClassName = null;
2941 mText = null;
Alan Viverettefccbff52014-07-07 15:06:14 -07002942 mError = null;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002943 mContentDescription = null;
Svetoslav22431a32013-02-05 14:30:19 -08002944 mViewIdResourceName = null;
Kristian Monsen74bc1942014-04-29 11:00:17 -07002945 if (mActions != null) {
2946 mActions.clear();
2947 }
Svetoslav8e3feb12014-02-24 13:46:47 -08002948 mTextSelectionStart = UNDEFINED_SELECTION_INDEX;
2949 mTextSelectionEnd = UNDEFINED_SELECTION_INDEX;
Svetoslav6254f482013-06-04 17:22:14 -07002950 mInputType = InputType.TYPE_NULL;
Alan Viverette77e9a282013-09-12 17:16:09 -07002951 mLiveRegion = View.ACCESSIBILITY_LIVE_REGION_NONE;
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002952 if (mExtras != null) {
2953 mExtras.clear();
Svetoslav6254f482013-06-04 17:22:14 -07002954 }
Svetoslav3577a282013-06-06 14:09:10 -07002955 if (mRangeInfo != null) {
2956 mRangeInfo.recycle();
2957 mRangeInfo = null;
2958 }
2959 if (mCollectionInfo != null) {
2960 mCollectionInfo.recycle();
2961 mCollectionInfo = null;
2962 }
2963 if (mCollectionItemInfo != null) {
2964 mCollectionItemInfo.recycle();
2965 mCollectionItemInfo = null;
2966 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002967 }
2968
Kristian Monsen74bc1942014-04-29 11:00:17 -07002969 private static boolean isDefaultLegacyStandardAction(AccessibilityAction action) {
2970 return (action.getId() <= LAST_LEGACY_STANDARD_ACTION
2971 && TextUtils.isEmpty(action.getLabel()));
2972 }
2973
2974 private static AccessibilityAction getActionSingleton(int actionId) {
2975 final int actions = AccessibilityAction.sStandardActions.size();
2976 for (int i = 0; i < actions; i++) {
2977 AccessibilityAction currentAction = AccessibilityAction.sStandardActions.valueAt(i);
2978 if (actionId == currentAction.getId()) {
2979 return currentAction;
2980 }
2981 }
2982
2983 return null;
2984 }
2985
2986 private void addLegacyStandardActions(int actionMask) {
2987 int remainingIds = actionMask;
2988 while (remainingIds > 0) {
2989 final int id = 1 << Integer.numberOfTrailingZeros(remainingIds);
2990 remainingIds &= ~id;
2991 AccessibilityAction action = getActionSingleton(id);
2992 addAction(action);
2993 }
2994 }
2995
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002996 /**
2997 * Gets the human readable action symbolic name.
2998 *
2999 * @param action The action.
3000 * @return The symbolic name.
3001 */
3002 private static String getActionSymbolicName(int action) {
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003003 switch (action) {
3004 case ACTION_FOCUS:
3005 return "ACTION_FOCUS";
3006 case ACTION_CLEAR_FOCUS:
3007 return "ACTION_CLEAR_FOCUS";
3008 case ACTION_SELECT:
3009 return "ACTION_SELECT";
3010 case ACTION_CLEAR_SELECTION:
3011 return "ACTION_CLEAR_SELECTION";
Svetoslav Ganove9bda152012-04-30 16:55:21 -07003012 case ACTION_CLICK:
3013 return "ACTION_CLICK";
3014 case ACTION_LONG_CLICK:
3015 return "ACTION_LONG_CLICK";
3016 case ACTION_ACCESSIBILITY_FOCUS:
3017 return "ACTION_ACCESSIBILITY_FOCUS";
3018 case ACTION_CLEAR_ACCESSIBILITY_FOCUS:
3019 return "ACTION_CLEAR_ACCESSIBILITY_FOCUS";
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003020 case ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
3021 return "ACTION_NEXT_AT_MOVEMENT_GRANULARITY";
3022 case ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY:
3023 return "ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY";
Svetoslav Ganove9bda152012-04-30 16:55:21 -07003024 case ACTION_NEXT_HTML_ELEMENT:
3025 return "ACTION_NEXT_HTML_ELEMENT";
3026 case ACTION_PREVIOUS_HTML_ELEMENT:
3027 return "ACTION_PREVIOUS_HTML_ELEMENT";
Svetoslav Ganova1dc7612012-05-10 04:14:53 -07003028 case ACTION_SCROLL_FORWARD:
3029 return "ACTION_SCROLL_FORWARD";
3030 case ACTION_SCROLL_BACKWARD:
3031 return "ACTION_SCROLL_BACKWARD";
Svetoslav Ganov242724e2013-02-01 14:42:18 -08003032 case ACTION_CUT:
3033 return "ACTION_CUT";
3034 case ACTION_COPY:
3035 return "ACTION_COPY";
3036 case ACTION_PASTE:
3037 return "ACTION_PASTE";
3038 case ACTION_SET_SELECTION:
3039 return "ACTION_SET_SELECTION";
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003040 default:
Svetoslav Ganov242724e2013-02-01 14:42:18 -08003041 return"ACTION_UNKNOWN";
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003042 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003043 }
3044
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003045 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003046 * Gets the human readable movement granularity symbolic name.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003047 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003048 * @param granularity The granularity.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003049 * @return The symbolic name.
3050 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003051 private static String getMovementGranularitySymbolicName(int granularity) {
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003052 switch (granularity) {
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003053 case MOVEMENT_GRANULARITY_CHARACTER:
3054 return "MOVEMENT_GRANULARITY_CHARACTER";
3055 case MOVEMENT_GRANULARITY_WORD:
3056 return "MOVEMENT_GRANULARITY_WORD";
3057 case MOVEMENT_GRANULARITY_LINE:
3058 return "MOVEMENT_GRANULARITY_LINE";
3059 case MOVEMENT_GRANULARITY_PARAGRAPH:
3060 return "MOVEMENT_GRANULARITY_PARAGRAPH";
3061 case MOVEMENT_GRANULARITY_PAGE:
3062 return "MOVEMENT_GRANULARITY_PAGE";
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003063 default:
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003064 throw new IllegalArgumentException("Unknown movement granularity: " + granularity);
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003065 }
3066 }
3067
Svetoslav Ganov02107852011-10-03 17:06:56 -07003068 private boolean canPerformRequestOverConnection(long accessibilityNodeId) {
Svetoslav8e3feb12014-02-24 13:46:47 -08003069 return (mWindowId != UNDEFINED_ITEM_ID
3070 && getAccessibilityViewId(accessibilityNodeId) != UNDEFINED_ITEM_ID
3071 && mConnectionId != UNDEFINED_CONNECTION_ID);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07003072 }
3073
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003074 @Override
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07003075 public boolean equals(Object object) {
3076 if (this == object) {
3077 return true;
3078 }
3079 if (object == null) {
3080 return false;
3081 }
3082 if (getClass() != object.getClass()) {
3083 return false;
3084 }
3085 AccessibilityNodeInfo other = (AccessibilityNodeInfo) object;
Svetoslav Ganov02107852011-10-03 17:06:56 -07003086 if (mSourceNodeId != other.mSourceNodeId) {
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07003087 return false;
3088 }
Svetoslav Ganov02107852011-10-03 17:06:56 -07003089 if (mWindowId != other.mWindowId) {
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07003090 return false;
3091 }
3092 return true;
3093 }
3094
3095 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003096 public int hashCode() {
3097 final int prime = 31;
3098 int result = 1;
Svetoslav Ganov02107852011-10-03 17:06:56 -07003099 result = prime * result + getAccessibilityViewId(mSourceNodeId);
3100 result = prime * result + getVirtualDescendantId(mSourceNodeId);
3101 result = prime * result + mWindowId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003102 return result;
3103 }
3104
3105 @Override
3106 public String toString() {
3107 StringBuilder builder = new StringBuilder();
3108 builder.append(super.toString());
3109
3110 if (DEBUG) {
Svetoslav8e3feb12014-02-24 13:46:47 -08003111 builder.append("; sourceNodeId: " + mSourceNodeId);
Svetoslav Ganov02107852011-10-03 17:06:56 -07003112 builder.append("; accessibilityViewId: " + getAccessibilityViewId(mSourceNodeId));
3113 builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId));
3114 builder.append("; mParentNodeId: " + mParentNodeId);
Svetoslav6c702902014-10-09 18:40:56 -07003115 builder.append("; traversalBefore: ").append(mTraversalBefore);
3116 builder.append("; traversalAfter: ").append(mTraversalAfter);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003117
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003118 int granularities = mMovementGranularities;
3119 builder.append("; MovementGranularities: [");
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003120 while (granularities != 0) {
3121 final int granularity = 1 << Integer.numberOfTrailingZeros(granularities);
3122 granularities &= ~granularity;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003123 builder.append(getMovementGranularitySymbolicName(granularity));
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003124 if (granularities != 0) {
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003125 builder.append(", ");
3126 }
3127 }
3128 builder.append("]");
3129
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003130 builder.append("; childAccessibilityIds: [");
Alan Viverettef0aed092013-11-06 15:33:03 -08003131 final LongArray childIds = mChildNodeIds;
3132 if (childIds != null) {
3133 for (int i = 0, count = childIds.size(); i < count; i++) {
3134 builder.append(childIds.get(i));
3135 if (i < count - 1) {
3136 builder.append(", ");
3137 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003138 }
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003139 }
3140 builder.append("]");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003141 }
3142
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07003143 builder.append("; boundsInParent: " + mBoundsInParent);
3144 builder.append("; boundsInScreen: " + mBoundsInScreen);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003145
3146 builder.append("; packageName: ").append(mPackageName);
3147 builder.append("; className: ").append(mClassName);
3148 builder.append("; text: ").append(mText);
Alan Viverettefccbff52014-07-07 15:06:14 -07003149 builder.append("; error: ").append(mError);
Alan Viverette029942f2014-08-12 14:55:56 -07003150 builder.append("; maxTextLength: ").append(mMaxTextLength);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003151 builder.append("; contentDescription: ").append(mContentDescription);
Svetoslav22431a32013-02-05 14:30:19 -08003152 builder.append("; viewIdResName: ").append(mViewIdResourceName);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003153
3154 builder.append("; checkable: ").append(isCheckable());
3155 builder.append("; checked: ").append(isChecked());
3156 builder.append("; focusable: ").append(isFocusable());
3157 builder.append("; focused: ").append(isFocused());
3158 builder.append("; selected: ").append(isSelected());
3159 builder.append("; clickable: ").append(isClickable());
3160 builder.append("; longClickable: ").append(isLongClickable());
Mady Mellore8608912015-06-05 09:02:55 -07003161 builder.append("; contextClickable: ").append(isContextClickable());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003162 builder.append("; enabled: ").append(isEnabled());
3163 builder.append("; password: ").append(isPassword());
Kristian Monsen74bc1942014-04-29 11:00:17 -07003164 builder.append("; scrollable: ").append(isScrollable());
3165 builder.append("; actions: ").append(mActions);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003166
3167 return builder.toString();
3168 }
3169
Svetoslav6c702902014-10-09 18:40:56 -07003170 private AccessibilityNodeInfo getNodeForAccessibilityId(long accessibilityId) {
3171 if (!canPerformRequestOverConnection(accessibilityId)) {
3172 return null;
3173 }
3174 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
3175 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
3176 mWindowId, accessibilityId, false, FLAG_PREFETCH_PREDECESSORS
3177 | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
3178 }
3179
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003180 /**
Kristian Monsen74bc1942014-04-29 11:00:17 -07003181 * A class defining an action that can be performed on an {@link AccessibilityNodeInfo}.
3182 * Each action has a unique id that is mandatory and optional data.
3183 * <p>
3184 * There are three categories of actions:
3185 * <ul>
3186 * <li><strong>Standard actions</strong> - These are actions that are reported and
3187 * handled by the standard UI widgets in the platform. For each standard action
3188 * there is a static constant defined in this class, e.g. {@link #ACTION_FOCUS}.
3189 * </li>
3190 * <li><strong>Custom actions action</strong> - These are actions that are reported
3191 * and handled by custom widgets. i.e. ones that are not part of the UI toolkit. For
3192 * example, an application may define a custom action for clearing the user history.
3193 * </li>
3194 * <li><strong>Overriden standard actions</strong> - These are actions that override
3195 * standard actions to customize them. For example, an app may add a label to the
3196 * standard click action to announce that this action clears browsing history.
3197 * </ul>
3198 * </p>
3199 */
3200 public static final class AccessibilityAction {
3201
3202 /**
3203 * Action that gives input focus to the node.
3204 */
3205 public static final AccessibilityAction ACTION_FOCUS =
3206 new AccessibilityAction(
3207 AccessibilityNodeInfo.ACTION_FOCUS, null);
3208
3209 /**
3210 * Action that clears input focus of the node.
3211 */
3212 public static final AccessibilityAction ACTION_CLEAR_FOCUS =
3213 new AccessibilityAction(
3214 AccessibilityNodeInfo.ACTION_CLEAR_FOCUS, null);
3215
3216 /**
3217 * Action that selects the node.
3218 */
3219 public static final AccessibilityAction ACTION_SELECT =
3220 new AccessibilityAction(
3221 AccessibilityNodeInfo.ACTION_SELECT, null);
3222
3223 /**
3224 * Action that deselects the node.
3225 */
3226 public static final AccessibilityAction ACTION_CLEAR_SELECTION =
3227 new AccessibilityAction(
3228 AccessibilityNodeInfo.ACTION_CLEAR_SELECTION, null);
3229
3230 /**
3231 * Action that clicks on the node info.
3232 */
3233 public static final AccessibilityAction ACTION_CLICK =
3234 new AccessibilityAction(
3235 AccessibilityNodeInfo.ACTION_CLICK, null);
3236
3237 /**
3238 * Action that long clicks on the node.
3239 */
3240 public static final AccessibilityAction ACTION_LONG_CLICK =
3241 new AccessibilityAction(
3242 AccessibilityNodeInfo.ACTION_LONG_CLICK, null);
3243
3244 /**
3245 * Action that gives accessibility focus to the node.
3246 */
3247 public static final AccessibilityAction ACTION_ACCESSIBILITY_FOCUS =
3248 new AccessibilityAction(
3249 AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
3250
3251 /**
3252 * Action that clears accessibility focus of the node.
3253 */
3254 public static final AccessibilityAction ACTION_CLEAR_ACCESSIBILITY_FOCUS =
3255 new AccessibilityAction(
3256 AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
3257
3258 /**
3259 * Action that requests to go to the next entity in this node's text
3260 * at a given movement granularity. For example, move to the next character,
3261 * word, etc.
3262 * <p>
3263 * <strong>Arguments:</strong>
3264 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3265 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT},
3266 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3267 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
3268 * <strong>Example:</strong> Move to the previous character and do not extend selection.
3269 * <code><pre><p>
3270 * Bundle arguments = new Bundle();
3271 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
3272 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
3273 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
3274 * false);
3275 * info.performAction(AccessibilityAction.ACTION_NEXT_AT_MOVEMENT_GRANULARITY.getId(),
3276 * arguments);
3277 * </code></pre></p>
3278 * </p>
3279 *
3280 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3281 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3282 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3283 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3284 *
3285 * @see AccessibilityNodeInfo#setMovementGranularities(int)
3286 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3287 * @see AccessibilityNodeInfo#getMovementGranularities()
3288 * AccessibilityNodeInfo.getMovementGranularities()
3289 *
3290 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_CHARACTER
3291 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
3292 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_WORD
3293 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
3294 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_LINE
3295 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
3296 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PARAGRAPH
3297 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
3298 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PAGE
3299 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE
3300 */
3301 public static final AccessibilityAction ACTION_NEXT_AT_MOVEMENT_GRANULARITY =
3302 new AccessibilityAction(
3303 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, null);
3304
3305 /**
3306 * Action that requests to go to the previous entity in this node's text
3307 * at a given movement granularity. For example, move to the next character,
3308 * word, etc.
3309 * <p>
3310 * <strong>Arguments:</strong>
3311 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3312 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT},
3313 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3314 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
3315 * <strong>Example:</strong> Move to the next character and do not extend selection.
3316 * <code><pre><p>
3317 * Bundle arguments = new Bundle();
3318 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
3319 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
3320 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
3321 * false);
3322 * info.performAction(AccessibilityAction.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY.getId(),
3323 * arguments);
3324 * </code></pre></p>
3325 * </p>
3326 *
3327 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3328 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3329 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3330 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3331 *
3332 * @see AccessibilityNodeInfo#setMovementGranularities(int)
3333 * AccessibilityNodeInfo.setMovementGranularities(int)
3334 * @see AccessibilityNodeInfo#getMovementGranularities()
3335 * AccessibilityNodeInfo.getMovementGranularities()
3336 *
3337 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_CHARACTER
3338 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
3339 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_WORD
3340 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
3341 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_LINE
3342 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
3343 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PARAGRAPH
3344 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
3345 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PAGE
3346 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE
3347 */
3348 public static final AccessibilityAction ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY =
3349 new AccessibilityAction(
3350 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, null);
3351
3352 /**
3353 * Action to move to the next HTML element of a given type. For example, move
3354 * to the BUTTON, INPUT, TABLE, etc.
3355 * <p>
3356 * <strong>Arguments:</strong>
3357 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_HTML_ELEMENT_STRING
3358 * AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
3359 * <strong>Example:</strong>
3360 * <code><pre><p>
3361 * Bundle arguments = new Bundle();
3362 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
3363 * info.performAction(AccessibilityAction.ACTION_NEXT_HTML_ELEMENT.getId(), arguments);
3364 * </code></pre></p>
3365 * </p>
3366 */
3367 public static final AccessibilityAction ACTION_NEXT_HTML_ELEMENT =
3368 new AccessibilityAction(
3369 AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, null);
3370
3371 /**
3372 * Action to move to the previous HTML element of a given type. For example, move
3373 * to the BUTTON, INPUT, TABLE, etc.
3374 * <p>
3375 * <strong>Arguments:</strong>
3376 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_HTML_ELEMENT_STRING
3377 * AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
3378 * <strong>Example:</strong>
3379 * <code><pre><p>
3380 * Bundle arguments = new Bundle();
3381 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
3382 * info.performAction(AccessibilityAction.ACTION_PREVIOUS_HTML_ELEMENT.getId(), arguments);
3383 * </code></pre></p>
3384 * </p>
3385 */
3386 public static final AccessibilityAction ACTION_PREVIOUS_HTML_ELEMENT =
3387 new AccessibilityAction(
3388 AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT, null);
3389
3390 /**
3391 * Action to scroll the node content forward.
3392 */
3393 public static final AccessibilityAction ACTION_SCROLL_FORWARD =
3394 new AccessibilityAction(
3395 AccessibilityNodeInfo.ACTION_SCROLL_FORWARD, null);
3396
3397 /**
3398 * Action to scroll the node content backward.
3399 */
3400 public static final AccessibilityAction ACTION_SCROLL_BACKWARD =
3401 new AccessibilityAction(
3402 AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD, null);
3403
3404 /**
3405 * Action to copy the current selection to the clipboard.
3406 */
3407 public static final AccessibilityAction ACTION_COPY =
3408 new AccessibilityAction(
3409 AccessibilityNodeInfo.ACTION_COPY, null);
3410
3411 /**
3412 * Action to paste the current clipboard content.
3413 */
3414 public static final AccessibilityAction ACTION_PASTE =
3415 new AccessibilityAction(
3416 AccessibilityNodeInfo.ACTION_PASTE, null);
3417
3418 /**
3419 * Action to cut the current selection and place it to the clipboard.
3420 */
3421 public static final AccessibilityAction ACTION_CUT =
3422 new AccessibilityAction(
3423 AccessibilityNodeInfo.ACTION_CUT, null);
3424
3425 /**
3426 * Action to set the selection. Performing this action with no arguments
3427 * clears the selection.
3428 * <p>
3429 * <strong>Arguments:</strong>
3430 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_START_INT
3431 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT},
3432 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_END_INT
3433 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT}<br>
3434 * <strong>Example:</strong>
3435 * <code><pre><p>
3436 * Bundle arguments = new Bundle();
3437 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1);
3438 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 2);
3439 * info.performAction(AccessibilityAction.ACTION_SET_SELECTION.getId(), arguments);
3440 * </code></pre></p>
3441 * </p>
3442 *
3443 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_START_INT
3444 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT
3445 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_END_INT
3446 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT
3447 */
3448 public static final AccessibilityAction ACTION_SET_SELECTION =
3449 new AccessibilityAction(
3450 AccessibilityNodeInfo.ACTION_SET_SELECTION, null);
3451
3452 /**
3453 * Action to expand an expandable node.
3454 */
3455 public static final AccessibilityAction ACTION_EXPAND =
3456 new AccessibilityAction(
3457 AccessibilityNodeInfo.ACTION_EXPAND, null);
3458
3459 /**
3460 * Action to collapse an expandable node.
3461 */
3462 public static final AccessibilityAction ACTION_COLLAPSE =
3463 new AccessibilityAction(
3464 AccessibilityNodeInfo.ACTION_COLLAPSE, null);
3465
3466 /**
3467 * Action to dismiss a dismissable node.
3468 */
3469 public static final AccessibilityAction ACTION_DISMISS =
3470 new AccessibilityAction(
3471 AccessibilityNodeInfo.ACTION_DISMISS, null);
3472
3473 /**
3474 * Action that sets the text of the node. Performing the action without argument,
3475 * using <code> null</code> or empty {@link CharSequence} will clear the text. This
3476 * action will also put the cursor at the end of text.
3477 * <p>
3478 * <strong>Arguments:</strong>
3479 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE
3480 * AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br>
3481 * <strong>Example:</strong>
3482 * <code><pre><p>
3483 * Bundle arguments = new Bundle();
3484 * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
3485 * "android");
3486 * info.performAction(AccessibilityAction.ACTION_SET_TEXT.getId(), arguments);
3487 * </code></pre></p>
3488 */
3489 public static final AccessibilityAction ACTION_SET_TEXT =
3490 new AccessibilityAction(
3491 AccessibilityNodeInfo.ACTION_SET_TEXT, null);
3492
Alan Viverette26c44ee2015-03-25 14:54:13 -07003493 /**
3494 * Action that requests the node make its bounding rectangle visible
3495 * on the screen, scrolling if necessary just enough.
3496 *
3497 * @see View#requestRectangleOnScreen(Rect)
3498 */
3499 public static final AccessibilityAction ACTION_SHOW_ON_SCREEN =
Alan Viverette23f44322015-04-06 16:04:56 -07003500 new AccessibilityAction(R.id.accessibilityActionShowOnScreen, null);
Alan Viverette26c44ee2015-03-25 14:54:13 -07003501
Alan Viverette23f44322015-04-06 16:04:56 -07003502 /**
3503 * Action that scrolls the node to make the specified collection
3504 * position visible on screen.
3505 * <p>
3506 * <strong>Arguments:</strong>
3507 * <ul>
3508 * <li>{@link AccessibilityNodeInfo#ACTION_ARGUMENT_ROW_INT}</li>
3509 * <li>{@link AccessibilityNodeInfo#ACTION_ARGUMENT_COLUMN_INT}</li>
3510 * <ul>
3511 *
3512 * @see AccessibilityNodeInfo#getCollectionInfo()
3513 */
3514 public static final AccessibilityAction ACTION_SCROLL_TO_POSITION =
3515 new AccessibilityAction(R.id.accessibilityActionScrollToPosition, null);
3516
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07003517 /**
3518 * Action to scroll the node content up.
3519 */
3520 public static final AccessibilityAction ACTION_SCROLL_UP =
3521 new AccessibilityAction(R.id.accessibilityActionScrollUp, null);
3522
3523 /**
3524 * Action to scroll the node content left.
3525 */
3526 public static final AccessibilityAction ACTION_SCROLL_LEFT =
3527 new AccessibilityAction(R.id.accessibilityActionScrollLeft, null);
3528
3529 /**
3530 * Action to scroll the node content down.
3531 */
3532 public static final AccessibilityAction ACTION_SCROLL_DOWN =
3533 new AccessibilityAction(R.id.accessibilityActionScrollDown, null);
3534
3535 /**
3536 * Action to scroll the node content right.
3537 */
3538 public static final AccessibilityAction ACTION_SCROLL_RIGHT =
3539 new AccessibilityAction(R.id.accessibilityActionScrollRight, null);
3540
Mady Mellord2744002015-04-30 16:17:16 -07003541 /**
Mady Mellore8608912015-06-05 09:02:55 -07003542 * Action that context clicks the node.
Mady Mellore82067b2015-04-30 09:58:35 -07003543 */
Mady Mellore8608912015-06-05 09:02:55 -07003544 public static final AccessibilityAction ACTION_CONTEXT_CLICK =
3545 new AccessibilityAction(R.id.accessibilityActionContextClick, null);
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07003546
Alan Viverette23f44322015-04-06 16:04:56 -07003547 private static final ArraySet<AccessibilityAction> sStandardActions = new ArraySet<>();
Kristian Monsen74bc1942014-04-29 11:00:17 -07003548 static {
3549 sStandardActions.add(ACTION_FOCUS);
3550 sStandardActions.add(ACTION_CLEAR_FOCUS);
3551 sStandardActions.add(ACTION_SELECT);
3552 sStandardActions.add(ACTION_CLEAR_SELECTION);
3553 sStandardActions.add(ACTION_CLICK);
3554 sStandardActions.add(ACTION_LONG_CLICK);
3555 sStandardActions.add(ACTION_ACCESSIBILITY_FOCUS);
3556 sStandardActions.add(ACTION_CLEAR_ACCESSIBILITY_FOCUS);
3557 sStandardActions.add(ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
3558 sStandardActions.add(ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
3559 sStandardActions.add(ACTION_NEXT_HTML_ELEMENT);
3560 sStandardActions.add(ACTION_PREVIOUS_HTML_ELEMENT);
3561 sStandardActions.add(ACTION_SCROLL_FORWARD);
3562 sStandardActions.add(ACTION_SCROLL_BACKWARD);
3563 sStandardActions.add(ACTION_COPY);
3564 sStandardActions.add(ACTION_PASTE);
3565 sStandardActions.add(ACTION_CUT);
3566 sStandardActions.add(ACTION_SET_SELECTION);
3567 sStandardActions.add(ACTION_EXPAND);
3568 sStandardActions.add(ACTION_COLLAPSE);
3569 sStandardActions.add(ACTION_DISMISS);
3570 sStandardActions.add(ACTION_SET_TEXT);
Alan Viverette26c44ee2015-03-25 14:54:13 -07003571 sStandardActions.add(ACTION_SHOW_ON_SCREEN);
Alan Viverette23f44322015-04-06 16:04:56 -07003572 sStandardActions.add(ACTION_SCROLL_TO_POSITION);
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07003573 sStandardActions.add(ACTION_SCROLL_UP);
3574 sStandardActions.add(ACTION_SCROLL_LEFT);
3575 sStandardActions.add(ACTION_SCROLL_DOWN);
3576 sStandardActions.add(ACTION_SCROLL_RIGHT);
Mady Mellore8608912015-06-05 09:02:55 -07003577 sStandardActions.add(ACTION_CONTEXT_CLICK);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003578 }
3579
3580 private final int mActionId;
3581 private final CharSequence mLabel;
3582
3583 /**
3584 * Creates a new AccessibilityAction. For adding a standard action without a specific label,
3585 * use the static constants.
3586 *
3587 * You can also override the description for one the standard actions. Below is an example
3588 * how to override the standard click action by adding a custom label:
3589 * <pre>
3590 * AccessibilityAction action = new AccessibilityAction(
3591 * AccessibilityAction.ACTION_ACTION_CLICK, getLocalizedLabel());
3592 * node.addAction(action);
3593 * </pre>
3594 *
3595 * @param actionId The id for this action. This should either be one of the
3596 * standard actions or a specific action for your app. In that case it is
3597 * required to use a resource identifier.
3598 * @param label The label for the new AccessibilityAction.
3599 */
3600 public AccessibilityAction(int actionId, @Nullable CharSequence label) {
Svetoslav5c4cd182014-05-21 14:53:16 -07003601 if ((actionId & ACTION_TYPE_MASK) == 0 && Integer.bitCount(actionId) != 1) {
Kristian Monsen74bc1942014-04-29 11:00:17 -07003602 throw new IllegalArgumentException("Invalid standard action id");
3603 }
3604
Kristian Monsen74bc1942014-04-29 11:00:17 -07003605 mActionId = actionId;
3606 mLabel = label;
3607 }
3608
3609 /**
3610 * Gets the id for this action.
3611 *
3612 * @return The action id.
3613 */
3614 public int getId() {
3615 return mActionId;
3616 }
3617
3618 /**
3619 * Gets the label for this action. Its purpose is to describe the
3620 * action to user.
3621 *
3622 * @return The label.
3623 */
3624 public CharSequence getLabel() {
3625 return mLabel;
3626 }
3627
3628 @Override
3629 public int hashCode() {
3630 return mActionId;
3631 }
3632
3633 @Override
3634 public boolean equals(Object other) {
3635 if (other == null) {
3636 return false;
3637 }
3638
3639 if (other == this) {
3640 return true;
3641 }
3642
3643 if (getClass() != other.getClass()) {
3644 return false;
3645 }
3646
3647 return mActionId == ((AccessibilityAction)other).mActionId;
3648 }
3649
3650 @Override
3651 public String toString() {
3652 return "AccessibilityAction: " + getActionSymbolicName(mActionId) + " - " + mLabel;
3653 }
3654 }
3655
3656 /**
Svetoslav3577a282013-06-06 14:09:10 -07003657 * Class with information if a node is a range. Use
Scott Main96844ed2013-10-18 14:43:02 -07003658 * {@link RangeInfo#obtain(int, float, float, float)} to get an instance.
Svetoslav3577a282013-06-06 14:09:10 -07003659 */
3660 public static final class RangeInfo {
3661 private static final int MAX_POOL_SIZE = 10;
3662
3663 /** Range type: integer. */
3664 public static final int RANGE_TYPE_INT = 0;
3665 /** Range type: float. */
3666 public static final int RANGE_TYPE_FLOAT = 1;
3667 /** Range type: percent with values from zero to one.*/
3668 public static final int RANGE_TYPE_PERCENT = 2;
3669
3670 private static final SynchronizedPool<RangeInfo> sPool =
3671 new SynchronizedPool<AccessibilityNodeInfo.RangeInfo>(MAX_POOL_SIZE);
3672
3673 private int mType;
3674 private float mMin;
3675 private float mMax;
3676 private float mCurrent;
3677
3678 /**
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07003679 * Obtains a pooled instance that is a clone of another one.
3680 *
3681 * @param other The instance to clone.
3682 *
3683 * @hide
3684 */
3685 public static RangeInfo obtain(RangeInfo other) {
3686 return obtain(other.mType, other.mMin, other.mMax, other.mCurrent);
3687 }
3688
3689 /**
Svetoslav3577a282013-06-06 14:09:10 -07003690 * Obtains a pooled instance.
3691 *
3692 * @param type The type of the range.
3693 * @param min The min value.
3694 * @param max The max value.
3695 * @param current The current value.
3696 */
3697 public static RangeInfo obtain(int type, float min, float max, float current) {
3698 RangeInfo info = sPool.acquire();
3699 return (info != null) ? info : new RangeInfo(type, min, max, current);
3700 }
3701
3702 /**
3703 * Creates a new range.
3704 *
3705 * @param type The type of the range.
3706 * @param min The min value.
3707 * @param max The max value.
3708 * @param current The current value.
3709 */
3710 private RangeInfo(int type, float min, float max, float current) {
3711 mType = type;
3712 mMin = min;
3713 mMax = max;
3714 mCurrent = current;
3715 }
3716
3717 /**
3718 * Gets the range type.
3719 *
3720 * @return The range type.
3721 *
3722 * @see #RANGE_TYPE_INT
3723 * @see #RANGE_TYPE_FLOAT
3724 * @see #RANGE_TYPE_PERCENT
3725 */
3726 public int getType() {
3727 return mType;
3728 }
3729
3730 /**
3731 * Gets the min value.
3732 *
3733 * @return The min value.
3734 */
3735 public float getMin() {
3736 return mMin;
3737 }
3738
3739 /**
3740 * Gets the max value.
3741 *
3742 * @return The max value.
3743 */
3744 public float getMax() {
3745 return mMax;
3746 }
3747
3748 /**
3749 * Gets the current value.
3750 *
3751 * @return The current value.
3752 */
3753 public float getCurrent() {
3754 return mCurrent;
3755 }
3756
3757 /**
3758 * Recycles this instance.
3759 */
3760 void recycle() {
3761 clear();
3762 sPool.release(this);
3763 }
3764
3765 private void clear() {
3766 mType = 0;
3767 mMin = 0;
3768 mMax = 0;
3769 mCurrent = 0;
3770 }
3771 }
3772
3773 /**
3774 * Class with information if a node is a collection. Use
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003775 * {@link CollectionInfo#obtain(int, int, boolean)} to get an instance.
3776 * <p>
3777 * A collection of items has rows and columns and may be hierarchical.
3778 * For example, a horizontal list is a collection with one column, as
3779 * many rows as the list items, and is not hierarchical; A table is a
3780 * collection with several rows, several columns, and is not hierarchical;
3781 * A vertical tree is a hierarchical collection with one column and
3782 * as many rows as the first level children.
3783 * </p>
Svetoslav3577a282013-06-06 14:09:10 -07003784 */
3785 public static final class CollectionInfo {
Alan Viverette76769ae2014-02-12 16:38:10 -08003786 /** Selection mode where items are not selectable. */
3787 public static final int SELECTION_MODE_NONE = 0;
3788
3789 /** Selection mode where a single item may be selected. */
3790 public static final int SELECTION_MODE_SINGLE = 1;
3791
3792 /** Selection mode where multiple items may be selected. */
3793 public static final int SELECTION_MODE_MULTIPLE = 2;
3794
Svetoslav3577a282013-06-06 14:09:10 -07003795 private static final int MAX_POOL_SIZE = 20;
3796
3797 private static final SynchronizedPool<CollectionInfo> sPool =
Alan Viverette23f44322015-04-06 16:04:56 -07003798 new SynchronizedPool<>(MAX_POOL_SIZE);
Svetoslav3577a282013-06-06 14:09:10 -07003799
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003800 private int mRowCount;
3801 private int mColumnCount;
Svetoslav3577a282013-06-06 14:09:10 -07003802 private boolean mHierarchical;
Alan Viverette76769ae2014-02-12 16:38:10 -08003803 private int mSelectionMode;
Svetoslav3577a282013-06-06 14:09:10 -07003804
3805 /**
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07003806 * Obtains a pooled instance that is a clone of another one.
3807 *
3808 * @param other The instance to clone.
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07003809 * @hide
3810 */
3811 public static CollectionInfo obtain(CollectionInfo other) {
Alan Viverette76769ae2014-02-12 16:38:10 -08003812 return CollectionInfo.obtain(other.mRowCount, other.mColumnCount, other.mHierarchical,
3813 other.mSelectionMode);
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07003814 }
3815
3816 /**
Svetoslav3577a282013-06-06 14:09:10 -07003817 * Obtains a pooled instance.
3818 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003819 * @param rowCount The number of rows.
3820 * @param columnCount The number of columns.
Svetoslav3577a282013-06-06 14:09:10 -07003821 * @param hierarchical Whether the collection is hierarchical.
3822 */
Alan Viverette76769ae2014-02-12 16:38:10 -08003823 public static CollectionInfo obtain(int rowCount, int columnCount,
3824 boolean hierarchical) {
3825 return obtain(rowCount, columnCount, hierarchical, SELECTION_MODE_NONE);
3826 }
3827
3828 /**
3829 * Obtains a pooled instance.
3830 *
3831 * @param rowCount The number of rows.
3832 * @param columnCount The number of columns.
3833 * @param hierarchical Whether the collection is hierarchical.
3834 * @param selectionMode The collection's selection mode, one of:
3835 * <ul>
3836 * <li>{@link #SELECTION_MODE_NONE}
3837 * <li>{@link #SELECTION_MODE_SINGLE}
3838 * <li>{@link #SELECTION_MODE_MULTIPLE}
3839 * </ul>
3840 */
3841 public static CollectionInfo obtain(int rowCount, int columnCount,
3842 boolean hierarchical, int selectionMode) {
3843 final CollectionInfo info = sPool.acquire();
Alan Viverettecdd2edd2014-02-12 11:28:33 -08003844 if (info == null) {
Alan Viverette76769ae2014-02-12 16:38:10 -08003845 return new CollectionInfo(rowCount, columnCount, hierarchical, selectionMode);
Alan Viverettecdd2edd2014-02-12 11:28:33 -08003846 }
3847
3848 info.mRowCount = rowCount;
3849 info.mColumnCount = columnCount;
3850 info.mHierarchical = hierarchical;
Alan Viverette76769ae2014-02-12 16:38:10 -08003851 info.mSelectionMode = selectionMode;
Alan Viverettecdd2edd2014-02-12 11:28:33 -08003852 return info;
Svetoslav3577a282013-06-06 14:09:10 -07003853 }
3854
3855 /**
3856 * Creates a new instance.
3857 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003858 * @param rowCount The number of rows.
3859 * @param columnCount The number of columns.
Svetoslav3577a282013-06-06 14:09:10 -07003860 * @param hierarchical Whether the collection is hierarchical.
Alan Viverette76769ae2014-02-12 16:38:10 -08003861 * @param selectionMode The collection's selection mode.
Svetoslav3577a282013-06-06 14:09:10 -07003862 */
Alan Viverette76769ae2014-02-12 16:38:10 -08003863 private CollectionInfo(int rowCount, int columnCount, boolean hierarchical,
3864 int selectionMode) {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003865 mRowCount = rowCount;
3866 mColumnCount = columnCount;
Svetoslav3577a282013-06-06 14:09:10 -07003867 mHierarchical = hierarchical;
Alan Viverette76769ae2014-02-12 16:38:10 -08003868 mSelectionMode = selectionMode;
Svetoslav3577a282013-06-06 14:09:10 -07003869 }
3870
3871 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003872 * Gets the number of rows.
Svetoslav3577a282013-06-06 14:09:10 -07003873 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003874 * @return The row count.
Svetoslav3577a282013-06-06 14:09:10 -07003875 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003876 public int getRowCount() {
3877 return mRowCount;
Svetoslav3577a282013-06-06 14:09:10 -07003878 }
3879
3880 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003881 * Gets the number of columns.
Svetoslav3577a282013-06-06 14:09:10 -07003882 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003883 * @return The column count.
Svetoslav3577a282013-06-06 14:09:10 -07003884 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003885 public int getColumnCount() {
3886 return mColumnCount;
Svetoslav3577a282013-06-06 14:09:10 -07003887 }
3888
3889 /**
3890 * Gets if the collection is a hierarchically ordered.
3891 *
3892 * @return Whether the collection is hierarchical.
3893 */
3894 public boolean isHierarchical() {
3895 return mHierarchical;
3896 }
3897
3898 /**
Alan Viverette76769ae2014-02-12 16:38:10 -08003899 * Gets the collection's selection mode.
3900 *
3901 * @return The collection's selection mode, one of:
3902 * <ul>
3903 * <li>{@link #SELECTION_MODE_NONE}
3904 * <li>{@link #SELECTION_MODE_SINGLE}
3905 * <li>{@link #SELECTION_MODE_MULTIPLE}
3906 * </ul>
3907 */
3908 public int getSelectionMode() {
3909 return mSelectionMode;
3910 }
3911
3912 /**
Svetoslav3577a282013-06-06 14:09:10 -07003913 * Recycles this instance.
3914 */
3915 void recycle() {
3916 clear();
3917 sPool.release(this);
3918 }
3919
3920 private void clear() {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003921 mRowCount = 0;
3922 mColumnCount = 0;
Svetoslav3577a282013-06-06 14:09:10 -07003923 mHierarchical = false;
Alan Viverette76769ae2014-02-12 16:38:10 -08003924 mSelectionMode = SELECTION_MODE_NONE;
Svetoslav3577a282013-06-06 14:09:10 -07003925 }
3926 }
3927
3928 /**
3929 * Class with information if a node is a collection item. Use
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003930 * {@link CollectionItemInfo#obtain(int, int, int, int, boolean)}
3931 * to get an instance.
3932 * <p>
3933 * A collection item is contained in a collection, it starts at
3934 * a given row and column in the collection, and spans one or
3935 * more rows and columns. For example, a header of two related
3936 * table columns starts at the first row and the first column,
3937 * spans one row and two columns.
3938 * </p>
Svetoslav3577a282013-06-06 14:09:10 -07003939 */
3940 public static final class CollectionItemInfo {
3941 private static final int MAX_POOL_SIZE = 20;
3942
3943 private static final SynchronizedPool<CollectionItemInfo> sPool =
Alan Viverette23f44322015-04-06 16:04:56 -07003944 new SynchronizedPool<>(MAX_POOL_SIZE);
Svetoslav3577a282013-06-06 14:09:10 -07003945
3946 /**
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07003947 * Obtains a pooled instance that is a clone of another one.
3948 *
3949 * @param other The instance to clone.
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07003950 * @hide
3951 */
3952 public static CollectionItemInfo obtain(CollectionItemInfo other) {
Alan Viverette76769ae2014-02-12 16:38:10 -08003953 return CollectionItemInfo.obtain(other.mRowIndex, other.mRowSpan, other.mColumnIndex,
3954 other.mColumnSpan, other.mHeading, other.mSelected);
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07003955 }
3956
3957 /**
Svetoslav3577a282013-06-06 14:09:10 -07003958 * Obtains a pooled instance.
3959 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003960 * @param rowIndex The row index at which the item is located.
3961 * @param rowSpan The number of rows the item spans.
3962 * @param columnIndex The column index at which the item is located.
3963 * @param columnSpan The number of columns the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07003964 * @param heading Whether the item is a heading.
3965 */
Alan Viverette76769ae2014-02-12 16:38:10 -08003966 public static CollectionItemInfo obtain(int rowIndex, int rowSpan,
3967 int columnIndex, int columnSpan, boolean heading) {
3968 return obtain(rowIndex, rowSpan, columnIndex, columnSpan, heading, false);
3969 }
3970
3971 /**
3972 * Obtains a pooled instance.
3973 *
3974 * @param rowIndex The row index at which the item is located.
3975 * @param rowSpan The number of rows the item spans.
3976 * @param columnIndex The column index at which the item is located.
3977 * @param columnSpan The number of columns the item spans.
3978 * @param heading Whether the item is a heading.
3979 * @param selected Whether the item is selected.
3980 */
3981 public static CollectionItemInfo obtain(int rowIndex, int rowSpan,
3982 int columnIndex, int columnSpan, boolean heading, boolean selected) {
Alan Viverettecdd2edd2014-02-12 11:28:33 -08003983 final CollectionItemInfo info = sPool.acquire();
3984 if (info == null) {
Alan Viverette76769ae2014-02-12 16:38:10 -08003985 return new CollectionItemInfo(
3986 rowIndex, rowSpan, columnIndex, columnSpan, heading, selected);
Alan Viverettecdd2edd2014-02-12 11:28:33 -08003987 }
3988
3989 info.mRowIndex = rowIndex;
3990 info.mRowSpan = rowSpan;
3991 info.mColumnIndex = columnIndex;
3992 info.mColumnSpan = columnSpan;
3993 info.mHeading = heading;
Alan Viverette76769ae2014-02-12 16:38:10 -08003994 info.mSelected = selected;
Alan Viverettecdd2edd2014-02-12 11:28:33 -08003995 return info;
Svetoslav3577a282013-06-06 14:09:10 -07003996 }
3997
3998 private boolean mHeading;
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003999 private int mColumnIndex;
4000 private int mRowIndex;
4001 private int mColumnSpan;
4002 private int mRowSpan;
Alan Viverette76769ae2014-02-12 16:38:10 -08004003 private boolean mSelected;
Svetoslav3577a282013-06-06 14:09:10 -07004004
4005 /**
4006 * Creates a new instance.
4007 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004008 * @param rowIndex The row index at which the item is located.
4009 * @param rowSpan The number of rows the item spans.
4010 * @param columnIndex The column index at which the item is located.
4011 * @param columnSpan The number of columns the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07004012 * @param heading Whether the item is a heading.
4013 */
Alan Viverette76769ae2014-02-12 16:38:10 -08004014 private CollectionItemInfo(int rowIndex, int rowSpan, int columnIndex, int columnSpan,
4015 boolean heading, boolean selected) {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004016 mRowIndex = rowIndex;
4017 mRowSpan = rowSpan;
4018 mColumnIndex = columnIndex;
4019 mColumnSpan = columnSpan;
Svetoslav3577a282013-06-06 14:09:10 -07004020 mHeading = heading;
Alan Viverette76769ae2014-02-12 16:38:10 -08004021 mSelected = selected;
Svetoslav3577a282013-06-06 14:09:10 -07004022 }
4023
4024 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004025 * Gets the column index at which the item is located.
Svetoslav3577a282013-06-06 14:09:10 -07004026 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004027 * @return The column index.
Svetoslav3577a282013-06-06 14:09:10 -07004028 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004029 public int getColumnIndex() {
4030 return mColumnIndex;
Svetoslav3577a282013-06-06 14:09:10 -07004031 }
4032
4033 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004034 * Gets the row index at which the item is located.
Svetoslav3577a282013-06-06 14:09:10 -07004035 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004036 * @return The row index.
Svetoslav3577a282013-06-06 14:09:10 -07004037 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004038 public int getRowIndex() {
4039 return mRowIndex;
Svetoslav3577a282013-06-06 14:09:10 -07004040 }
4041
4042 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004043 * Gets the number of columns the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07004044 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004045 * @return The column span.
Svetoslav3577a282013-06-06 14:09:10 -07004046 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004047 public int getColumnSpan() {
4048 return mColumnSpan;
Svetoslav3577a282013-06-06 14:09:10 -07004049 }
4050
4051 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004052 * Gets the number of rows the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07004053 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004054 * @return The row span.
Svetoslav3577a282013-06-06 14:09:10 -07004055 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004056 public int getRowSpan() {
4057 return mRowSpan;
Svetoslav3577a282013-06-06 14:09:10 -07004058 }
4059
4060 /**
4061 * Gets if the collection item is a heading. For example, section
4062 * heading, table header, etc.
4063 *
4064 * @return If the item is a heading.
4065 */
4066 public boolean isHeading() {
4067 return mHeading;
4068 }
4069
4070 /**
Alan Viverette76769ae2014-02-12 16:38:10 -08004071 * Gets if the collection item is selected.
4072 *
4073 * @return If the item is selected.
4074 */
4075 public boolean isSelected() {
4076 return mSelected;
4077 }
4078
4079 /**
Svetoslav3577a282013-06-06 14:09:10 -07004080 * Recycles this instance.
4081 */
4082 void recycle() {
4083 clear();
4084 sPool.release(this);
4085 }
4086
4087 private void clear() {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004088 mColumnIndex = 0;
4089 mColumnSpan = 0;
4090 mRowIndex = 0;
4091 mRowSpan = 0;
Svetoslav3577a282013-06-06 14:09:10 -07004092 mHeading = false;
Alan Viverette76769ae2014-02-12 16:38:10 -08004093 mSelected = false;
Svetoslav3577a282013-06-06 14:09:10 -07004094 }
4095 }
4096
4097 /**
Alan Viverettef0aed092013-11-06 15:33:03 -08004098 * @see android.os.Parcelable.Creator
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004099 */
4100 public static final Parcelable.Creator<AccessibilityNodeInfo> CREATOR =
4101 new Parcelable.Creator<AccessibilityNodeInfo>() {
Alan Viverettef0aed092013-11-06 15:33:03 -08004102 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004103 public AccessibilityNodeInfo createFromParcel(Parcel parcel) {
4104 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
4105 info.initFromParcel(parcel);
4106 return info;
4107 }
4108
Alan Viverettef0aed092013-11-06 15:33:03 -08004109 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004110 public AccessibilityNodeInfo[] newArray(int size) {
4111 return new AccessibilityNodeInfo[size];
4112 }
4113 };
4114}