blob: 750e0226f2fec839a45a3dafd4351674308a5c76 [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 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700271 * Argument for which movement granularity to be used when traversing the node text.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700272 * <p>
273 * <strong>Type:</strong> int<br>
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700274 * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_MOVEMENT_GRANULARITY},
275 * {@link #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700276 * </p>
Svetoslav7c512842013-01-30 23:02:08 -0800277 *
278 * @see #ACTION_NEXT_AT_MOVEMENT_GRANULARITY
279 * @see #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700280 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700281 public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT =
Svetoslav7c512842013-01-30 23:02:08 -0800282 "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700283
284 /**
285 * Argument for which HTML element to get moving to the next/previous HTML element.
286 * <p>
287 * <strong>Type:</strong> String<br>
288 * <strong>Actions:</strong> {@link #ACTION_NEXT_HTML_ELEMENT},
289 * {@link #ACTION_PREVIOUS_HTML_ELEMENT}
290 * </p>
Svetoslav7c512842013-01-30 23:02:08 -0800291 *
292 * @see #ACTION_NEXT_HTML_ELEMENT
293 * @see #ACTION_PREVIOUS_HTML_ELEMENT
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700294 */
295 public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING =
Svetoslav7c512842013-01-30 23:02:08 -0800296 "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
297
298 /**
299 * Argument for whether when moving at granularity to extend the selection
300 * or to move it otherwise.
301 * <p>
302 * <strong>Type:</strong> boolean<br>
303 * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_MOVEMENT_GRANULARITY},
304 * {@link #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}
305 * </p>
306 *
307 * @see #ACTION_NEXT_AT_MOVEMENT_GRANULARITY
308 * @see #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
309 */
310 public static final String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN =
311 "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
312
313 /**
314 * Argument for specifying the selection start.
315 * <p>
316 * <strong>Type:</strong> int<br>
317 * <strong>Actions:</strong> {@link #ACTION_SET_SELECTION}
318 * </p>
319 *
320 * @see #ACTION_SET_SELECTION
321 */
322 public static final String ACTION_ARGUMENT_SELECTION_START_INT =
323 "ACTION_ARGUMENT_SELECTION_START_INT";
324
325 /**
326 * Argument for specifying the selection end.
327 * <p>
328 * <strong>Type:</strong> int<br>
329 * <strong>Actions:</strong> {@link #ACTION_SET_SELECTION}
330 * </p>
331 *
332 * @see #ACTION_SET_SELECTION
333 */
334 public static final String ACTION_ARGUMENT_SELECTION_END_INT =
335 "ACTION_ARGUMENT_SELECTION_END_INT";
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700336
337 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700338 * The input focus.
339 */
340 public static final int FOCUS_INPUT = 1;
341
342 /**
343 * The accessibility focus.
344 */
345 public static final int FOCUS_ACCESSIBILITY = 2;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700346
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700347 // Movement granularities
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700348
349 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700350 * Movement granularity bit for traversing the text of a node by character.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700351 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700352 public static final int MOVEMENT_GRANULARITY_CHARACTER = 0x00000001;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700353
354 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700355 * Movement granularity bit for traversing the text of a node by word.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700356 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700357 public static final int MOVEMENT_GRANULARITY_WORD = 0x00000002;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700358
359 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700360 * Movement granularity bit for traversing the text of a node by line.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700361 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700362 public static final int MOVEMENT_GRANULARITY_LINE = 0x00000004;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700363
364 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700365 * Movement granularity bit for traversing the text of a node by paragraph.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700366 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700367 public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 0x00000008;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700368
369 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700370 * Movement granularity bit for traversing the text of a node by page.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700371 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700372 public static final int MOVEMENT_GRANULARITY_PAGE = 0x00000010;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700373
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700374 // Boolean attributes.
375
Svetoslavbcc46a02013-02-06 11:56:00 -0800376 private static final int BOOLEAN_PROPERTY_CHECKABLE = 0x00000001;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700377
Svetoslavbcc46a02013-02-06 11:56:00 -0800378 private static final int BOOLEAN_PROPERTY_CHECKED = 0x00000002;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700379
Svetoslavbcc46a02013-02-06 11:56:00 -0800380 private static final int BOOLEAN_PROPERTY_FOCUSABLE = 0x00000004;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700381
Svetoslavbcc46a02013-02-06 11:56:00 -0800382 private static final int BOOLEAN_PROPERTY_FOCUSED = 0x00000008;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700383
Svetoslavbcc46a02013-02-06 11:56:00 -0800384 private static final int BOOLEAN_PROPERTY_SELECTED = 0x00000010;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700385
Svetoslavbcc46a02013-02-06 11:56:00 -0800386 private static final int BOOLEAN_PROPERTY_CLICKABLE = 0x00000020;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700387
Svetoslavbcc46a02013-02-06 11:56:00 -0800388 private static final int BOOLEAN_PROPERTY_LONG_CLICKABLE = 0x00000040;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700389
Svetoslavbcc46a02013-02-06 11:56:00 -0800390 private static final int BOOLEAN_PROPERTY_ENABLED = 0x00000080;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700391
Svetoslavbcc46a02013-02-06 11:56:00 -0800392 private static final int BOOLEAN_PROPERTY_PASSWORD = 0x00000100;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700393
Svetoslavbcc46a02013-02-06 11:56:00 -0800394 private static final int BOOLEAN_PROPERTY_SCROLLABLE = 0x00000200;
Svetoslav Ganova0156172011-06-26 17:55:44 -0700395
Svetoslavbcc46a02013-02-06 11:56:00 -0800396 private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED = 0x00000400;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700397
Svetoslavbcc46a02013-02-06 11:56:00 -0800398 private static final int BOOLEAN_PROPERTY_VISIBLE_TO_USER = 0x00000800;
399
400 private static final int BOOLEAN_PROPERTY_EDITABLE = 0x00001000;
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -0700401
Svetoslav Ganov02107852011-10-03 17:06:56 -0700402 /**
403 * Bits that provide the id of a virtual descendant of a view.
404 */
405 private static final long VIRTUAL_DESCENDANT_ID_MASK = 0xffffffff00000000L;
406
407 /**
408 * Bit shift of {@link #VIRTUAL_DESCENDANT_ID_MASK} to get to the id for a
409 * virtual descendant of a view. Such a descendant does not exist in the view
410 * hierarchy and is only reported via the accessibility APIs.
411 */
412 private static final int VIRTUAL_DESCENDANT_ID_SHIFT = 32;
413
414 /**
415 * Gets the accessibility view id which identifies a View in the view three.
416 *
417 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}.
418 * @return The accessibility view id part of the node id.
419 *
420 * @hide
421 */
422 public static int getAccessibilityViewId(long accessibilityNodeId) {
423 return (int) accessibilityNodeId;
424 }
425
426 /**
427 * Gets the virtual descendant id which identifies an imaginary view in a
428 * containing View.
429 *
430 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}.
431 * @return The virtual view id part of the node id.
432 *
433 * @hide
434 */
435 public static int getVirtualDescendantId(long accessibilityNodeId) {
436 return (int) ((accessibilityNodeId & VIRTUAL_DESCENDANT_ID_MASK)
437 >> VIRTUAL_DESCENDANT_ID_SHIFT);
438 }
439
440 /**
441 * Makes a node id by shifting the <code>virtualDescendantId</code>
442 * by {@link #VIRTUAL_DESCENDANT_ID_SHIFT} and taking
443 * the bitwise or with the <code>accessibilityViewId</code>.
444 *
445 * @param accessibilityViewId A View accessibility id.
446 * @param virtualDescendantId A virtual descendant id.
447 * @return The node id.
448 *
449 * @hide
450 */
451 public static long makeNodeId(int accessibilityViewId, int virtualDescendantId) {
452 return (((long) virtualDescendantId) << VIRTUAL_DESCENDANT_ID_SHIFT) | accessibilityViewId;
453 }
454
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700455 // Housekeeping.
456 private static final int MAX_POOL_SIZE = 50;
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -0800457 private static final SynchronizedPool<AccessibilityNodeInfo> sPool =
458 new SynchronizedPool<AccessibilityNodeInfo>(MAX_POOL_SIZE);
459
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700460 private boolean mSealed;
461
462 // Data.
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800463 private int mWindowId = UNDEFINED;
Svetoslav Ganov0d04e242012-02-21 13:46:36 -0800464 private long mSourceNodeId = ROOT_NODE_ID;
465 private long mParentNodeId = ROOT_NODE_ID;
Svetoslav Ganov33aef982012-09-13 12:49:03 -0700466 private long mLabelForId = ROOT_NODE_ID;
467 private long mLabeledById = ROOT_NODE_ID;
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800468
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700469 private int mBooleanProperties;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700470 private final Rect mBoundsInParent = new Rect();
471 private final Rect mBoundsInScreen = new Rect();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700472
473 private CharSequence mPackageName;
474 private CharSequence mClassName;
475 private CharSequence mText;
476 private CharSequence mContentDescription;
Svetoslav9fa1ee52013-04-22 12:43:03 -0700477 private String mViewIdResourceName;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700478
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700479 private final SparseLongArray mChildNodeIds = new SparseLongArray();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700480 private int mActions;
481
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700482 private int mMovementGranularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700483
Svetoslavbcc46a02013-02-06 11:56:00 -0800484 private int mTextSelectionStart = UNDEFINED;
485 private int mTextSelectionEnd = UNDEFINED;
Svetoslav6254f482013-06-04 17:22:14 -0700486 private int mInputType = InputType.TYPE_NULL;
487
488 private Bundle mBundle;
Svetoslavbcc46a02013-02-06 11:56:00 -0800489
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -0800490 private int mConnectionId = UNDEFINED;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700491
492 /**
493 * Hide constructor from clients.
494 */
495 private AccessibilityNodeInfo() {
496 /* do nothing */
497 }
498
499 /**
500 * Sets the source.
Svetoslav Ganov02107852011-10-03 17:06:56 -0700501 * <p>
502 * <strong>Note:</strong> Cannot be called from an
503 * {@link android.accessibilityservice.AccessibilityService}.
504 * This class is made immutable before being delivered to an AccessibilityService.
505 * </p>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700506 *
507 * @param source The info source.
508 */
509 public void setSource(View source) {
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800510 setSource(source, UNDEFINED);
Svetoslav Ganov02107852011-10-03 17:06:56 -0700511 }
512
513 /**
514 * Sets the source to be a virtual descendant of the given <code>root</code>.
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700515 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
Svetoslav Ganov02107852011-10-03 17:06:56 -0700516 * is set as the source.
517 * <p>
518 * A virtual descendant is an imaginary View that is reported as a part of the view
519 * hierarchy for accessibility purposes. This enables custom views that draw complex
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700520 * content to report themselves as a tree of virtual views, thus conveying their
Svetoslav Ganov02107852011-10-03 17:06:56 -0700521 * logical structure.
522 * </p>
523 * <p>
524 * <strong>Note:</strong> Cannot be called from an
525 * {@link android.accessibilityservice.AccessibilityService}.
526 * This class is made immutable before being delivered to an AccessibilityService.
527 * </p>
528 *
529 * @param root The root of the virtual subtree.
530 * @param virtualDescendantId The id of the virtual descendant.
531 */
532 public void setSource(View root, int virtualDescendantId) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700533 enforceNotSealed();
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800534 mWindowId = (root != null) ? root.getAccessibilityWindowId() : UNDEFINED;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700535 final int rootAccessibilityViewId =
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800536 (root != null) ? root.getAccessibilityViewId() : UNDEFINED;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700537 mSourceNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700538 }
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700539
Svetoslav Ganov42138042012-03-20 11:51:39 -0700540 /**
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700541 * Find the view that has the specified focus type. The search starts from
Svetoslav Ganov42138042012-03-20 11:51:39 -0700542 * the view represented by this node info.
543 *
544 * @param focus The focus to find. One of {@link #FOCUS_INPUT} or
545 * {@link #FOCUS_ACCESSIBILITY}.
546 * @return The node info of the focused view or null.
547 *
548 * @see #FOCUS_INPUT
549 * @see #FOCUS_ACCESSIBILITY
550 */
551 public AccessibilityNodeInfo findFocus(int focus) {
552 enforceSealed();
Svetoslav Ganov2ef69052012-06-04 08:55:16 -0700553 enforceValidFocusType(focus);
Svetoslav Ganov42138042012-03-20 11:51:39 -0700554 if (!canPerformRequestOverConnection(mSourceNodeId)) {
555 return null;
556 }
557 return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId, mWindowId,
558 mSourceNodeId, focus);
559 }
560
561 /**
562 * Searches for the nearest view in the specified direction that can take
563 * the input focus.
564 *
565 * @param direction The direction. Can be one of:
566 * {@link View#FOCUS_DOWN},
567 * {@link View#FOCUS_UP},
568 * {@link View#FOCUS_LEFT},
569 * {@link View#FOCUS_RIGHT},
570 * {@link View#FOCUS_FORWARD},
Svetoslav Ganov8ffe8b32012-06-15 10:31:31 -0700571 * {@link View#FOCUS_BACKWARD}.
Svetoslav Ganov42138042012-03-20 11:51:39 -0700572 *
573 * @return The node info for the view that can take accessibility focus.
574 */
575 public AccessibilityNodeInfo focusSearch(int direction) {
576 enforceSealed();
Svetoslav Ganov2ef69052012-06-04 08:55:16 -0700577 enforceValidFocusDirection(direction);
Svetoslav Ganov42138042012-03-20 11:51:39 -0700578 if (!canPerformRequestOverConnection(mSourceNodeId)) {
579 return null;
580 }
581 return AccessibilityInteractionClient.getInstance().focusSearch(mConnectionId, mWindowId,
582 mSourceNodeId, direction);
583 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700584
585 /**
586 * Gets the id of the window from which the info comes from.
587 *
588 * @return The window id.
589 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700590 public int getWindowId() {
Svetoslav Ganov02107852011-10-03 17:06:56 -0700591 return mWindowId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700592 }
593
594 /**
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800595 * Refreshes this info with the latest state of the view it represents.
596 * <p>
597 * <strong>Note:</strong> If this method returns false this info is obsolete
598 * since it represents a view that is no longer in the view tree and should
599 * be recycled.
600 * </p>
Svetoslav6254f482013-06-04 17:22:14 -0700601 *
602 * @param bypassCache Whether to bypass the cache.
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800603 * @return Whether the refresh succeeded.
Svetoslav6254f482013-06-04 17:22:14 -0700604 *
605 * @hide
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800606 */
Svetoslav6254f482013-06-04 17:22:14 -0700607 public boolean refresh(boolean bypassCache) {
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800608 enforceSealed();
609 if (!canPerformRequestOverConnection(mSourceNodeId)) {
610 return false;
611 }
612 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
613 AccessibilityNodeInfo refreshedInfo = client.findAccessibilityNodeInfoByAccessibilityId(
Svetoslav6254f482013-06-04 17:22:14 -0700614 mConnectionId, mWindowId, mSourceNodeId, bypassCache, 0);
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800615 if (refreshedInfo == null) {
616 return false;
617 }
618 init(refreshedInfo);
619 refreshedInfo.recycle();
620 return true;
621 }
622
623 /**
Svetoslav6254f482013-06-04 17:22:14 -0700624 * Refreshes this info with the latest state of the view it represents.
625 * <p>
626 * <strong>Note:</strong> If this method returns false this info is obsolete
627 * since it represents a view that is no longer in the view tree and should
628 * be recycled.
629 * </p>
630 * @return Whether the refresh succeeded.
631 */
632 public boolean refresh() {
633 return refresh(false);
634 }
635
636 /**
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800637 * @return The ids of the children.
638 *
639 * @hide
640 */
641 public SparseLongArray getChildNodeIds() {
642 return mChildNodeIds;
643 }
644
645 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700646 * Gets the number of children.
647 *
648 * @return The child count.
649 */
650 public int getChildCount() {
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800651 return mChildNodeIds.size();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700652 }
653
654 /**
655 * Get the child at given index.
656 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700657 * <strong>Note:</strong> It is a client responsibility to recycle the
658 * received info by calling {@link AccessibilityNodeInfo#recycle()}
659 * to avoid creating of multiple instances.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700660 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700661 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700662 * @param index The child index.
663 * @return The child node.
664 *
665 * @throws IllegalStateException If called outside of an AccessibilityService.
666 *
667 */
668 public AccessibilityNodeInfo getChild(int index) {
669 enforceSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -0700670 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700671 return null;
672 }
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800673 final long childId = mChildNodeIds.get(index);
Svetoslav Ganov8bd69612011-08-23 13:40:30 -0700674 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800675 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId,
Svetoslav6254f482013-06-04 17:22:14 -0700676 childId, false, FLAG_PREFETCH_DESCENDANTS);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700677 }
678
679 /**
680 * Adds a child.
681 * <p>
Svetoslav Ganov02107852011-10-03 17:06:56 -0700682 * <strong>Note:</strong> Cannot be called from an
683 * {@link android.accessibilityservice.AccessibilityService}.
684 * This class is made immutable before being delivered to an AccessibilityService.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700685 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700686 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700687 * @param child The child.
688 *
689 * @throws IllegalStateException If called from an AccessibilityService.
690 */
691 public void addChild(View child) {
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800692 addChild(child, UNDEFINED);
Svetoslav Ganov02107852011-10-03 17:06:56 -0700693 }
694
695 /**
696 * Adds a virtual child which is a descendant of the given <code>root</code>.
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700697 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
Svetoslav Ganov02107852011-10-03 17:06:56 -0700698 * is added as a child.
699 * <p>
700 * A virtual descendant is an imaginary View that is reported as a part of the view
701 * hierarchy for accessibility purposes. This enables custom views that draw complex
702 * content to report them selves as a tree of virtual views, thus conveying their
703 * logical structure.
704 * </p>
705 *
706 * @param root The root of the virtual subtree.
707 * @param virtualDescendantId The id of the virtual child.
708 */
709 public void addChild(View root, int virtualDescendantId) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700710 enforceNotSealed();
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800711 final int index = mChildNodeIds.size();
Svetoslav Ganov02107852011-10-03 17:06:56 -0700712 final int rootAccessibilityViewId =
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800713 (root != null) ? root.getAccessibilityViewId() : UNDEFINED;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700714 final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800715 mChildNodeIds.put(index, childNodeId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700716 }
717
718 /**
719 * Gets the actions that can be performed on the node.
720 *
721 * @return The bit mask of with actions.
722 *
723 * @see AccessibilityNodeInfo#ACTION_FOCUS
724 * @see AccessibilityNodeInfo#ACTION_CLEAR_FOCUS
725 * @see AccessibilityNodeInfo#ACTION_SELECT
726 * @see AccessibilityNodeInfo#ACTION_CLEAR_SELECTION
Svetoslav Ganova1dc7612012-05-10 04:14:53 -0700727 * @see AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS
728 * @see AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS
729 * @see AccessibilityNodeInfo#ACTION_CLICK
730 * @see AccessibilityNodeInfo#ACTION_LONG_CLICK
731 * @see AccessibilityNodeInfo#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
732 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
733 * @see AccessibilityNodeInfo#ACTION_NEXT_HTML_ELEMENT
734 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_HTML_ELEMENT
735 * @see AccessibilityNodeInfo#ACTION_SCROLL_FORWARD
736 * @see AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700737 */
738 public int getActions() {
739 return mActions;
740 }
741
742 /**
743 * Adds an action that can be performed on the node.
744 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700745 * <strong>Note:</strong> Cannot be called from an
746 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700747 * This class is made immutable before being delivered to an AccessibilityService.
748 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700749 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700750 * @param action The action.
751 *
752 * @throws IllegalStateException If called from an AccessibilityService.
753 */
754 public void addAction(int action) {
755 enforceNotSealed();
756 mActions |= action;
757 }
758
759 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700760 * Sets the movement granularities for traversing the text of this node.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700761 * <p>
762 * <strong>Note:</strong> Cannot be called from an
763 * {@link android.accessibilityservice.AccessibilityService}.
764 * This class is made immutable before being delivered to an AccessibilityService.
765 * </p>
766 *
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700767 * @param granularities The bit mask with granularities.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700768 *
769 * @throws IllegalStateException If called from an AccessibilityService.
770 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700771 public void setMovementGranularities(int granularities) {
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700772 enforceNotSealed();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700773 mMovementGranularities = granularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700774 }
775
776 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700777 * Gets the movement granularities for traversing the text of this node.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700778 *
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700779 * @return The bit mask with granularities.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700780 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700781 public int getMovementGranularities() {
782 return mMovementGranularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700783 }
784
785 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700786 * Performs an action on the node.
787 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700788 * <strong>Note:</strong> An action can be performed only if the request is made
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700789 * from an {@link android.accessibilityservice.AccessibilityService}.
790 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700791 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700792 * @param action The action to perform.
793 * @return True if the action was performed.
794 *
795 * @throws IllegalStateException If called outside of an AccessibilityService.
796 */
797 public boolean performAction(int action) {
798 enforceSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -0700799 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700800 return false;
801 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -0700802 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700803 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
804 action, null);
805 }
806
807 /**
808 * Performs an action on the node.
809 * <p>
810 * <strong>Note:</strong> An action can be performed only if the request is made
811 * from an {@link android.accessibilityservice.AccessibilityService}.
812 * </p>
813 *
814 * @param action The action to perform.
815 * @param arguments A bundle with additional arguments.
816 * @return True if the action was performed.
817 *
818 * @throws IllegalStateException If called outside of an AccessibilityService.
819 */
820 public boolean performAction(int action, Bundle arguments) {
821 enforceSealed();
822 if (!canPerformRequestOverConnection(mSourceNodeId)) {
823 return false;
824 }
825 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
826 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
827 action, arguments);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700828 }
829
830 /**
831 * Finds {@link AccessibilityNodeInfo}s by text. The match is case
Svetoslav Ganov86398bd2011-06-21 17:38:43 -0700832 * insensitive containment. The search is relative to this info i.e.
833 * this info is the root of the traversed tree.
Svetoslav Ganovea515ae2011-09-14 18:15:32 -0700834 *
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700835 * <p>
836 * <strong>Note:</strong> It is a client responsibility to recycle the
837 * received info by calling {@link AccessibilityNodeInfo#recycle()}
838 * to avoid creating of multiple instances.
839 * </p>
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700840 *
841 * @param text The searched text.
842 * @return A list of node info.
843 */
844 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text) {
845 enforceSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -0700846 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganov86398bd2011-06-21 17:38:43 -0700847 return Collections.emptyList();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700848 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -0700849 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganov79311c42012-01-17 20:24:26 -0800850 return client.findAccessibilityNodeInfosByText(mConnectionId, mWindowId, mSourceNodeId,
851 text);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700852 }
853
854 /**
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800855 * Finds {@link AccessibilityNodeInfo}s by the fully qualified view id's resource
856 * name where a fully qualified id is of the from "package:id/id_resource_name".
857 * For example, if the target application's package is "foo.bar" and the id
858 * resource name is "baz", the fully qualified resource id is "foo.bar:id/baz".
859 *
860 * <p>
861 * <strong>Note:</strong> It is a client responsibility to recycle the
862 * received info by calling {@link AccessibilityNodeInfo#recycle()}
863 * to avoid creating of multiple instances.
864 * </p>
865 * <p>
866 * <strong>Note:</strong> The primary usage of this API is for UI test automation
867 * and in order to report the fully qualified view id if an {@link AccessibilityNodeInfo}
868 * the client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
Svetoslav14ff9962013-01-29 03:21:37 -0800869 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800870 * </p>
871 *
872 * @param viewId The fully qualified resource name of the view id to find.
873 * @return A list of node info.
874 */
875 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId(String viewId) {
876 enforceSealed();
877 if (!canPerformRequestOverConnection(mSourceNodeId)) {
878 return Collections.emptyList();
879 }
880 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
881 return client.findAccessibilityNodeInfosByViewId(mConnectionId, mWindowId, mSourceNodeId,
882 viewId);
883 }
884
885 /**
Svetoslav Ganov00aabf72011-07-21 11:35:03 -0700886 * Gets the parent.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700887 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700888 * <strong>Note:</strong> It is a client responsibility to recycle the
889 * received info by calling {@link AccessibilityNodeInfo#recycle()}
890 * to avoid creating of multiple instances.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700891 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700892 *
Svetoslav Ganov00aabf72011-07-21 11:35:03 -0700893 * @return The parent.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700894 */
895 public AccessibilityNodeInfo getParent() {
896 enforceSealed();
Svetoslav Ganovaf0d9842011-10-26 15:29:26 -0700897 if (!canPerformRequestOverConnection(mParentNodeId)) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700898 return null;
899 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -0700900 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -0800901 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
Svetoslav6254f482013-06-04 17:22:14 -0700902 mWindowId, mParentNodeId, false, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800903 }
904
905 /**
906 * @return The parent node id.
907 *
908 * @hide
909 */
910 public long getParentNodeId() {
911 return mParentNodeId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700912 }
913
914 /**
915 * Sets the parent.
916 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700917 * <strong>Note:</strong> Cannot be called from an
918 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700919 * This class is made immutable before being delivered to an AccessibilityService.
920 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700921 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700922 * @param parent The parent.
923 *
924 * @throws IllegalStateException If called from an AccessibilityService.
925 */
926 public void setParent(View parent) {
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800927 setParent(parent, UNDEFINED);
Svetoslav Ganov02107852011-10-03 17:06:56 -0700928 }
929
930 /**
931 * Sets the parent to be a virtual descendant of the given <code>root</code>.
932 * If <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root
933 * is set as the parent.
934 * <p>
935 * A virtual descendant is an imaginary View that is reported as a part of the view
936 * hierarchy for accessibility purposes. This enables custom views that draw complex
937 * content to report them selves as a tree of virtual views, thus conveying their
938 * logical structure.
939 * </p>
940 * <p>
941 * <strong>Note:</strong> Cannot be called from an
942 * {@link android.accessibilityservice.AccessibilityService}.
943 * This class is made immutable before being delivered to an AccessibilityService.
944 * </p>
945 *
946 * @param root The root of the virtual subtree.
947 * @param virtualDescendantId The id of the virtual descendant.
948 */
949 public void setParent(View root, int virtualDescendantId) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700950 enforceNotSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -0700951 final int rootAccessibilityViewId =
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800952 (root != null) ? root.getAccessibilityViewId() : UNDEFINED;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700953 mParentNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700954 }
955
956 /**
957 * Gets the node bounds in parent coordinates.
958 *
959 * @param outBounds The output node bounds.
960 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700961 public void getBoundsInParent(Rect outBounds) {
962 outBounds.set(mBoundsInParent.left, mBoundsInParent.top,
963 mBoundsInParent.right, mBoundsInParent.bottom);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700964 }
965
966 /**
967 * Sets the node bounds in parent coordinates.
968 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700969 * <strong>Note:</strong> Cannot be called from an
970 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700971 * This class is made immutable before being delivered to an AccessibilityService.
972 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700973 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700974 * @param bounds The node bounds.
975 *
976 * @throws IllegalStateException If called from an AccessibilityService.
977 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700978 public void setBoundsInParent(Rect bounds) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700979 enforceNotSealed();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700980 mBoundsInParent.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
981 }
982
983 /**
984 * Gets the node bounds in screen coordinates.
985 *
986 * @param outBounds The output node bounds.
987 */
988 public void getBoundsInScreen(Rect outBounds) {
989 outBounds.set(mBoundsInScreen.left, mBoundsInScreen.top,
990 mBoundsInScreen.right, mBoundsInScreen.bottom);
991 }
992
993 /**
994 * Sets the node bounds in screen coordinates.
995 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700996 * <strong>Note:</strong> Cannot be called from an
997 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700998 * This class is made immutable before being delivered to an AccessibilityService.
999 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001000 *
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001001 * @param bounds The node bounds.
1002 *
1003 * @throws IllegalStateException If called from an AccessibilityService.
1004 */
1005 public void setBoundsInScreen(Rect bounds) {
1006 enforceNotSealed();
1007 mBoundsInScreen.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001008 }
1009
1010 /**
1011 * Gets whether this node is checkable.
1012 *
1013 * @return True if the node is checkable.
1014 */
1015 public boolean isCheckable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001016 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001017 }
1018
1019 /**
1020 * Sets whether this node is checkable.
1021 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001022 * <strong>Note:</strong> Cannot be called from an
1023 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001024 * This class is made immutable before being delivered to an AccessibilityService.
1025 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001026 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001027 * @param checkable True if the node is checkable.
1028 *
1029 * @throws IllegalStateException If called from an AccessibilityService.
1030 */
1031 public void setCheckable(boolean checkable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001032 setBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE, checkable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001033 }
1034
1035 /**
1036 * Gets whether this node is checked.
1037 *
1038 * @return True if the node is checked.
1039 */
1040 public boolean isChecked() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001041 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001042 }
1043
1044 /**
1045 * Sets whether this node is checked.
1046 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001047 * <strong>Note:</strong> Cannot be called from an
1048 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001049 * This class is made immutable before being delivered to an AccessibilityService.
1050 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001051 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001052 * @param checked True if the node is checked.
1053 *
1054 * @throws IllegalStateException If called from an AccessibilityService.
1055 */
1056 public void setChecked(boolean checked) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001057 setBooleanProperty(BOOLEAN_PROPERTY_CHECKED, checked);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001058 }
1059
1060 /**
1061 * Gets whether this node is focusable.
1062 *
1063 * @return True if the node is focusable.
1064 */
1065 public boolean isFocusable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001066 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001067 }
1068
1069 /**
1070 * Sets whether this node is focusable.
1071 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001072 * <strong>Note:</strong> Cannot be called from an
1073 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001074 * This class is made immutable before being delivered to an AccessibilityService.
1075 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001076 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001077 * @param focusable True if the node is focusable.
1078 *
1079 * @throws IllegalStateException If called from an AccessibilityService.
1080 */
1081 public void setFocusable(boolean focusable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001082 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE, focusable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001083 }
1084
1085 /**
1086 * Gets whether this node is focused.
1087 *
1088 * @return True if the node is focused.
1089 */
1090 public boolean isFocused() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001091 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001092 }
1093
1094 /**
1095 * Sets whether this node is focused.
1096 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001097 * <strong>Note:</strong> Cannot be called from an
1098 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001099 * This class is made immutable before being delivered to an AccessibilityService.
1100 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001101 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001102 * @param focused True if the node is focused.
1103 *
1104 * @throws IllegalStateException If called from an AccessibilityService.
1105 */
1106 public void setFocused(boolean focused) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001107 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSED, focused);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001108 }
1109
1110 /**
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001111 * Sets whether this node is visible to the user.
1112 *
1113 * @return Whether the node is visible to the user.
1114 */
1115 public boolean isVisibleToUser() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001116 return getBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001117 }
1118
1119 /**
1120 * Sets whether this node is visible to the user.
1121 * <p>
1122 * <strong>Note:</strong> Cannot be called from an
1123 * {@link android.accessibilityservice.AccessibilityService}.
1124 * This class is made immutable before being delivered to an AccessibilityService.
1125 * </p>
1126 *
1127 * @param visibleToUser Whether the node is visible to the user.
1128 *
1129 * @throws IllegalStateException If called from an AccessibilityService.
1130 */
1131 public void setVisibleToUser(boolean visibleToUser) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001132 setBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER, visibleToUser);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001133 }
1134
1135 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -07001136 * Gets whether this node is accessibility focused.
1137 *
1138 * @return True if the node is accessibility focused.
1139 */
1140 public boolean isAccessibilityFocused() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001141 return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED);
Svetoslav Ganov42138042012-03-20 11:51:39 -07001142 }
1143
1144 /**
1145 * Sets whether this node is accessibility focused.
1146 * <p>
1147 * <strong>Note:</strong> Cannot be called from an
1148 * {@link android.accessibilityservice.AccessibilityService}.
1149 * This class is made immutable before being delivered to an AccessibilityService.
1150 * </p>
1151 *
1152 * @param focused True if the node is accessibility focused.
1153 *
1154 * @throws IllegalStateException If called from an AccessibilityService.
1155 */
1156 public void setAccessibilityFocused(boolean focused) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001157 setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED, focused);
Svetoslav Ganov42138042012-03-20 11:51:39 -07001158 }
1159
1160 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001161 * Gets whether this node is selected.
1162 *
1163 * @return True if the node is selected.
1164 */
1165 public boolean isSelected() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001166 return getBooleanProperty(BOOLEAN_PROPERTY_SELECTED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001167 }
1168
1169 /**
1170 * Sets whether this node is selected.
1171 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001172 * <strong>Note:</strong> Cannot be called from an
1173 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001174 * This class is made immutable before being delivered to an AccessibilityService.
1175 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001176 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001177 * @param selected True if the node is selected.
1178 *
1179 * @throws IllegalStateException If called from an AccessibilityService.
1180 */
1181 public void setSelected(boolean selected) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001182 setBooleanProperty(BOOLEAN_PROPERTY_SELECTED, selected);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001183 }
1184
1185 /**
1186 * Gets whether this node is clickable.
1187 *
1188 * @return True if the node is clickable.
1189 */
1190 public boolean isClickable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001191 return getBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001192 }
1193
1194 /**
1195 * Sets whether this node is clickable.
1196 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001197 * <strong>Note:</strong> Cannot be called from an
1198 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001199 * This class is made immutable before being delivered to an AccessibilityService.
1200 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001201 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001202 * @param clickable True if the node is clickable.
1203 *
1204 * @throws IllegalStateException If called from an AccessibilityService.
1205 */
1206 public void setClickable(boolean clickable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001207 setBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE, clickable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001208 }
1209
1210 /**
1211 * Gets whether this node is long clickable.
1212 *
1213 * @return True if the node is long clickable.
1214 */
1215 public boolean isLongClickable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001216 return getBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001217 }
1218
1219 /**
1220 * Sets whether this node is long clickable.
1221 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001222 * <strong>Note:</strong> Cannot be called from an
1223 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001224 * This class is made immutable before being delivered to an AccessibilityService.
1225 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001226 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001227 * @param longClickable True if the node is long clickable.
1228 *
1229 * @throws IllegalStateException If called from an AccessibilityService.
1230 */
1231 public void setLongClickable(boolean longClickable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001232 setBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE, longClickable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001233 }
1234
1235 /**
1236 * Gets whether this node is enabled.
1237 *
1238 * @return True if the node is enabled.
1239 */
1240 public boolean isEnabled() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001241 return getBooleanProperty(BOOLEAN_PROPERTY_ENABLED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001242 }
1243
1244 /**
1245 * Sets whether this node is enabled.
1246 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001247 * <strong>Note:</strong> Cannot be called from an
1248 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001249 * This class is made immutable before being delivered to an AccessibilityService.
1250 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001251 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001252 * @param enabled True if the node is enabled.
1253 *
1254 * @throws IllegalStateException If called from an AccessibilityService.
1255 */
1256 public void setEnabled(boolean enabled) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001257 setBooleanProperty(BOOLEAN_PROPERTY_ENABLED, enabled);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001258 }
1259
1260 /**
1261 * Gets whether this node is a password.
1262 *
1263 * @return True if the node is a password.
1264 */
1265 public boolean isPassword() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001266 return getBooleanProperty(BOOLEAN_PROPERTY_PASSWORD);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001267 }
1268
1269 /**
1270 * Sets whether this node is a password.
1271 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001272 * <strong>Note:</strong> Cannot be called from an
1273 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001274 * This class is made immutable before being delivered to an AccessibilityService.
1275 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001276 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001277 * @param password True if the node is a password.
1278 *
1279 * @throws IllegalStateException If called from an AccessibilityService.
1280 */
1281 public void setPassword(boolean password) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001282 setBooleanProperty(BOOLEAN_PROPERTY_PASSWORD, password);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001283 }
1284
1285 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -07001286 * Gets if the node is scrollable.
1287 *
1288 * @return True if the node is scrollable, false otherwise.
1289 */
1290 public boolean isScrollable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001291 return getBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE);
Svetoslav Ganova0156172011-06-26 17:55:44 -07001292 }
1293
1294 /**
1295 * Sets if the node is scrollable.
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001296 * <p>
1297 * <strong>Note:</strong> Cannot be called from an
1298 * {@link android.accessibilityservice.AccessibilityService}.
1299 * This class is made immutable before being delivered to an AccessibilityService.
1300 * </p>
Svetoslav Ganova0156172011-06-26 17:55:44 -07001301 *
1302 * @param scrollable True if the node is scrollable, false otherwise.
1303 *
1304 * @throws IllegalStateException If called from an AccessibilityService.
1305 */
1306 public void setScrollable(boolean scrollable) {
1307 enforceNotSealed();
Svetoslavbcc46a02013-02-06 11:56:00 -08001308 setBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE, scrollable);
1309 }
1310
1311 /**
1312 * Gets if the node is editable.
1313 *
1314 * @return True if the node is editable, false otherwise.
1315 */
1316 public boolean isEditable() {
1317 return getBooleanProperty(BOOLEAN_PROPERTY_EDITABLE);
1318 }
1319
1320 /**
1321 * Sets whether this node is editable.
1322 * <p>
1323 * <strong>Note:</strong> Cannot be called from an
1324 * {@link android.accessibilityservice.AccessibilityService}.
1325 * This class is made immutable before being delivered to an AccessibilityService.
1326 * </p>
1327 *
1328 * @param editable True if the node is editable.
1329 *
1330 * @throws IllegalStateException If called from an AccessibilityService.
1331 */
1332 public void setEditable(boolean editable) {
1333 setBooleanProperty(BOOLEAN_PROPERTY_EDITABLE, editable);
Svetoslav Ganova0156172011-06-26 17:55:44 -07001334 }
1335
1336 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001337 * Gets the package this node comes from.
1338 *
1339 * @return The package name.
1340 */
1341 public CharSequence getPackageName() {
1342 return mPackageName;
1343 }
1344
1345 /**
1346 * Sets the package this node comes from.
1347 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001348 * <strong>Note:</strong> Cannot be called from an
1349 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001350 * This class is made immutable before being delivered to an AccessibilityService.
1351 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001352 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001353 * @param packageName The package name.
1354 *
1355 * @throws IllegalStateException If called from an AccessibilityService.
1356 */
1357 public void setPackageName(CharSequence packageName) {
1358 enforceNotSealed();
1359 mPackageName = packageName;
1360 }
1361
1362 /**
1363 * Gets the class this node comes from.
1364 *
1365 * @return The class name.
1366 */
1367 public CharSequence getClassName() {
1368 return mClassName;
1369 }
1370
1371 /**
1372 * Sets the class this node comes from.
1373 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001374 * <strong>Note:</strong> Cannot be called from an
1375 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001376 * This class is made immutable before being delivered to an AccessibilityService.
1377 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001378 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001379 * @param className The class name.
1380 *
1381 * @throws IllegalStateException If called from an AccessibilityService.
1382 */
1383 public void setClassName(CharSequence className) {
1384 enforceNotSealed();
1385 mClassName = className;
1386 }
1387
1388 /**
1389 * Gets the text of this node.
1390 *
1391 * @return The text.
1392 */
1393 public CharSequence getText() {
1394 return mText;
1395 }
1396
1397 /**
1398 * Sets the text of this node.
1399 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001400 * <strong>Note:</strong> Cannot be called from an
1401 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001402 * This class is made immutable before being delivered to an AccessibilityService.
1403 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001404 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001405 * @param text The text.
1406 *
1407 * @throws IllegalStateException If called from an AccessibilityService.
1408 */
1409 public void setText(CharSequence text) {
1410 enforceNotSealed();
1411 mText = text;
1412 }
1413
1414 /**
1415 * Gets the content description of this node.
1416 *
1417 * @return The content description.
1418 */
1419 public CharSequence getContentDescription() {
1420 return mContentDescription;
1421 }
1422
1423 /**
1424 * Sets the content description of this node.
1425 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001426 * <strong>Note:</strong> Cannot be called from an
1427 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001428 * This class is made immutable before being delivered to an AccessibilityService.
1429 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001430 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001431 * @param contentDescription The content description.
1432 *
1433 * @throws IllegalStateException If called from an AccessibilityService.
1434 */
1435 public void setContentDescription(CharSequence contentDescription) {
1436 enforceNotSealed();
1437 mContentDescription = contentDescription;
1438 }
1439
1440 /**
Svetoslav Ganov33aef982012-09-13 12:49:03 -07001441 * Sets the view for which the view represented by this info serves as a
1442 * label for accessibility purposes.
1443 *
1444 * @param labeled The view for which this info serves as a label.
1445 */
1446 public void setLabelFor(View labeled) {
1447 setLabelFor(labeled, UNDEFINED);
1448 }
1449
1450 /**
1451 * Sets the view for which the view represented by this info serves as a
1452 * label for accessibility purposes. If <code>virtualDescendantId</code>
1453 * is {@link View#NO_ID} the root is set as the labeled.
1454 * <p>
1455 * A virtual descendant is an imaginary View that is reported as a part of the view
1456 * hierarchy for accessibility purposes. This enables custom views that draw complex
1457 * content to report themselves as a tree of virtual views, thus conveying their
1458 * logical structure.
1459 * </p>
1460 * <p>
1461 * <strong>Note:</strong> Cannot be called from an
1462 * {@link android.accessibilityservice.AccessibilityService}.
1463 * This class is made immutable before being delivered to an AccessibilityService.
1464 * </p>
1465 *
1466 * @param root The root whose virtual descendant serves as a label.
1467 * @param virtualDescendantId The id of the virtual descendant.
1468 */
1469 public void setLabelFor(View root, int virtualDescendantId) {
1470 enforceNotSealed();
1471 final int rootAccessibilityViewId = (root != null)
1472 ? root.getAccessibilityViewId() : UNDEFINED;
1473 mLabelForId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1474 }
1475
1476 /**
1477 * Gets the node info for which the view represented by this info serves as
1478 * a label for accessibility purposes.
1479 * <p>
1480 * <strong>Note:</strong> It is a client responsibility to recycle the
1481 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1482 * to avoid creating of multiple instances.
1483 * </p>
1484 *
1485 * @return The labeled info.
1486 */
1487 public AccessibilityNodeInfo getLabelFor() {
1488 enforceSealed();
1489 if (!canPerformRequestOverConnection(mLabelForId)) {
1490 return null;
1491 }
1492 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1493 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
Svetoslav6254f482013-06-04 17:22:14 -07001494 mWindowId, mLabelForId, false, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07001495 }
1496
1497 /**
1498 * Sets the view which serves as the label of the view represented by
1499 * this info for accessibility purposes.
1500 *
1501 * @param label The view that labels this node's source.
1502 */
1503 public void setLabeledBy(View label) {
1504 setLabeledBy(label, UNDEFINED);
1505 }
1506
1507 /**
1508 * Sets the view which serves as the label of the view represented by
1509 * this info for accessibility purposes. If <code>virtualDescendantId</code>
1510 * is {@link View#NO_ID} the root is set as the label.
1511 * <p>
1512 * A virtual descendant is an imaginary View that is reported as a part of the view
1513 * hierarchy for accessibility purposes. This enables custom views that draw complex
1514 * content to report themselves as a tree of virtual views, thus conveying their
1515 * logical structure.
1516 * </p>
1517 * <p>
1518 * <strong>Note:</strong> Cannot be called from an
1519 * {@link android.accessibilityservice.AccessibilityService}.
1520 * This class is made immutable before being delivered to an AccessibilityService.
1521 * </p>
1522 *
1523 * @param root The root whose virtual descendant labels this node's source.
1524 * @param virtualDescendantId The id of the virtual descendant.
1525 */
1526 public void setLabeledBy(View root, int virtualDescendantId) {
1527 enforceNotSealed();
1528 final int rootAccessibilityViewId = (root != null)
1529 ? root.getAccessibilityViewId() : UNDEFINED;
1530 mLabeledById = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1531 }
1532
1533 /**
1534 * Gets the node info which serves as the label of the view represented by
1535 * this info for accessibility purposes.
1536 * <p>
1537 * <strong>Note:</strong> It is a client responsibility to recycle the
1538 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1539 * to avoid creating of multiple instances.
1540 * </p>
1541 *
1542 * @return The label.
1543 */
1544 public AccessibilityNodeInfo getLabeledBy() {
1545 enforceSealed();
1546 if (!canPerformRequestOverConnection(mLabeledById)) {
1547 return null;
1548 }
1549 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1550 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
Svetoslav6254f482013-06-04 17:22:14 -07001551 mWindowId, mLabeledById, false, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07001552 }
1553
1554 /**
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001555 * Sets the fully qualified resource name of the source view's id.
1556 *
1557 * <p>
1558 * <strong>Note:</strong> Cannot be called from an
1559 * {@link android.accessibilityservice.AccessibilityService}.
1560 * This class is made immutable before being delivered to an AccessibilityService.
1561 * </p>
1562 *
Svetoslav92826452013-02-05 14:57:42 -08001563 * @param viewIdResName The id resource name.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001564 */
Svetoslav9fa1ee52013-04-22 12:43:03 -07001565 public void setViewIdResourceName(String viewIdResName) {
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001566 enforceNotSealed();
Svetoslav22431a32013-02-05 14:30:19 -08001567 mViewIdResourceName = viewIdResName;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001568 }
1569
1570 /**
1571 * Gets the fully qualified resource name of the source view's id.
1572 *
1573 * <p>
1574 * <strong>Note:</strong> The primary usage of this API is for UI test automation
1575 * and in order to report the source view id of an {@link AccessibilityNodeInfo} the
1576 * client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
Svetoslav14ff9962013-01-29 03:21:37 -08001577 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001578 * </p>
1579
1580 * @return The id resource name.
1581 */
Svetoslav9fa1ee52013-04-22 12:43:03 -07001582 public String getViewIdResourceName() {
Svetoslav22431a32013-02-05 14:30:19 -08001583 return mViewIdResourceName;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001584 }
1585
1586 /**
Svetoslavbcc46a02013-02-06 11:56:00 -08001587 * Gets the text selection start.
1588 *
1589 * @return The text selection start if there is selection or -1.
1590 */
1591 public int getTextSelectionStart() {
1592 return mTextSelectionStart;
1593 }
1594
1595 /**
1596 * Gets the text selection end.
1597 *
1598 * @return The text selection end if there is selection or -1.
1599 */
1600 public int getTextSelectionEnd() {
1601 return mTextSelectionEnd;
1602 }
1603
1604 /**
1605 * Sets the text selection start and end.
1606 * <p>
1607 * <strong>Note:</strong> Cannot be called from an
1608 * {@link android.accessibilityservice.AccessibilityService}.
1609 * This class is made immutable before being delivered to an AccessibilityService.
1610 * </p>
1611 *
1612 * @param start The text selection start.
1613 * @param end The text selection end.
1614 *
1615 * @throws IllegalStateException If called from an AccessibilityService.
1616 */
1617 public void setTextSelection(int start, int end) {
1618 enforceNotSealed();
1619 mTextSelectionStart = start;
1620 mTextSelectionEnd = end;
1621 }
1622
1623 /**
Svetoslav6254f482013-06-04 17:22:14 -07001624 * Gets the input type of the source as defined by {@link InputType}.
1625 *
1626 * @return The input type.
1627 */
1628 public int getInputType() {
1629 return mInputType;
1630 }
1631
1632 /**
1633 * Sets the input type of the source as defined by {@link InputType}.
1634 * <p>
1635 * <strong>Note:</strong> Cannot be called from an
1636 * {@link android.accessibilityservice.AccessibilityService}.
1637 * This class is made immutable before being delivered to an
1638 * AccessibilityService.
1639 * </p>
1640 *
1641 * @param inputType The input type.
1642 *
1643 * @throws IllegalStateException If called from an AccessibilityService.
1644 */
1645 public void setInputType(int inputType) {
1646 mInputType = inputType;
1647 }
1648
1649 /**
1650 * Gets an optional bundle with additional data. The bundle
1651 * is lazily created and never <code>null</code>.
1652 * <p>
1653 * <strong>Note:</strong> It is recommended to use the package
1654 * name of your application as a prefix for the keys to avoid
1655 * collisions which may confuse an accessibility service if the
1656 * same key has different meaning when emitted from different
1657 * applications.
1658 * </p>
1659 *
1660 * @return The bundle.
1661 */
1662 public Bundle getBundle() {
1663 if (mBundle == null) {
1664 mBundle = new Bundle();
1665 }
1666 return mBundle;
1667 }
1668
1669 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001670 * Gets the value of a boolean property.
1671 *
1672 * @param property The property.
1673 * @return The value.
1674 */
1675 private boolean getBooleanProperty(int property) {
1676 return (mBooleanProperties & property) != 0;
1677 }
1678
1679 /**
1680 * Sets a boolean property.
1681 *
1682 * @param property The property.
1683 * @param value The value.
1684 *
1685 * @throws IllegalStateException If called from an AccessibilityService.
1686 */
1687 private void setBooleanProperty(int property, boolean value) {
1688 enforceNotSealed();
1689 if (value) {
1690 mBooleanProperties |= property;
1691 } else {
1692 mBooleanProperties &= ~property;
1693 }
1694 }
1695
1696 /**
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08001697 * Sets the unique id of the IAccessibilityServiceConnection over which
1698 * this instance can send requests to the system.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001699 *
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08001700 * @param connectionId The connection id.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001701 *
1702 * @hide
1703 */
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08001704 public void setConnectionId(int connectionId) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001705 enforceNotSealed();
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08001706 mConnectionId = connectionId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001707 }
1708
1709 /**
1710 * {@inheritDoc}
1711 */
1712 public int describeContents() {
1713 return 0;
1714 }
1715
1716 /**
Svetoslav Ganov79311c42012-01-17 20:24:26 -08001717 * Gets the id of the source node.
1718 *
1719 * @return The id.
1720 *
1721 * @hide
1722 */
1723 public long getSourceNodeId() {
1724 return mSourceNodeId;
1725 }
1726
1727 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001728 * Sets if this instance is sealed.
1729 *
1730 * @param sealed Whether is sealed.
1731 *
1732 * @hide
1733 */
1734 public void setSealed(boolean sealed) {
1735 mSealed = sealed;
1736 }
1737
1738 /**
1739 * Gets if this instance is sealed.
1740 *
1741 * @return Whether is sealed.
1742 *
1743 * @hide
1744 */
1745 public boolean isSealed() {
1746 return mSealed;
1747 }
1748
1749 /**
1750 * Enforces that this instance is sealed.
1751 *
1752 * @throws IllegalStateException If this instance is not sealed.
1753 *
1754 * @hide
1755 */
1756 protected void enforceSealed() {
1757 if (!isSealed()) {
1758 throw new IllegalStateException("Cannot perform this "
1759 + "action on a not sealed instance.");
1760 }
1761 }
1762
Svetoslav Ganov2ef69052012-06-04 08:55:16 -07001763 private void enforceValidFocusDirection(int direction) {
1764 switch (direction) {
1765 case View.FOCUS_DOWN:
1766 case View.FOCUS_UP:
1767 case View.FOCUS_LEFT:
1768 case View.FOCUS_RIGHT:
1769 case View.FOCUS_FORWARD:
1770 case View.FOCUS_BACKWARD:
Svetoslav Ganov2ef69052012-06-04 08:55:16 -07001771 return;
1772 default:
1773 throw new IllegalArgumentException("Unknown direction: " + direction);
1774 }
1775 }
1776
1777 private void enforceValidFocusType(int focusType) {
1778 switch (focusType) {
1779 case FOCUS_INPUT:
1780 case FOCUS_ACCESSIBILITY:
1781 return;
1782 default:
1783 throw new IllegalArgumentException("Unknown focus type: " + focusType);
1784 }
1785 }
1786
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001787 /**
1788 * Enforces that this instance is not sealed.
1789 *
1790 * @throws IllegalStateException If this instance is sealed.
1791 *
1792 * @hide
1793 */
1794 protected void enforceNotSealed() {
1795 if (isSealed()) {
1796 throw new IllegalStateException("Cannot perform this "
Ken Wakasaf76a50c2012-03-09 19:56:35 +09001797 + "action on a sealed instance.");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001798 }
1799 }
1800
1801 /**
1802 * Returns a cached instance if such is available otherwise a new one
1803 * and sets the source.
1804 *
Svetoslav Ganov02107852011-10-03 17:06:56 -07001805 * @param source The source view.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001806 * @return An instance.
1807 *
1808 * @see #setSource(View)
1809 */
1810 public static AccessibilityNodeInfo obtain(View source) {
1811 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
1812 info.setSource(source);
1813 return info;
1814 }
1815
1816 /**
Svetoslav Ganov02107852011-10-03 17:06:56 -07001817 * Returns a cached instance if such is available otherwise a new one
1818 * and sets the source.
1819 *
1820 * @param root The root of the virtual subtree.
1821 * @param virtualDescendantId The id of the virtual descendant.
1822 * @return An instance.
1823 *
1824 * @see #setSource(View, int)
1825 */
1826 public static AccessibilityNodeInfo obtain(View root, int virtualDescendantId) {
1827 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
1828 info.setSource(root, virtualDescendantId);
1829 return info;
1830 }
1831
1832 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001833 * Returns a cached instance if such is available otherwise a new one.
1834 *
1835 * @return An instance.
1836 */
1837 public static AccessibilityNodeInfo obtain() {
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -08001838 AccessibilityNodeInfo info = sPool.acquire();
1839 return (info != null) ? info : new AccessibilityNodeInfo();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001840 }
1841
1842 /**
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07001843 * Returns a cached instance if such is available or a new one is
1844 * create. The returned instance is initialized from the given
1845 * <code>info</code>.
1846 *
1847 * @param info The other info.
1848 * @return An instance.
1849 */
1850 public static AccessibilityNodeInfo obtain(AccessibilityNodeInfo info) {
1851 AccessibilityNodeInfo infoClone = AccessibilityNodeInfo.obtain();
1852 infoClone.init(info);
1853 return infoClone;
1854 }
1855
1856 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001857 * Return an instance back to be reused.
1858 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001859 * <strong>Note:</strong> You must not touch the object after calling this function.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001860 *
1861 * @throws IllegalStateException If the info is already recycled.
1862 */
1863 public void recycle() {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001864 clear();
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -08001865 sPool.release(this);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001866 }
1867
1868 /**
1869 * {@inheritDoc}
1870 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001871 * <strong>Note:</strong> After the instance is written to a parcel it
1872 * is recycled. You must not touch the object after calling this function.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001873 * </p>
1874 */
1875 public void writeToParcel(Parcel parcel, int flags) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001876 parcel.writeInt(isSealed() ? 1 : 0);
Svetoslav Ganov02107852011-10-03 17:06:56 -07001877 parcel.writeLong(mSourceNodeId);
1878 parcel.writeInt(mWindowId);
1879 parcel.writeLong(mParentNodeId);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07001880 parcel.writeLong(mLabelForId);
1881 parcel.writeLong(mLabeledById);
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08001882 parcel.writeInt(mConnectionId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001883
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -08001884 SparseLongArray childIds = mChildNodeIds;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001885 final int childIdsSize = childIds.size();
1886 parcel.writeInt(childIdsSize);
1887 for (int i = 0; i < childIdsSize; i++) {
Svetoslav Ganov02107852011-10-03 17:06:56 -07001888 parcel.writeLong(childIds.valueAt(i));
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001889 }
1890
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001891 parcel.writeInt(mBoundsInParent.top);
1892 parcel.writeInt(mBoundsInParent.bottom);
1893 parcel.writeInt(mBoundsInParent.left);
1894 parcel.writeInt(mBoundsInParent.right);
1895
1896 parcel.writeInt(mBoundsInScreen.top);
1897 parcel.writeInt(mBoundsInScreen.bottom);
1898 parcel.writeInt(mBoundsInScreen.left);
1899 parcel.writeInt(mBoundsInScreen.right);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001900
1901 parcel.writeInt(mActions);
1902
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001903 parcel.writeInt(mMovementGranularities);
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07001904
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001905 parcel.writeInt(mBooleanProperties);
1906
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001907 parcel.writeCharSequence(mPackageName);
1908 parcel.writeCharSequence(mClassName);
1909 parcel.writeCharSequence(mText);
1910 parcel.writeCharSequence(mContentDescription);
Svetoslav9fa1ee52013-04-22 12:43:03 -07001911 parcel.writeString(mViewIdResourceName);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001912
Svetoslavbcc46a02013-02-06 11:56:00 -08001913 parcel.writeInt(mTextSelectionStart);
1914 parcel.writeInt(mTextSelectionEnd);
Svetoslav6254f482013-06-04 17:22:14 -07001915 parcel.writeInt(mInputType);
1916
1917 if (mBundle != null) {
1918 parcel.writeInt(1);
1919 parcel.writeBundle(mBundle);
1920 } else {
1921 parcel.writeInt(0);
1922 }
Svetoslavbcc46a02013-02-06 11:56:00 -08001923
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001924 // Since instances of this class are fetched via synchronous i.e. blocking
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001925 // calls in IPCs we always recycle as soon as the instance is marshaled.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001926 recycle();
1927 }
1928
1929 /**
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07001930 * Initializes this instance from another one.
1931 *
1932 * @param other The other instance.
1933 */
1934 private void init(AccessibilityNodeInfo other) {
1935 mSealed = other.mSealed;
Svetoslav Ganov02107852011-10-03 17:06:56 -07001936 mSourceNodeId = other.mSourceNodeId;
1937 mParentNodeId = other.mParentNodeId;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07001938 mLabelForId = other.mLabelForId;
1939 mLabeledById = other.mLabeledById;
Svetoslav Ganov02107852011-10-03 17:06:56 -07001940 mWindowId = other.mWindowId;
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08001941 mConnectionId = other.mConnectionId;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07001942 mBoundsInParent.set(other.mBoundsInParent);
1943 mBoundsInScreen.set(other.mBoundsInScreen);
1944 mPackageName = other.mPackageName;
1945 mClassName = other.mClassName;
1946 mText = other.mText;
1947 mContentDescription = other.mContentDescription;
Svetoslav22431a32013-02-05 14:30:19 -08001948 mViewIdResourceName = other.mViewIdResourceName;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07001949 mActions= other.mActions;
1950 mBooleanProperties = other.mBooleanProperties;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001951 mMovementGranularities = other.mMovementGranularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001952 final int otherChildIdCount = other.mChildNodeIds.size();
1953 for (int i = 0; i < otherChildIdCount; i++) {
1954 mChildNodeIds.put(i, other.mChildNodeIds.valueAt(i));
1955 }
Svetoslavbcc46a02013-02-06 11:56:00 -08001956 mTextSelectionStart = other.mTextSelectionStart;
1957 mTextSelectionEnd = other.mTextSelectionEnd;
Svetoslav6254f482013-06-04 17:22:14 -07001958 mInputType = other.mInputType;
1959 if (other.mBundle != null && !other.mBundle.isEmpty()) {
1960 getBundle().putAll(other.mBundle);
1961 }
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07001962 }
1963
1964 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001965 * Creates a new instance from a {@link Parcel}.
1966 *
1967 * @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}.
1968 */
1969 private void initFromParcel(Parcel parcel) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001970 mSealed = (parcel.readInt() == 1);
Svetoslav Ganov02107852011-10-03 17:06:56 -07001971 mSourceNodeId = parcel.readLong();
1972 mWindowId = parcel.readInt();
1973 mParentNodeId = parcel.readLong();
Svetoslav Ganov33aef982012-09-13 12:49:03 -07001974 mLabelForId = parcel.readLong();
1975 mLabeledById = parcel.readLong();
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08001976 mConnectionId = parcel.readInt();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001977
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -08001978 SparseLongArray childIds = mChildNodeIds;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001979 final int childrenSize = parcel.readInt();
1980 for (int i = 0; i < childrenSize; i++) {
Svetoslav Ganov02107852011-10-03 17:06:56 -07001981 final long childId = parcel.readLong();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001982 childIds.put(i, childId);
1983 }
1984
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001985 mBoundsInParent.top = parcel.readInt();
1986 mBoundsInParent.bottom = parcel.readInt();
1987 mBoundsInParent.left = parcel.readInt();
1988 mBoundsInParent.right = parcel.readInt();
1989
1990 mBoundsInScreen.top = parcel.readInt();
1991 mBoundsInScreen.bottom = parcel.readInt();
1992 mBoundsInScreen.left = parcel.readInt();
1993 mBoundsInScreen.right = parcel.readInt();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001994
1995 mActions = parcel.readInt();
1996
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001997 mMovementGranularities = parcel.readInt();
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07001998
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001999 mBooleanProperties = parcel.readInt();
2000
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002001 mPackageName = parcel.readCharSequence();
2002 mClassName = parcel.readCharSequence();
2003 mText = parcel.readCharSequence();
2004 mContentDescription = parcel.readCharSequence();
Svetoslav9fa1ee52013-04-22 12:43:03 -07002005 mViewIdResourceName = parcel.readString();
Svetoslavbcc46a02013-02-06 11:56:00 -08002006
2007 mTextSelectionStart = parcel.readInt();
2008 mTextSelectionEnd = parcel.readInt();
Svetoslav6254f482013-06-04 17:22:14 -07002009 mInputType = parcel.readInt();
2010
2011 if (parcel.readInt() == 1) {
2012 getBundle().putAll(parcel.readBundle());
2013 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002014 }
2015
2016 /**
2017 * Clears the state of this instance.
2018 */
2019 private void clear() {
2020 mSealed = false;
Svetoslav Ganov0d04e242012-02-21 13:46:36 -08002021 mSourceNodeId = ROOT_NODE_ID;
2022 mParentNodeId = ROOT_NODE_ID;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002023 mLabelForId = ROOT_NODE_ID;
2024 mLabeledById = ROOT_NODE_ID;
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -08002025 mWindowId = UNDEFINED;
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002026 mConnectionId = UNDEFINED;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002027 mMovementGranularities = 0;
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -08002028 mChildNodeIds.clear();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002029 mBoundsInParent.set(0, 0, 0, 0);
2030 mBoundsInScreen.set(0, 0, 0, 0);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002031 mBooleanProperties = 0;
2032 mPackageName = null;
2033 mClassName = null;
2034 mText = null;
2035 mContentDescription = null;
Svetoslav22431a32013-02-05 14:30:19 -08002036 mViewIdResourceName = null;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002037 mActions = 0;
Svetoslavbcc46a02013-02-06 11:56:00 -08002038 mTextSelectionStart = UNDEFINED;
2039 mTextSelectionEnd = UNDEFINED;
Svetoslav6254f482013-06-04 17:22:14 -07002040 mInputType = InputType.TYPE_NULL;
2041 if (mBundle != null) {
2042 mBundle.clear();
2043 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002044 }
2045
2046 /**
2047 * Gets the human readable action symbolic name.
2048 *
2049 * @param action The action.
2050 * @return The symbolic name.
2051 */
2052 private static String getActionSymbolicName(int action) {
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002053 switch (action) {
2054 case ACTION_FOCUS:
2055 return "ACTION_FOCUS";
2056 case ACTION_CLEAR_FOCUS:
2057 return "ACTION_CLEAR_FOCUS";
2058 case ACTION_SELECT:
2059 return "ACTION_SELECT";
2060 case ACTION_CLEAR_SELECTION:
2061 return "ACTION_CLEAR_SELECTION";
Svetoslav Ganove9bda152012-04-30 16:55:21 -07002062 case ACTION_CLICK:
2063 return "ACTION_CLICK";
2064 case ACTION_LONG_CLICK:
2065 return "ACTION_LONG_CLICK";
2066 case ACTION_ACCESSIBILITY_FOCUS:
2067 return "ACTION_ACCESSIBILITY_FOCUS";
2068 case ACTION_CLEAR_ACCESSIBILITY_FOCUS:
2069 return "ACTION_CLEAR_ACCESSIBILITY_FOCUS";
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002070 case ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
2071 return "ACTION_NEXT_AT_MOVEMENT_GRANULARITY";
2072 case ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY:
2073 return "ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY";
Svetoslav Ganove9bda152012-04-30 16:55:21 -07002074 case ACTION_NEXT_HTML_ELEMENT:
2075 return "ACTION_NEXT_HTML_ELEMENT";
2076 case ACTION_PREVIOUS_HTML_ELEMENT:
2077 return "ACTION_PREVIOUS_HTML_ELEMENT";
Svetoslav Ganova1dc7612012-05-10 04:14:53 -07002078 case ACTION_SCROLL_FORWARD:
2079 return "ACTION_SCROLL_FORWARD";
2080 case ACTION_SCROLL_BACKWARD:
2081 return "ACTION_SCROLL_BACKWARD";
Svetoslav Ganov242724e2013-02-01 14:42:18 -08002082 case ACTION_CUT:
2083 return "ACTION_CUT";
2084 case ACTION_COPY:
2085 return "ACTION_COPY";
2086 case ACTION_PASTE:
2087 return "ACTION_PASTE";
2088 case ACTION_SET_SELECTION:
2089 return "ACTION_SET_SELECTION";
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002090 default:
Svetoslav Ganov242724e2013-02-01 14:42:18 -08002091 return"ACTION_UNKNOWN";
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002092 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002093 }
2094
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002095 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002096 * Gets the human readable movement granularity symbolic name.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002097 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002098 * @param granularity The granularity.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002099 * @return The symbolic name.
2100 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002101 private static String getMovementGranularitySymbolicName(int granularity) {
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002102 switch (granularity) {
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002103 case MOVEMENT_GRANULARITY_CHARACTER:
2104 return "MOVEMENT_GRANULARITY_CHARACTER";
2105 case MOVEMENT_GRANULARITY_WORD:
2106 return "MOVEMENT_GRANULARITY_WORD";
2107 case MOVEMENT_GRANULARITY_LINE:
2108 return "MOVEMENT_GRANULARITY_LINE";
2109 case MOVEMENT_GRANULARITY_PARAGRAPH:
2110 return "MOVEMENT_GRANULARITY_PARAGRAPH";
2111 case MOVEMENT_GRANULARITY_PAGE:
2112 return "MOVEMENT_GRANULARITY_PAGE";
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002113 default:
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002114 throw new IllegalArgumentException("Unknown movement granularity: " + granularity);
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002115 }
2116 }
2117
Svetoslav Ganov02107852011-10-03 17:06:56 -07002118 private boolean canPerformRequestOverConnection(long accessibilityNodeId) {
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -08002119 return (mWindowId != UNDEFINED
2120 && getAccessibilityViewId(accessibilityNodeId) != UNDEFINED
2121 && mConnectionId != UNDEFINED);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002122 }
2123
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002124 @Override
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07002125 public boolean equals(Object object) {
2126 if (this == object) {
2127 return true;
2128 }
2129 if (object == null) {
2130 return false;
2131 }
2132 if (getClass() != object.getClass()) {
2133 return false;
2134 }
2135 AccessibilityNodeInfo other = (AccessibilityNodeInfo) object;
Svetoslav Ganov02107852011-10-03 17:06:56 -07002136 if (mSourceNodeId != other.mSourceNodeId) {
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07002137 return false;
2138 }
Svetoslav Ganov02107852011-10-03 17:06:56 -07002139 if (mWindowId != other.mWindowId) {
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07002140 return false;
2141 }
2142 return true;
2143 }
2144
2145 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002146 public int hashCode() {
2147 final int prime = 31;
2148 int result = 1;
Svetoslav Ganov02107852011-10-03 17:06:56 -07002149 result = prime * result + getAccessibilityViewId(mSourceNodeId);
2150 result = prime * result + getVirtualDescendantId(mSourceNodeId);
2151 result = prime * result + mWindowId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002152 return result;
2153 }
2154
2155 @Override
2156 public String toString() {
2157 StringBuilder builder = new StringBuilder();
2158 builder.append(super.toString());
2159
2160 if (DEBUG) {
Svetoslav Ganov02107852011-10-03 17:06:56 -07002161 builder.append("; accessibilityViewId: " + getAccessibilityViewId(mSourceNodeId));
2162 builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId));
2163 builder.append("; mParentNodeId: " + mParentNodeId);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002164
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002165 int granularities = mMovementGranularities;
2166 builder.append("; MovementGranularities: [");
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002167 while (granularities != 0) {
2168 final int granularity = 1 << Integer.numberOfTrailingZeros(granularities);
2169 granularities &= ~granularity;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07002170 builder.append(getMovementGranularitySymbolicName(granularity));
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07002171 if (granularities != 0) {
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002172 builder.append(", ");
2173 }
2174 }
2175 builder.append("]");
2176
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -08002177 SparseLongArray childIds = mChildNodeIds;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002178 builder.append("; childAccessibilityIds: [");
2179 for (int i = 0, count = childIds.size(); i < count; i++) {
2180 builder.append(childIds.valueAt(i));
2181 if (i < count - 1) {
2182 builder.append(", ");
2183 }
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07002184 }
2185 builder.append("]");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002186 }
2187
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002188 builder.append("; boundsInParent: " + mBoundsInParent);
2189 builder.append("; boundsInScreen: " + mBoundsInScreen);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002190
2191 builder.append("; packageName: ").append(mPackageName);
2192 builder.append("; className: ").append(mClassName);
2193 builder.append("; text: ").append(mText);
2194 builder.append("; contentDescription: ").append(mContentDescription);
Svetoslav22431a32013-02-05 14:30:19 -08002195 builder.append("; viewIdResName: ").append(mViewIdResourceName);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002196
2197 builder.append("; checkable: ").append(isCheckable());
2198 builder.append("; checked: ").append(isChecked());
2199 builder.append("; focusable: ").append(isFocusable());
2200 builder.append("; focused: ").append(isFocused());
2201 builder.append("; selected: ").append(isSelected());
2202 builder.append("; clickable: ").append(isClickable());
2203 builder.append("; longClickable: ").append(isLongClickable());
2204 builder.append("; enabled: ").append(isEnabled());
2205 builder.append("; password: ").append(isPassword());
Svetoslav Ganova0156172011-06-26 17:55:44 -07002206 builder.append("; scrollable: " + isScrollable());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002207
2208 builder.append("; [");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002209 for (int actionBits = mActions; actionBits != 0;) {
2210 final int action = 1 << Integer.numberOfTrailingZeros(actionBits);
2211 actionBits &= ~action;
2212 builder.append(getActionSymbolicName(action));
2213 if (actionBits != 0) {
2214 builder.append(", ");
2215 }
2216 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002217 builder.append("]");
2218
2219 return builder.toString();
2220 }
2221
2222 /**
2223 * @see Parcelable.Creator
2224 */
2225 public static final Parcelable.Creator<AccessibilityNodeInfo> CREATOR =
2226 new Parcelable.Creator<AccessibilityNodeInfo>() {
2227 public AccessibilityNodeInfo createFromParcel(Parcel parcel) {
2228 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
2229 info.initFromParcel(parcel);
2230 return info;
2231 }
2232
2233 public AccessibilityNodeInfo[] newArray(int size) {
2234 return new AccessibilityNodeInfo[size];
2235 }
2236 };
2237}