blob: e924e8b7f8a288cce66ba24684bf1411ee3c60d7 [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
Svetoslav3577a282013-06-06 14:09:10 -0700421 private static final int BOOLEAN_PROPERTY_LIVE_REGION = 0x00002000;
422
423 private static final int BOOLEAN_PROPERTY_OPENS_POPUP = 0x00004000;
424
425 private static final int BOOLEAN_PROPERTY_EXPANDABLE = 0x00008000;
426
427 private static final int BOOLEAN_PROPERTY_EXPANDED = 0x00010000;
428
429 private static final int BOOLEAN_PROPERTY_DISMISSABLE = 0x00020000;
430
431 private static final int BOOLEAN_PROPERTY_MULTI_LINE = 0x00040000;
432
433 private static final int BOOLEAN_PROPERTY_CONTENT_INVALID = 0x00080000;
434
Svetoslav Ganov02107852011-10-03 17:06:56 -0700435 /**
436 * Bits that provide the id of a virtual descendant of a view.
437 */
438 private static final long VIRTUAL_DESCENDANT_ID_MASK = 0xffffffff00000000L;
439
440 /**
441 * Bit shift of {@link #VIRTUAL_DESCENDANT_ID_MASK} to get to the id for a
442 * virtual descendant of a view. Such a descendant does not exist in the view
443 * hierarchy and is only reported via the accessibility APIs.
444 */
445 private static final int VIRTUAL_DESCENDANT_ID_SHIFT = 32;
446
447 /**
448 * Gets the accessibility view id which identifies a View in the view three.
449 *
450 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}.
451 * @return The accessibility view id part of the node id.
452 *
453 * @hide
454 */
455 public static int getAccessibilityViewId(long accessibilityNodeId) {
456 return (int) accessibilityNodeId;
457 }
458
459 /**
460 * Gets the virtual descendant id which identifies an imaginary view in a
461 * containing View.
462 *
463 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}.
464 * @return The virtual view id part of the node id.
465 *
466 * @hide
467 */
468 public static int getVirtualDescendantId(long accessibilityNodeId) {
469 return (int) ((accessibilityNodeId & VIRTUAL_DESCENDANT_ID_MASK)
470 >> VIRTUAL_DESCENDANT_ID_SHIFT);
471 }
472
473 /**
474 * Makes a node id by shifting the <code>virtualDescendantId</code>
475 * by {@link #VIRTUAL_DESCENDANT_ID_SHIFT} and taking
476 * the bitwise or with the <code>accessibilityViewId</code>.
477 *
478 * @param accessibilityViewId A View accessibility id.
479 * @param virtualDescendantId A virtual descendant id.
480 * @return The node id.
481 *
482 * @hide
483 */
484 public static long makeNodeId(int accessibilityViewId, int virtualDescendantId) {
485 return (((long) virtualDescendantId) << VIRTUAL_DESCENDANT_ID_SHIFT) | accessibilityViewId;
486 }
487
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700488 // Housekeeping.
489 private static final int MAX_POOL_SIZE = 50;
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -0800490 private static final SynchronizedPool<AccessibilityNodeInfo> sPool =
491 new SynchronizedPool<AccessibilityNodeInfo>(MAX_POOL_SIZE);
492
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700493 private boolean mSealed;
494
495 // Data.
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800496 private int mWindowId = UNDEFINED;
Svetoslav Ganov0d04e242012-02-21 13:46:36 -0800497 private long mSourceNodeId = ROOT_NODE_ID;
498 private long mParentNodeId = ROOT_NODE_ID;
Svetoslav Ganov33aef982012-09-13 12:49:03 -0700499 private long mLabelForId = ROOT_NODE_ID;
500 private long mLabeledById = ROOT_NODE_ID;
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800501
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700502 private int mBooleanProperties;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700503 private final Rect mBoundsInParent = new Rect();
504 private final Rect mBoundsInScreen = new Rect();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700505
506 private CharSequence mPackageName;
507 private CharSequence mClassName;
508 private CharSequence mText;
509 private CharSequence mContentDescription;
Svetoslav9fa1ee52013-04-22 12:43:03 -0700510 private String mViewIdResourceName;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700511
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700512 private final SparseLongArray mChildNodeIds = new SparseLongArray();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700513 private int mActions;
514
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700515 private int mMovementGranularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700516
Svetoslavbcc46a02013-02-06 11:56:00 -0800517 private int mTextSelectionStart = UNDEFINED;
518 private int mTextSelectionEnd = UNDEFINED;
Svetoslav6254f482013-06-04 17:22:14 -0700519 private int mInputType = InputType.TYPE_NULL;
520
521 private Bundle mBundle;
Svetoslavbcc46a02013-02-06 11:56:00 -0800522
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -0800523 private int mConnectionId = UNDEFINED;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700524
Svetoslav3577a282013-06-06 14:09:10 -0700525 private RangeInfo mRangeInfo;
526 private CollectionInfo mCollectionInfo;
527 private CollectionItemInfo mCollectionItemInfo;
528
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700529 /**
530 * Hide constructor from clients.
531 */
532 private AccessibilityNodeInfo() {
533 /* do nothing */
534 }
535
536 /**
537 * Sets the source.
Svetoslav Ganov02107852011-10-03 17:06:56 -0700538 * <p>
539 * <strong>Note:</strong> Cannot be called from an
540 * {@link android.accessibilityservice.AccessibilityService}.
541 * This class is made immutable before being delivered to an AccessibilityService.
542 * </p>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700543 *
544 * @param source The info source.
545 */
546 public void setSource(View source) {
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800547 setSource(source, UNDEFINED);
Svetoslav Ganov02107852011-10-03 17:06:56 -0700548 }
549
550 /**
551 * Sets the source to be a virtual descendant of the given <code>root</code>.
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700552 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
Svetoslav Ganov02107852011-10-03 17:06:56 -0700553 * is set as the source.
554 * <p>
555 * A virtual descendant is an imaginary View that is reported as a part of the view
556 * hierarchy for accessibility purposes. This enables custom views that draw complex
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700557 * content to report themselves as a tree of virtual views, thus conveying their
Svetoslav Ganov02107852011-10-03 17:06:56 -0700558 * logical structure.
559 * </p>
560 * <p>
561 * <strong>Note:</strong> Cannot be called from an
562 * {@link android.accessibilityservice.AccessibilityService}.
563 * This class is made immutable before being delivered to an AccessibilityService.
564 * </p>
565 *
566 * @param root The root of the virtual subtree.
567 * @param virtualDescendantId The id of the virtual descendant.
568 */
569 public void setSource(View root, int virtualDescendantId) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700570 enforceNotSealed();
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800571 mWindowId = (root != null) ? root.getAccessibilityWindowId() : UNDEFINED;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700572 final int rootAccessibilityViewId =
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800573 (root != null) ? root.getAccessibilityViewId() : UNDEFINED;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700574 mSourceNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700575 }
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700576
Svetoslav Ganov42138042012-03-20 11:51:39 -0700577 /**
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700578 * Find the view that has the specified focus type. The search starts from
Svetoslav Ganov42138042012-03-20 11:51:39 -0700579 * the view represented by this node info.
580 *
581 * @param focus The focus to find. One of {@link #FOCUS_INPUT} or
582 * {@link #FOCUS_ACCESSIBILITY}.
583 * @return The node info of the focused view or null.
584 *
585 * @see #FOCUS_INPUT
586 * @see #FOCUS_ACCESSIBILITY
587 */
588 public AccessibilityNodeInfo findFocus(int focus) {
589 enforceSealed();
Svetoslav Ganov2ef69052012-06-04 08:55:16 -0700590 enforceValidFocusType(focus);
Svetoslav Ganov42138042012-03-20 11:51:39 -0700591 if (!canPerformRequestOverConnection(mSourceNodeId)) {
592 return null;
593 }
594 return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId, mWindowId,
595 mSourceNodeId, focus);
596 }
597
598 /**
599 * Searches for the nearest view in the specified direction that can take
600 * the input focus.
601 *
602 * @param direction The direction. Can be one of:
603 * {@link View#FOCUS_DOWN},
604 * {@link View#FOCUS_UP},
605 * {@link View#FOCUS_LEFT},
606 * {@link View#FOCUS_RIGHT},
607 * {@link View#FOCUS_FORWARD},
Svetoslav Ganov8ffe8b32012-06-15 10:31:31 -0700608 * {@link View#FOCUS_BACKWARD}.
Svetoslav Ganov42138042012-03-20 11:51:39 -0700609 *
610 * @return The node info for the view that can take accessibility focus.
611 */
612 public AccessibilityNodeInfo focusSearch(int direction) {
613 enforceSealed();
Svetoslav Ganov2ef69052012-06-04 08:55:16 -0700614 enforceValidFocusDirection(direction);
Svetoslav Ganov42138042012-03-20 11:51:39 -0700615 if (!canPerformRequestOverConnection(mSourceNodeId)) {
616 return null;
617 }
618 return AccessibilityInteractionClient.getInstance().focusSearch(mConnectionId, mWindowId,
619 mSourceNodeId, direction);
620 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700621
622 /**
623 * Gets the id of the window from which the info comes from.
624 *
625 * @return The window id.
626 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700627 public int getWindowId() {
Svetoslav Ganov02107852011-10-03 17:06:56 -0700628 return mWindowId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700629 }
630
631 /**
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800632 * Refreshes this info with the latest state of the view it represents.
633 * <p>
634 * <strong>Note:</strong> If this method returns false this info is obsolete
635 * since it represents a view that is no longer in the view tree and should
636 * be recycled.
637 * </p>
Svetoslav6254f482013-06-04 17:22:14 -0700638 *
639 * @param bypassCache Whether to bypass the cache.
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800640 * @return Whether the refresh succeeded.
Svetoslav6254f482013-06-04 17:22:14 -0700641 *
642 * @hide
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800643 */
Svetoslav6254f482013-06-04 17:22:14 -0700644 public boolean refresh(boolean bypassCache) {
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800645 enforceSealed();
646 if (!canPerformRequestOverConnection(mSourceNodeId)) {
647 return false;
648 }
649 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
650 AccessibilityNodeInfo refreshedInfo = client.findAccessibilityNodeInfoByAccessibilityId(
Svetoslav6254f482013-06-04 17:22:14 -0700651 mConnectionId, mWindowId, mSourceNodeId, bypassCache, 0);
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800652 if (refreshedInfo == null) {
653 return false;
654 }
655 init(refreshedInfo);
656 refreshedInfo.recycle();
657 return true;
658 }
659
660 /**
Svetoslav6254f482013-06-04 17:22:14 -0700661 * Refreshes this info with the latest state of the view it represents.
662 * <p>
663 * <strong>Note:</strong> If this method returns false this info is obsolete
664 * since it represents a view that is no longer in the view tree and should
665 * be recycled.
666 * </p>
667 * @return Whether the refresh succeeded.
668 */
669 public boolean refresh() {
670 return refresh(false);
671 }
672
673 /**
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800674 * @return The ids of the children.
675 *
676 * @hide
677 */
678 public SparseLongArray getChildNodeIds() {
679 return mChildNodeIds;
680 }
681
682 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700683 * Gets the number of children.
684 *
685 * @return The child count.
686 */
687 public int getChildCount() {
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800688 return mChildNodeIds.size();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700689 }
690
691 /**
692 * Get the child at given index.
693 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700694 * <strong>Note:</strong> It is a client responsibility to recycle the
695 * received info by calling {@link AccessibilityNodeInfo#recycle()}
696 * to avoid creating of multiple instances.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700697 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700698 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700699 * @param index The child index.
700 * @return The child node.
701 *
702 * @throws IllegalStateException If called outside of an AccessibilityService.
703 *
704 */
705 public AccessibilityNodeInfo getChild(int index) {
706 enforceSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -0700707 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700708 return null;
709 }
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800710 final long childId = mChildNodeIds.get(index);
Svetoslav Ganov8bd69612011-08-23 13:40:30 -0700711 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800712 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId,
Svetoslav6254f482013-06-04 17:22:14 -0700713 childId, false, FLAG_PREFETCH_DESCENDANTS);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700714 }
715
716 /**
717 * Adds a child.
718 * <p>
Svetoslav Ganov02107852011-10-03 17:06:56 -0700719 * <strong>Note:</strong> Cannot be called from an
720 * {@link android.accessibilityservice.AccessibilityService}.
721 * This class is made immutable before being delivered to an AccessibilityService.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700722 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700723 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700724 * @param child The child.
725 *
726 * @throws IllegalStateException If called from an AccessibilityService.
727 */
728 public void addChild(View child) {
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800729 addChild(child, UNDEFINED);
Svetoslav Ganov02107852011-10-03 17:06:56 -0700730 }
731
732 /**
733 * Adds a virtual child which is a descendant of the given <code>root</code>.
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700734 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
Svetoslav Ganov02107852011-10-03 17:06:56 -0700735 * is added as a child.
736 * <p>
737 * A virtual descendant is an imaginary View that is reported as a part of the view
738 * hierarchy for accessibility purposes. This enables custom views that draw complex
739 * content to report them selves as a tree of virtual views, thus conveying their
740 * logical structure.
741 * </p>
742 *
743 * @param root The root of the virtual subtree.
744 * @param virtualDescendantId The id of the virtual child.
745 */
746 public void addChild(View root, int virtualDescendantId) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700747 enforceNotSealed();
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800748 final int index = mChildNodeIds.size();
Svetoslav Ganov02107852011-10-03 17:06:56 -0700749 final int rootAccessibilityViewId =
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800750 (root != null) ? root.getAccessibilityViewId() : UNDEFINED;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700751 final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800752 mChildNodeIds.put(index, childNodeId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700753 }
754
755 /**
756 * Gets the actions that can be performed on the node.
757 *
758 * @return The bit mask of with actions.
759 *
760 * @see AccessibilityNodeInfo#ACTION_FOCUS
761 * @see AccessibilityNodeInfo#ACTION_CLEAR_FOCUS
762 * @see AccessibilityNodeInfo#ACTION_SELECT
763 * @see AccessibilityNodeInfo#ACTION_CLEAR_SELECTION
Svetoslav Ganova1dc7612012-05-10 04:14:53 -0700764 * @see AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS
765 * @see AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS
766 * @see AccessibilityNodeInfo#ACTION_CLICK
767 * @see AccessibilityNodeInfo#ACTION_LONG_CLICK
768 * @see AccessibilityNodeInfo#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
769 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
770 * @see AccessibilityNodeInfo#ACTION_NEXT_HTML_ELEMENT
771 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_HTML_ELEMENT
772 * @see AccessibilityNodeInfo#ACTION_SCROLL_FORWARD
773 * @see AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700774 */
775 public int getActions() {
776 return mActions;
777 }
778
779 /**
780 * Adds an action that can be performed on the node.
781 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700782 * <strong>Note:</strong> Cannot be called from an
783 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700784 * This class is made immutable before being delivered to an AccessibilityService.
785 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700786 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700787 * @param action The action.
788 *
789 * @throws IllegalStateException If called from an AccessibilityService.
790 */
791 public void addAction(int action) {
792 enforceNotSealed();
793 mActions |= action;
794 }
795
796 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700797 * Sets the movement granularities for traversing the text of this node.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700798 * <p>
799 * <strong>Note:</strong> Cannot be called from an
800 * {@link android.accessibilityservice.AccessibilityService}.
801 * This class is made immutable before being delivered to an AccessibilityService.
802 * </p>
803 *
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700804 * @param granularities The bit mask with granularities.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700805 *
806 * @throws IllegalStateException If called from an AccessibilityService.
807 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700808 public void setMovementGranularities(int granularities) {
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700809 enforceNotSealed();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700810 mMovementGranularities = granularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700811 }
812
813 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700814 * Gets the movement granularities for traversing the text of this node.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700815 *
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700816 * @return The bit mask with granularities.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700817 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700818 public int getMovementGranularities() {
819 return mMovementGranularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700820 }
821
822 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700823 * Performs an action on the node.
824 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700825 * <strong>Note:</strong> An action can be performed only if the request is made
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700826 * from an {@link android.accessibilityservice.AccessibilityService}.
827 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700828 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700829 * @param action The action to perform.
830 * @return True if the action was performed.
831 *
832 * @throws IllegalStateException If called outside of an AccessibilityService.
833 */
834 public boolean performAction(int action) {
835 enforceSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -0700836 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700837 return false;
838 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -0700839 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700840 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
841 action, null);
842 }
843
844 /**
845 * Performs an action on the node.
846 * <p>
847 * <strong>Note:</strong> An action can be performed only if the request is made
848 * from an {@link android.accessibilityservice.AccessibilityService}.
849 * </p>
850 *
851 * @param action The action to perform.
852 * @param arguments A bundle with additional arguments.
853 * @return True if the action was performed.
854 *
855 * @throws IllegalStateException If called outside of an AccessibilityService.
856 */
857 public boolean performAction(int action, Bundle arguments) {
858 enforceSealed();
859 if (!canPerformRequestOverConnection(mSourceNodeId)) {
860 return false;
861 }
862 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
863 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
864 action, arguments);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700865 }
866
867 /**
868 * Finds {@link AccessibilityNodeInfo}s by text. The match is case
Svetoslav Ganov86398bd2011-06-21 17:38:43 -0700869 * insensitive containment. The search is relative to this info i.e.
870 * this info is the root of the traversed tree.
Svetoslav Ganovea515ae2011-09-14 18:15:32 -0700871 *
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700872 * <p>
873 * <strong>Note:</strong> It is a client responsibility to recycle the
874 * received info by calling {@link AccessibilityNodeInfo#recycle()}
875 * to avoid creating of multiple instances.
876 * </p>
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700877 *
878 * @param text The searched text.
879 * @return A list of node info.
880 */
881 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text) {
882 enforceSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -0700883 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganov86398bd2011-06-21 17:38:43 -0700884 return Collections.emptyList();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700885 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -0700886 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganov79311c42012-01-17 20:24:26 -0800887 return client.findAccessibilityNodeInfosByText(mConnectionId, mWindowId, mSourceNodeId,
888 text);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700889 }
890
891 /**
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800892 * Finds {@link AccessibilityNodeInfo}s by the fully qualified view id's resource
893 * name where a fully qualified id is of the from "package:id/id_resource_name".
894 * For example, if the target application's package is "foo.bar" and the id
895 * resource name is "baz", the fully qualified resource id is "foo.bar:id/baz".
896 *
897 * <p>
898 * <strong>Note:</strong> It is a client responsibility to recycle the
899 * received info by calling {@link AccessibilityNodeInfo#recycle()}
900 * to avoid creating of multiple instances.
901 * </p>
902 * <p>
903 * <strong>Note:</strong> The primary usage of this API is for UI test automation
904 * and in order to report the fully qualified view id if an {@link AccessibilityNodeInfo}
905 * the client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
Svetoslav14ff9962013-01-29 03:21:37 -0800906 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800907 * </p>
908 *
909 * @param viewId The fully qualified resource name of the view id to find.
910 * @return A list of node info.
911 */
912 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId(String viewId) {
913 enforceSealed();
914 if (!canPerformRequestOverConnection(mSourceNodeId)) {
915 return Collections.emptyList();
916 }
917 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
918 return client.findAccessibilityNodeInfosByViewId(mConnectionId, mWindowId, mSourceNodeId,
919 viewId);
920 }
921
922 /**
Svetoslav Ganov00aabf72011-07-21 11:35:03 -0700923 * Gets the parent.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700924 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700925 * <strong>Note:</strong> It is a client responsibility to recycle the
926 * received info by calling {@link AccessibilityNodeInfo#recycle()}
927 * to avoid creating of multiple instances.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700928 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700929 *
Svetoslav Ganov00aabf72011-07-21 11:35:03 -0700930 * @return The parent.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700931 */
932 public AccessibilityNodeInfo getParent() {
933 enforceSealed();
Svetoslav Ganovaf0d9842011-10-26 15:29:26 -0700934 if (!canPerformRequestOverConnection(mParentNodeId)) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700935 return null;
936 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -0700937 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -0800938 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
Svetoslav6254f482013-06-04 17:22:14 -0700939 mWindowId, mParentNodeId, false, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800940 }
941
942 /**
943 * @return The parent node id.
944 *
945 * @hide
946 */
947 public long getParentNodeId() {
948 return mParentNodeId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700949 }
950
951 /**
952 * Sets the parent.
953 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700954 * <strong>Note:</strong> Cannot be called from an
955 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700956 * This class is made immutable before being delivered to an AccessibilityService.
957 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700958 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700959 * @param parent The parent.
960 *
961 * @throws IllegalStateException If called from an AccessibilityService.
962 */
963 public void setParent(View parent) {
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800964 setParent(parent, UNDEFINED);
Svetoslav Ganov02107852011-10-03 17:06:56 -0700965 }
966
967 /**
968 * Sets the parent to be a virtual descendant of the given <code>root</code>.
969 * If <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root
970 * is set as the parent.
971 * <p>
972 * A virtual descendant is an imaginary View that is reported as a part of the view
973 * hierarchy for accessibility purposes. This enables custom views that draw complex
974 * content to report them selves as a tree of virtual views, thus conveying their
975 * logical structure.
976 * </p>
977 * <p>
978 * <strong>Note:</strong> Cannot be called from an
979 * {@link android.accessibilityservice.AccessibilityService}.
980 * This class is made immutable before being delivered to an AccessibilityService.
981 * </p>
982 *
983 * @param root The root of the virtual subtree.
984 * @param virtualDescendantId The id of the virtual descendant.
985 */
986 public void setParent(View root, int virtualDescendantId) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700987 enforceNotSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -0700988 final int rootAccessibilityViewId =
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800989 (root != null) ? root.getAccessibilityViewId() : UNDEFINED;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700990 mParentNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700991 }
992
993 /**
994 * Gets the node bounds in parent coordinates.
995 *
996 * @param outBounds The output node bounds.
997 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700998 public void getBoundsInParent(Rect outBounds) {
999 outBounds.set(mBoundsInParent.left, mBoundsInParent.top,
1000 mBoundsInParent.right, mBoundsInParent.bottom);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001001 }
1002
1003 /**
1004 * Sets the node bounds in parent coordinates.
1005 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001006 * <strong>Note:</strong> Cannot be called from an
1007 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001008 * This class is made immutable before being delivered to an AccessibilityService.
1009 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001010 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001011 * @param bounds The node bounds.
1012 *
1013 * @throws IllegalStateException If called from an AccessibilityService.
1014 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001015 public void setBoundsInParent(Rect bounds) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001016 enforceNotSealed();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001017 mBoundsInParent.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
1018 }
1019
1020 /**
1021 * Gets the node bounds in screen coordinates.
1022 *
1023 * @param outBounds The output node bounds.
1024 */
1025 public void getBoundsInScreen(Rect outBounds) {
1026 outBounds.set(mBoundsInScreen.left, mBoundsInScreen.top,
1027 mBoundsInScreen.right, mBoundsInScreen.bottom);
1028 }
1029
1030 /**
1031 * Sets the node bounds in screen coordinates.
1032 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001033 * <strong>Note:</strong> Cannot be called from an
1034 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001035 * This class is made immutable before being delivered to an AccessibilityService.
1036 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001037 *
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001038 * @param bounds The node bounds.
1039 *
1040 * @throws IllegalStateException If called from an AccessibilityService.
1041 */
1042 public void setBoundsInScreen(Rect bounds) {
1043 enforceNotSealed();
1044 mBoundsInScreen.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001045 }
1046
1047 /**
1048 * Gets whether this node is checkable.
1049 *
1050 * @return True if the node is checkable.
1051 */
1052 public boolean isCheckable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001053 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001054 }
1055
1056 /**
1057 * Sets whether this node is checkable.
1058 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001059 * <strong>Note:</strong> Cannot be called from an
1060 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001061 * This class is made immutable before being delivered to an AccessibilityService.
1062 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001063 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001064 * @param checkable True if the node is checkable.
1065 *
1066 * @throws IllegalStateException If called from an AccessibilityService.
1067 */
1068 public void setCheckable(boolean checkable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001069 setBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE, checkable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001070 }
1071
1072 /**
1073 * Gets whether this node is checked.
1074 *
1075 * @return True if the node is checked.
1076 */
1077 public boolean isChecked() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001078 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001079 }
1080
1081 /**
1082 * Sets whether this node is checked.
1083 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001084 * <strong>Note:</strong> Cannot be called from an
1085 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001086 * This class is made immutable before being delivered to an AccessibilityService.
1087 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001088 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001089 * @param checked True if the node is checked.
1090 *
1091 * @throws IllegalStateException If called from an AccessibilityService.
1092 */
1093 public void setChecked(boolean checked) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001094 setBooleanProperty(BOOLEAN_PROPERTY_CHECKED, checked);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001095 }
1096
1097 /**
1098 * Gets whether this node is focusable.
1099 *
1100 * @return True if the node is focusable.
1101 */
1102 public boolean isFocusable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001103 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001104 }
1105
1106 /**
1107 * Sets whether this node is focusable.
1108 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001109 * <strong>Note:</strong> Cannot be called from an
1110 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001111 * This class is made immutable before being delivered to an AccessibilityService.
1112 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001113 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001114 * @param focusable True if the node is focusable.
1115 *
1116 * @throws IllegalStateException If called from an AccessibilityService.
1117 */
1118 public void setFocusable(boolean focusable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001119 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE, focusable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001120 }
1121
1122 /**
1123 * Gets whether this node is focused.
1124 *
1125 * @return True if the node is focused.
1126 */
1127 public boolean isFocused() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001128 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001129 }
1130
1131 /**
1132 * Sets whether this node is focused.
1133 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001134 * <strong>Note:</strong> Cannot be called from an
1135 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001136 * This class is made immutable before being delivered to an AccessibilityService.
1137 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001138 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001139 * @param focused True if the node is focused.
1140 *
1141 * @throws IllegalStateException If called from an AccessibilityService.
1142 */
1143 public void setFocused(boolean focused) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001144 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSED, focused);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001145 }
1146
1147 /**
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001148 * Sets whether this node is visible to the user.
1149 *
1150 * @return Whether the node is visible to the user.
1151 */
1152 public boolean isVisibleToUser() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001153 return getBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001154 }
1155
1156 /**
1157 * Sets whether this node is visible to the user.
1158 * <p>
1159 * <strong>Note:</strong> Cannot be called from an
1160 * {@link android.accessibilityservice.AccessibilityService}.
1161 * This class is made immutable before being delivered to an AccessibilityService.
1162 * </p>
1163 *
1164 * @param visibleToUser Whether the node is visible to the user.
1165 *
1166 * @throws IllegalStateException If called from an AccessibilityService.
1167 */
1168 public void setVisibleToUser(boolean visibleToUser) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001169 setBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER, visibleToUser);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001170 }
1171
1172 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -07001173 * Gets whether this node is accessibility focused.
1174 *
1175 * @return True if the node is accessibility focused.
1176 */
1177 public boolean isAccessibilityFocused() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001178 return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED);
Svetoslav Ganov42138042012-03-20 11:51:39 -07001179 }
1180
1181 /**
1182 * Sets whether this node is accessibility focused.
1183 * <p>
1184 * <strong>Note:</strong> Cannot be called from an
1185 * {@link android.accessibilityservice.AccessibilityService}.
1186 * This class is made immutable before being delivered to an AccessibilityService.
1187 * </p>
1188 *
1189 * @param focused True if the node is accessibility focused.
1190 *
1191 * @throws IllegalStateException If called from an AccessibilityService.
1192 */
1193 public void setAccessibilityFocused(boolean focused) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001194 setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED, focused);
Svetoslav Ganov42138042012-03-20 11:51:39 -07001195 }
1196
1197 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001198 * Gets whether this node is selected.
1199 *
1200 * @return True if the node is selected.
1201 */
1202 public boolean isSelected() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001203 return getBooleanProperty(BOOLEAN_PROPERTY_SELECTED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001204 }
1205
1206 /**
1207 * Sets whether this node is selected.
1208 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001209 * <strong>Note:</strong> Cannot be called from an
1210 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001211 * This class is made immutable before being delivered to an AccessibilityService.
1212 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001213 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001214 * @param selected True if the node is selected.
1215 *
1216 * @throws IllegalStateException If called from an AccessibilityService.
1217 */
1218 public void setSelected(boolean selected) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001219 setBooleanProperty(BOOLEAN_PROPERTY_SELECTED, selected);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001220 }
1221
1222 /**
1223 * Gets whether this node is clickable.
1224 *
1225 * @return True if the node is clickable.
1226 */
1227 public boolean isClickable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001228 return getBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001229 }
1230
1231 /**
1232 * Sets whether this node is clickable.
1233 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001234 * <strong>Note:</strong> Cannot be called from an
1235 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001236 * This class is made immutable before being delivered to an AccessibilityService.
1237 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001238 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001239 * @param clickable True if the node is clickable.
1240 *
1241 * @throws IllegalStateException If called from an AccessibilityService.
1242 */
1243 public void setClickable(boolean clickable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001244 setBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE, clickable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001245 }
1246
1247 /**
1248 * Gets whether this node is long clickable.
1249 *
1250 * @return True if the node is long clickable.
1251 */
1252 public boolean isLongClickable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001253 return getBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001254 }
1255
1256 /**
1257 * Sets whether this node is long clickable.
1258 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001259 * <strong>Note:</strong> Cannot be called from an
1260 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001261 * This class is made immutable before being delivered to an AccessibilityService.
1262 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001263 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001264 * @param longClickable True if the node is long clickable.
1265 *
1266 * @throws IllegalStateException If called from an AccessibilityService.
1267 */
1268 public void setLongClickable(boolean longClickable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001269 setBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE, longClickable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001270 }
1271
1272 /**
1273 * Gets whether this node is enabled.
1274 *
1275 * @return True if the node is enabled.
1276 */
1277 public boolean isEnabled() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001278 return getBooleanProperty(BOOLEAN_PROPERTY_ENABLED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001279 }
1280
1281 /**
1282 * Sets whether this node is enabled.
1283 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001284 * <strong>Note:</strong> Cannot be called from an
1285 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001286 * This class is made immutable before being delivered to an AccessibilityService.
1287 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001288 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001289 * @param enabled True if the node is enabled.
1290 *
1291 * @throws IllegalStateException If called from an AccessibilityService.
1292 */
1293 public void setEnabled(boolean enabled) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001294 setBooleanProperty(BOOLEAN_PROPERTY_ENABLED, enabled);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001295 }
1296
1297 /**
1298 * Gets whether this node is a password.
1299 *
1300 * @return True if the node is a password.
1301 */
1302 public boolean isPassword() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001303 return getBooleanProperty(BOOLEAN_PROPERTY_PASSWORD);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001304 }
1305
1306 /**
1307 * Sets whether this node is a password.
1308 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001309 * <strong>Note:</strong> Cannot be called from an
1310 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001311 * This class is made immutable before being delivered to an AccessibilityService.
1312 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001313 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001314 * @param password True if the node is a password.
1315 *
1316 * @throws IllegalStateException If called from an AccessibilityService.
1317 */
1318 public void setPassword(boolean password) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001319 setBooleanProperty(BOOLEAN_PROPERTY_PASSWORD, password);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001320 }
1321
1322 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -07001323 * Gets if the node is scrollable.
1324 *
1325 * @return True if the node is scrollable, false otherwise.
1326 */
1327 public boolean isScrollable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001328 return getBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE);
Svetoslav Ganova0156172011-06-26 17:55:44 -07001329 }
1330
1331 /**
1332 * Sets if the node is scrollable.
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001333 * <p>
1334 * <strong>Note:</strong> Cannot be called from an
1335 * {@link android.accessibilityservice.AccessibilityService}.
1336 * This class is made immutable before being delivered to an AccessibilityService.
1337 * </p>
Svetoslav Ganova0156172011-06-26 17:55:44 -07001338 *
1339 * @param scrollable True if the node is scrollable, false otherwise.
1340 *
1341 * @throws IllegalStateException If called from an AccessibilityService.
1342 */
1343 public void setScrollable(boolean scrollable) {
1344 enforceNotSealed();
Svetoslavbcc46a02013-02-06 11:56:00 -08001345 setBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE, scrollable);
1346 }
1347
1348 /**
1349 * Gets if the node is editable.
1350 *
1351 * @return True if the node is editable, false otherwise.
1352 */
1353 public boolean isEditable() {
1354 return getBooleanProperty(BOOLEAN_PROPERTY_EDITABLE);
1355 }
1356
1357 /**
1358 * Sets whether this node is editable.
1359 * <p>
1360 * <strong>Note:</strong> Cannot be called from an
1361 * {@link android.accessibilityservice.AccessibilityService}.
1362 * This class is made immutable before being delivered to an AccessibilityService.
1363 * </p>
1364 *
1365 * @param editable True if the node is editable.
1366 *
1367 * @throws IllegalStateException If called from an AccessibilityService.
1368 */
1369 public void setEditable(boolean editable) {
1370 setBooleanProperty(BOOLEAN_PROPERTY_EDITABLE, editable);
Svetoslav Ganova0156172011-06-26 17:55:44 -07001371 }
1372
1373 /**
Svetoslav3577a282013-06-06 14:09:10 -07001374 * Gets the collection info if the node is a collection. A collection
1375 * child is always a collection item.
1376 *
1377 * @return The collection info.
1378 */
1379 public CollectionInfo getCollectionInfo() {
1380 return mCollectionInfo;
1381 }
1382
1383 /**
1384 * Sets the collection info if the node is a collection. A collection
1385 * child is always a collection item.
1386 * <p>
1387 * <strong>Note:</strong> Cannot be called from an
1388 * {@link android.accessibilityservice.AccessibilityService}.
1389 * This class is made immutable before being delivered to an AccessibilityService.
1390 * </p>
1391 *
1392 * @param collectionInfo The collection info.
1393 */
1394 public void setCollectionInfo(CollectionInfo collectionInfo) {
1395 enforceNotSealed();
1396 mCollectionInfo = collectionInfo;
1397 }
1398
1399 /**
1400 * Gets the collection item info if the node is a collection item. A collection
1401 * item is always a child of a collection.
1402 *
1403 * @return The collection item info.
1404 */
1405 public CollectionItemInfo getCollectionItemInfo() {
1406 return mCollectionItemInfo;
1407 }
1408
1409 /**
1410 * Sets the collection item info if the node is a collection item. A collection
1411 * item is always a child of a collection.
1412 * <p>
1413 * <strong>Note:</strong> Cannot be called from an
1414 * {@link android.accessibilityservice.AccessibilityService}.
1415 * This class is made immutable before being delivered to an AccessibilityService.
1416 * </p>
1417 *
1418 * @return collectionItem True if the node is an item.
1419 */
1420 public void setCollectionItemInfo(CollectionItemInfo collectionItemInfo) {
1421 enforceNotSealed();
1422 mCollectionItemInfo = collectionItemInfo;
1423 }
1424
1425 /**
1426 * Gets the range info if this node is a range.
1427 *
1428 * @return The range.
1429 */
1430 public RangeInfo getRangeInfo() {
1431 return mRangeInfo;
1432 }
1433
1434 /**
1435 * Sets the range info if this node is a range.
1436 * <p>
1437 * <strong>Note:</strong> Cannot be called from an
1438 * {@link android.accessibilityservice.AccessibilityService}.
1439 * This class is made immutable before being delivered to an AccessibilityService.
1440 * </p>
1441 *
1442 * @param rangeInfo The range info.
1443 */
1444 public void setRangeInfo(RangeInfo rangeInfo) {
1445 enforceNotSealed();
1446 mRangeInfo = rangeInfo;
1447 }
1448
1449 /**
1450 * Gets if the content of this node is invalid. For example,
1451 * a date is not well-formed.
1452 *
1453 * @return If the node content is invalid.
1454 */
1455 public boolean isContentInvalid() {
1456 return getBooleanProperty(BOOLEAN_PROPERTY_CONTENT_INVALID);
1457 }
1458
1459 /**
1460 * Sets if the content of this node is invalid. For example,
1461 * a date is not well-formed.
1462 * <p>
1463 * <strong>Note:</strong> Cannot be called from an
1464 * {@link android.accessibilityservice.AccessibilityService}.
1465 * This class is made immutable before being delivered to an AccessibilityService.
1466 * </p>
1467 *
1468 * @param contentInvalid If the node content is invalid.
1469 */
1470 public void setContentInvalid(boolean contentInvalid) {
1471 setBooleanProperty(BOOLEAN_PROPERTY_CONTENT_INVALID, contentInvalid);
1472 }
1473
1474 /**
1475 * Gets if the node is a live region for whose changes the user
1476 * should be notified. It is the responsibility of the accessibility
1477 * service to monitor this region and notify the user if it changes.
1478 *
1479 * @return If the node is a live region.
1480 */
1481 public boolean isLiveRegion() {
1482 return getBooleanProperty(BOOLEAN_PROPERTY_LIVE_REGION);
1483 }
1484
1485 /**
1486 * Sets if the node is a live region for whose changes the user
1487 * should be notified. It is the responsibility of the accessibility
1488 * service to monitor this region and notify the user if it changes.
1489 * <p>
1490 * <strong>Note:</strong> Cannot be called from an
1491 * {@link android.accessibilityservice.AccessibilityService}.
1492 * This class is made immutable before being delivered to an AccessibilityService.
1493 * </p>
1494 *
1495 * @param liveRegion If the node is a live region.
1496 */
1497 public void setLiveRegion(boolean liveRegion) {
1498 enforceNotSealed();
1499 setBooleanProperty(BOOLEAN_PROPERTY_LIVE_REGION, liveRegion);
1500 }
1501
1502 /**
1503 * Gets if the node is a multi line editable text.
1504 *
1505 * @return True if the node is multi line.
1506 */
1507 public boolean isMultiLine() {
1508 return getBooleanProperty(BOOLEAN_PROPERTY_MULTI_LINE);
1509 }
1510
1511 /**
1512 * Sets if the node is a multi line editable text.
1513 * <p>
1514 * <strong>Note:</strong> Cannot be called from an
1515 * {@link android.accessibilityservice.AccessibilityService}.
1516 * This class is made immutable before being delivered to an AccessibilityService.
1517 * </p>
1518 *
1519 * @param multiLine True if the node is multi line.
1520 */
1521 public void setMultiLine(boolean multiLine) {
1522 enforceNotSealed();
1523 setBooleanProperty(BOOLEAN_PROPERTY_MULTI_LINE, multiLine);
1524 }
1525
1526 /**
1527 * Gets if this node opens a popup or a dialog.
1528 *
1529 * @return If the the node opens a popup.
1530 */
1531 public boolean getOpensPopup() {
1532 return getBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP);
1533 }
1534
1535 /**
1536 * Sets if this node opens a popup or a dialog.
1537 * <p>
1538 * <strong>Note:</strong> Cannot be called from an
1539 * {@link android.accessibilityservice.AccessibilityService}.
1540 * This class is made immutable before being delivered to an AccessibilityService.
1541 * </p>
1542 *
1543 * @param opensPopup If the the node opens a popup.
1544 */
1545 public void setOpensPopup(boolean opensPopup) {
1546 enforceNotSealed();
1547 setBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP, opensPopup);
1548 }
1549
1550 /**
1551 * Gets if the node can be expanded.
1552 *
1553 * @return If the node can be expanded.
1554 */
1555 public boolean isExpandable() {
1556 return getBooleanProperty(BOOLEAN_PROPERTY_EXPANDABLE);
1557 }
1558
1559 /**
1560 * Sets if the node can be expanded.
1561 * <p>
1562 * <strong>Note:</strong> Cannot be called from an
1563 * {@link android.accessibilityservice.AccessibilityService}.
1564 * This class is made immutable before being delivered to an AccessibilityService.
1565 * </p>
1566 *
1567 * @param expandable If the node can be expanded.
1568 */
1569 public void setExpandable(boolean expandable) {
1570 enforceNotSealed();
1571 setBooleanProperty(BOOLEAN_PROPERTY_EXPANDABLE, expandable);
1572 }
1573
1574 /**
1575 * Gets if the node is expanded.
1576 *
1577 * @return If the node is expanded.
1578 */
1579 public boolean isExpanded() {
1580 return getBooleanProperty(BOOLEAN_PROPERTY_EXPANDED);
1581 }
1582
1583 /**
1584 * Sets if the node is expanded.
1585 * <p>
1586 * <strong>Note:</strong> Cannot be called from an
1587 * {@link android.accessibilityservice.AccessibilityService}.
1588 * This class is made immutable before being delivered to an AccessibilityService.
1589 * </p>
1590 *
1591 * @param expanded If the node is expanded.
1592 */
1593 public void setExpanded(boolean expanded) {
1594 enforceNotSealed();
1595 setBooleanProperty(BOOLEAN_PROPERTY_EXPANDED, expanded);
1596 }
1597
1598 /**
1599 * Gets if the node can be dismissed.
1600 *
1601 * @return If the node can be dismissed.
1602 */
1603 public boolean isDismissable() {
1604 return getBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE);
1605 }
1606
1607 /**
1608 * Sets if the node can be dismissed.
1609 * <p>
1610 * <strong>Note:</strong> Cannot be called from an
1611 * {@link android.accessibilityservice.AccessibilityService}.
1612 * This class is made immutable before being delivered to an AccessibilityService.
1613 * </p>
1614 *
1615 * @param dismissable If the node can be dismissed.
1616 */
1617 public void setDismissable(boolean dismissable) {
1618 enforceNotSealed();
1619 setBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE, dismissable);
1620 }
1621
1622 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001623 * Gets the package this node comes from.
1624 *
1625 * @return The package name.
1626 */
1627 public CharSequence getPackageName() {
1628 return mPackageName;
1629 }
1630
1631 /**
1632 * Sets the package this node comes from.
1633 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001634 * <strong>Note:</strong> Cannot be called from an
1635 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001636 * This class is made immutable before being delivered to an AccessibilityService.
1637 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001638 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001639 * @param packageName The package name.
1640 *
1641 * @throws IllegalStateException If called from an AccessibilityService.
1642 */
1643 public void setPackageName(CharSequence packageName) {
1644 enforceNotSealed();
1645 mPackageName = packageName;
1646 }
1647
1648 /**
1649 * Gets the class this node comes from.
1650 *
1651 * @return The class name.
1652 */
1653 public CharSequence getClassName() {
1654 return mClassName;
1655 }
1656
1657 /**
1658 * Sets the class this node comes from.
1659 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001660 * <strong>Note:</strong> Cannot be called from an
1661 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001662 * This class is made immutable before being delivered to an AccessibilityService.
1663 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001664 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001665 * @param className The class name.
1666 *
1667 * @throws IllegalStateException If called from an AccessibilityService.
1668 */
1669 public void setClassName(CharSequence className) {
1670 enforceNotSealed();
1671 mClassName = className;
1672 }
1673
1674 /**
1675 * Gets the text of this node.
1676 *
1677 * @return The text.
1678 */
1679 public CharSequence getText() {
1680 return mText;
1681 }
1682
1683 /**
1684 * Sets the text of this node.
1685 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001686 * <strong>Note:</strong> Cannot be called from an
1687 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001688 * This class is made immutable before being delivered to an AccessibilityService.
1689 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001690 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001691 * @param text The text.
1692 *
1693 * @throws IllegalStateException If called from an AccessibilityService.
1694 */
1695 public void setText(CharSequence text) {
1696 enforceNotSealed();
1697 mText = text;
1698 }
1699
1700 /**
1701 * Gets the content description of this node.
1702 *
1703 * @return The content description.
1704 */
1705 public CharSequence getContentDescription() {
1706 return mContentDescription;
1707 }
1708
1709 /**
1710 * Sets the content description of this node.
1711 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001712 * <strong>Note:</strong> Cannot be called from an
1713 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001714 * This class is made immutable before being delivered to an AccessibilityService.
1715 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001716 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001717 * @param contentDescription The content description.
1718 *
1719 * @throws IllegalStateException If called from an AccessibilityService.
1720 */
1721 public void setContentDescription(CharSequence contentDescription) {
1722 enforceNotSealed();
1723 mContentDescription = contentDescription;
1724 }
1725
1726 /**
Svetoslav Ganov33aef982012-09-13 12:49:03 -07001727 * Sets the view for which the view represented by this info serves as a
1728 * label for accessibility purposes.
1729 *
1730 * @param labeled The view for which this info serves as a label.
1731 */
1732 public void setLabelFor(View labeled) {
1733 setLabelFor(labeled, UNDEFINED);
1734 }
1735
1736 /**
1737 * Sets the view for which the view represented by this info serves as a
1738 * label for accessibility purposes. If <code>virtualDescendantId</code>
1739 * is {@link View#NO_ID} the root is set as the labeled.
1740 * <p>
1741 * A virtual descendant is an imaginary View that is reported as a part of the view
1742 * hierarchy for accessibility purposes. This enables custom views that draw complex
1743 * content to report themselves as a tree of virtual views, thus conveying their
1744 * logical structure.
1745 * </p>
1746 * <p>
1747 * <strong>Note:</strong> Cannot be called from an
1748 * {@link android.accessibilityservice.AccessibilityService}.
1749 * This class is made immutable before being delivered to an AccessibilityService.
1750 * </p>
1751 *
1752 * @param root The root whose virtual descendant serves as a label.
1753 * @param virtualDescendantId The id of the virtual descendant.
1754 */
1755 public void setLabelFor(View root, int virtualDescendantId) {
1756 enforceNotSealed();
1757 final int rootAccessibilityViewId = (root != null)
1758 ? root.getAccessibilityViewId() : UNDEFINED;
1759 mLabelForId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1760 }
1761
1762 /**
1763 * Gets the node info for which the view represented by this info serves as
1764 * a label for accessibility purposes.
1765 * <p>
1766 * <strong>Note:</strong> It is a client responsibility to recycle the
1767 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1768 * to avoid creating of multiple instances.
1769 * </p>
1770 *
1771 * @return The labeled info.
1772 */
1773 public AccessibilityNodeInfo getLabelFor() {
1774 enforceSealed();
1775 if (!canPerformRequestOverConnection(mLabelForId)) {
1776 return null;
1777 }
1778 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1779 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
Svetoslav6254f482013-06-04 17:22:14 -07001780 mWindowId, mLabelForId, false, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07001781 }
1782
1783 /**
1784 * Sets the view which serves as the label of the view represented by
1785 * this info for accessibility purposes.
1786 *
1787 * @param label The view that labels this node's source.
1788 */
1789 public void setLabeledBy(View label) {
1790 setLabeledBy(label, UNDEFINED);
1791 }
1792
1793 /**
1794 * Sets the view which serves as the label of the view represented by
1795 * this info for accessibility purposes. If <code>virtualDescendantId</code>
1796 * is {@link View#NO_ID} the root is set as the label.
1797 * <p>
1798 * A virtual descendant is an imaginary View that is reported as a part of the view
1799 * hierarchy for accessibility purposes. This enables custom views that draw complex
1800 * content to report themselves as a tree of virtual views, thus conveying their
1801 * logical structure.
1802 * </p>
1803 * <p>
1804 * <strong>Note:</strong> Cannot be called from an
1805 * {@link android.accessibilityservice.AccessibilityService}.
1806 * This class is made immutable before being delivered to an AccessibilityService.
1807 * </p>
1808 *
1809 * @param root The root whose virtual descendant labels this node's source.
1810 * @param virtualDescendantId The id of the virtual descendant.
1811 */
1812 public void setLabeledBy(View root, int virtualDescendantId) {
1813 enforceNotSealed();
1814 final int rootAccessibilityViewId = (root != null)
1815 ? root.getAccessibilityViewId() : UNDEFINED;
1816 mLabeledById = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1817 }
1818
1819 /**
1820 * Gets the node info which serves as the label of the view represented by
1821 * this info for accessibility purposes.
1822 * <p>
1823 * <strong>Note:</strong> It is a client responsibility to recycle the
1824 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1825 * to avoid creating of multiple instances.
1826 * </p>
1827 *
1828 * @return The label.
1829 */
1830 public AccessibilityNodeInfo getLabeledBy() {
1831 enforceSealed();
1832 if (!canPerformRequestOverConnection(mLabeledById)) {
1833 return null;
1834 }
1835 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1836 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
Svetoslav6254f482013-06-04 17:22:14 -07001837 mWindowId, mLabeledById, false, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07001838 }
1839
1840 /**
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001841 * Sets the fully qualified resource name of the source view's id.
1842 *
1843 * <p>
1844 * <strong>Note:</strong> Cannot be called from an
1845 * {@link android.accessibilityservice.AccessibilityService}.
1846 * This class is made immutable before being delivered to an AccessibilityService.
1847 * </p>
1848 *
Svetoslav92826452013-02-05 14:57:42 -08001849 * @param viewIdResName The id resource name.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001850 */
Svetoslav9fa1ee52013-04-22 12:43:03 -07001851 public void setViewIdResourceName(String viewIdResName) {
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001852 enforceNotSealed();
Svetoslav22431a32013-02-05 14:30:19 -08001853 mViewIdResourceName = viewIdResName;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001854 }
1855
1856 /**
1857 * Gets the fully qualified resource name of the source view's id.
1858 *
1859 * <p>
1860 * <strong>Note:</strong> The primary usage of this API is for UI test automation
1861 * and in order to report the source view id of an {@link AccessibilityNodeInfo} the
1862 * client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
Svetoslav14ff9962013-01-29 03:21:37 -08001863 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001864 * </p>
1865
1866 * @return The id resource name.
1867 */
Svetoslav9fa1ee52013-04-22 12:43:03 -07001868 public String getViewIdResourceName() {
Svetoslav22431a32013-02-05 14:30:19 -08001869 return mViewIdResourceName;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001870 }
1871
1872 /**
Svetoslavbcc46a02013-02-06 11:56:00 -08001873 * Gets the text selection start.
1874 *
1875 * @return The text selection start if there is selection or -1.
1876 */
1877 public int getTextSelectionStart() {
1878 return mTextSelectionStart;
1879 }
1880
1881 /**
1882 * Gets the text selection end.
1883 *
1884 * @return The text selection end if there is selection or -1.
1885 */
1886 public int getTextSelectionEnd() {
1887 return mTextSelectionEnd;
1888 }
1889
1890 /**
1891 * Sets the text selection start and end.
1892 * <p>
1893 * <strong>Note:</strong> Cannot be called from an
1894 * {@link android.accessibilityservice.AccessibilityService}.
1895 * This class is made immutable before being delivered to an AccessibilityService.
1896 * </p>
1897 *
1898 * @param start The text selection start.
1899 * @param end The text selection end.
1900 *
1901 * @throws IllegalStateException If called from an AccessibilityService.
1902 */
1903 public void setTextSelection(int start, int end) {
1904 enforceNotSealed();
1905 mTextSelectionStart = start;
1906 mTextSelectionEnd = end;
1907 }
1908
1909 /**
Svetoslav6254f482013-06-04 17:22:14 -07001910 * Gets the input type of the source as defined by {@link InputType}.
1911 *
1912 * @return The input type.
1913 */
1914 public int getInputType() {
1915 return mInputType;
1916 }
1917
1918 /**
1919 * Sets the input type of the source as defined by {@link InputType}.
1920 * <p>
1921 * <strong>Note:</strong> Cannot be called from an
1922 * {@link android.accessibilityservice.AccessibilityService}.
1923 * This class is made immutable before being delivered to an
1924 * AccessibilityService.
1925 * </p>
1926 *
1927 * @param inputType The input type.
1928 *
1929 * @throws IllegalStateException If called from an AccessibilityService.
1930 */
1931 public void setInputType(int inputType) {
1932 mInputType = inputType;
1933 }
1934
1935 /**
1936 * Gets an optional bundle with additional data. The bundle
1937 * is lazily created and never <code>null</code>.
1938 * <p>
1939 * <strong>Note:</strong> It is recommended to use the package
1940 * name of your application as a prefix for the keys to avoid
1941 * collisions which may confuse an accessibility service if the
1942 * same key has different meaning when emitted from different
1943 * applications.
1944 * </p>
1945 *
1946 * @return The bundle.
1947 */
1948 public Bundle getBundle() {
1949 if (mBundle == null) {
1950 mBundle = new Bundle();
1951 }
1952 return mBundle;
1953 }
1954
1955 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001956 * Gets the value of a boolean property.
1957 *
1958 * @param property The property.
1959 * @return The value.
1960 */
1961 private boolean getBooleanProperty(int property) {
1962 return (mBooleanProperties & property) != 0;
1963 }
1964
1965 /**
1966 * Sets a boolean property.
1967 *
1968 * @param property The property.
1969 * @param value The value.
1970 *
1971 * @throws IllegalStateException If called from an AccessibilityService.
1972 */
1973 private void setBooleanProperty(int property, boolean value) {
1974 enforceNotSealed();
1975 if (value) {
1976 mBooleanProperties |= property;
1977 } else {
1978 mBooleanProperties &= ~property;
1979 }
1980 }
1981
1982 /**
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08001983 * Sets the unique id of the IAccessibilityServiceConnection over which
1984 * this instance can send requests to the system.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001985 *
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08001986 * @param connectionId The connection id.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001987 *
1988 * @hide
1989 */
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08001990 public void setConnectionId(int connectionId) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001991 enforceNotSealed();
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08001992 mConnectionId = connectionId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001993 }
1994
1995 /**
1996 * {@inheritDoc}
1997 */
1998 public int describeContents() {
1999 return 0;
2000 }
2001
2002 /**
Svetoslav Ganov79311c42012-01-17 20:24:26 -08002003 * Gets the id of the source node.
2004 *
2005 * @return The id.
2006 *
2007 * @hide
2008 */
2009 public long getSourceNodeId() {
2010 return mSourceNodeId;
2011 }
2012
2013 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002014 * Sets if this instance is sealed.
2015 *
2016 * @param sealed Whether is sealed.
2017 *
2018 * @hide
2019 */
2020 public void setSealed(boolean sealed) {
2021 mSealed = sealed;
2022 }
2023
2024 /**
2025 * Gets if this instance is sealed.
2026 *
2027 * @return Whether is sealed.
2028 *
2029 * @hide
2030 */
2031 public boolean isSealed() {
2032 return mSealed;
2033 }
2034
2035 /**
2036 * Enforces that this instance is sealed.
2037 *
2038 * @throws IllegalStateException If this instance is not sealed.
2039 *
2040 * @hide
2041 */
2042 protected void enforceSealed() {
2043 if (!isSealed()) {
2044 throw new IllegalStateException("Cannot perform this "
2045 + "action on a not sealed instance.");
2046 }
2047 }
2048
Svetoslav Ganov2ef69052012-06-04 08:55:16 -07002049 private void enforceValidFocusDirection(int direction) {
2050 switch (direction) {
2051 case View.FOCUS_DOWN:
2052 case View.FOCUS_UP:
2053 case View.FOCUS_LEFT:
2054 case View.FOCUS_RIGHT:
2055 case View.FOCUS_FORWARD:
2056 case View.FOCUS_BACKWARD:
Svetoslav Ganov2ef69052012-06-04 08:55:16 -07002057 return;
2058 default:
2059 throw new IllegalArgumentException("Unknown direction: " + direction);
2060 }
2061 }
2062
2063 private void enforceValidFocusType(int focusType) {
2064 switch (focusType) {
2065 case FOCUS_INPUT:
2066 case FOCUS_ACCESSIBILITY:
2067 return;
2068 default:
2069 throw new IllegalArgumentException("Unknown focus type: " + focusType);
2070 }
2071 }
2072
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002073 /**
2074 * Enforces that this instance is not sealed.
2075 *
2076 * @throws IllegalStateException If this instance is sealed.
2077 *
2078 * @hide
2079 */
2080 protected void enforceNotSealed() {
2081 if (isSealed()) {
2082 throw new IllegalStateException("Cannot perform this "
Ken Wakasaf76a50c2012-03-09 19:56:35 +09002083 + "action on a sealed instance.");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002084 }
2085 }
2086
2087 /**
2088 * Returns a cached instance if such is available otherwise a new one
2089 * and sets the source.
2090 *
Svetoslav Ganov02107852011-10-03 17:06:56 -07002091 * @param source The source view.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002092 * @return An instance.
2093 *
2094 * @see #setSource(View)
2095 */
2096 public static AccessibilityNodeInfo obtain(View source) {
2097 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
2098 info.setSource(source);
2099 return info;
2100 }
2101
2102 /**
Svetoslav Ganov02107852011-10-03 17:06:56 -07002103 * Returns a cached instance if such is available otherwise a new one
2104 * and sets the source.
2105 *
2106 * @param root The root of the virtual subtree.
2107 * @param virtualDescendantId The id of the virtual descendant.
2108 * @return An instance.
2109 *
2110 * @see #setSource(View, int)
2111 */
2112 public static AccessibilityNodeInfo obtain(View root, int virtualDescendantId) {
2113 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
2114 info.setSource(root, virtualDescendantId);
2115 return info;
2116 }
2117
2118 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002119 * Returns a cached instance if such is available otherwise a new one.
2120 *
2121 * @return An instance.
2122 */
2123 public static AccessibilityNodeInfo obtain() {
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -08002124 AccessibilityNodeInfo info = sPool.acquire();
2125 return (info != null) ? info : new AccessibilityNodeInfo();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002126 }
2127
2128 /**
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07002129 * Returns a cached instance if such is available or a new one is
2130 * create. The returned instance is initialized from the given
2131 * <code>info</code>.
2132 *
2133 * @param info The other info.
2134 * @return An instance.
2135 */
2136 public static AccessibilityNodeInfo obtain(AccessibilityNodeInfo info) {
2137 AccessibilityNodeInfo infoClone = AccessibilityNodeInfo.obtain();
2138 infoClone.init(info);
2139 return infoClone;
2140 }
2141
2142 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002143 * Return an instance back to be reused.
2144 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002145 * <strong>Note:</strong> You must not touch the object after calling this function.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002146 *
2147 * @throws IllegalStateException If the info is already recycled.
2148 */
2149 public void recycle() {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002150 clear();
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -08002151 sPool.release(this);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002152 }
2153
2154 /**
2155 * {@inheritDoc}
2156 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002157 * <strong>Note:</strong> After the instance is written to a parcel it
2158 * is recycled. You must not touch the object after calling this function.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002159 * </p>
2160 */
2161 public void writeToParcel(Parcel parcel, int flags) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002162 parcel.writeInt(isSealed() ? 1 : 0);
Svetoslav Ganov02107852011-10-03 17:06:56 -07002163 parcel.writeLong(mSourceNodeId);
2164 parcel.writeInt(mWindowId);
2165 parcel.writeLong(mParentNodeId);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002166 parcel.writeLong(mLabelForId);
2167 parcel.writeLong(mLabeledById);
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002168 parcel.writeInt(mConnectionId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002169
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -08002170 SparseLongArray childIds = mChildNodeIds;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002171 final int childIdsSize = childIds.size();
2172 parcel.writeInt(childIdsSize);
2173 for (int i = 0; i < childIdsSize; i++) {
Svetoslav Ganov02107852011-10-03 17:06:56 -07002174 parcel.writeLong(childIds.valueAt(i));
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002175 }
2176
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002177 parcel.writeInt(mBoundsInParent.top);
2178 parcel.writeInt(mBoundsInParent.bottom);
2179 parcel.writeInt(mBoundsInParent.left);
2180 parcel.writeInt(mBoundsInParent.right);
2181
2182 parcel.writeInt(mBoundsInScreen.top);
2183 parcel.writeInt(mBoundsInScreen.bottom);
2184 parcel.writeInt(mBoundsInScreen.left);
2185 parcel.writeInt(mBoundsInScreen.right);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002186
2187 parcel.writeInt(mActions);
2188
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002189 parcel.writeInt(mMovementGranularities);
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002190
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002191 parcel.writeInt(mBooleanProperties);
2192
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002193 parcel.writeCharSequence(mPackageName);
2194 parcel.writeCharSequence(mClassName);
2195 parcel.writeCharSequence(mText);
2196 parcel.writeCharSequence(mContentDescription);
Svetoslav9fa1ee52013-04-22 12:43:03 -07002197 parcel.writeString(mViewIdResourceName);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002198
Svetoslavbcc46a02013-02-06 11:56:00 -08002199 parcel.writeInt(mTextSelectionStart);
2200 parcel.writeInt(mTextSelectionEnd);
Svetoslav6254f482013-06-04 17:22:14 -07002201 parcel.writeInt(mInputType);
2202
2203 if (mBundle != null) {
2204 parcel.writeInt(1);
2205 parcel.writeBundle(mBundle);
2206 } else {
2207 parcel.writeInt(0);
2208 }
Svetoslavbcc46a02013-02-06 11:56:00 -08002209
Svetoslav3577a282013-06-06 14:09:10 -07002210 if (mRangeInfo != null) {
2211 parcel.writeInt(1);
2212 parcel.writeInt(mRangeInfo.getType());
2213 parcel.writeFloat(mRangeInfo.getMin());
2214 parcel.writeFloat(mRangeInfo.getMax());
2215 parcel.writeFloat(mRangeInfo.getCurrent());
2216 } else {
2217 parcel.writeInt(0);
2218 }
2219
2220 if (mCollectionInfo != null) {
2221 parcel.writeInt(1);
2222 parcel.writeInt(mCollectionInfo.getHorizontalSize());
2223 parcel.writeInt(mCollectionInfo.getVerticalSize());
2224 parcel.writeInt(mCollectionInfo.isHierarchical() ? 1 : 0);
2225 } else {
2226 parcel.writeInt(0);
2227 }
2228
2229 if (mCollectionItemInfo != null) {
2230 parcel.writeInt(1);
2231 parcel.writeInt(mCollectionItemInfo.getHorizontalPosition());
2232 parcel.writeInt(mCollectionItemInfo.getHorizontalSpan());
2233 parcel.writeInt(mCollectionItemInfo.getVerticalPosition());
2234 parcel.writeInt(mCollectionItemInfo.getVerticalSpan());
2235 parcel.writeInt(mCollectionItemInfo.isHeading() ? 1 : 0);
2236 } else {
2237 parcel.writeInt(0);
2238 }
2239
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002240 // Since instances of this class are fetched via synchronous i.e. blocking
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002241 // calls in IPCs we always recycle as soon as the instance is marshaled.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002242 recycle();
2243 }
2244
2245 /**
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07002246 * Initializes this instance from another one.
2247 *
2248 * @param other The other instance.
2249 */
2250 private void init(AccessibilityNodeInfo other) {
2251 mSealed = other.mSealed;
Svetoslav Ganov02107852011-10-03 17:06:56 -07002252 mSourceNodeId = other.mSourceNodeId;
2253 mParentNodeId = other.mParentNodeId;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002254 mLabelForId = other.mLabelForId;
2255 mLabeledById = other.mLabeledById;
Svetoslav Ganov02107852011-10-03 17:06:56 -07002256 mWindowId = other.mWindowId;
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002257 mConnectionId = other.mConnectionId;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07002258 mBoundsInParent.set(other.mBoundsInParent);
2259 mBoundsInScreen.set(other.mBoundsInScreen);
2260 mPackageName = other.mPackageName;
2261 mClassName = other.mClassName;
2262 mText = other.mText;
2263 mContentDescription = other.mContentDescription;
Svetoslav22431a32013-02-05 14:30:19 -08002264 mViewIdResourceName = other.mViewIdResourceName;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07002265 mActions= other.mActions;
2266 mBooleanProperties = other.mBooleanProperties;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002267 mMovementGranularities = other.mMovementGranularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002268 final int otherChildIdCount = other.mChildNodeIds.size();
2269 for (int i = 0; i < otherChildIdCount; i++) {
Svetoslav3577a282013-06-06 14:09:10 -07002270 mChildNodeIds.put(i, other.mChildNodeIds.valueAt(i));
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002271 }
Svetoslavbcc46a02013-02-06 11:56:00 -08002272 mTextSelectionStart = other.mTextSelectionStart;
2273 mTextSelectionEnd = other.mTextSelectionEnd;
Svetoslav6254f482013-06-04 17:22:14 -07002274 mInputType = other.mInputType;
2275 if (other.mBundle != null && !other.mBundle.isEmpty()) {
2276 getBundle().putAll(other.mBundle);
2277 }
Svetoslav3577a282013-06-06 14:09:10 -07002278 mRangeInfo = other.mRangeInfo;
2279 mCollectionInfo = other.mCollectionInfo;
2280 mCollectionItemInfo = other.mCollectionItemInfo;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07002281 }
2282
2283 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002284 * Creates a new instance from a {@link Parcel}.
2285 *
2286 * @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}.
2287 */
2288 private void initFromParcel(Parcel parcel) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002289 mSealed = (parcel.readInt() == 1);
Svetoslav Ganov02107852011-10-03 17:06:56 -07002290 mSourceNodeId = parcel.readLong();
2291 mWindowId = parcel.readInt();
2292 mParentNodeId = parcel.readLong();
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002293 mLabelForId = parcel.readLong();
2294 mLabeledById = parcel.readLong();
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002295 mConnectionId = parcel.readInt();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002296
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -08002297 SparseLongArray childIds = mChildNodeIds;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002298 final int childrenSize = parcel.readInt();
2299 for (int i = 0; i < childrenSize; i++) {
Svetoslav Ganov02107852011-10-03 17:06:56 -07002300 final long childId = parcel.readLong();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002301 childIds.put(i, childId);
2302 }
2303
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002304 mBoundsInParent.top = parcel.readInt();
2305 mBoundsInParent.bottom = parcel.readInt();
2306 mBoundsInParent.left = parcel.readInt();
2307 mBoundsInParent.right = parcel.readInt();
2308
2309 mBoundsInScreen.top = parcel.readInt();
2310 mBoundsInScreen.bottom = parcel.readInt();
2311 mBoundsInScreen.left = parcel.readInt();
2312 mBoundsInScreen.right = parcel.readInt();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002313
2314 mActions = parcel.readInt();
2315
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002316 mMovementGranularities = parcel.readInt();
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002317
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002318 mBooleanProperties = parcel.readInt();
2319
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002320 mPackageName = parcel.readCharSequence();
2321 mClassName = parcel.readCharSequence();
2322 mText = parcel.readCharSequence();
2323 mContentDescription = parcel.readCharSequence();
Svetoslav9fa1ee52013-04-22 12:43:03 -07002324 mViewIdResourceName = parcel.readString();
Svetoslavbcc46a02013-02-06 11:56:00 -08002325
2326 mTextSelectionStart = parcel.readInt();
2327 mTextSelectionEnd = parcel.readInt();
Svetoslav3577a282013-06-06 14:09:10 -07002328
Svetoslav6254f482013-06-04 17:22:14 -07002329 mInputType = parcel.readInt();
2330
2331 if (parcel.readInt() == 1) {
2332 getBundle().putAll(parcel.readBundle());
2333 }
Svetoslav3577a282013-06-06 14:09:10 -07002334
2335 if (parcel.readInt() == 1) {
2336 mRangeInfo = RangeInfo.obtain(
2337 parcel.readInt(),
2338 parcel.readFloat(),
2339 parcel.readFloat(),
2340 parcel.readFloat());
2341 }
2342
2343 if (parcel.readInt() == 1) {
2344 mCollectionInfo = CollectionInfo.obtain(
2345 parcel.readInt(),
2346 parcel.readInt(),
2347 parcel.readInt() == 1);
2348 }
2349
2350 if (parcel.readInt() == 1) {
2351 mCollectionItemInfo = CollectionItemInfo.obtain(
2352 parcel.readInt(),
2353 parcel.readInt(),
2354 parcel.readInt(),
2355 parcel.readInt(),
2356 parcel.readInt() == 1);
2357 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002358 }
2359
2360 /**
2361 * Clears the state of this instance.
2362 */
2363 private void clear() {
2364 mSealed = false;
Svetoslav Ganov0d04e242012-02-21 13:46:36 -08002365 mSourceNodeId = ROOT_NODE_ID;
2366 mParentNodeId = ROOT_NODE_ID;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002367 mLabelForId = ROOT_NODE_ID;
2368 mLabeledById = ROOT_NODE_ID;
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -08002369 mWindowId = UNDEFINED;
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002370 mConnectionId = UNDEFINED;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002371 mMovementGranularities = 0;
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -08002372 mChildNodeIds.clear();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002373 mBoundsInParent.set(0, 0, 0, 0);
2374 mBoundsInScreen.set(0, 0, 0, 0);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002375 mBooleanProperties = 0;
2376 mPackageName = null;
2377 mClassName = null;
2378 mText = null;
2379 mContentDescription = null;
Svetoslav22431a32013-02-05 14:30:19 -08002380 mViewIdResourceName = null;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002381 mActions = 0;
Svetoslavbcc46a02013-02-06 11:56:00 -08002382 mTextSelectionStart = UNDEFINED;
2383 mTextSelectionEnd = UNDEFINED;
Svetoslav6254f482013-06-04 17:22:14 -07002384 mInputType = InputType.TYPE_NULL;
2385 if (mBundle != null) {
2386 mBundle.clear();
2387 }
Svetoslav3577a282013-06-06 14:09:10 -07002388 if (mRangeInfo != null) {
2389 mRangeInfo.recycle();
2390 mRangeInfo = null;
2391 }
2392 if (mCollectionInfo != null) {
2393 mCollectionInfo.recycle();
2394 mCollectionInfo = null;
2395 }
2396 if (mCollectionItemInfo != null) {
2397 mCollectionItemInfo.recycle();
2398 mCollectionItemInfo = null;
2399 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002400 }
2401
2402 /**
2403 * Gets the human readable action symbolic name.
2404 *
2405 * @param action The action.
2406 * @return The symbolic name.
2407 */
2408 private static String getActionSymbolicName(int action) {
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002409 switch (action) {
2410 case ACTION_FOCUS:
2411 return "ACTION_FOCUS";
2412 case ACTION_CLEAR_FOCUS:
2413 return "ACTION_CLEAR_FOCUS";
2414 case ACTION_SELECT:
2415 return "ACTION_SELECT";
2416 case ACTION_CLEAR_SELECTION:
2417 return "ACTION_CLEAR_SELECTION";
Svetoslav Ganove9bda152012-04-30 16:55:21 -07002418 case ACTION_CLICK:
2419 return "ACTION_CLICK";
2420 case ACTION_LONG_CLICK:
2421 return "ACTION_LONG_CLICK";
2422 case ACTION_ACCESSIBILITY_FOCUS:
2423 return "ACTION_ACCESSIBILITY_FOCUS";
2424 case ACTION_CLEAR_ACCESSIBILITY_FOCUS:
2425 return "ACTION_CLEAR_ACCESSIBILITY_FOCUS";
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002426 case ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
2427 return "ACTION_NEXT_AT_MOVEMENT_GRANULARITY";
2428 case ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY:
2429 return "ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY";
Svetoslav Ganove9bda152012-04-30 16:55:21 -07002430 case ACTION_NEXT_HTML_ELEMENT:
2431 return "ACTION_NEXT_HTML_ELEMENT";
2432 case ACTION_PREVIOUS_HTML_ELEMENT:
2433 return "ACTION_PREVIOUS_HTML_ELEMENT";
Svetoslav Ganova1dc7612012-05-10 04:14:53 -07002434 case ACTION_SCROLL_FORWARD:
2435 return "ACTION_SCROLL_FORWARD";
2436 case ACTION_SCROLL_BACKWARD:
2437 return "ACTION_SCROLL_BACKWARD";
Svetoslav Ganov242724e2013-02-01 14:42:18 -08002438 case ACTION_CUT:
2439 return "ACTION_CUT";
2440 case ACTION_COPY:
2441 return "ACTION_COPY";
2442 case ACTION_PASTE:
2443 return "ACTION_PASTE";
2444 case ACTION_SET_SELECTION:
2445 return "ACTION_SET_SELECTION";
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002446 default:
Svetoslav Ganov242724e2013-02-01 14:42:18 -08002447 return"ACTION_UNKNOWN";
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002448 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002449 }
2450
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002451 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002452 * Gets the human readable movement granularity symbolic name.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002453 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002454 * @param granularity The granularity.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002455 * @return The symbolic name.
2456 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002457 private static String getMovementGranularitySymbolicName(int granularity) {
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002458 switch (granularity) {
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002459 case MOVEMENT_GRANULARITY_CHARACTER:
2460 return "MOVEMENT_GRANULARITY_CHARACTER";
2461 case MOVEMENT_GRANULARITY_WORD:
2462 return "MOVEMENT_GRANULARITY_WORD";
2463 case MOVEMENT_GRANULARITY_LINE:
2464 return "MOVEMENT_GRANULARITY_LINE";
2465 case MOVEMENT_GRANULARITY_PARAGRAPH:
2466 return "MOVEMENT_GRANULARITY_PARAGRAPH";
2467 case MOVEMENT_GRANULARITY_PAGE:
2468 return "MOVEMENT_GRANULARITY_PAGE";
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002469 default:
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002470 throw new IllegalArgumentException("Unknown movement granularity: " + granularity);
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002471 }
2472 }
2473
Svetoslav Ganov02107852011-10-03 17:06:56 -07002474 private boolean canPerformRequestOverConnection(long accessibilityNodeId) {
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -08002475 return (mWindowId != UNDEFINED
2476 && getAccessibilityViewId(accessibilityNodeId) != UNDEFINED
2477 && mConnectionId != UNDEFINED);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002478 }
2479
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002480 @Override
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07002481 public boolean equals(Object object) {
2482 if (this == object) {
2483 return true;
2484 }
2485 if (object == null) {
2486 return false;
2487 }
2488 if (getClass() != object.getClass()) {
2489 return false;
2490 }
2491 AccessibilityNodeInfo other = (AccessibilityNodeInfo) object;
Svetoslav Ganov02107852011-10-03 17:06:56 -07002492 if (mSourceNodeId != other.mSourceNodeId) {
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07002493 return false;
2494 }
Svetoslav Ganov02107852011-10-03 17:06:56 -07002495 if (mWindowId != other.mWindowId) {
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07002496 return false;
2497 }
2498 return true;
2499 }
2500
2501 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002502 public int hashCode() {
2503 final int prime = 31;
2504 int result = 1;
Svetoslav Ganov02107852011-10-03 17:06:56 -07002505 result = prime * result + getAccessibilityViewId(mSourceNodeId);
2506 result = prime * result + getVirtualDescendantId(mSourceNodeId);
2507 result = prime * result + mWindowId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002508 return result;
2509 }
2510
2511 @Override
2512 public String toString() {
2513 StringBuilder builder = new StringBuilder();
2514 builder.append(super.toString());
2515
2516 if (DEBUG) {
Svetoslav Ganov02107852011-10-03 17:06:56 -07002517 builder.append("; accessibilityViewId: " + getAccessibilityViewId(mSourceNodeId));
2518 builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId));
2519 builder.append("; mParentNodeId: " + mParentNodeId);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002520
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002521 int granularities = mMovementGranularities;
2522 builder.append("; MovementGranularities: [");
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002523 while (granularities != 0) {
2524 final int granularity = 1 << Integer.numberOfTrailingZeros(granularities);
2525 granularities &= ~granularity;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002526 builder.append(getMovementGranularitySymbolicName(granularity));
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002527 if (granularities != 0) {
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002528 builder.append(", ");
2529 }
2530 }
2531 builder.append("]");
2532
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -08002533 SparseLongArray childIds = mChildNodeIds;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002534 builder.append("; childAccessibilityIds: [");
2535 for (int i = 0, count = childIds.size(); i < count; i++) {
2536 builder.append(childIds.valueAt(i));
2537 if (i < count - 1) {
2538 builder.append(", ");
2539 }
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002540 }
2541 builder.append("]");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002542 }
2543
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002544 builder.append("; boundsInParent: " + mBoundsInParent);
2545 builder.append("; boundsInScreen: " + mBoundsInScreen);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002546
2547 builder.append("; packageName: ").append(mPackageName);
2548 builder.append("; className: ").append(mClassName);
2549 builder.append("; text: ").append(mText);
2550 builder.append("; contentDescription: ").append(mContentDescription);
Svetoslav22431a32013-02-05 14:30:19 -08002551 builder.append("; viewIdResName: ").append(mViewIdResourceName);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002552
2553 builder.append("; checkable: ").append(isCheckable());
2554 builder.append("; checked: ").append(isChecked());
2555 builder.append("; focusable: ").append(isFocusable());
2556 builder.append("; focused: ").append(isFocused());
2557 builder.append("; selected: ").append(isSelected());
2558 builder.append("; clickable: ").append(isClickable());
2559 builder.append("; longClickable: ").append(isLongClickable());
2560 builder.append("; enabled: ").append(isEnabled());
2561 builder.append("; password: ").append(isPassword());
Svetoslav Ganova0156172011-06-26 17:55:44 -07002562 builder.append("; scrollable: " + isScrollable());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002563
2564 builder.append("; [");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002565 for (int actionBits = mActions; actionBits != 0;) {
2566 final int action = 1 << Integer.numberOfTrailingZeros(actionBits);
2567 actionBits &= ~action;
2568 builder.append(getActionSymbolicName(action));
2569 if (actionBits != 0) {
2570 builder.append(", ");
2571 }
2572 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002573 builder.append("]");
2574
2575 return builder.toString();
2576 }
2577
2578 /**
Svetoslav3577a282013-06-06 14:09:10 -07002579 * Class with information if a node is a range. Use
Svetoslav3fcf1ed2013-06-18 13:30:35 -07002580 * {@link RangeInfo#obtain(int, float, float, float) to get an instance.
Svetoslav3577a282013-06-06 14:09:10 -07002581 */
2582 public static final class RangeInfo {
2583 private static final int MAX_POOL_SIZE = 10;
2584
2585 /** Range type: integer. */
2586 public static final int RANGE_TYPE_INT = 0;
2587 /** Range type: float. */
2588 public static final int RANGE_TYPE_FLOAT = 1;
2589 /** Range type: percent with values from zero to one.*/
2590 public static final int RANGE_TYPE_PERCENT = 2;
2591
2592 private static final SynchronizedPool<RangeInfo> sPool =
2593 new SynchronizedPool<AccessibilityNodeInfo.RangeInfo>(MAX_POOL_SIZE);
2594
2595 private int mType;
2596 private float mMin;
2597 private float mMax;
2598 private float mCurrent;
2599
2600 /**
2601 * Obtains a pooled instance.
2602 *
2603 * @param type The type of the range.
2604 * @param min The min value.
2605 * @param max The max value.
2606 * @param current The current value.
2607 */
2608 public static RangeInfo obtain(int type, float min, float max, float current) {
2609 RangeInfo info = sPool.acquire();
2610 return (info != null) ? info : new RangeInfo(type, min, max, current);
2611 }
2612
2613 /**
2614 * Creates a new range.
2615 *
2616 * @param type The type of the range.
2617 * @param min The min value.
2618 * @param max The max value.
2619 * @param current The current value.
2620 */
2621 private RangeInfo(int type, float min, float max, float current) {
2622 mType = type;
2623 mMin = min;
2624 mMax = max;
2625 mCurrent = current;
2626 }
2627
2628 /**
2629 * Gets the range type.
2630 *
2631 * @return The range type.
2632 *
2633 * @see #RANGE_TYPE_INT
2634 * @see #RANGE_TYPE_FLOAT
2635 * @see #RANGE_TYPE_PERCENT
2636 */
2637 public int getType() {
2638 return mType;
2639 }
2640
2641 /**
2642 * Gets the min value.
2643 *
2644 * @return The min value.
2645 */
2646 public float getMin() {
2647 return mMin;
2648 }
2649
2650 /**
2651 * Gets the max value.
2652 *
2653 * @return The max value.
2654 */
2655 public float getMax() {
2656 return mMax;
2657 }
2658
2659 /**
2660 * Gets the current value.
2661 *
2662 * @return The current value.
2663 */
2664 public float getCurrent() {
2665 return mCurrent;
2666 }
2667
2668 /**
2669 * Recycles this instance.
2670 */
2671 void recycle() {
2672 clear();
2673 sPool.release(this);
2674 }
2675
2676 private void clear() {
2677 mType = 0;
2678 mMin = 0;
2679 mMax = 0;
2680 mCurrent = 0;
2681 }
2682 }
2683
2684 /**
2685 * Class with information if a node is a collection. Use
Svetoslav3fcf1ed2013-06-18 13:30:35 -07002686 * {@link CollectionInfo#obtain(int, int, boolean) to an instance.
Svetoslav3577a282013-06-06 14:09:10 -07002687 */
2688 public static final class CollectionInfo {
2689 private static final int MAX_POOL_SIZE = 20;
2690
2691 private static final SynchronizedPool<CollectionInfo> sPool =
2692 new SynchronizedPool<CollectionInfo>(MAX_POOL_SIZE);
2693
2694 private int mHorizontalSize;
2695 private int mVerticalSize;
2696 private boolean mHierarchical;
2697
2698 /**
2699 * Obtains a pooled instance.
2700 *
2701 * @param horizontalSize The horizontal size.
2702 * @param verticalSize The vertical size.
2703 * @param hierarchical Whether the collection is hierarchical.
2704 */
2705 public static CollectionInfo obtain(int horizontalSize, int verticalSize,
2706 boolean hierarchical) {
2707 CollectionInfo info = sPool.acquire();
2708 return (info != null) ? info : new CollectionInfo(horizontalSize,
2709 verticalSize, hierarchical);
2710 }
2711
2712 /**
2713 * Creates a new instance.
2714 *
2715 * @param horizontalSize The horizontal size.
2716 * @param verticalSize The vertical size.
2717 * @param hierarchical Whether the collection is hierarchical.
2718 */
2719 private CollectionInfo(int horizontalSize, int verticalSize,
2720 boolean hierarchical) {
2721 mHorizontalSize = horizontalSize;
2722 mVerticalSize = verticalSize;
2723 mHierarchical = hierarchical;
2724 }
2725
2726 /**
2727 * Gets the horizontal size in terms of item positions.
2728 *
2729 * @return The size.
2730 */
2731 public int getHorizontalSize() {
2732 return mHorizontalSize;
2733 }
2734
2735 /**
2736 * Gets the vertical size in terms of item positions.
2737 *
2738 * @return The size.
2739 */
2740 public int getVerticalSize() {
2741 return mVerticalSize;
2742 }
2743
2744 /**
2745 * Gets if the collection is a hierarchically ordered.
2746 *
2747 * @return Whether the collection is hierarchical.
2748 */
2749 public boolean isHierarchical() {
2750 return mHierarchical;
2751 }
2752
2753 /**
2754 * Recycles this instance.
2755 */
2756 void recycle() {
2757 clear();
2758 sPool.release(this);
2759 }
2760
2761 private void clear() {
2762 mHorizontalSize = 0;
2763 mVerticalSize = 0;
2764 mHierarchical = false;
2765 }
2766 }
2767
2768 /**
2769 * Class with information if a node is a collection item. Use
Svetoslav3fcf1ed2013-06-18 13:30:35 -07002770 * {@link CollectionItemInfo#obtain(int, int, int, int, boolean) to get an instance.
Svetoslav3577a282013-06-06 14:09:10 -07002771 */
2772 public static final class CollectionItemInfo {
2773 private static final int MAX_POOL_SIZE = 20;
2774
2775 private static final SynchronizedPool<CollectionItemInfo> sPool =
2776 new SynchronizedPool<CollectionItemInfo>(MAX_POOL_SIZE);
2777
2778 /**
2779 * Obtains a pooled instance.
2780 *
2781 * @param horizontalPosition The horizontal item position.
2782 * @param horizontalSpan The horizontal item span.
2783 * @param verticalPosition The vertical item position.
2784 * @param verticalSpan The vertical item span.
2785 * @param heading Whether the item is a heading.
2786 */
2787 public static CollectionItemInfo obtain(int horizontalPosition, int horizontalSpan,
2788 int verticalPosition, int verticalSpan, boolean heading) {
2789 CollectionItemInfo info = sPool.acquire();
2790 return (info != null) ? info : new CollectionItemInfo(horizontalPosition,
2791 horizontalSpan, verticalPosition, verticalSpan, heading);
2792 }
2793
2794 private boolean mHeading;
2795 private int mHorizontalPosition;
2796 private int mVerticalPosition;
2797 private int mHorizontalSpan;
2798 private int mVerticalSpan;
2799
2800 /**
2801 * Creates a new instance.
2802 *
2803 * @param horizontalPosition The horizontal item position.
2804 * @param horizontalSpan The horizontal item span.
2805 * @param verticalPosition The vertical item position.
2806 * @param verticalSpan The vertical item span.
2807 * @param heading Whether the item is a heading.
2808 */
2809 private CollectionItemInfo(int horizontalPosition, int horizontalSpan,
2810 int verticalPosition, int verticalSpan, boolean heading) {
2811 mHorizontalPosition = horizontalPosition;
2812 mHorizontalSpan = horizontalSpan;
2813 mVerticalPosition = verticalPosition;
2814 mVerticalSpan = verticalSpan;
2815 mHeading = heading;
2816 }
2817
2818 /**
2819 * Gets the horizontal item position in the parent collection.
2820 *
2821 * @return The position.
2822 */
2823 public int getHorizontalPosition() {
2824 return mHorizontalPosition;
2825 }
2826
2827 /**
2828 * Gets the vertical item position in the parent collection.
2829 *
2830 * @return The position.
2831 */
2832 public int getVerticalPosition() {
2833 return mVerticalPosition;
2834 }
2835
2836 /**
2837 * Gets the horizontal span in terms of item positions
2838 * of the parent collection.
2839 *
2840 * @return The span.
2841 */
2842 public int getHorizontalSpan() {
2843 return mHorizontalSpan;
2844 }
2845
2846 /**
2847 * Gets the vertical span in terms of item positions
2848 * of the parent collection.
2849 *
2850 * @return The span.
2851 */
2852 public int getVerticalSpan() {
2853 return mVerticalSpan;
2854 }
2855
2856 /**
2857 * Gets if the collection item is a heading. For example, section
2858 * heading, table header, etc.
2859 *
2860 * @return If the item is a heading.
2861 */
2862 public boolean isHeading() {
2863 return mHeading;
2864 }
2865
2866 /**
2867 * Recycles this instance.
2868 */
2869 void recycle() {
2870 clear();
2871 sPool.release(this);
2872 }
2873
2874 private void clear() {
2875 mHorizontalPosition = 0;
2876 mHorizontalSpan = 0;
2877 mVerticalPosition = 0;
2878 mVerticalSpan = 0;
2879 mHeading = false;
2880 }
2881 }
2882
2883 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002884 * @see Parcelable.Creator
2885 */
2886 public static final Parcelable.Creator<AccessibilityNodeInfo> CREATOR =
2887 new Parcelable.Creator<AccessibilityNodeInfo>() {
2888 public AccessibilityNodeInfo createFromParcel(Parcel parcel) {
2889 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
2890 info.initFromParcel(parcel);
2891 return info;
2892 }
2893
2894 public AccessibilityNodeInfo[] newArray(int size) {
2895 return new AccessibilityNodeInfo[size];
2896 }
2897 };
2898}