blob: 4f53c1e78c7566485994789fb4d1bca0afa5d105 [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;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070020import android.graphics.Rect;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -070021import android.os.Bundle;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070022import android.os.Parcel;
23import android.os.Parcelable;
Svetoslav6254f482013-06-04 17:22:14 -070024import android.text.InputType;
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -080025import android.util.Pools.SynchronizedPool;
Svetoslav Ganov02107852011-10-03 17:06:56 -070026import android.util.SparseLongArray;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070027import android.view.View;
28
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -070029import java.util.Collections;
30import java.util.List;
31
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070032/**
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070033 * This class represents a node of the window content as well as actions that
34 * can be requested from its source. From the point of view of an
35 * {@link android.accessibilityservice.AccessibilityService} a window content is
36 * presented as tree of accessibility node info which may or may not map one-to-one
37 * to the view hierarchy. In other words, a custom view is free to report itself as
38 * a tree of accessibility node info.
39 * </p>
40 * <p>
41 * Once an accessibility node info is delivered to an accessibility service it is
42 * made immutable and calling a state mutation method generates an error.
43 * </p>
44 * <p>
45 * Please refer to {@link android.accessibilityservice.AccessibilityService} for
46 * details about how to obtain a handle to window content as a tree of accessibility
47 * node info as well as familiarizing with the security model.
48 * </p>
Joe Fernandeze1302ed2012-02-06 14:30:15 -080049 * <div class="special reference">
50 * <h3>Developer Guides</h3>
51 * <p>For more information about making applications accessible, read the
52 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
53 * developer guide.</p>
54 * </div>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070055 *
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070056 * @see android.accessibilityservice.AccessibilityService
57 * @see AccessibilityEvent
58 * @see AccessibilityManager
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070059 */
60public class AccessibilityNodeInfo implements Parcelable {
61
62 private static final boolean DEBUG = false;
63
Svetoslav Ganov0d04e242012-02-21 13:46:36 -080064 /** @hide */
65 public static final int UNDEFINED = -1;
66
67 /** @hide */
68 public static final long ROOT_NODE_ID = makeNodeId(UNDEFINED, UNDEFINED);
69
70 /** @hide */
71 public static final int ACTIVE_WINDOW_ID = UNDEFINED;
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -080072
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -080073 /** @hide */
74 public static final int FLAG_PREFETCH_PREDECESSORS = 0x00000001;
75
76 /** @hide */
77 public static final int FLAG_PREFETCH_SIBLINGS = 0x00000002;
78
79 /** @hide */
Svetoslav Ganov42138042012-03-20 11:51:39 -070080 public static final int FLAG_PREFETCH_DESCENDANTS = 0x00000004;
81
82 /** @hide */
Svetoslav Ganov80943d82013-01-02 10:25:37 -080083 public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x00000008;
84
85 /** @hide */
86 public static final int FLAG_REPORT_VIEW_IDS = 0x00000010;
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -080087
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070088 // Actions.
89
90 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -070091 * Action that gives input focus to the node.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070092 */
Svetoslav Ganov005b83b2012-04-16 18:17:17 -070093 public static final int ACTION_FOCUS = 0x00000001;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070094
95 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -070096 * Action that clears input focus of the node.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070097 */
Svetoslav Ganov42138042012-03-20 11:51:39 -070098 public static final int ACTION_CLEAR_FOCUS = 0x00000002;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070099
100 /**
101 * Action that selects the node.
102 */
Svetoslav Ganov42138042012-03-20 11:51:39 -0700103 public static final int ACTION_SELECT = 0x00000004;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700104
105 /**
106 * Action that unselects the node.
107 */
Svetoslav Ganov42138042012-03-20 11:51:39 -0700108 public static final int ACTION_CLEAR_SELECTION = 0x00000008;
109
110 /**
Svetoslav Ganov6d17a932012-04-27 19:30:38 -0700111 * Action that clicks on the node info.
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700112 */
113 public static final int ACTION_CLICK = 0x00000010;
114
115 /**
Svetoslav Ganov6d17a932012-04-27 19:30:38 -0700116 * Action that long clicks on the node.
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700117 */
118 public static final int ACTION_LONG_CLICK = 0x00000020;
119
120 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700121 * Action that gives accessibility focus to the node.
122 */
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700123 public static final int ACTION_ACCESSIBILITY_FOCUS = 0x00000040;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700124
125 /**
126 * Action that clears accessibility focus of the node.
127 */
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700128 public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 0x00000080;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700129
130 /**
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700131 * Action that requests to go to the next entity in this node's text
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700132 * at a given movement granularity. For example, move to the next character,
133 * word, etc.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700134 * <p>
Svetoslav7c512842013-01-30 23:02:08 -0800135 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
136 * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
137 * <strong>Example:</strong> Move to the previous character and do not extend selection.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700138 * <code><pre><p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700139 * Bundle arguments = new Bundle();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700140 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
141 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
Svetoslav7c512842013-01-30 23:02:08 -0800142 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
143 * false);
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700144 * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700145 * </code></pre></p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700146 * </p>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700147 *
Svetoslav7c512842013-01-30 23:02:08 -0800148 * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
149 * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
150 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700151 * @see #setMovementGranularities(int)
152 * @see #getMovementGranularities()
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700153 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700154 * @see #MOVEMENT_GRANULARITY_CHARACTER
155 * @see #MOVEMENT_GRANULARITY_WORD
156 * @see #MOVEMENT_GRANULARITY_LINE
157 * @see #MOVEMENT_GRANULARITY_PARAGRAPH
158 * @see #MOVEMENT_GRANULARITY_PAGE
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700159 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700160 public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 0x00000100;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700161
162 /**
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700163 * Action that requests to go to the previous entity in this node's text
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700164 * at a given movement granularity. For example, move to the next character,
165 * word, etc.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700166 * <p>
Svetoslav7c512842013-01-30 23:02:08 -0800167 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
168 * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
169 * <strong>Example:</strong> Move to the next character and do not extend selection.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700170 * <code><pre><p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700171 * Bundle arguments = new Bundle();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700172 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
173 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
Svetoslav7c512842013-01-30 23:02:08 -0800174 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
175 * false);
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700176 * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
177 * arguments);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700178 * </code></pre></p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700179 * </p>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700180 *
Svetoslav7c512842013-01-30 23:02:08 -0800181 * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
182 * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
183 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700184 * @see #setMovementGranularities(int)
185 * @see #getMovementGranularities()
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700186 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700187 * @see #MOVEMENT_GRANULARITY_CHARACTER
188 * @see #MOVEMENT_GRANULARITY_WORD
189 * @see #MOVEMENT_GRANULARITY_LINE
190 * @see #MOVEMENT_GRANULARITY_PARAGRAPH
191 * @see #MOVEMENT_GRANULARITY_PAGE
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700192 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700193 public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 0x00000200;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700194
195 /**
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700196 * Action to move to the next HTML element of a given type. For example, move
197 * to the BUTTON, INPUT, TABLE, etc.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700198 * <p>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700199 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
200 * <strong>Example:</strong>
201 * <code><pre><p>
202 * Bundle arguments = new Bundle();
203 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
204 * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, arguments);
205 * </code></pre></p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700206 * </p>
207 */
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700208 public static final int ACTION_NEXT_HTML_ELEMENT = 0x00000400;
209
210 /**
211 * Action to move to the previous HTML element of a given type. For example, move
212 * to the BUTTON, INPUT, TABLE, etc.
213 * <p>
214 * <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_PREVIOUS_HTML_ELEMENT, arguments);
220 * </code></pre></p>
221 * </p>
222 */
223 public static final int ACTION_PREVIOUS_HTML_ELEMENT = 0x00000800;
224
225 /**
Svetoslav Ganova1dc7612012-05-10 04:14:53 -0700226 * Action to scroll the node content forward.
227 */
228 public static final int ACTION_SCROLL_FORWARD = 0x00001000;
229
230 /**
231 * Action to scroll the node content backward.
232 */
233 public static final int ACTION_SCROLL_BACKWARD = 0x00002000;
234
235 /**
Svetoslav7c512842013-01-30 23:02:08 -0800236 * Action to copy the current selection to the clipboard.
237 */
238 public static final int ACTION_COPY = 0x00004000;
239
240 /**
241 * Action to paste the current clipboard content.
242 */
243 public static final int ACTION_PASTE = 0x00008000;
244
245 /**
246 * Action to cut the current selection and place it to the clipboard.
247 */
248 public static final int ACTION_CUT = 0x00010000;
249
250 /**
251 * Action to set the selection. Performing this action with no arguments
252 * clears the selection.
253 * <p>
254 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_SELECTION_START_INT},
255 * {@link #ACTION_ARGUMENT_SELECTION_END_INT}<br>
256 * <strong>Example:</strong>
257 * <code><pre><p>
258 * Bundle arguments = new Bundle();
259 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1);
260 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 2);
261 * info.performAction(AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments);
262 * </code></pre></p>
263 * </p>
264 *
265 * @see #ACTION_ARGUMENT_SELECTION_START_INT
266 * @see #ACTION_ARGUMENT_SELECTION_END_INT
267 */
268 public static final int ACTION_SET_SELECTION = 0x00020000;
269
270 /**
Svetoslav3577a282013-06-06 14:09:10 -0700271 * Action to expand an expandable node.
272 */
273 public static final int ACTION_EXPAND = 0x00040000;
274
275 /**
276 * Action to collapse an expandable node.
277 */
278 public static final int ACTION_COLLAPSE = 0x00080000;
279
280 /**
281 * Action to dismiss a dismissable node.
282 */
283 public static final int ACTION_DISMISS = 0x00100000;
284
285 // Action arguments
286
287 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700288 * Argument for which movement granularity to be used when traversing the node text.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700289 * <p>
290 * <strong>Type:</strong> int<br>
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700291 * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_MOVEMENT_GRANULARITY},
292 * {@link #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700293 * </p>
Svetoslav7c512842013-01-30 23:02:08 -0800294 *
295 * @see #ACTION_NEXT_AT_MOVEMENT_GRANULARITY
296 * @see #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700297 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700298 public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT =
Svetoslav7c512842013-01-30 23:02:08 -0800299 "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700300
301 /**
302 * Argument for which HTML element to get moving to the next/previous HTML element.
303 * <p>
304 * <strong>Type:</strong> String<br>
305 * <strong>Actions:</strong> {@link #ACTION_NEXT_HTML_ELEMENT},
306 * {@link #ACTION_PREVIOUS_HTML_ELEMENT}
307 * </p>
Svetoslav7c512842013-01-30 23:02:08 -0800308 *
309 * @see #ACTION_NEXT_HTML_ELEMENT
310 * @see #ACTION_PREVIOUS_HTML_ELEMENT
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700311 */
312 public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING =
Svetoslav7c512842013-01-30 23:02:08 -0800313 "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
314
315 /**
316 * Argument for whether when moving at granularity to extend the selection
317 * or to move it otherwise.
318 * <p>
319 * <strong>Type:</strong> boolean<br>
320 * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_MOVEMENT_GRANULARITY},
321 * {@link #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}
322 * </p>
323 *
324 * @see #ACTION_NEXT_AT_MOVEMENT_GRANULARITY
325 * @see #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
326 */
327 public static final String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN =
328 "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
329
330 /**
331 * Argument for specifying the selection start.
332 * <p>
333 * <strong>Type:</strong> int<br>
334 * <strong>Actions:</strong> {@link #ACTION_SET_SELECTION}
335 * </p>
336 *
337 * @see #ACTION_SET_SELECTION
338 */
339 public static final String ACTION_ARGUMENT_SELECTION_START_INT =
340 "ACTION_ARGUMENT_SELECTION_START_INT";
341
342 /**
343 * Argument for specifying the selection end.
344 * <p>
345 * <strong>Type:</strong> int<br>
346 * <strong>Actions:</strong> {@link #ACTION_SET_SELECTION}
347 * </p>
348 *
349 * @see #ACTION_SET_SELECTION
350 */
351 public static final String ACTION_ARGUMENT_SELECTION_END_INT =
352 "ACTION_ARGUMENT_SELECTION_END_INT";
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700353
Svetoslav3577a282013-06-06 14:09:10 -0700354 // Focus types
355
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700356 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700357 * The input focus.
358 */
359 public static final int FOCUS_INPUT = 1;
360
361 /**
362 * The accessibility focus.
363 */
364 public static final int FOCUS_ACCESSIBILITY = 2;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700365
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700366 // Movement granularities
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700367
368 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700369 * Movement granularity bit for traversing the text of a node by character.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700370 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700371 public static final int MOVEMENT_GRANULARITY_CHARACTER = 0x00000001;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700372
373 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700374 * Movement granularity bit for traversing the text of a node by word.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700375 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700376 public static final int MOVEMENT_GRANULARITY_WORD = 0x00000002;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700377
378 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700379 * Movement granularity bit for traversing the text of a node by line.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700380 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700381 public static final int MOVEMENT_GRANULARITY_LINE = 0x00000004;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700382
383 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700384 * Movement granularity bit for traversing the text of a node by paragraph.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700385 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700386 public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 0x00000008;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700387
388 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700389 * Movement granularity bit for traversing the text of a node by page.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700390 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700391 public static final int MOVEMENT_GRANULARITY_PAGE = 0x00000010;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700392
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700393 // Boolean attributes.
394
Svetoslavbcc46a02013-02-06 11:56:00 -0800395 private static final int BOOLEAN_PROPERTY_CHECKABLE = 0x00000001;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700396
Svetoslavbcc46a02013-02-06 11:56:00 -0800397 private static final int BOOLEAN_PROPERTY_CHECKED = 0x00000002;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700398
Svetoslavbcc46a02013-02-06 11:56:00 -0800399 private static final int BOOLEAN_PROPERTY_FOCUSABLE = 0x00000004;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700400
Svetoslavbcc46a02013-02-06 11:56:00 -0800401 private static final int BOOLEAN_PROPERTY_FOCUSED = 0x00000008;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700402
Svetoslavbcc46a02013-02-06 11:56:00 -0800403 private static final int BOOLEAN_PROPERTY_SELECTED = 0x00000010;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700404
Svetoslavbcc46a02013-02-06 11:56:00 -0800405 private static final int BOOLEAN_PROPERTY_CLICKABLE = 0x00000020;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700406
Svetoslavbcc46a02013-02-06 11:56:00 -0800407 private static final int BOOLEAN_PROPERTY_LONG_CLICKABLE = 0x00000040;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700408
Svetoslavbcc46a02013-02-06 11:56:00 -0800409 private static final int BOOLEAN_PROPERTY_ENABLED = 0x00000080;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700410
Svetoslavbcc46a02013-02-06 11:56:00 -0800411 private static final int BOOLEAN_PROPERTY_PASSWORD = 0x00000100;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700412
Svetoslavbcc46a02013-02-06 11:56:00 -0800413 private static final int BOOLEAN_PROPERTY_SCROLLABLE = 0x00000200;
Svetoslav Ganova0156172011-06-26 17:55:44 -0700414
Svetoslavbcc46a02013-02-06 11:56:00 -0800415 private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED = 0x00000400;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700416
Svetoslavbcc46a02013-02-06 11:56:00 -0800417 private static final int BOOLEAN_PROPERTY_VISIBLE_TO_USER = 0x00000800;
418
419 private static final int BOOLEAN_PROPERTY_EDITABLE = 0x00001000;
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -0700420
Alan Viverette77e9a282013-09-12 17:16:09 -0700421 private static final int BOOLEAN_PROPERTY_OPENS_POPUP = 0x00002000;
Svetoslav3577a282013-06-06 14:09:10 -0700422
Alan Viverette77e9a282013-09-12 17:16:09 -0700423 private static final int BOOLEAN_PROPERTY_DISMISSABLE = 0x00004000;
Svetoslav3577a282013-06-06 14:09:10 -0700424
Alan Viverette77e9a282013-09-12 17:16:09 -0700425 private static final int BOOLEAN_PROPERTY_MULTI_LINE = 0x00008000;
Svetoslav3577a282013-06-06 14:09:10 -0700426
Alan Viverette77e9a282013-09-12 17:16:09 -0700427 private static final int BOOLEAN_PROPERTY_CONTENT_INVALID = 0x00010000;
Svetoslav3577a282013-06-06 14:09:10 -0700428
Svetoslav Ganov02107852011-10-03 17:06:56 -0700429 /**
430 * Bits that provide the id of a virtual descendant of a view.
431 */
432 private static final long VIRTUAL_DESCENDANT_ID_MASK = 0xffffffff00000000L;
433
434 /**
435 * Bit shift of {@link #VIRTUAL_DESCENDANT_ID_MASK} to get to the id for a
436 * virtual descendant of a view. Such a descendant does not exist in the view
437 * hierarchy and is only reported via the accessibility APIs.
438 */
439 private static final int VIRTUAL_DESCENDANT_ID_SHIFT = 32;
440
441 /**
442 * Gets the accessibility view id which identifies a View in the view three.
443 *
444 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}.
445 * @return The accessibility view id part of the node id.
446 *
447 * @hide
448 */
449 public static int getAccessibilityViewId(long accessibilityNodeId) {
450 return (int) accessibilityNodeId;
451 }
452
453 /**
454 * Gets the virtual descendant id which identifies an imaginary view in a
455 * containing View.
456 *
457 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}.
458 * @return The virtual view id part of the node id.
459 *
460 * @hide
461 */
462 public static int getVirtualDescendantId(long accessibilityNodeId) {
463 return (int) ((accessibilityNodeId & VIRTUAL_DESCENDANT_ID_MASK)
464 >> VIRTUAL_DESCENDANT_ID_SHIFT);
465 }
466
467 /**
468 * Makes a node id by shifting the <code>virtualDescendantId</code>
469 * by {@link #VIRTUAL_DESCENDANT_ID_SHIFT} and taking
470 * the bitwise or with the <code>accessibilityViewId</code>.
471 *
472 * @param accessibilityViewId A View accessibility id.
473 * @param virtualDescendantId A virtual descendant id.
474 * @return The node id.
475 *
476 * @hide
477 */
478 public static long makeNodeId(int accessibilityViewId, int virtualDescendantId) {
479 return (((long) virtualDescendantId) << VIRTUAL_DESCENDANT_ID_SHIFT) | accessibilityViewId;
480 }
481
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700482 // Housekeeping.
483 private static final int MAX_POOL_SIZE = 50;
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -0800484 private static final SynchronizedPool<AccessibilityNodeInfo> sPool =
485 new SynchronizedPool<AccessibilityNodeInfo>(MAX_POOL_SIZE);
486
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700487 private boolean mSealed;
488
489 // Data.
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800490 private int mWindowId = UNDEFINED;
Svetoslav Ganov0d04e242012-02-21 13:46:36 -0800491 private long mSourceNodeId = ROOT_NODE_ID;
492 private long mParentNodeId = ROOT_NODE_ID;
Svetoslav Ganov33aef982012-09-13 12:49:03 -0700493 private long mLabelForId = ROOT_NODE_ID;
494 private long mLabeledById = ROOT_NODE_ID;
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800495
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700496 private int mBooleanProperties;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700497 private final Rect mBoundsInParent = new Rect();
498 private final Rect mBoundsInScreen = new Rect();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700499
500 private CharSequence mPackageName;
501 private CharSequence mClassName;
502 private CharSequence mText;
503 private CharSequence mContentDescription;
Svetoslav9fa1ee52013-04-22 12:43:03 -0700504 private String mViewIdResourceName;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700505
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700506 private final SparseLongArray mChildNodeIds = new SparseLongArray();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700507 private int mActions;
508
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700509 private int mMovementGranularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700510
Svetoslavbcc46a02013-02-06 11:56:00 -0800511 private int mTextSelectionStart = UNDEFINED;
512 private int mTextSelectionEnd = UNDEFINED;
Svetoslav6254f482013-06-04 17:22:14 -0700513 private int mInputType = InputType.TYPE_NULL;
Alan Viverette77e9a282013-09-12 17:16:09 -0700514 private int mLiveRegion = View.ACCESSIBILITY_LIVE_REGION_NONE;
Svetoslav6254f482013-06-04 17:22:14 -0700515
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -0700516 private Bundle mExtras;
Svetoslavbcc46a02013-02-06 11:56:00 -0800517
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -0800518 private int mConnectionId = UNDEFINED;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700519
Svetoslav3577a282013-06-06 14:09:10 -0700520 private RangeInfo mRangeInfo;
521 private CollectionInfo mCollectionInfo;
522 private CollectionItemInfo mCollectionItemInfo;
523
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700524 /**
525 * Hide constructor from clients.
526 */
527 private AccessibilityNodeInfo() {
528 /* do nothing */
529 }
530
531 /**
532 * Sets the source.
Svetoslav Ganov02107852011-10-03 17:06:56 -0700533 * <p>
534 * <strong>Note:</strong> Cannot be called from an
535 * {@link android.accessibilityservice.AccessibilityService}.
536 * This class is made immutable before being delivered to an AccessibilityService.
537 * </p>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700538 *
539 * @param source The info source.
540 */
541 public void setSource(View source) {
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800542 setSource(source, UNDEFINED);
Svetoslav Ganov02107852011-10-03 17:06:56 -0700543 }
544
545 /**
546 * Sets the source to be a virtual descendant of the given <code>root</code>.
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700547 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
Svetoslav Ganov02107852011-10-03 17:06:56 -0700548 * is set as the source.
549 * <p>
550 * A virtual descendant is an imaginary View that is reported as a part of the view
551 * hierarchy for accessibility purposes. This enables custom views that draw complex
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700552 * content to report themselves as a tree of virtual views, thus conveying their
Svetoslav Ganov02107852011-10-03 17:06:56 -0700553 * logical structure.
554 * </p>
555 * <p>
556 * <strong>Note:</strong> Cannot be called from an
557 * {@link android.accessibilityservice.AccessibilityService}.
558 * This class is made immutable before being delivered to an AccessibilityService.
559 * </p>
560 *
561 * @param root The root of the virtual subtree.
562 * @param virtualDescendantId The id of the virtual descendant.
563 */
564 public void setSource(View root, int virtualDescendantId) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700565 enforceNotSealed();
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800566 mWindowId = (root != null) ? root.getAccessibilityWindowId() : UNDEFINED;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700567 final int rootAccessibilityViewId =
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800568 (root != null) ? root.getAccessibilityViewId() : UNDEFINED;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700569 mSourceNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700570 }
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700571
Svetoslav Ganov42138042012-03-20 11:51:39 -0700572 /**
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700573 * Find the view that has the specified focus type. The search starts from
Svetoslav Ganov42138042012-03-20 11:51:39 -0700574 * the view represented by this node info.
575 *
576 * @param focus The focus to find. One of {@link #FOCUS_INPUT} or
577 * {@link #FOCUS_ACCESSIBILITY}.
578 * @return The node info of the focused view or null.
579 *
580 * @see #FOCUS_INPUT
581 * @see #FOCUS_ACCESSIBILITY
582 */
583 public AccessibilityNodeInfo findFocus(int focus) {
584 enforceSealed();
Svetoslav Ganov2ef69052012-06-04 08:55:16 -0700585 enforceValidFocusType(focus);
Svetoslav Ganov42138042012-03-20 11:51:39 -0700586 if (!canPerformRequestOverConnection(mSourceNodeId)) {
587 return null;
588 }
589 return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId, mWindowId,
590 mSourceNodeId, focus);
591 }
592
593 /**
594 * Searches for the nearest view in the specified direction that can take
595 * the input focus.
596 *
597 * @param direction The direction. Can be one of:
598 * {@link View#FOCUS_DOWN},
599 * {@link View#FOCUS_UP},
600 * {@link View#FOCUS_LEFT},
601 * {@link View#FOCUS_RIGHT},
602 * {@link View#FOCUS_FORWARD},
Svetoslav Ganov8ffe8b32012-06-15 10:31:31 -0700603 * {@link View#FOCUS_BACKWARD}.
Svetoslav Ganov42138042012-03-20 11:51:39 -0700604 *
605 * @return The node info for the view that can take accessibility focus.
606 */
607 public AccessibilityNodeInfo focusSearch(int direction) {
608 enforceSealed();
Svetoslav Ganov2ef69052012-06-04 08:55:16 -0700609 enforceValidFocusDirection(direction);
Svetoslav Ganov42138042012-03-20 11:51:39 -0700610 if (!canPerformRequestOverConnection(mSourceNodeId)) {
611 return null;
612 }
613 return AccessibilityInteractionClient.getInstance().focusSearch(mConnectionId, mWindowId,
614 mSourceNodeId, direction);
615 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700616
617 /**
618 * Gets the id of the window from which the info comes from.
619 *
620 * @return The window id.
621 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700622 public int getWindowId() {
Svetoslav Ganov02107852011-10-03 17:06:56 -0700623 return mWindowId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700624 }
625
626 /**
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800627 * Refreshes this info with the latest state of the view it represents.
628 * <p>
629 * <strong>Note:</strong> If this method returns false this info is obsolete
630 * since it represents a view that is no longer in the view tree and should
631 * be recycled.
632 * </p>
Svetoslav6254f482013-06-04 17:22:14 -0700633 *
634 * @param bypassCache Whether to bypass the cache.
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800635 * @return Whether the refresh succeeded.
Svetoslav6254f482013-06-04 17:22:14 -0700636 *
637 * @hide
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800638 */
Svetoslav6254f482013-06-04 17:22:14 -0700639 public boolean refresh(boolean bypassCache) {
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800640 enforceSealed();
641 if (!canPerformRequestOverConnection(mSourceNodeId)) {
642 return false;
643 }
644 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
645 AccessibilityNodeInfo refreshedInfo = client.findAccessibilityNodeInfoByAccessibilityId(
Svetoslav6254f482013-06-04 17:22:14 -0700646 mConnectionId, mWindowId, mSourceNodeId, bypassCache, 0);
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800647 if (refreshedInfo == null) {
648 return false;
649 }
650 init(refreshedInfo);
651 refreshedInfo.recycle();
652 return true;
653 }
654
655 /**
Svetoslav6254f482013-06-04 17:22:14 -0700656 * Refreshes this info with the latest state of the view it represents.
657 * <p>
658 * <strong>Note:</strong> If this method returns false this info is obsolete
659 * since it represents a view that is no longer in the view tree and should
660 * be recycled.
661 * </p>
662 * @return Whether the refresh succeeded.
663 */
664 public boolean refresh() {
665 return refresh(false);
666 }
667
668 /**
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800669 * @return The ids of the children.
670 *
671 * @hide
672 */
673 public SparseLongArray getChildNodeIds() {
674 return mChildNodeIds;
675 }
676
677 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700678 * Gets the number of children.
679 *
680 * @return The child count.
681 */
682 public int getChildCount() {
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800683 return mChildNodeIds.size();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700684 }
685
686 /**
687 * Get the child at given index.
688 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700689 * <strong>Note:</strong> It is a client responsibility to recycle the
690 * received info by calling {@link AccessibilityNodeInfo#recycle()}
691 * to avoid creating of multiple instances.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700692 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700693 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700694 * @param index The child index.
695 * @return The child node.
696 *
697 * @throws IllegalStateException If called outside of an AccessibilityService.
698 *
699 */
700 public AccessibilityNodeInfo getChild(int index) {
701 enforceSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -0700702 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700703 return null;
704 }
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800705 final long childId = mChildNodeIds.get(index);
Svetoslav Ganov8bd69612011-08-23 13:40:30 -0700706 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800707 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId,
Svetoslav6254f482013-06-04 17:22:14 -0700708 childId, false, FLAG_PREFETCH_DESCENDANTS);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700709 }
710
711 /**
712 * Adds a child.
713 * <p>
Svetoslav Ganov02107852011-10-03 17:06:56 -0700714 * <strong>Note:</strong> Cannot be called from an
715 * {@link android.accessibilityservice.AccessibilityService}.
716 * This class is made immutable before being delivered to an AccessibilityService.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700717 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700718 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700719 * @param child The child.
720 *
721 * @throws IllegalStateException If called from an AccessibilityService.
722 */
723 public void addChild(View child) {
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800724 addChild(child, UNDEFINED);
Svetoslav Ganov02107852011-10-03 17:06:56 -0700725 }
726
727 /**
728 * Adds a virtual child which is a descendant of the given <code>root</code>.
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700729 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
Svetoslav Ganov02107852011-10-03 17:06:56 -0700730 * is added as a child.
731 * <p>
732 * A virtual descendant is an imaginary View that is reported as a part of the view
733 * hierarchy for accessibility purposes. This enables custom views that draw complex
734 * content to report them selves as a tree of virtual views, thus conveying their
735 * logical structure.
736 * </p>
737 *
738 * @param root The root of the virtual subtree.
739 * @param virtualDescendantId The id of the virtual child.
740 */
741 public void addChild(View root, int virtualDescendantId) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700742 enforceNotSealed();
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800743 final int index = mChildNodeIds.size();
Svetoslav Ganov02107852011-10-03 17:06:56 -0700744 final int rootAccessibilityViewId =
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800745 (root != null) ? root.getAccessibilityViewId() : UNDEFINED;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700746 final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800747 mChildNodeIds.put(index, childNodeId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700748 }
749
750 /**
751 * Gets the actions that can be performed on the node.
752 *
753 * @return The bit mask of with actions.
754 *
755 * @see AccessibilityNodeInfo#ACTION_FOCUS
756 * @see AccessibilityNodeInfo#ACTION_CLEAR_FOCUS
757 * @see AccessibilityNodeInfo#ACTION_SELECT
758 * @see AccessibilityNodeInfo#ACTION_CLEAR_SELECTION
Svetoslav Ganova1dc7612012-05-10 04:14:53 -0700759 * @see AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS
760 * @see AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS
761 * @see AccessibilityNodeInfo#ACTION_CLICK
762 * @see AccessibilityNodeInfo#ACTION_LONG_CLICK
763 * @see AccessibilityNodeInfo#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
764 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
765 * @see AccessibilityNodeInfo#ACTION_NEXT_HTML_ELEMENT
766 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_HTML_ELEMENT
767 * @see AccessibilityNodeInfo#ACTION_SCROLL_FORWARD
768 * @see AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700769 */
770 public int getActions() {
771 return mActions;
772 }
773
774 /**
775 * Adds an action that can be performed on the node.
776 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700777 * <strong>Note:</strong> Cannot be called from an
778 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700779 * This class is made immutable before being delivered to an AccessibilityService.
780 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700781 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700782 * @param action The action.
783 *
784 * @throws IllegalStateException If called from an AccessibilityService.
785 */
786 public void addAction(int action) {
787 enforceNotSealed();
788 mActions |= action;
789 }
790
791 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700792 * Sets the movement granularities for traversing the text of this node.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700793 * <p>
794 * <strong>Note:</strong> Cannot be called from an
795 * {@link android.accessibilityservice.AccessibilityService}.
796 * This class is made immutable before being delivered to an AccessibilityService.
797 * </p>
798 *
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700799 * @param granularities The bit mask with granularities.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700800 *
801 * @throws IllegalStateException If called from an AccessibilityService.
802 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700803 public void setMovementGranularities(int granularities) {
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700804 enforceNotSealed();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700805 mMovementGranularities = granularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700806 }
807
808 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700809 * Gets the movement granularities for traversing the text of this node.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700810 *
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700811 * @return The bit mask with granularities.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700812 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700813 public int getMovementGranularities() {
814 return mMovementGranularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700815 }
816
817 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700818 * Performs an action on the node.
819 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700820 * <strong>Note:</strong> An action can be performed only if the request is made
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700821 * from an {@link android.accessibilityservice.AccessibilityService}.
822 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700823 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700824 * @param action The action to perform.
825 * @return True if the action was performed.
826 *
827 * @throws IllegalStateException If called outside of an AccessibilityService.
828 */
829 public boolean performAction(int action) {
830 enforceSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -0700831 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700832 return false;
833 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -0700834 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700835 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
836 action, null);
837 }
838
839 /**
840 * Performs an action on the node.
841 * <p>
842 * <strong>Note:</strong> An action can be performed only if the request is made
843 * from an {@link android.accessibilityservice.AccessibilityService}.
844 * </p>
845 *
846 * @param action The action to perform.
847 * @param arguments A bundle with additional arguments.
848 * @return True if the action was performed.
849 *
850 * @throws IllegalStateException If called outside of an AccessibilityService.
851 */
852 public boolean performAction(int action, Bundle arguments) {
853 enforceSealed();
854 if (!canPerformRequestOverConnection(mSourceNodeId)) {
855 return false;
856 }
857 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
858 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
859 action, arguments);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700860 }
861
862 /**
863 * Finds {@link AccessibilityNodeInfo}s by text. The match is case
Svetoslav Ganov86398bd2011-06-21 17:38:43 -0700864 * insensitive containment. The search is relative to this info i.e.
865 * this info is the root of the traversed tree.
Svetoslav Ganovea515ae2011-09-14 18:15:32 -0700866 *
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700867 * <p>
868 * <strong>Note:</strong> It is a client responsibility to recycle the
869 * received info by calling {@link AccessibilityNodeInfo#recycle()}
870 * to avoid creating of multiple instances.
871 * </p>
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700872 *
873 * @param text The searched text.
874 * @return A list of node info.
875 */
876 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text) {
877 enforceSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -0700878 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganov86398bd2011-06-21 17:38:43 -0700879 return Collections.emptyList();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700880 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -0700881 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganov79311c42012-01-17 20:24:26 -0800882 return client.findAccessibilityNodeInfosByText(mConnectionId, mWindowId, mSourceNodeId,
883 text);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700884 }
885
886 /**
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800887 * Finds {@link AccessibilityNodeInfo}s by the fully qualified view id's resource
888 * name where a fully qualified id is of the from "package:id/id_resource_name".
889 * For example, if the target application's package is "foo.bar" and the id
890 * resource name is "baz", the fully qualified resource id is "foo.bar:id/baz".
891 *
892 * <p>
893 * <strong>Note:</strong> It is a client responsibility to recycle the
894 * received info by calling {@link AccessibilityNodeInfo#recycle()}
895 * to avoid creating of multiple instances.
896 * </p>
897 * <p>
898 * <strong>Note:</strong> The primary usage of this API is for UI test automation
899 * and in order to report the fully qualified view id if an {@link AccessibilityNodeInfo}
900 * the client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
Svetoslav14ff9962013-01-29 03:21:37 -0800901 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800902 * </p>
903 *
904 * @param viewId The fully qualified resource name of the view id to find.
905 * @return A list of node info.
906 */
907 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId(String viewId) {
908 enforceSealed();
909 if (!canPerformRequestOverConnection(mSourceNodeId)) {
910 return Collections.emptyList();
911 }
912 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
913 return client.findAccessibilityNodeInfosByViewId(mConnectionId, mWindowId, mSourceNodeId,
914 viewId);
915 }
916
917 /**
Svetoslav Ganov00aabf72011-07-21 11:35:03 -0700918 * Gets the parent.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700919 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700920 * <strong>Note:</strong> It is a client responsibility to recycle the
921 * received info by calling {@link AccessibilityNodeInfo#recycle()}
922 * to avoid creating of multiple instances.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700923 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700924 *
Svetoslav Ganov00aabf72011-07-21 11:35:03 -0700925 * @return The parent.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700926 */
927 public AccessibilityNodeInfo getParent() {
928 enforceSealed();
Svetoslav Ganovaf0d9842011-10-26 15:29:26 -0700929 if (!canPerformRequestOverConnection(mParentNodeId)) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700930 return null;
931 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -0700932 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -0800933 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
Svetoslav6254f482013-06-04 17:22:14 -0700934 mWindowId, mParentNodeId, false, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800935 }
936
937 /**
938 * @return The parent node id.
939 *
940 * @hide
941 */
942 public long getParentNodeId() {
943 return mParentNodeId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700944 }
945
946 /**
947 * Sets the parent.
948 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700949 * <strong>Note:</strong> Cannot be called from an
950 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700951 * This class is made immutable before being delivered to an AccessibilityService.
952 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700953 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700954 * @param parent The parent.
955 *
956 * @throws IllegalStateException If called from an AccessibilityService.
957 */
958 public void setParent(View parent) {
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800959 setParent(parent, UNDEFINED);
Svetoslav Ganov02107852011-10-03 17:06:56 -0700960 }
961
962 /**
963 * Sets the parent to be a virtual descendant of the given <code>root</code>.
964 * If <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root
965 * is set as the parent.
966 * <p>
967 * A virtual descendant is an imaginary View that is reported as a part of the view
968 * hierarchy for accessibility purposes. This enables custom views that draw complex
969 * content to report them selves as a tree of virtual views, thus conveying their
970 * logical structure.
971 * </p>
972 * <p>
973 * <strong>Note:</strong> Cannot be called from an
974 * {@link android.accessibilityservice.AccessibilityService}.
975 * This class is made immutable before being delivered to an AccessibilityService.
976 * </p>
977 *
978 * @param root The root of the virtual subtree.
979 * @param virtualDescendantId The id of the virtual descendant.
980 */
981 public void setParent(View root, int virtualDescendantId) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700982 enforceNotSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -0700983 final int rootAccessibilityViewId =
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800984 (root != null) ? root.getAccessibilityViewId() : UNDEFINED;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700985 mParentNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700986 }
987
988 /**
989 * Gets the node bounds in parent coordinates.
990 *
991 * @param outBounds The output node bounds.
992 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700993 public void getBoundsInParent(Rect outBounds) {
994 outBounds.set(mBoundsInParent.left, mBoundsInParent.top,
995 mBoundsInParent.right, mBoundsInParent.bottom);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700996 }
997
998 /**
999 * Sets the node bounds in parent coordinates.
1000 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001001 * <strong>Note:</strong> Cannot be called from an
1002 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001003 * This class is made immutable before being delivered to an AccessibilityService.
1004 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001005 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001006 * @param bounds The node bounds.
1007 *
1008 * @throws IllegalStateException If called from an AccessibilityService.
1009 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001010 public void setBoundsInParent(Rect bounds) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001011 enforceNotSealed();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001012 mBoundsInParent.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
1013 }
1014
1015 /**
1016 * Gets the node bounds in screen coordinates.
1017 *
1018 * @param outBounds The output node bounds.
1019 */
1020 public void getBoundsInScreen(Rect outBounds) {
1021 outBounds.set(mBoundsInScreen.left, mBoundsInScreen.top,
1022 mBoundsInScreen.right, mBoundsInScreen.bottom);
1023 }
1024
1025 /**
1026 * Sets the node bounds in screen coordinates.
1027 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001028 * <strong>Note:</strong> Cannot be called from an
1029 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001030 * This class is made immutable before being delivered to an AccessibilityService.
1031 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001032 *
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001033 * @param bounds The node bounds.
1034 *
1035 * @throws IllegalStateException If called from an AccessibilityService.
1036 */
1037 public void setBoundsInScreen(Rect bounds) {
1038 enforceNotSealed();
1039 mBoundsInScreen.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001040 }
1041
1042 /**
1043 * Gets whether this node is checkable.
1044 *
1045 * @return True if the node is checkable.
1046 */
1047 public boolean isCheckable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001048 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001049 }
1050
1051 /**
1052 * Sets whether this node is checkable.
1053 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001054 * <strong>Note:</strong> Cannot be called from an
1055 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001056 * This class is made immutable before being delivered to an AccessibilityService.
1057 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001058 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001059 * @param checkable True if the node is checkable.
1060 *
1061 * @throws IllegalStateException If called from an AccessibilityService.
1062 */
1063 public void setCheckable(boolean checkable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001064 setBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE, checkable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001065 }
1066
1067 /**
1068 * Gets whether this node is checked.
1069 *
1070 * @return True if the node is checked.
1071 */
1072 public boolean isChecked() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001073 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001074 }
1075
1076 /**
1077 * Sets whether this node is checked.
1078 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001079 * <strong>Note:</strong> Cannot be called from an
1080 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001081 * This class is made immutable before being delivered to an AccessibilityService.
1082 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001083 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001084 * @param checked True if the node is checked.
1085 *
1086 * @throws IllegalStateException If called from an AccessibilityService.
1087 */
1088 public void setChecked(boolean checked) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001089 setBooleanProperty(BOOLEAN_PROPERTY_CHECKED, checked);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001090 }
1091
1092 /**
1093 * Gets whether this node is focusable.
1094 *
1095 * @return True if the node is focusable.
1096 */
1097 public boolean isFocusable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001098 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001099 }
1100
1101 /**
1102 * Sets whether this node is focusable.
1103 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001104 * <strong>Note:</strong> Cannot be called from an
1105 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001106 * This class is made immutable before being delivered to an AccessibilityService.
1107 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001108 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001109 * @param focusable True if the node is focusable.
1110 *
1111 * @throws IllegalStateException If called from an AccessibilityService.
1112 */
1113 public void setFocusable(boolean focusable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001114 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE, focusable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001115 }
1116
1117 /**
1118 * Gets whether this node is focused.
1119 *
1120 * @return True if the node is focused.
1121 */
1122 public boolean isFocused() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001123 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001124 }
1125
1126 /**
1127 * Sets whether this node is focused.
1128 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001129 * <strong>Note:</strong> Cannot be called from an
1130 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001131 * This class is made immutable before being delivered to an AccessibilityService.
1132 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001133 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001134 * @param focused True if the node is focused.
1135 *
1136 * @throws IllegalStateException If called from an AccessibilityService.
1137 */
1138 public void setFocused(boolean focused) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001139 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSED, focused);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001140 }
1141
1142 /**
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001143 * Sets whether this node is visible to the user.
1144 *
1145 * @return Whether the node is visible to the user.
1146 */
1147 public boolean isVisibleToUser() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001148 return getBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001149 }
1150
1151 /**
1152 * Sets whether this node is visible to the user.
1153 * <p>
1154 * <strong>Note:</strong> Cannot be called from an
1155 * {@link android.accessibilityservice.AccessibilityService}.
1156 * This class is made immutable before being delivered to an AccessibilityService.
1157 * </p>
1158 *
1159 * @param visibleToUser Whether the node is visible to the user.
1160 *
1161 * @throws IllegalStateException If called from an AccessibilityService.
1162 */
1163 public void setVisibleToUser(boolean visibleToUser) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001164 setBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER, visibleToUser);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001165 }
1166
1167 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -07001168 * Gets whether this node is accessibility focused.
1169 *
1170 * @return True if the node is accessibility focused.
1171 */
1172 public boolean isAccessibilityFocused() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001173 return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED);
Svetoslav Ganov42138042012-03-20 11:51:39 -07001174 }
1175
1176 /**
1177 * Sets whether this node is accessibility focused.
1178 * <p>
1179 * <strong>Note:</strong> Cannot be called from an
1180 * {@link android.accessibilityservice.AccessibilityService}.
1181 * This class is made immutable before being delivered to an AccessibilityService.
1182 * </p>
1183 *
1184 * @param focused True if the node is accessibility focused.
1185 *
1186 * @throws IllegalStateException If called from an AccessibilityService.
1187 */
1188 public void setAccessibilityFocused(boolean focused) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001189 setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED, focused);
Svetoslav Ganov42138042012-03-20 11:51:39 -07001190 }
1191
1192 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001193 * Gets whether this node is selected.
1194 *
1195 * @return True if the node is selected.
1196 */
1197 public boolean isSelected() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001198 return getBooleanProperty(BOOLEAN_PROPERTY_SELECTED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001199 }
1200
1201 /**
1202 * Sets whether this node is selected.
1203 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001204 * <strong>Note:</strong> Cannot be called from an
1205 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001206 * This class is made immutable before being delivered to an AccessibilityService.
1207 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001208 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001209 * @param selected True if the node is selected.
1210 *
1211 * @throws IllegalStateException If called from an AccessibilityService.
1212 */
1213 public void setSelected(boolean selected) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001214 setBooleanProperty(BOOLEAN_PROPERTY_SELECTED, selected);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001215 }
1216
1217 /**
1218 * Gets whether this node is clickable.
1219 *
1220 * @return True if the node is clickable.
1221 */
1222 public boolean isClickable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001223 return getBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001224 }
1225
1226 /**
1227 * Sets whether this node is clickable.
1228 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001229 * <strong>Note:</strong> Cannot be called from an
1230 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001231 * This class is made immutable before being delivered to an AccessibilityService.
1232 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001233 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001234 * @param clickable True if the node is clickable.
1235 *
1236 * @throws IllegalStateException If called from an AccessibilityService.
1237 */
1238 public void setClickable(boolean clickable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001239 setBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE, clickable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001240 }
1241
1242 /**
1243 * Gets whether this node is long clickable.
1244 *
1245 * @return True if the node is long clickable.
1246 */
1247 public boolean isLongClickable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001248 return getBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001249 }
1250
1251 /**
1252 * Sets whether this node is long clickable.
1253 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001254 * <strong>Note:</strong> Cannot be called from an
1255 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001256 * This class is made immutable before being delivered to an AccessibilityService.
1257 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001258 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001259 * @param longClickable True if the node is long clickable.
1260 *
1261 * @throws IllegalStateException If called from an AccessibilityService.
1262 */
1263 public void setLongClickable(boolean longClickable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001264 setBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE, longClickable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001265 }
1266
1267 /**
1268 * Gets whether this node is enabled.
1269 *
1270 * @return True if the node is enabled.
1271 */
1272 public boolean isEnabled() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001273 return getBooleanProperty(BOOLEAN_PROPERTY_ENABLED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001274 }
1275
1276 /**
1277 * Sets whether this node is enabled.
1278 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001279 * <strong>Note:</strong> Cannot be called from an
1280 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001281 * This class is made immutable before being delivered to an AccessibilityService.
1282 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001283 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001284 * @param enabled True if the node is enabled.
1285 *
1286 * @throws IllegalStateException If called from an AccessibilityService.
1287 */
1288 public void setEnabled(boolean enabled) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001289 setBooleanProperty(BOOLEAN_PROPERTY_ENABLED, enabled);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001290 }
1291
1292 /**
1293 * Gets whether this node is a password.
1294 *
1295 * @return True if the node is a password.
1296 */
1297 public boolean isPassword() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001298 return getBooleanProperty(BOOLEAN_PROPERTY_PASSWORD);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001299 }
1300
1301 /**
1302 * Sets whether this node is a password.
1303 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001304 * <strong>Note:</strong> Cannot be called from an
1305 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001306 * This class is made immutable before being delivered to an AccessibilityService.
1307 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001308 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001309 * @param password True if the node is a password.
1310 *
1311 * @throws IllegalStateException If called from an AccessibilityService.
1312 */
1313 public void setPassword(boolean password) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001314 setBooleanProperty(BOOLEAN_PROPERTY_PASSWORD, password);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001315 }
1316
1317 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -07001318 * Gets if the node is scrollable.
1319 *
1320 * @return True if the node is scrollable, false otherwise.
1321 */
1322 public boolean isScrollable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001323 return getBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE);
Svetoslav Ganova0156172011-06-26 17:55:44 -07001324 }
1325
1326 /**
1327 * Sets if the node is scrollable.
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001328 * <p>
1329 * <strong>Note:</strong> Cannot be called from an
1330 * {@link android.accessibilityservice.AccessibilityService}.
1331 * This class is made immutable before being delivered to an AccessibilityService.
1332 * </p>
Svetoslav Ganova0156172011-06-26 17:55:44 -07001333 *
1334 * @param scrollable True if the node is scrollable, false otherwise.
1335 *
1336 * @throws IllegalStateException If called from an AccessibilityService.
1337 */
1338 public void setScrollable(boolean scrollable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001339 setBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE, scrollable);
1340 }
1341
1342 /**
1343 * Gets if the node is editable.
1344 *
1345 * @return True if the node is editable, false otherwise.
1346 */
1347 public boolean isEditable() {
1348 return getBooleanProperty(BOOLEAN_PROPERTY_EDITABLE);
1349 }
1350
1351 /**
1352 * Sets whether this node is editable.
1353 * <p>
1354 * <strong>Note:</strong> Cannot be called from an
1355 * {@link android.accessibilityservice.AccessibilityService}.
1356 * This class is made immutable before being delivered to an AccessibilityService.
1357 * </p>
1358 *
1359 * @param editable True if the node is editable.
1360 *
1361 * @throws IllegalStateException If called from an AccessibilityService.
1362 */
1363 public void setEditable(boolean editable) {
1364 setBooleanProperty(BOOLEAN_PROPERTY_EDITABLE, editable);
Svetoslav Ganova0156172011-06-26 17:55:44 -07001365 }
1366
1367 /**
Svetoslav3577a282013-06-06 14:09:10 -07001368 * Gets the collection info if the node is a collection. A collection
1369 * child is always a collection item.
1370 *
1371 * @return The collection info.
1372 */
1373 public CollectionInfo getCollectionInfo() {
1374 return mCollectionInfo;
1375 }
1376
1377 /**
1378 * Sets the collection info if the node is a collection. A collection
1379 * child is always a collection item.
1380 * <p>
1381 * <strong>Note:</strong> Cannot be called from an
1382 * {@link android.accessibilityservice.AccessibilityService}.
1383 * This class is made immutable before being delivered to an AccessibilityService.
1384 * </p>
1385 *
1386 * @param collectionInfo The collection info.
1387 */
1388 public void setCollectionInfo(CollectionInfo collectionInfo) {
1389 enforceNotSealed();
1390 mCollectionInfo = collectionInfo;
1391 }
1392
1393 /**
1394 * Gets the collection item info if the node is a collection item. A collection
1395 * item is always a child of a collection.
1396 *
1397 * @return The collection item info.
1398 */
1399 public CollectionItemInfo getCollectionItemInfo() {
1400 return mCollectionItemInfo;
1401 }
1402
1403 /**
1404 * Sets the collection item info if the node is a collection item. A collection
1405 * item is always a child of a collection.
1406 * <p>
1407 * <strong>Note:</strong> Cannot be called from an
1408 * {@link android.accessibilityservice.AccessibilityService}.
1409 * This class is made immutable before being delivered to an AccessibilityService.
1410 * </p>
1411 *
1412 * @return collectionItem True if the node is an item.
1413 */
1414 public void setCollectionItemInfo(CollectionItemInfo collectionItemInfo) {
1415 enforceNotSealed();
1416 mCollectionItemInfo = collectionItemInfo;
1417 }
1418
1419 /**
1420 * Gets the range info if this node is a range.
1421 *
1422 * @return The range.
1423 */
1424 public RangeInfo getRangeInfo() {
1425 return mRangeInfo;
1426 }
1427
1428 /**
1429 * Sets the range info if this node is a range.
1430 * <p>
1431 * <strong>Note:</strong> Cannot be called from an
1432 * {@link android.accessibilityservice.AccessibilityService}.
1433 * This class is made immutable before being delivered to an AccessibilityService.
1434 * </p>
1435 *
1436 * @param rangeInfo The range info.
1437 */
1438 public void setRangeInfo(RangeInfo rangeInfo) {
1439 enforceNotSealed();
1440 mRangeInfo = rangeInfo;
1441 }
1442
1443 /**
1444 * Gets if the content of this node is invalid. For example,
1445 * a date is not well-formed.
1446 *
1447 * @return If the node content is invalid.
1448 */
1449 public boolean isContentInvalid() {
1450 return getBooleanProperty(BOOLEAN_PROPERTY_CONTENT_INVALID);
1451 }
1452
1453 /**
1454 * Sets if the content of this node is invalid. For example,
1455 * a date is not well-formed.
1456 * <p>
1457 * <strong>Note:</strong> Cannot be called from an
1458 * {@link android.accessibilityservice.AccessibilityService}.
1459 * This class is made immutable before being delivered to an AccessibilityService.
1460 * </p>
1461 *
1462 * @param contentInvalid If the node content is invalid.
1463 */
1464 public void setContentInvalid(boolean contentInvalid) {
1465 setBooleanProperty(BOOLEAN_PROPERTY_CONTENT_INVALID, contentInvalid);
1466 }
1467
1468 /**
Alan Viverette77e9a282013-09-12 17:16:09 -07001469 * Gets the node's live region mode.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07001470 * <p>
Alan Viverette77e9a282013-09-12 17:16:09 -07001471 * A live region is a node that contains information that is important for
1472 * the user and when it changes the user should be notified. For example,
1473 * in a login screen with a TextView that displays an "incorrect password"
1474 * notification, that view should be marked as a live region with mode
1475 * {@link View#ACCESSIBILITY_LIVE_REGION_POLITE}.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07001476 * <p>
Alan Viverette77e9a282013-09-12 17:16:09 -07001477 * It is the responsibility of the accessibility service to monitor
1478 * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} events indicating
1479 * changes to live region nodes and their children.
Svetoslav3577a282013-06-06 14:09:10 -07001480 *
Alan Viverette77e9a282013-09-12 17:16:09 -07001481 * @return The live region mode, or
1482 * {@link View#ACCESSIBILITY_LIVE_REGION_NONE} if the view is not a
1483 * live region.
1484 * @see android.view.View#getAccessibilityLiveRegion()
Svetoslav3577a282013-06-06 14:09:10 -07001485 */
Alan Viverette77e9a282013-09-12 17:16:09 -07001486 public int getLiveRegion() {
1487 return mLiveRegion;
Svetoslav3577a282013-06-06 14:09:10 -07001488 }
1489
1490 /**
Alan Viverette77e9a282013-09-12 17:16:09 -07001491 * Sets the node's live region mode.
Svetoslav3577a282013-06-06 14:09:10 -07001492 * <p>
Alan Viverette77e9a282013-09-12 17:16:09 -07001493 * <strong>Note:</strong> Cannot be called from an
1494 * {@link android.accessibilityservice.AccessibilityService}. This class is
1495 * made immutable before being delivered to an AccessibilityService.
Svetoslav3577a282013-06-06 14:09:10 -07001496 *
Alan Viverette77e9a282013-09-12 17:16:09 -07001497 * @param mode The live region mode, or
1498 * {@link View#ACCESSIBILITY_LIVE_REGION_NONE} if the view is not a
1499 * live region.
1500 * @see android.view.View#setAccessibilityLiveRegion(int)
Svetoslav3577a282013-06-06 14:09:10 -07001501 */
Alan Viverette77e9a282013-09-12 17:16:09 -07001502 public void setLiveRegion(int mode) {
1503 enforceNotSealed();
1504 mLiveRegion = mode;
Svetoslav3577a282013-06-06 14:09:10 -07001505 }
1506
1507 /**
1508 * Gets if the node is a multi line editable text.
1509 *
1510 * @return True if the node is multi line.
1511 */
1512 public boolean isMultiLine() {
1513 return getBooleanProperty(BOOLEAN_PROPERTY_MULTI_LINE);
1514 }
1515
1516 /**
1517 * Sets if the node is a multi line editable text.
1518 * <p>
1519 * <strong>Note:</strong> Cannot be called from an
1520 * {@link android.accessibilityservice.AccessibilityService}.
1521 * This class is made immutable before being delivered to an AccessibilityService.
1522 * </p>
1523 *
1524 * @param multiLine True if the node is multi line.
1525 */
1526 public void setMultiLine(boolean multiLine) {
Svetoslav3577a282013-06-06 14:09:10 -07001527 setBooleanProperty(BOOLEAN_PROPERTY_MULTI_LINE, multiLine);
1528 }
1529
1530 /**
1531 * Gets if this node opens a popup or a dialog.
1532 *
1533 * @return If the the node opens a popup.
1534 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07001535 public boolean canOpenPopup() {
Svetoslav3577a282013-06-06 14:09:10 -07001536 return getBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP);
1537 }
1538
1539 /**
1540 * Sets if this node opens a popup or a dialog.
1541 * <p>
1542 * <strong>Note:</strong> Cannot be called from an
1543 * {@link android.accessibilityservice.AccessibilityService}.
1544 * This class is made immutable before being delivered to an AccessibilityService.
1545 * </p>
1546 *
1547 * @param opensPopup If the the node opens a popup.
1548 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07001549 public void setCanOpenPopup(boolean opensPopup) {
1550 enforceNotSealed();
Svetoslav3577a282013-06-06 14:09:10 -07001551 setBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP, opensPopup);
1552 }
1553
1554 /**
Svetoslav3577a282013-06-06 14:09:10 -07001555 * Gets if the node can be dismissed.
1556 *
1557 * @return If the node can be dismissed.
1558 */
1559 public boolean isDismissable() {
1560 return getBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE);
1561 }
1562
1563 /**
1564 * Sets if the node can be dismissed.
1565 * <p>
1566 * <strong>Note:</strong> Cannot be called from an
1567 * {@link android.accessibilityservice.AccessibilityService}.
1568 * This class is made immutable before being delivered to an AccessibilityService.
1569 * </p>
1570 *
1571 * @param dismissable If the node can be dismissed.
1572 */
1573 public void setDismissable(boolean dismissable) {
Svetoslav3577a282013-06-06 14:09:10 -07001574 setBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE, dismissable);
1575 }
1576
1577 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001578 * Gets the package this node comes from.
1579 *
1580 * @return The package name.
1581 */
1582 public CharSequence getPackageName() {
1583 return mPackageName;
1584 }
1585
1586 /**
1587 * Sets the package this node comes from.
1588 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001589 * <strong>Note:</strong> Cannot be called from an
1590 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001591 * This class is made immutable before being delivered to an AccessibilityService.
1592 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001593 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001594 * @param packageName The package name.
1595 *
1596 * @throws IllegalStateException If called from an AccessibilityService.
1597 */
1598 public void setPackageName(CharSequence packageName) {
1599 enforceNotSealed();
1600 mPackageName = packageName;
1601 }
1602
1603 /**
1604 * Gets the class this node comes from.
1605 *
1606 * @return The class name.
1607 */
1608 public CharSequence getClassName() {
1609 return mClassName;
1610 }
1611
1612 /**
1613 * Sets the class this node comes from.
1614 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001615 * <strong>Note:</strong> Cannot be called from an
1616 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001617 * This class is made immutable before being delivered to an AccessibilityService.
1618 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001619 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001620 * @param className The class name.
1621 *
1622 * @throws IllegalStateException If called from an AccessibilityService.
1623 */
1624 public void setClassName(CharSequence className) {
1625 enforceNotSealed();
1626 mClassName = className;
1627 }
1628
1629 /**
1630 * Gets the text of this node.
1631 *
1632 * @return The text.
1633 */
1634 public CharSequence getText() {
1635 return mText;
1636 }
1637
1638 /**
1639 * Sets the text of this node.
1640 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001641 * <strong>Note:</strong> Cannot be called from an
1642 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001643 * This class is made immutable before being delivered to an AccessibilityService.
1644 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001645 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001646 * @param text The text.
1647 *
1648 * @throws IllegalStateException If called from an AccessibilityService.
1649 */
1650 public void setText(CharSequence text) {
1651 enforceNotSealed();
1652 mText = text;
1653 }
1654
1655 /**
1656 * Gets the content description of this node.
1657 *
1658 * @return The content description.
1659 */
1660 public CharSequence getContentDescription() {
1661 return mContentDescription;
1662 }
1663
1664 /**
1665 * Sets the content description of this node.
1666 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001667 * <strong>Note:</strong> Cannot be called from an
1668 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001669 * This class is made immutable before being delivered to an AccessibilityService.
1670 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001671 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001672 * @param contentDescription The content description.
1673 *
1674 * @throws IllegalStateException If called from an AccessibilityService.
1675 */
1676 public void setContentDescription(CharSequence contentDescription) {
1677 enforceNotSealed();
1678 mContentDescription = contentDescription;
1679 }
1680
1681 /**
Svetoslav Ganov33aef982012-09-13 12:49:03 -07001682 * Sets the view for which the view represented by this info serves as a
1683 * label for accessibility purposes.
1684 *
1685 * @param labeled The view for which this info serves as a label.
1686 */
1687 public void setLabelFor(View labeled) {
1688 setLabelFor(labeled, UNDEFINED);
1689 }
1690
1691 /**
1692 * Sets the view for which the view represented by this info serves as a
1693 * label for accessibility purposes. If <code>virtualDescendantId</code>
1694 * is {@link View#NO_ID} the root is set as the labeled.
1695 * <p>
1696 * A virtual descendant is an imaginary View that is reported as a part of the view
1697 * hierarchy for accessibility purposes. This enables custom views that draw complex
1698 * content to report themselves as a tree of virtual views, thus conveying their
1699 * logical structure.
1700 * </p>
1701 * <p>
1702 * <strong>Note:</strong> Cannot be called from an
1703 * {@link android.accessibilityservice.AccessibilityService}.
1704 * This class is made immutable before being delivered to an AccessibilityService.
1705 * </p>
1706 *
1707 * @param root The root whose virtual descendant serves as a label.
1708 * @param virtualDescendantId The id of the virtual descendant.
1709 */
1710 public void setLabelFor(View root, int virtualDescendantId) {
1711 enforceNotSealed();
1712 final int rootAccessibilityViewId = (root != null)
1713 ? root.getAccessibilityViewId() : UNDEFINED;
1714 mLabelForId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1715 }
1716
1717 /**
1718 * Gets the node info for which the view represented by this info serves as
1719 * a label for accessibility purposes.
1720 * <p>
1721 * <strong>Note:</strong> It is a client responsibility to recycle the
1722 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1723 * to avoid creating of multiple instances.
1724 * </p>
1725 *
1726 * @return The labeled info.
1727 */
1728 public AccessibilityNodeInfo getLabelFor() {
1729 enforceSealed();
1730 if (!canPerformRequestOverConnection(mLabelForId)) {
1731 return null;
1732 }
1733 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1734 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
Svetoslav6254f482013-06-04 17:22:14 -07001735 mWindowId, mLabelForId, false, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07001736 }
1737
1738 /**
1739 * Sets the view which serves as the label of the view represented by
1740 * this info for accessibility purposes.
1741 *
1742 * @param label The view that labels this node's source.
1743 */
1744 public void setLabeledBy(View label) {
1745 setLabeledBy(label, UNDEFINED);
1746 }
1747
1748 /**
1749 * Sets the view which serves as the label of the view represented by
1750 * this info for accessibility purposes. If <code>virtualDescendantId</code>
1751 * is {@link View#NO_ID} the root is set as the label.
1752 * <p>
1753 * A virtual descendant is an imaginary View that is reported as a part of the view
1754 * hierarchy for accessibility purposes. This enables custom views that draw complex
1755 * content to report themselves as a tree of virtual views, thus conveying their
1756 * logical structure.
1757 * </p>
1758 * <p>
1759 * <strong>Note:</strong> Cannot be called from an
1760 * {@link android.accessibilityservice.AccessibilityService}.
1761 * This class is made immutable before being delivered to an AccessibilityService.
1762 * </p>
1763 *
1764 * @param root The root whose virtual descendant labels this node's source.
1765 * @param virtualDescendantId The id of the virtual descendant.
1766 */
1767 public void setLabeledBy(View root, int virtualDescendantId) {
1768 enforceNotSealed();
1769 final int rootAccessibilityViewId = (root != null)
1770 ? root.getAccessibilityViewId() : UNDEFINED;
1771 mLabeledById = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1772 }
1773
1774 /**
1775 * Gets the node info which serves as the label of the view represented by
1776 * this info for accessibility purposes.
1777 * <p>
1778 * <strong>Note:</strong> It is a client responsibility to recycle the
1779 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1780 * to avoid creating of multiple instances.
1781 * </p>
1782 *
1783 * @return The label.
1784 */
1785 public AccessibilityNodeInfo getLabeledBy() {
1786 enforceSealed();
1787 if (!canPerformRequestOverConnection(mLabeledById)) {
1788 return null;
1789 }
1790 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1791 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
Svetoslav6254f482013-06-04 17:22:14 -07001792 mWindowId, mLabeledById, false, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07001793 }
1794
1795 /**
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001796 * Sets the fully qualified resource name of the source view's id.
1797 *
1798 * <p>
1799 * <strong>Note:</strong> Cannot be called from an
1800 * {@link android.accessibilityservice.AccessibilityService}.
1801 * This class is made immutable before being delivered to an AccessibilityService.
1802 * </p>
1803 *
Svetoslav92826452013-02-05 14:57:42 -08001804 * @param viewIdResName The id resource name.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001805 */
Svetoslav9fa1ee52013-04-22 12:43:03 -07001806 public void setViewIdResourceName(String viewIdResName) {
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001807 enforceNotSealed();
Svetoslav22431a32013-02-05 14:30:19 -08001808 mViewIdResourceName = viewIdResName;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001809 }
1810
1811 /**
1812 * Gets the fully qualified resource name of the source view's id.
1813 *
1814 * <p>
1815 * <strong>Note:</strong> The primary usage of this API is for UI test automation
1816 * and in order to report the source view id of an {@link AccessibilityNodeInfo} the
1817 * client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
Svetoslav14ff9962013-01-29 03:21:37 -08001818 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001819 * </p>
1820
1821 * @return The id resource name.
1822 */
Svetoslav9fa1ee52013-04-22 12:43:03 -07001823 public String getViewIdResourceName() {
Svetoslav22431a32013-02-05 14:30:19 -08001824 return mViewIdResourceName;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001825 }
1826
1827 /**
Svetoslavbcc46a02013-02-06 11:56:00 -08001828 * Gets the text selection start.
1829 *
1830 * @return The text selection start if there is selection or -1.
1831 */
1832 public int getTextSelectionStart() {
1833 return mTextSelectionStart;
1834 }
1835
1836 /**
1837 * Gets the text selection end.
1838 *
1839 * @return The text selection end if there is selection or -1.
1840 */
1841 public int getTextSelectionEnd() {
1842 return mTextSelectionEnd;
1843 }
1844
1845 /**
1846 * Sets the text selection start and end.
1847 * <p>
1848 * <strong>Note:</strong> Cannot be called from an
1849 * {@link android.accessibilityservice.AccessibilityService}.
1850 * This class is made immutable before being delivered to an AccessibilityService.
1851 * </p>
1852 *
1853 * @param start The text selection start.
1854 * @param end The text selection end.
1855 *
1856 * @throws IllegalStateException If called from an AccessibilityService.
1857 */
1858 public void setTextSelection(int start, int end) {
1859 enforceNotSealed();
1860 mTextSelectionStart = start;
1861 mTextSelectionEnd = end;
1862 }
1863
1864 /**
Svetoslav6254f482013-06-04 17:22:14 -07001865 * Gets the input type of the source as defined by {@link InputType}.
1866 *
1867 * @return The input type.
1868 */
1869 public int getInputType() {
1870 return mInputType;
1871 }
1872
1873 /**
1874 * Sets the input type of the source as defined by {@link InputType}.
1875 * <p>
1876 * <strong>Note:</strong> Cannot be called from an
1877 * {@link android.accessibilityservice.AccessibilityService}.
1878 * This class is made immutable before being delivered to an
1879 * AccessibilityService.
1880 * </p>
1881 *
1882 * @param inputType The input type.
1883 *
1884 * @throws IllegalStateException If called from an AccessibilityService.
1885 */
1886 public void setInputType(int inputType) {
Alan Viverettedf39cb92013-08-19 12:28:04 -07001887 enforceNotSealed();
Svetoslav6254f482013-06-04 17:22:14 -07001888 mInputType = inputType;
1889 }
1890
1891 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07001892 * Gets an optional bundle with extra data. The bundle
Svetoslav6254f482013-06-04 17:22:14 -07001893 * is lazily created and never <code>null</code>.
1894 * <p>
1895 * <strong>Note:</strong> It is recommended to use the package
1896 * name of your application as a prefix for the keys to avoid
1897 * collisions which may confuse an accessibility service if the
1898 * same key has different meaning when emitted from different
1899 * applications.
1900 * </p>
1901 *
1902 * @return The bundle.
1903 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07001904 public Bundle getExtras() {
1905 if (mExtras == null) {
1906 mExtras = new Bundle();
Svetoslav6254f482013-06-04 17:22:14 -07001907 }
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07001908 return mExtras;
Svetoslav6254f482013-06-04 17:22:14 -07001909 }
1910
1911 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001912 * Gets the value of a boolean property.
1913 *
1914 * @param property The property.
1915 * @return The value.
1916 */
1917 private boolean getBooleanProperty(int property) {
1918 return (mBooleanProperties & property) != 0;
1919 }
1920
1921 /**
1922 * Sets a boolean property.
1923 *
1924 * @param property The property.
1925 * @param value The value.
1926 *
1927 * @throws IllegalStateException If called from an AccessibilityService.
1928 */
1929 private void setBooleanProperty(int property, boolean value) {
1930 enforceNotSealed();
1931 if (value) {
1932 mBooleanProperties |= property;
1933 } else {
1934 mBooleanProperties &= ~property;
1935 }
1936 }
1937
1938 /**
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08001939 * Sets the unique id of the IAccessibilityServiceConnection over which
1940 * this instance can send requests to the system.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001941 *
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08001942 * @param connectionId The connection id.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001943 *
1944 * @hide
1945 */
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08001946 public void setConnectionId(int connectionId) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001947 enforceNotSealed();
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08001948 mConnectionId = connectionId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001949 }
1950
1951 /**
1952 * {@inheritDoc}
1953 */
1954 public int describeContents() {
1955 return 0;
1956 }
1957
1958 /**
Svetoslav Ganov79311c42012-01-17 20:24:26 -08001959 * Gets the id of the source node.
1960 *
1961 * @return The id.
1962 *
1963 * @hide
1964 */
1965 public long getSourceNodeId() {
1966 return mSourceNodeId;
1967 }
1968
1969 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001970 * Sets if this instance is sealed.
1971 *
1972 * @param sealed Whether is sealed.
1973 *
1974 * @hide
1975 */
1976 public void setSealed(boolean sealed) {
1977 mSealed = sealed;
1978 }
1979
1980 /**
1981 * Gets if this instance is sealed.
1982 *
1983 * @return Whether is sealed.
1984 *
1985 * @hide
1986 */
1987 public boolean isSealed() {
1988 return mSealed;
1989 }
1990
1991 /**
1992 * Enforces that this instance is sealed.
1993 *
1994 * @throws IllegalStateException If this instance is not sealed.
1995 *
1996 * @hide
1997 */
1998 protected void enforceSealed() {
1999 if (!isSealed()) {
2000 throw new IllegalStateException("Cannot perform this "
2001 + "action on a not sealed instance.");
2002 }
2003 }
2004
Svetoslav Ganov2ef69052012-06-04 08:55:16 -07002005 private void enforceValidFocusDirection(int direction) {
2006 switch (direction) {
2007 case View.FOCUS_DOWN:
2008 case View.FOCUS_UP:
2009 case View.FOCUS_LEFT:
2010 case View.FOCUS_RIGHT:
2011 case View.FOCUS_FORWARD:
2012 case View.FOCUS_BACKWARD:
Svetoslav Ganov2ef69052012-06-04 08:55:16 -07002013 return;
2014 default:
2015 throw new IllegalArgumentException("Unknown direction: " + direction);
2016 }
2017 }
2018
2019 private void enforceValidFocusType(int focusType) {
2020 switch (focusType) {
2021 case FOCUS_INPUT:
2022 case FOCUS_ACCESSIBILITY:
2023 return;
2024 default:
2025 throw new IllegalArgumentException("Unknown focus type: " + focusType);
2026 }
2027 }
2028
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002029 /**
2030 * Enforces that this instance is not sealed.
2031 *
2032 * @throws IllegalStateException If this instance is sealed.
2033 *
2034 * @hide
2035 */
2036 protected void enforceNotSealed() {
2037 if (isSealed()) {
2038 throw new IllegalStateException("Cannot perform this "
Ken Wakasaf76a50c2012-03-09 19:56:35 +09002039 + "action on a sealed instance.");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002040 }
2041 }
2042
2043 /**
2044 * Returns a cached instance if such is available otherwise a new one
2045 * and sets the source.
2046 *
Svetoslav Ganov02107852011-10-03 17:06:56 -07002047 * @param source The source view.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002048 * @return An instance.
2049 *
2050 * @see #setSource(View)
2051 */
2052 public static AccessibilityNodeInfo obtain(View source) {
2053 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
2054 info.setSource(source);
2055 return info;
2056 }
2057
2058 /**
Svetoslav Ganov02107852011-10-03 17:06:56 -07002059 * Returns a cached instance if such is available otherwise a new one
2060 * and sets the source.
2061 *
2062 * @param root The root of the virtual subtree.
2063 * @param virtualDescendantId The id of the virtual descendant.
2064 * @return An instance.
2065 *
2066 * @see #setSource(View, int)
2067 */
2068 public static AccessibilityNodeInfo obtain(View root, int virtualDescendantId) {
2069 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
2070 info.setSource(root, virtualDescendantId);
2071 return info;
2072 }
2073
2074 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002075 * Returns a cached instance if such is available otherwise a new one.
2076 *
2077 * @return An instance.
2078 */
2079 public static AccessibilityNodeInfo obtain() {
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -08002080 AccessibilityNodeInfo info = sPool.acquire();
2081 return (info != null) ? info : new AccessibilityNodeInfo();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002082 }
2083
2084 /**
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07002085 * Returns a cached instance if such is available or a new one is
2086 * create. The returned instance is initialized from the given
2087 * <code>info</code>.
2088 *
2089 * @param info The other info.
2090 * @return An instance.
2091 */
2092 public static AccessibilityNodeInfo obtain(AccessibilityNodeInfo info) {
2093 AccessibilityNodeInfo infoClone = AccessibilityNodeInfo.obtain();
2094 infoClone.init(info);
2095 return infoClone;
2096 }
2097
2098 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002099 * Return an instance back to be reused.
2100 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002101 * <strong>Note:</strong> You must not touch the object after calling this function.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002102 *
2103 * @throws IllegalStateException If the info is already recycled.
2104 */
2105 public void recycle() {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002106 clear();
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -08002107 sPool.release(this);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002108 }
2109
2110 /**
2111 * {@inheritDoc}
2112 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002113 * <strong>Note:</strong> After the instance is written to a parcel it
2114 * is recycled. You must not touch the object after calling this function.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002115 * </p>
2116 */
2117 public void writeToParcel(Parcel parcel, int flags) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002118 parcel.writeInt(isSealed() ? 1 : 0);
Svetoslav Ganov02107852011-10-03 17:06:56 -07002119 parcel.writeLong(mSourceNodeId);
2120 parcel.writeInt(mWindowId);
2121 parcel.writeLong(mParentNodeId);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002122 parcel.writeLong(mLabelForId);
2123 parcel.writeLong(mLabeledById);
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002124 parcel.writeInt(mConnectionId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002125
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -08002126 SparseLongArray childIds = mChildNodeIds;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002127 final int childIdsSize = childIds.size();
2128 parcel.writeInt(childIdsSize);
2129 for (int i = 0; i < childIdsSize; i++) {
Svetoslav Ganov02107852011-10-03 17:06:56 -07002130 parcel.writeLong(childIds.valueAt(i));
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002131 }
2132
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002133 parcel.writeInt(mBoundsInParent.top);
2134 parcel.writeInt(mBoundsInParent.bottom);
2135 parcel.writeInt(mBoundsInParent.left);
2136 parcel.writeInt(mBoundsInParent.right);
2137
2138 parcel.writeInt(mBoundsInScreen.top);
2139 parcel.writeInt(mBoundsInScreen.bottom);
2140 parcel.writeInt(mBoundsInScreen.left);
2141 parcel.writeInt(mBoundsInScreen.right);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002142
2143 parcel.writeInt(mActions);
2144
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002145 parcel.writeInt(mMovementGranularities);
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002146
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002147 parcel.writeInt(mBooleanProperties);
2148
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002149 parcel.writeCharSequence(mPackageName);
2150 parcel.writeCharSequence(mClassName);
2151 parcel.writeCharSequence(mText);
2152 parcel.writeCharSequence(mContentDescription);
Svetoslav9fa1ee52013-04-22 12:43:03 -07002153 parcel.writeString(mViewIdResourceName);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002154
Svetoslavbcc46a02013-02-06 11:56:00 -08002155 parcel.writeInt(mTextSelectionStart);
2156 parcel.writeInt(mTextSelectionEnd);
Svetoslav6254f482013-06-04 17:22:14 -07002157 parcel.writeInt(mInputType);
Alan Viverette77e9a282013-09-12 17:16:09 -07002158 parcel.writeInt(mLiveRegion);
Svetoslav6254f482013-06-04 17:22:14 -07002159
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002160 if (mExtras != null) {
Svetoslav6254f482013-06-04 17:22:14 -07002161 parcel.writeInt(1);
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002162 parcel.writeBundle(mExtras);
Svetoslav6254f482013-06-04 17:22:14 -07002163 } else {
2164 parcel.writeInt(0);
2165 }
Svetoslavbcc46a02013-02-06 11:56:00 -08002166
Svetoslav3577a282013-06-06 14:09:10 -07002167 if (mRangeInfo != null) {
2168 parcel.writeInt(1);
2169 parcel.writeInt(mRangeInfo.getType());
2170 parcel.writeFloat(mRangeInfo.getMin());
2171 parcel.writeFloat(mRangeInfo.getMax());
2172 parcel.writeFloat(mRangeInfo.getCurrent());
2173 } else {
2174 parcel.writeInt(0);
2175 }
2176
2177 if (mCollectionInfo != null) {
2178 parcel.writeInt(1);
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002179 parcel.writeInt(mCollectionInfo.getRowCount());
2180 parcel.writeInt(mCollectionInfo.getColumnCount());
Svetoslav3577a282013-06-06 14:09:10 -07002181 parcel.writeInt(mCollectionInfo.isHierarchical() ? 1 : 0);
2182 } else {
2183 parcel.writeInt(0);
2184 }
2185
2186 if (mCollectionItemInfo != null) {
2187 parcel.writeInt(1);
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002188 parcel.writeInt(mCollectionItemInfo.getColumnIndex());
2189 parcel.writeInt(mCollectionItemInfo.getColumnSpan());
2190 parcel.writeInt(mCollectionItemInfo.getRowIndex());
2191 parcel.writeInt(mCollectionItemInfo.getRowSpan());
Svetoslav3577a282013-06-06 14:09:10 -07002192 parcel.writeInt(mCollectionItemInfo.isHeading() ? 1 : 0);
2193 } else {
2194 parcel.writeInt(0);
2195 }
2196
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002197 // Since instances of this class are fetched via synchronous i.e. blocking
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002198 // calls in IPCs we always recycle as soon as the instance is marshaled.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002199 recycle();
2200 }
2201
2202 /**
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07002203 * Initializes this instance from another one.
2204 *
2205 * @param other The other instance.
2206 */
2207 private void init(AccessibilityNodeInfo other) {
2208 mSealed = other.mSealed;
Svetoslav Ganov02107852011-10-03 17:06:56 -07002209 mSourceNodeId = other.mSourceNodeId;
2210 mParentNodeId = other.mParentNodeId;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002211 mLabelForId = other.mLabelForId;
2212 mLabeledById = other.mLabeledById;
Svetoslav Ganov02107852011-10-03 17:06:56 -07002213 mWindowId = other.mWindowId;
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002214 mConnectionId = other.mConnectionId;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07002215 mBoundsInParent.set(other.mBoundsInParent);
2216 mBoundsInScreen.set(other.mBoundsInScreen);
2217 mPackageName = other.mPackageName;
2218 mClassName = other.mClassName;
2219 mText = other.mText;
2220 mContentDescription = other.mContentDescription;
Svetoslav22431a32013-02-05 14:30:19 -08002221 mViewIdResourceName = other.mViewIdResourceName;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07002222 mActions= other.mActions;
2223 mBooleanProperties = other.mBooleanProperties;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002224 mMovementGranularities = other.mMovementGranularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002225 final int otherChildIdCount = other.mChildNodeIds.size();
2226 for (int i = 0; i < otherChildIdCount; i++) {
Svetoslav3577a282013-06-06 14:09:10 -07002227 mChildNodeIds.put(i, other.mChildNodeIds.valueAt(i));
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002228 }
Svetoslavbcc46a02013-02-06 11:56:00 -08002229 mTextSelectionStart = other.mTextSelectionStart;
2230 mTextSelectionEnd = other.mTextSelectionEnd;
Svetoslav6254f482013-06-04 17:22:14 -07002231 mInputType = other.mInputType;
Alan Viverette77e9a282013-09-12 17:16:09 -07002232 mLiveRegion = other.mLiveRegion;
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002233 if (other.mExtras != null && !other.mExtras.isEmpty()) {
2234 getExtras().putAll(other.mExtras);
Svetoslav6254f482013-06-04 17:22:14 -07002235 }
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07002236 mRangeInfo = (other.mRangeInfo != null)
2237 ? RangeInfo.obtain(other.mRangeInfo) : null;
2238 mCollectionInfo = (other.mCollectionInfo != null)
2239 ? CollectionInfo.obtain(other.mCollectionInfo) : null;
2240 mCollectionItemInfo = (other.mCollectionItemInfo != null)
2241 ? CollectionItemInfo.obtain(other.mCollectionItemInfo) : null;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07002242 }
2243
2244 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002245 * Creates a new instance from a {@link Parcel}.
2246 *
2247 * @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}.
2248 */
2249 private void initFromParcel(Parcel parcel) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002250 mSealed = (parcel.readInt() == 1);
Svetoslav Ganov02107852011-10-03 17:06:56 -07002251 mSourceNodeId = parcel.readLong();
2252 mWindowId = parcel.readInt();
2253 mParentNodeId = parcel.readLong();
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002254 mLabelForId = parcel.readLong();
2255 mLabeledById = parcel.readLong();
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002256 mConnectionId = parcel.readInt();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002257
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -08002258 SparseLongArray childIds = mChildNodeIds;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002259 final int childrenSize = parcel.readInt();
2260 for (int i = 0; i < childrenSize; i++) {
Svetoslav Ganov02107852011-10-03 17:06:56 -07002261 final long childId = parcel.readLong();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002262 childIds.put(i, childId);
2263 }
2264
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002265 mBoundsInParent.top = parcel.readInt();
2266 mBoundsInParent.bottom = parcel.readInt();
2267 mBoundsInParent.left = parcel.readInt();
2268 mBoundsInParent.right = parcel.readInt();
2269
2270 mBoundsInScreen.top = parcel.readInt();
2271 mBoundsInScreen.bottom = parcel.readInt();
2272 mBoundsInScreen.left = parcel.readInt();
2273 mBoundsInScreen.right = parcel.readInt();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002274
2275 mActions = parcel.readInt();
2276
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002277 mMovementGranularities = parcel.readInt();
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002278
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002279 mBooleanProperties = parcel.readInt();
2280
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002281 mPackageName = parcel.readCharSequence();
2282 mClassName = parcel.readCharSequence();
2283 mText = parcel.readCharSequence();
2284 mContentDescription = parcel.readCharSequence();
Svetoslav9fa1ee52013-04-22 12:43:03 -07002285 mViewIdResourceName = parcel.readString();
Svetoslavbcc46a02013-02-06 11:56:00 -08002286
2287 mTextSelectionStart = parcel.readInt();
2288 mTextSelectionEnd = parcel.readInt();
Svetoslav3577a282013-06-06 14:09:10 -07002289
Svetoslav6254f482013-06-04 17:22:14 -07002290 mInputType = parcel.readInt();
Alan Viverette77e9a282013-09-12 17:16:09 -07002291 mLiveRegion = parcel.readInt();
Svetoslav6254f482013-06-04 17:22:14 -07002292
2293 if (parcel.readInt() == 1) {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002294 getExtras().putAll(parcel.readBundle());
Svetoslav6254f482013-06-04 17:22:14 -07002295 }
Svetoslav3577a282013-06-06 14:09:10 -07002296
2297 if (parcel.readInt() == 1) {
2298 mRangeInfo = RangeInfo.obtain(
2299 parcel.readInt(),
2300 parcel.readFloat(),
2301 parcel.readFloat(),
2302 parcel.readFloat());
2303 }
2304
2305 if (parcel.readInt() == 1) {
2306 mCollectionInfo = CollectionInfo.obtain(
2307 parcel.readInt(),
2308 parcel.readInt(),
2309 parcel.readInt() == 1);
2310 }
2311
2312 if (parcel.readInt() == 1) {
2313 mCollectionItemInfo = CollectionItemInfo.obtain(
2314 parcel.readInt(),
2315 parcel.readInt(),
2316 parcel.readInt(),
2317 parcel.readInt(),
2318 parcel.readInt() == 1);
2319 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002320 }
2321
2322 /**
2323 * Clears the state of this instance.
2324 */
2325 private void clear() {
2326 mSealed = false;
Svetoslav Ganov0d04e242012-02-21 13:46:36 -08002327 mSourceNodeId = ROOT_NODE_ID;
2328 mParentNodeId = ROOT_NODE_ID;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002329 mLabelForId = ROOT_NODE_ID;
2330 mLabeledById = ROOT_NODE_ID;
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -08002331 mWindowId = UNDEFINED;
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002332 mConnectionId = UNDEFINED;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002333 mMovementGranularities = 0;
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -08002334 mChildNodeIds.clear();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002335 mBoundsInParent.set(0, 0, 0, 0);
2336 mBoundsInScreen.set(0, 0, 0, 0);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002337 mBooleanProperties = 0;
2338 mPackageName = null;
2339 mClassName = null;
2340 mText = null;
2341 mContentDescription = null;
Svetoslav22431a32013-02-05 14:30:19 -08002342 mViewIdResourceName = null;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002343 mActions = 0;
Svetoslavbcc46a02013-02-06 11:56:00 -08002344 mTextSelectionStart = UNDEFINED;
2345 mTextSelectionEnd = UNDEFINED;
Svetoslav6254f482013-06-04 17:22:14 -07002346 mInputType = InputType.TYPE_NULL;
Alan Viverette77e9a282013-09-12 17:16:09 -07002347 mLiveRegion = View.ACCESSIBILITY_LIVE_REGION_NONE;
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002348 if (mExtras != null) {
2349 mExtras.clear();
Svetoslav6254f482013-06-04 17:22:14 -07002350 }
Svetoslav3577a282013-06-06 14:09:10 -07002351 if (mRangeInfo != null) {
2352 mRangeInfo.recycle();
2353 mRangeInfo = null;
2354 }
2355 if (mCollectionInfo != null) {
2356 mCollectionInfo.recycle();
2357 mCollectionInfo = null;
2358 }
2359 if (mCollectionItemInfo != null) {
2360 mCollectionItemInfo.recycle();
2361 mCollectionItemInfo = null;
2362 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002363 }
2364
2365 /**
2366 * Gets the human readable action symbolic name.
2367 *
2368 * @param action The action.
2369 * @return The symbolic name.
2370 */
2371 private static String getActionSymbolicName(int action) {
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002372 switch (action) {
2373 case ACTION_FOCUS:
2374 return "ACTION_FOCUS";
2375 case ACTION_CLEAR_FOCUS:
2376 return "ACTION_CLEAR_FOCUS";
2377 case ACTION_SELECT:
2378 return "ACTION_SELECT";
2379 case ACTION_CLEAR_SELECTION:
2380 return "ACTION_CLEAR_SELECTION";
Svetoslav Ganove9bda152012-04-30 16:55:21 -07002381 case ACTION_CLICK:
2382 return "ACTION_CLICK";
2383 case ACTION_LONG_CLICK:
2384 return "ACTION_LONG_CLICK";
2385 case ACTION_ACCESSIBILITY_FOCUS:
2386 return "ACTION_ACCESSIBILITY_FOCUS";
2387 case ACTION_CLEAR_ACCESSIBILITY_FOCUS:
2388 return "ACTION_CLEAR_ACCESSIBILITY_FOCUS";
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002389 case ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
2390 return "ACTION_NEXT_AT_MOVEMENT_GRANULARITY";
2391 case ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY:
2392 return "ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY";
Svetoslav Ganove9bda152012-04-30 16:55:21 -07002393 case ACTION_NEXT_HTML_ELEMENT:
2394 return "ACTION_NEXT_HTML_ELEMENT";
2395 case ACTION_PREVIOUS_HTML_ELEMENT:
2396 return "ACTION_PREVIOUS_HTML_ELEMENT";
Svetoslav Ganova1dc7612012-05-10 04:14:53 -07002397 case ACTION_SCROLL_FORWARD:
2398 return "ACTION_SCROLL_FORWARD";
2399 case ACTION_SCROLL_BACKWARD:
2400 return "ACTION_SCROLL_BACKWARD";
Svetoslav Ganov242724e2013-02-01 14:42:18 -08002401 case ACTION_CUT:
2402 return "ACTION_CUT";
2403 case ACTION_COPY:
2404 return "ACTION_COPY";
2405 case ACTION_PASTE:
2406 return "ACTION_PASTE";
2407 case ACTION_SET_SELECTION:
2408 return "ACTION_SET_SELECTION";
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002409 default:
Svetoslav Ganov242724e2013-02-01 14:42:18 -08002410 return"ACTION_UNKNOWN";
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002411 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002412 }
2413
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002414 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002415 * Gets the human readable movement granularity symbolic name.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002416 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002417 * @param granularity The granularity.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002418 * @return The symbolic name.
2419 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002420 private static String getMovementGranularitySymbolicName(int granularity) {
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002421 switch (granularity) {
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002422 case MOVEMENT_GRANULARITY_CHARACTER:
2423 return "MOVEMENT_GRANULARITY_CHARACTER";
2424 case MOVEMENT_GRANULARITY_WORD:
2425 return "MOVEMENT_GRANULARITY_WORD";
2426 case MOVEMENT_GRANULARITY_LINE:
2427 return "MOVEMENT_GRANULARITY_LINE";
2428 case MOVEMENT_GRANULARITY_PARAGRAPH:
2429 return "MOVEMENT_GRANULARITY_PARAGRAPH";
2430 case MOVEMENT_GRANULARITY_PAGE:
2431 return "MOVEMENT_GRANULARITY_PAGE";
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002432 default:
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002433 throw new IllegalArgumentException("Unknown movement granularity: " + granularity);
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002434 }
2435 }
2436
Svetoslav Ganov02107852011-10-03 17:06:56 -07002437 private boolean canPerformRequestOverConnection(long accessibilityNodeId) {
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -08002438 return (mWindowId != UNDEFINED
2439 && getAccessibilityViewId(accessibilityNodeId) != UNDEFINED
2440 && mConnectionId != UNDEFINED);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002441 }
2442
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002443 @Override
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07002444 public boolean equals(Object object) {
2445 if (this == object) {
2446 return true;
2447 }
2448 if (object == null) {
2449 return false;
2450 }
2451 if (getClass() != object.getClass()) {
2452 return false;
2453 }
2454 AccessibilityNodeInfo other = (AccessibilityNodeInfo) object;
Svetoslav Ganov02107852011-10-03 17:06:56 -07002455 if (mSourceNodeId != other.mSourceNodeId) {
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07002456 return false;
2457 }
Svetoslav Ganov02107852011-10-03 17:06:56 -07002458 if (mWindowId != other.mWindowId) {
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07002459 return false;
2460 }
2461 return true;
2462 }
2463
2464 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002465 public int hashCode() {
2466 final int prime = 31;
2467 int result = 1;
Svetoslav Ganov02107852011-10-03 17:06:56 -07002468 result = prime * result + getAccessibilityViewId(mSourceNodeId);
2469 result = prime * result + getVirtualDescendantId(mSourceNodeId);
2470 result = prime * result + mWindowId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002471 return result;
2472 }
2473
2474 @Override
2475 public String toString() {
2476 StringBuilder builder = new StringBuilder();
2477 builder.append(super.toString());
2478
2479 if (DEBUG) {
Svetoslav Ganov02107852011-10-03 17:06:56 -07002480 builder.append("; accessibilityViewId: " + getAccessibilityViewId(mSourceNodeId));
2481 builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId));
2482 builder.append("; mParentNodeId: " + mParentNodeId);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002483
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002484 int granularities = mMovementGranularities;
2485 builder.append("; MovementGranularities: [");
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002486 while (granularities != 0) {
2487 final int granularity = 1 << Integer.numberOfTrailingZeros(granularities);
2488 granularities &= ~granularity;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002489 builder.append(getMovementGranularitySymbolicName(granularity));
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002490 if (granularities != 0) {
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002491 builder.append(", ");
2492 }
2493 }
2494 builder.append("]");
2495
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -08002496 SparseLongArray childIds = mChildNodeIds;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002497 builder.append("; childAccessibilityIds: [");
2498 for (int i = 0, count = childIds.size(); i < count; i++) {
2499 builder.append(childIds.valueAt(i));
2500 if (i < count - 1) {
2501 builder.append(", ");
2502 }
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002503 }
2504 builder.append("]");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002505 }
2506
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002507 builder.append("; boundsInParent: " + mBoundsInParent);
2508 builder.append("; boundsInScreen: " + mBoundsInScreen);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002509
2510 builder.append("; packageName: ").append(mPackageName);
2511 builder.append("; className: ").append(mClassName);
2512 builder.append("; text: ").append(mText);
2513 builder.append("; contentDescription: ").append(mContentDescription);
Svetoslav22431a32013-02-05 14:30:19 -08002514 builder.append("; viewIdResName: ").append(mViewIdResourceName);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002515
2516 builder.append("; checkable: ").append(isCheckable());
2517 builder.append("; checked: ").append(isChecked());
2518 builder.append("; focusable: ").append(isFocusable());
2519 builder.append("; focused: ").append(isFocused());
2520 builder.append("; selected: ").append(isSelected());
2521 builder.append("; clickable: ").append(isClickable());
2522 builder.append("; longClickable: ").append(isLongClickable());
2523 builder.append("; enabled: ").append(isEnabled());
2524 builder.append("; password: ").append(isPassword());
Svetoslav Ganova0156172011-06-26 17:55:44 -07002525 builder.append("; scrollable: " + isScrollable());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002526
2527 builder.append("; [");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002528 for (int actionBits = mActions; actionBits != 0;) {
2529 final int action = 1 << Integer.numberOfTrailingZeros(actionBits);
2530 actionBits &= ~action;
2531 builder.append(getActionSymbolicName(action));
2532 if (actionBits != 0) {
2533 builder.append(", ");
2534 }
2535 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002536 builder.append("]");
2537
2538 return builder.toString();
2539 }
2540
2541 /**
Svetoslav3577a282013-06-06 14:09:10 -07002542 * Class with information if a node is a range. Use
Scott Main96844ed2013-10-18 14:43:02 -07002543 * {@link RangeInfo#obtain(int, float, float, float)} to get an instance.
Svetoslav3577a282013-06-06 14:09:10 -07002544 */
2545 public static final class RangeInfo {
2546 private static final int MAX_POOL_SIZE = 10;
2547
2548 /** Range type: integer. */
2549 public static final int RANGE_TYPE_INT = 0;
2550 /** Range type: float. */
2551 public static final int RANGE_TYPE_FLOAT = 1;
2552 /** Range type: percent with values from zero to one.*/
2553 public static final int RANGE_TYPE_PERCENT = 2;
2554
2555 private static final SynchronizedPool<RangeInfo> sPool =
2556 new SynchronizedPool<AccessibilityNodeInfo.RangeInfo>(MAX_POOL_SIZE);
2557
2558 private int mType;
2559 private float mMin;
2560 private float mMax;
2561 private float mCurrent;
2562
2563 /**
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07002564 * Obtains a pooled instance that is a clone of another one.
2565 *
2566 * @param other The instance to clone.
2567 *
2568 * @hide
2569 */
2570 public static RangeInfo obtain(RangeInfo other) {
2571 return obtain(other.mType, other.mMin, other.mMax, other.mCurrent);
2572 }
2573
2574 /**
Svetoslav3577a282013-06-06 14:09:10 -07002575 * Obtains a pooled instance.
2576 *
2577 * @param type The type of the range.
2578 * @param min The min value.
2579 * @param max The max value.
2580 * @param current The current value.
2581 */
2582 public static RangeInfo obtain(int type, float min, float max, float current) {
2583 RangeInfo info = sPool.acquire();
2584 return (info != null) ? info : new RangeInfo(type, min, max, current);
2585 }
2586
2587 /**
2588 * Creates a new range.
2589 *
2590 * @param type The type of the range.
2591 * @param min The min value.
2592 * @param max The max value.
2593 * @param current The current value.
2594 */
2595 private RangeInfo(int type, float min, float max, float current) {
2596 mType = type;
2597 mMin = min;
2598 mMax = max;
2599 mCurrent = current;
2600 }
2601
2602 /**
2603 * Gets the range type.
2604 *
2605 * @return The range type.
2606 *
2607 * @see #RANGE_TYPE_INT
2608 * @see #RANGE_TYPE_FLOAT
2609 * @see #RANGE_TYPE_PERCENT
2610 */
2611 public int getType() {
2612 return mType;
2613 }
2614
2615 /**
2616 * Gets the min value.
2617 *
2618 * @return The min value.
2619 */
2620 public float getMin() {
2621 return mMin;
2622 }
2623
2624 /**
2625 * Gets the max value.
2626 *
2627 * @return The max value.
2628 */
2629 public float getMax() {
2630 return mMax;
2631 }
2632
2633 /**
2634 * Gets the current value.
2635 *
2636 * @return The current value.
2637 */
2638 public float getCurrent() {
2639 return mCurrent;
2640 }
2641
2642 /**
2643 * Recycles this instance.
2644 */
2645 void recycle() {
2646 clear();
2647 sPool.release(this);
2648 }
2649
2650 private void clear() {
2651 mType = 0;
2652 mMin = 0;
2653 mMax = 0;
2654 mCurrent = 0;
2655 }
2656 }
2657
2658 /**
2659 * Class with information if a node is a collection. Use
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002660 * {@link CollectionInfo#obtain(int, int, boolean)} to get an instance.
2661 * <p>
2662 * A collection of items has rows and columns and may be hierarchical.
2663 * For example, a horizontal list is a collection with one column, as
2664 * many rows as the list items, and is not hierarchical; A table is a
2665 * collection with several rows, several columns, and is not hierarchical;
2666 * A vertical tree is a hierarchical collection with one column and
2667 * as many rows as the first level children.
2668 * </p>
Svetoslav3577a282013-06-06 14:09:10 -07002669 */
2670 public static final class CollectionInfo {
2671 private static final int MAX_POOL_SIZE = 20;
2672
2673 private static final SynchronizedPool<CollectionInfo> sPool =
2674 new SynchronizedPool<CollectionInfo>(MAX_POOL_SIZE);
2675
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002676 private int mRowCount;
2677 private int mColumnCount;
Svetoslav3577a282013-06-06 14:09:10 -07002678 private boolean mHierarchical;
2679
2680 /**
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07002681 * Obtains a pooled instance that is a clone of another one.
2682 *
2683 * @param other The instance to clone.
2684 *
2685 * @hide
2686 */
2687 public static CollectionInfo obtain(CollectionInfo other) {
2688 return CollectionInfo.obtain(other.mRowCount, other.mColumnCount,
2689 other.mHierarchical);
2690 }
2691
2692 /**
Svetoslav3577a282013-06-06 14:09:10 -07002693 * Obtains a pooled instance.
2694 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002695 * @param rowCount The number of rows.
2696 * @param columnCount The number of columns.
Svetoslav3577a282013-06-06 14:09:10 -07002697 * @param hierarchical Whether the collection is hierarchical.
2698 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002699 public static CollectionInfo obtain(int rowCount, int columnCount,
Svetoslav3577a282013-06-06 14:09:10 -07002700 boolean hierarchical) {
2701 CollectionInfo info = sPool.acquire();
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002702 return (info != null) ? info : new CollectionInfo(rowCount,
2703 columnCount, hierarchical);
Svetoslav3577a282013-06-06 14:09:10 -07002704 }
2705
2706 /**
2707 * Creates a new instance.
2708 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002709 * @param rowCount The number of rows.
2710 * @param columnCount The number of columns.
Svetoslav3577a282013-06-06 14:09:10 -07002711 * @param hierarchical Whether the collection is hierarchical.
2712 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002713 private CollectionInfo(int rowCount, int columnCount,
Svetoslav3577a282013-06-06 14:09:10 -07002714 boolean hierarchical) {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002715 mRowCount = rowCount;
2716 mColumnCount = columnCount;
Svetoslav3577a282013-06-06 14:09:10 -07002717 mHierarchical = hierarchical;
2718 }
2719
2720 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002721 * Gets the number of rows.
Svetoslav3577a282013-06-06 14:09:10 -07002722 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002723 * @return The row count.
Svetoslav3577a282013-06-06 14:09:10 -07002724 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002725 public int getRowCount() {
2726 return mRowCount;
Svetoslav3577a282013-06-06 14:09:10 -07002727 }
2728
2729 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002730 * Gets the number of columns.
Svetoslav3577a282013-06-06 14:09:10 -07002731 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002732 * @return The column count.
Svetoslav3577a282013-06-06 14:09:10 -07002733 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002734 public int getColumnCount() {
2735 return mColumnCount;
Svetoslav3577a282013-06-06 14:09:10 -07002736 }
2737
2738 /**
2739 * Gets if the collection is a hierarchically ordered.
2740 *
2741 * @return Whether the collection is hierarchical.
2742 */
2743 public boolean isHierarchical() {
2744 return mHierarchical;
2745 }
2746
2747 /**
2748 * Recycles this instance.
2749 */
2750 void recycle() {
2751 clear();
2752 sPool.release(this);
2753 }
2754
2755 private void clear() {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002756 mRowCount = 0;
2757 mColumnCount = 0;
Svetoslav3577a282013-06-06 14:09:10 -07002758 mHierarchical = false;
2759 }
2760 }
2761
2762 /**
2763 * Class with information if a node is a collection item. Use
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002764 * {@link CollectionItemInfo#obtain(int, int, int, int, boolean)}
2765 * to get an instance.
2766 * <p>
2767 * A collection item is contained in a collection, it starts at
2768 * a given row and column in the collection, and spans one or
2769 * more rows and columns. For example, a header of two related
2770 * table columns starts at the first row and the first column,
2771 * spans one row and two columns.
2772 * </p>
Svetoslav3577a282013-06-06 14:09:10 -07002773 */
2774 public static final class CollectionItemInfo {
2775 private static final int MAX_POOL_SIZE = 20;
2776
2777 private static final SynchronizedPool<CollectionItemInfo> sPool =
2778 new SynchronizedPool<CollectionItemInfo>(MAX_POOL_SIZE);
2779
2780 /**
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07002781 * Obtains a pooled instance that is a clone of another one.
2782 *
2783 * @param other The instance to clone.
2784 *
2785 * @hide
2786 */
2787 public static CollectionItemInfo obtain(CollectionItemInfo other) {
2788 return CollectionItemInfo.obtain(other.mRowIndex, other.mRowSpan,
2789 other.mColumnIndex, other.mColumnSpan, other.mHeading);
2790 }
2791
2792 /**
Svetoslav3577a282013-06-06 14:09:10 -07002793 * Obtains a pooled instance.
2794 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002795 * @param rowIndex The row index at which the item is located.
2796 * @param rowSpan The number of rows the item spans.
2797 * @param columnIndex The column index at which the item is located.
2798 * @param columnSpan The number of columns the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07002799 * @param heading Whether the item is a heading.
2800 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002801 public static CollectionItemInfo obtain(int rowIndex, int rowSpan,
2802 int columnIndex, int columnSpan, boolean heading) {
Svetoslav3577a282013-06-06 14:09:10 -07002803 CollectionItemInfo info = sPool.acquire();
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002804 return (info != null) ? info : new CollectionItemInfo(rowIndex,
2805 rowSpan, columnIndex, columnSpan, heading);
Svetoslav3577a282013-06-06 14:09:10 -07002806 }
2807
2808 private boolean mHeading;
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002809 private int mColumnIndex;
2810 private int mRowIndex;
2811 private int mColumnSpan;
2812 private int mRowSpan;
Svetoslav3577a282013-06-06 14:09:10 -07002813
2814 /**
2815 * Creates a new instance.
2816 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002817 * @param rowIndex The row index at which the item is located.
2818 * @param rowSpan The number of rows the item spans.
2819 * @param columnIndex The column index at which the item is located.
2820 * @param columnSpan The number of columns the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07002821 * @param heading Whether the item is a heading.
2822 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002823 private CollectionItemInfo(int rowIndex, int rowSpan,
2824 int columnIndex, int columnSpan, boolean heading) {
2825 mRowIndex = rowIndex;
2826 mRowSpan = rowSpan;
2827 mColumnIndex = columnIndex;
2828 mColumnSpan = columnSpan;
Svetoslav3577a282013-06-06 14:09:10 -07002829 mHeading = heading;
2830 }
2831
2832 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002833 * Gets the column index at which the item is located.
Svetoslav3577a282013-06-06 14:09:10 -07002834 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002835 * @return The column index.
Svetoslav3577a282013-06-06 14:09:10 -07002836 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002837 public int getColumnIndex() {
2838 return mColumnIndex;
Svetoslav3577a282013-06-06 14:09:10 -07002839 }
2840
2841 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002842 * Gets the row index at which the item is located.
Svetoslav3577a282013-06-06 14:09:10 -07002843 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002844 * @return The row index.
Svetoslav3577a282013-06-06 14:09:10 -07002845 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002846 public int getRowIndex() {
2847 return mRowIndex;
Svetoslav3577a282013-06-06 14:09:10 -07002848 }
2849
2850 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002851 * Gets the number of columns the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07002852 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002853 * @return The column span.
Svetoslav3577a282013-06-06 14:09:10 -07002854 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002855 public int getColumnSpan() {
2856 return mColumnSpan;
Svetoslav3577a282013-06-06 14:09:10 -07002857 }
2858
2859 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002860 * Gets the number of rows the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07002861 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002862 * @return The row span.
Svetoslav3577a282013-06-06 14:09:10 -07002863 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002864 public int getRowSpan() {
2865 return mRowSpan;
Svetoslav3577a282013-06-06 14:09:10 -07002866 }
2867
2868 /**
2869 * Gets if the collection item is a heading. For example, section
2870 * heading, table header, etc.
2871 *
2872 * @return If the item is a heading.
2873 */
2874 public boolean isHeading() {
2875 return mHeading;
2876 }
2877
2878 /**
2879 * Recycles this instance.
2880 */
2881 void recycle() {
2882 clear();
2883 sPool.release(this);
2884 }
2885
2886 private void clear() {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002887 mColumnIndex = 0;
2888 mColumnSpan = 0;
2889 mRowIndex = 0;
2890 mRowSpan = 0;
Svetoslav3577a282013-06-06 14:09:10 -07002891 mHeading = false;
2892 }
2893 }
2894
2895 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002896 * @see Parcelable.Creator
2897 */
2898 public static final Parcelable.Creator<AccessibilityNodeInfo> CREATOR =
2899 new Parcelable.Creator<AccessibilityNodeInfo>() {
2900 public AccessibilityNodeInfo createFromParcel(Parcel parcel) {
2901 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
2902 info.initFromParcel(parcel);
2903 return info;
2904 }
2905
2906 public AccessibilityNodeInfo[] newArray(int size) {
2907 return new AccessibilityNodeInfo[size];
2908 }
2909 };
2910}