blob: 23e7d61912765426a27f41fbd13a5406e9246a9d [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
Eugene Susla0eb2b6e2017-05-15 14:06:32 -070019import static com.android.internal.util.BitUtils.bitAt;
20import static com.android.internal.util.BitUtils.isBitSet;
21
Phil Weaverc2e28932016-12-08 12:29:25 -080022import static java.util.Collections.EMPTY_LIST;
23
Casey Burkhardt7ef48be2016-01-31 11:51:09 -080024import android.accessibilityservice.AccessibilityService;
Svetoslav Ganov80943d82013-01-02 10:25:37 -080025import android.accessibilityservice.AccessibilityServiceInfo;
Kristian Monsen74bc1942014-04-29 11:00:17 -070026import android.annotation.Nullable;
Phil Weaver62d20fa2016-09-15 11:05:55 -070027import android.annotation.TestApi;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070028import android.graphics.Rect;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -070029import android.os.Bundle;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070030import android.os.Parcel;
31import android.os.Parcelable;
Svetoslav6254f482013-06-04 17:22:14 -070032import android.text.InputType;
Phil Weaver193520e2016-12-13 09:39:06 -080033import android.text.Spannable;
Phil Weaver0ebe6bd2017-02-21 16:24:31 -080034import android.text.SpannableStringBuilder;
Phil Weaver193520e2016-12-13 09:39:06 -080035import android.text.Spanned;
Kristian Monsen74bc1942014-04-29 11:00:17 -070036import android.text.TextUtils;
Phil Weaver193520e2016-12-13 09:39:06 -080037import android.text.style.AccessibilityClickableSpan;
38import android.text.style.AccessibilityURLSpan;
39import android.text.style.ClickableSpan;
40import android.text.style.URLSpan;
Kristian Monsen74bc1942014-04-29 11:00:17 -070041import android.util.ArraySet;
Alan Viverettef0aed092013-11-06 15:33:03 -080042import android.util.LongArray;
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -080043import android.util.Pools.SynchronizedPool;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070044import android.view.View;
45
Alan Viverette26c44ee2015-03-25 14:54:13 -070046import com.android.internal.R;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -070047import com.android.internal.util.CollectionUtils;
Alan Viverette26c44ee2015-03-25 14:54:13 -070048
Kristian Monsen74bc1942014-04-29 11:00:17 -070049import java.util.ArrayList;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -070050import java.util.Collections;
51import java.util.List;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -070052import java.util.Objects;
Phil Weaverb010b122016-08-17 17:47:48 -070053import java.util.concurrent.atomic.AtomicInteger;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -070054
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070055/**
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070056 * This class represents a node of the window content as well as actions that
57 * can be requested from its source. From the point of view of an
Phil Weaver40ded282016-01-25 15:49:02 -080058 * {@link android.accessibilityservice.AccessibilityService} a window's content is
59 * presented as a tree of accessibility node infos, which may or may not map one-to-one
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070060 * to the view hierarchy. In other words, a custom view is free to report itself as
61 * a tree of accessibility node info.
62 * </p>
63 * <p>
64 * Once an accessibility node info is delivered to an accessibility service it is
65 * made immutable and calling a state mutation method generates an error.
66 * </p>
67 * <p>
68 * Please refer to {@link android.accessibilityservice.AccessibilityService} for
69 * details about how to obtain a handle to window content as a tree of accessibility
Phil Weaver40ded282016-01-25 15:49:02 -080070 * node info as well as details about the security model.
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070071 * </p>
Joe Fernandeze1302ed2012-02-06 14:30:15 -080072 * <div class="special reference">
73 * <h3>Developer Guides</h3>
74 * <p>For more information about making applications accessible, read the
75 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
76 * developer guide.</p>
77 * </div>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070078 *
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070079 * @see android.accessibilityservice.AccessibilityService
80 * @see AccessibilityEvent
81 * @see AccessibilityManager
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070082 */
83public class AccessibilityNodeInfo implements Parcelable {
84
85 private static final boolean DEBUG = false;
86
Svetoslav Ganov0d04e242012-02-21 13:46:36 -080087 /** @hide */
Svetoslav8e3feb12014-02-24 13:46:47 -080088 public static final int UNDEFINED_CONNECTION_ID = -1;
Svetoslav Ganov0d04e242012-02-21 13:46:36 -080089
90 /** @hide */
Svetoslav8e3feb12014-02-24 13:46:47 -080091 public static final int UNDEFINED_SELECTION_INDEX = -1;
Svetoslav Ganov0d04e242012-02-21 13:46:36 -080092
93 /** @hide */
Svetoslav8e3feb12014-02-24 13:46:47 -080094 public static final int UNDEFINED_ITEM_ID = Integer.MAX_VALUE;
95
96 /** @hide */
Phil Weaverf00cd142017-03-03 13:44:00 -080097 public static final int ROOT_ITEM_ID = Integer.MAX_VALUE - 1;
Svetoslav8e3feb12014-02-24 13:46:47 -080098
99 /** @hide */
Phil Weaverf00cd142017-03-03 13:44:00 -0800100 public static final long UNDEFINED_NODE_ID = makeNodeId(UNDEFINED_ITEM_ID, UNDEFINED_ITEM_ID);
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -0800101
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800102 /** @hide */
Phil Weaverf00cd142017-03-03 13:44:00 -0800103 public static final long ROOT_NODE_ID = makeNodeId(ROOT_ITEM_ID,
104 AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav1e0d4af2014-04-10 17:41:29 -0700105
106 /** @hide */
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800107 public static final int FLAG_PREFETCH_PREDECESSORS = 0x00000001;
108
109 /** @hide */
110 public static final int FLAG_PREFETCH_SIBLINGS = 0x00000002;
111
112 /** @hide */
Svetoslav Ganov42138042012-03-20 11:51:39 -0700113 public static final int FLAG_PREFETCH_DESCENDANTS = 0x00000004;
114
115 /** @hide */
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800116 public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x00000008;
117
118 /** @hide */
119 public static final int FLAG_REPORT_VIEW_IDS = 0x00000010;
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800120
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700121 // Actions.
122
123 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700124 * Action that gives input focus to the node.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700125 */
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700126 public static final int ACTION_FOCUS = 0x00000001;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700127
128 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700129 * Action that clears input focus of the node.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700130 */
Svetoslav Ganov42138042012-03-20 11:51:39 -0700131 public static final int ACTION_CLEAR_FOCUS = 0x00000002;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700132
133 /**
134 * Action that selects the node.
135 */
Svetoslav Ganov42138042012-03-20 11:51:39 -0700136 public static final int ACTION_SELECT = 0x00000004;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700137
138 /**
Kristian Monsen74bc1942014-04-29 11:00:17 -0700139 * Action that deselects the node.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700140 */
Svetoslav Ganov42138042012-03-20 11:51:39 -0700141 public static final int ACTION_CLEAR_SELECTION = 0x00000008;
142
143 /**
Svetoslav Ganov6d17a932012-04-27 19:30:38 -0700144 * Action that clicks on the node info.
Maxim Bogatov219b41d2015-05-01 14:00:24 -0700145 *
146 * See {@link AccessibilityAction#ACTION_CLICK}
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700147 */
148 public static final int ACTION_CLICK = 0x00000010;
149
150 /**
Svetoslav Ganov6d17a932012-04-27 19:30:38 -0700151 * Action that long clicks on the node.
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700152 */
153 public static final int ACTION_LONG_CLICK = 0x00000020;
154
155 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700156 * Action that gives accessibility focus to the node.
157 */
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700158 public static final int ACTION_ACCESSIBILITY_FOCUS = 0x00000040;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700159
160 /**
161 * Action that clears accessibility focus of the node.
162 */
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700163 public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 0x00000080;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700164
165 /**
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700166 * Action that requests to go to the next entity in this node's text
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700167 * at a given movement granularity. For example, move to the next character,
168 * word, etc.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700169 * <p>
Svetoslav7c512842013-01-30 23:02:08 -0800170 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
171 * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
172 * <strong>Example:</strong> Move to the previous character and do not extend selection.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700173 * <code><pre><p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700174 * Bundle arguments = new Bundle();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700175 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
176 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
Svetoslav7c512842013-01-30 23:02:08 -0800177 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
178 * false);
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700179 * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700180 * </code></pre></p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700181 * </p>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700182 *
Svetoslav7c512842013-01-30 23:02:08 -0800183 * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
184 * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
185 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700186 * @see #setMovementGranularities(int)
187 * @see #getMovementGranularities()
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700188 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700189 * @see #MOVEMENT_GRANULARITY_CHARACTER
190 * @see #MOVEMENT_GRANULARITY_WORD
191 * @see #MOVEMENT_GRANULARITY_LINE
192 * @see #MOVEMENT_GRANULARITY_PARAGRAPH
193 * @see #MOVEMENT_GRANULARITY_PAGE
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700194 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700195 public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 0x00000100;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700196
197 /**
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700198 * Action that requests to go to the previous entity in this node's text
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700199 * at a given movement granularity. For example, move to the next character,
200 * word, etc.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700201 * <p>
Svetoslav7c512842013-01-30 23:02:08 -0800202 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
203 * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
204 * <strong>Example:</strong> Move to the next character and do not extend selection.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700205 * <code><pre><p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700206 * Bundle arguments = new Bundle();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700207 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
208 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
Svetoslav7c512842013-01-30 23:02:08 -0800209 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
210 * false);
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700211 * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
212 * arguments);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700213 * </code></pre></p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700214 * </p>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700215 *
Svetoslav7c512842013-01-30 23:02:08 -0800216 * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
217 * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
218 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700219 * @see #setMovementGranularities(int)
220 * @see #getMovementGranularities()
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700221 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700222 * @see #MOVEMENT_GRANULARITY_CHARACTER
223 * @see #MOVEMENT_GRANULARITY_WORD
224 * @see #MOVEMENT_GRANULARITY_LINE
225 * @see #MOVEMENT_GRANULARITY_PARAGRAPH
226 * @see #MOVEMENT_GRANULARITY_PAGE
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700227 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700228 public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 0x00000200;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700229
230 /**
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700231 * Action to move to the next HTML element of a given type. For example, move
232 * to the BUTTON, INPUT, TABLE, etc.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700233 * <p>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700234 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
235 * <strong>Example:</strong>
236 * <code><pre><p>
237 * Bundle arguments = new Bundle();
238 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
239 * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, arguments);
240 * </code></pre></p>
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700241 * </p>
242 */
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700243 public static final int ACTION_NEXT_HTML_ELEMENT = 0x00000400;
244
245 /**
246 * Action to move to the previous HTML element of a given type. For example, move
247 * to the BUTTON, INPUT, TABLE, etc.
248 * <p>
249 * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
250 * <strong>Example:</strong>
251 * <code><pre><p>
252 * Bundle arguments = new Bundle();
253 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
254 * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT, arguments);
255 * </code></pre></p>
256 * </p>
257 */
258 public static final int ACTION_PREVIOUS_HTML_ELEMENT = 0x00000800;
259
260 /**
Svetoslav Ganova1dc7612012-05-10 04:14:53 -0700261 * Action to scroll the node content forward.
262 */
263 public static final int ACTION_SCROLL_FORWARD = 0x00001000;
264
265 /**
266 * Action to scroll the node content backward.
267 */
268 public static final int ACTION_SCROLL_BACKWARD = 0x00002000;
269
270 /**
Svetoslav7c512842013-01-30 23:02:08 -0800271 * Action to copy the current selection to the clipboard.
272 */
273 public static final int ACTION_COPY = 0x00004000;
274
275 /**
276 * Action to paste the current clipboard content.
277 */
278 public static final int ACTION_PASTE = 0x00008000;
279
280 /**
281 * Action to cut the current selection and place it to the clipboard.
282 */
283 public static final int ACTION_CUT = 0x00010000;
284
285 /**
286 * Action to set the selection. Performing this action with no arguments
287 * clears the selection.
288 * <p>
Alan Viverette23f44322015-04-06 16:04:56 -0700289 * <strong>Arguments:</strong>
290 * {@link #ACTION_ARGUMENT_SELECTION_START_INT},
Svetoslav7c512842013-01-30 23:02:08 -0800291 * {@link #ACTION_ARGUMENT_SELECTION_END_INT}<br>
292 * <strong>Example:</strong>
293 * <code><pre><p>
294 * Bundle arguments = new Bundle();
295 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1);
296 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 2);
297 * info.performAction(AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments);
298 * </code></pre></p>
299 * </p>
300 *
301 * @see #ACTION_ARGUMENT_SELECTION_START_INT
302 * @see #ACTION_ARGUMENT_SELECTION_END_INT
303 */
304 public static final int ACTION_SET_SELECTION = 0x00020000;
305
306 /**
Svetoslav3577a282013-06-06 14:09:10 -0700307 * Action to expand an expandable node.
308 */
309 public static final int ACTION_EXPAND = 0x00040000;
310
311 /**
312 * Action to collapse an expandable node.
313 */
314 public static final int ACTION_COLLAPSE = 0x00080000;
315
316 /**
317 * Action to dismiss a dismissable node.
318 */
319 public static final int ACTION_DISMISS = 0x00100000;
320
Guang Zhu4cd353c2014-02-12 19:54:30 -0800321 /**
322 * Action that sets the text of the node. Performing the action without argument, using <code>
323 * null</code> or empty {@link CharSequence} will clear the text. This action will also put the
324 * cursor at the end of text.
325 * <p>
Alan Viverette23f44322015-04-06 16:04:56 -0700326 * <strong>Arguments:</strong>
327 * {@link #ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br>
Guang Zhu4cd353c2014-02-12 19:54:30 -0800328 * <strong>Example:</strong>
329 * <code><pre><p>
330 * Bundle arguments = new Bundle();
331 * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
332 * "android");
333 * info.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
334 * </code></pre></p>
335 */
336 public static final int ACTION_SET_TEXT = 0x00200000;
337
Eugene Susla554edd32017-05-24 16:49:59 -0700338 /** @hide */
339 public static final int LAST_LEGACY_STANDARD_ACTION = ACTION_SET_TEXT;
Kristian Monsen74bc1942014-04-29 11:00:17 -0700340
341 /**
342 * Mask to see if the value is larger than the largest ACTION_ constant
343 */
344 private static final int ACTION_TYPE_MASK = 0xFF000000;
345
Svetoslav3577a282013-06-06 14:09:10 -0700346 // Action arguments
347
348 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700349 * Argument for which movement granularity to be used when traversing the node text.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700350 * <p>
351 * <strong>Type:</strong> int<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700352 * <strong>Actions:</strong>
353 * <ul>
354 * <li>{@link AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY}</li>
355 * <li>{@link AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}</li>
356 * </ul>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700357 * </p>
Svetoslav7c512842013-01-30 23:02:08 -0800358 *
Alan Viverette23f44322015-04-06 16:04:56 -0700359 * @see AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
360 * @see AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700361 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700362 public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT =
Svetoslav7c512842013-01-30 23:02:08 -0800363 "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700364
365 /**
366 * Argument for which HTML element to get moving to the next/previous HTML element.
367 * <p>
368 * <strong>Type:</strong> String<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700369 * <strong>Actions:</strong>
370 * <ul>
371 * <li>{@link AccessibilityAction#ACTION_NEXT_HTML_ELEMENT}</li>
372 * <li>{@link AccessibilityAction#ACTION_PREVIOUS_HTML_ELEMENT}</li>
373 * </ul>
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700374 * </p>
Svetoslav7c512842013-01-30 23:02:08 -0800375 *
Alan Viverette23f44322015-04-06 16:04:56 -0700376 * @see AccessibilityAction#ACTION_NEXT_HTML_ELEMENT
377 * @see AccessibilityAction#ACTION_PREVIOUS_HTML_ELEMENT
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700378 */
379 public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING =
Svetoslav7c512842013-01-30 23:02:08 -0800380 "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
381
382 /**
383 * Argument for whether when moving at granularity to extend the selection
384 * or to move it otherwise.
385 * <p>
386 * <strong>Type:</strong> boolean<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700387 * <strong>Actions:</strong>
388 * <ul>
389 * <li>{@link AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY}</li>
390 * <li>{@link AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}</li>
391 * </ul>
Svetoslav7c512842013-01-30 23:02:08 -0800392 *
Alan Viverette23f44322015-04-06 16:04:56 -0700393 * @see AccessibilityAction#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
394 * @see AccessibilityAction#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
Svetoslav7c512842013-01-30 23:02:08 -0800395 */
396 public static final String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN =
397 "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
398
399 /**
400 * Argument for specifying the selection start.
401 * <p>
402 * <strong>Type:</strong> int<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700403 * <strong>Actions:</strong>
404 * <ul>
405 * <li>{@link AccessibilityAction#ACTION_SET_SELECTION}</li>
406 * </ul>
Svetoslav7c512842013-01-30 23:02:08 -0800407 *
Alan Viverette23f44322015-04-06 16:04:56 -0700408 * @see AccessibilityAction#ACTION_SET_SELECTION
Svetoslav7c512842013-01-30 23:02:08 -0800409 */
410 public static final String ACTION_ARGUMENT_SELECTION_START_INT =
411 "ACTION_ARGUMENT_SELECTION_START_INT";
412
413 /**
414 * Argument for specifying the selection end.
415 * <p>
416 * <strong>Type:</strong> int<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700417 * <strong>Actions:</strong>
418 * <ul>
419 * <li>{@link AccessibilityAction#ACTION_SET_SELECTION}</li>
420 * </ul>
Svetoslav7c512842013-01-30 23:02:08 -0800421 *
Alan Viverette23f44322015-04-06 16:04:56 -0700422 * @see AccessibilityAction#ACTION_SET_SELECTION
Svetoslav7c512842013-01-30 23:02:08 -0800423 */
424 public static final String ACTION_ARGUMENT_SELECTION_END_INT =
425 "ACTION_ARGUMENT_SELECTION_END_INT";
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700426
Guang Zhu4cd353c2014-02-12 19:54:30 -0800427 /**
Alan Viverette23f44322015-04-06 16:04:56 -0700428 * Argument for specifying the text content to set.
Guang Zhu4cd353c2014-02-12 19:54:30 -0800429 * <p>
430 * <strong>Type:</strong> CharSequence<br>
Alan Viverette23f44322015-04-06 16:04:56 -0700431 * <strong>Actions:</strong>
432 * <ul>
433 * <li>{@link AccessibilityAction#ACTION_SET_TEXT}</li>
434 * </ul>
Guang Zhu4cd353c2014-02-12 19:54:30 -0800435 *
Alan Viverette23f44322015-04-06 16:04:56 -0700436 * @see AccessibilityAction#ACTION_SET_TEXT
Guang Zhu4cd353c2014-02-12 19:54:30 -0800437 */
438 public static final String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE =
439 "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE";
440
Alan Viverette23f44322015-04-06 16:04:56 -0700441 /**
442 * Argument for specifying the collection row to make visible on screen.
443 * <p>
444 * <strong>Type:</strong> int<br>
445 * <strong>Actions:</strong>
446 * <ul>
447 * <li>{@link AccessibilityAction#ACTION_SCROLL_TO_POSITION}</li>
448 * </ul>
449 *
450 * @see AccessibilityAction#ACTION_SCROLL_TO_POSITION
451 */
452 public static final String ACTION_ARGUMENT_ROW_INT =
453 "android.view.accessibility.action.ARGUMENT_ROW_INT";
454
455 /**
456 * Argument for specifying the collection column to make visible on screen.
457 * <p>
458 * <strong>Type:</strong> int<br>
459 * <strong>Actions:</strong>
460 * <ul>
461 * <li>{@link AccessibilityAction#ACTION_SCROLL_TO_POSITION}</li>
462 * </ul>
463 *
464 * @see AccessibilityAction#ACTION_SCROLL_TO_POSITION
465 */
466 public static final String ACTION_ARGUMENT_COLUMN_INT =
467 "android.view.accessibility.action.ARGUMENT_COLUMN_INT";
468
Maxim Bogatov32e59d52015-04-30 16:57:33 -0700469 /**
470 * Argument for specifying the progress value to set.
471 * <p>
472 * <strong>Type:</strong> float<br>
473 * <strong>Actions:</strong>
474 * <ul>
475 * <li>{@link AccessibilityAction#ACTION_SET_PROGRESS}</li>
476 * </ul>
477 *
478 * @see AccessibilityAction#ACTION_SET_PROGRESS
479 */
480 public static final String ACTION_ARGUMENT_PROGRESS_VALUE =
481 "android.view.accessibility.action.ARGUMENT_PROGRESS_VALUE";
482
Phil Weaver193520e2016-12-13 09:39:06 -0800483 /**
Phil Weaverf00cd142017-03-03 13:44:00 -0800484 * Argument for specifying the x coordinate to which to move a window.
485 * <p>
486 * <strong>Type:</strong> int<br>
487 * <strong>Actions:</strong>
488 * <ul>
489 * <li>{@link AccessibilityAction#ACTION_MOVE_WINDOW}</li>
490 * </ul>
491 *
492 * @see AccessibilityAction#ACTION_MOVE_WINDOW
493 */
494 public static final String ACTION_ARGUMENT_MOVE_WINDOW_X =
Phil Weaverbe2922f2017-04-28 14:58:35 -0700495 "ACTION_ARGUMENT_MOVE_WINDOW_X";
Phil Weaverf00cd142017-03-03 13:44:00 -0800496
497 /**
498 * Argument for specifying the y coordinate to which to move a window.
499 * <p>
500 * <strong>Type:</strong> int<br>
501 * <strong>Actions:</strong>
502 * <ul>
503 * <li>{@link AccessibilityAction#ACTION_MOVE_WINDOW}</li>
504 * </ul>
505 *
506 * @see AccessibilityAction#ACTION_MOVE_WINDOW
507 */
508 public static final String ACTION_ARGUMENT_MOVE_WINDOW_Y =
Phil Weaverbe2922f2017-04-28 14:58:35 -0700509 "ACTION_ARGUMENT_MOVE_WINDOW_Y";
Phil Weaverf00cd142017-03-03 13:44:00 -0800510
511 /**
Phil Weaver193520e2016-12-13 09:39:06 -0800512 * Argument to pass the {@link AccessibilityClickableSpan}.
513 * For use with R.id.accessibilityActionClickOnClickableSpan
514 * @hide
515 */
516 public static final String ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN =
517 "android.view.accessibility.action.ACTION_ARGUMENT_ACCESSIBLE_CLICKABLE_SPAN";
518
Svetoslav3577a282013-06-06 14:09:10 -0700519 // Focus types
520
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700521 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700522 * The input focus.
523 */
524 public static final int FOCUS_INPUT = 1;
525
526 /**
527 * The accessibility focus.
528 */
529 public static final int FOCUS_ACCESSIBILITY = 2;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700530
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700531 // Movement granularities
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700532
533 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700534 * Movement granularity bit for traversing the text of a node by character.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700535 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700536 public static final int MOVEMENT_GRANULARITY_CHARACTER = 0x00000001;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700537
538 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700539 * Movement granularity bit for traversing the text of a node by word.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700540 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700541 public static final int MOVEMENT_GRANULARITY_WORD = 0x00000002;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700542
543 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700544 * Movement granularity bit for traversing the text of a node by line.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700545 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700546 public static final int MOVEMENT_GRANULARITY_LINE = 0x00000004;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700547
548 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700549 * Movement granularity bit for traversing the text of a node by paragraph.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700550 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700551 public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 0x00000008;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700552
553 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700554 * Movement granularity bit for traversing the text of a node by page.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700555 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700556 public static final int MOVEMENT_GRANULARITY_PAGE = 0x00000010;
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -0700557
Phil Weaverc2e28932016-12-08 12:29:25 -0800558 /**
559 * Key used to request and locate extra data for text character location. This key requests that
560 * an array of {@link android.graphics.RectF}s be added to the extras. This request is made with
561 * {@link #refreshWithExtraData(String, Bundle)}. The arguments taken by this request are two
562 * integers: {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX} and
563 * {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH}. The starting index must be valid
564 * inside the CharSequence returned by {@link #getText()}, and the length must be positive.
565 * <p>
566 * The data can be retrieved from the {@code Bundle} returned by {@link #getExtras()} using this
567 * string as a key for {@link Bundle#getParcelableArray(String)}. The
568 * {@link android.graphics.RectF} will be null for characters that either do not exist or are
569 * off the screen.
570 *
571 * {@see #refreshWithExtraData(String, Bundle)}
572 */
573 public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY =
574 "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY";
575
576 /**
577 * Integer argument specifying the start index of the requested text location data. Must be
578 * valid inside the CharSequence returned by {@link #getText()}.
579 *
580 * {@see EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY}
581 */
582 public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX =
583 "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX";
584
585 /**
586 * Integer argument specifying the end index of the requested text location data. Must be
587 * positive.
588 *
589 * {@see EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY}
590 */
591 public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH =
592 "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH";
593
594 /** @hide */
595 public static final String EXTRA_DATA_REQUESTED_KEY =
596 "android.view.accessibility.AccessibilityNodeInfo.extra_data_requested";
597
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700598 // Boolean attributes.
599
Svetoslavbcc46a02013-02-06 11:56:00 -0800600 private static final int BOOLEAN_PROPERTY_CHECKABLE = 0x00000001;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700601
Svetoslavbcc46a02013-02-06 11:56:00 -0800602 private static final int BOOLEAN_PROPERTY_CHECKED = 0x00000002;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700603
Svetoslavbcc46a02013-02-06 11:56:00 -0800604 private static final int BOOLEAN_PROPERTY_FOCUSABLE = 0x00000004;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700605
Svetoslavbcc46a02013-02-06 11:56:00 -0800606 private static final int BOOLEAN_PROPERTY_FOCUSED = 0x00000008;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700607
Svetoslavbcc46a02013-02-06 11:56:00 -0800608 private static final int BOOLEAN_PROPERTY_SELECTED = 0x00000010;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700609
Svetoslavbcc46a02013-02-06 11:56:00 -0800610 private static final int BOOLEAN_PROPERTY_CLICKABLE = 0x00000020;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700611
Svetoslavbcc46a02013-02-06 11:56:00 -0800612 private static final int BOOLEAN_PROPERTY_LONG_CLICKABLE = 0x00000040;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700613
Svetoslavbcc46a02013-02-06 11:56:00 -0800614 private static final int BOOLEAN_PROPERTY_ENABLED = 0x00000080;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700615
Svetoslavbcc46a02013-02-06 11:56:00 -0800616 private static final int BOOLEAN_PROPERTY_PASSWORD = 0x00000100;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700617
Svetoslavbcc46a02013-02-06 11:56:00 -0800618 private static final int BOOLEAN_PROPERTY_SCROLLABLE = 0x00000200;
Svetoslav Ganova0156172011-06-26 17:55:44 -0700619
Svetoslavbcc46a02013-02-06 11:56:00 -0800620 private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED = 0x00000400;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700621
Svetoslavbcc46a02013-02-06 11:56:00 -0800622 private static final int BOOLEAN_PROPERTY_VISIBLE_TO_USER = 0x00000800;
623
624 private static final int BOOLEAN_PROPERTY_EDITABLE = 0x00001000;
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -0700625
Alan Viverette77e9a282013-09-12 17:16:09 -0700626 private static final int BOOLEAN_PROPERTY_OPENS_POPUP = 0x00002000;
Svetoslav3577a282013-06-06 14:09:10 -0700627
Alan Viverette77e9a282013-09-12 17:16:09 -0700628 private static final int BOOLEAN_PROPERTY_DISMISSABLE = 0x00004000;
Svetoslav3577a282013-06-06 14:09:10 -0700629
Alan Viverette77e9a282013-09-12 17:16:09 -0700630 private static final int BOOLEAN_PROPERTY_MULTI_LINE = 0x00008000;
Svetoslav3577a282013-06-06 14:09:10 -0700631
Alan Viverette77e9a282013-09-12 17:16:09 -0700632 private static final int BOOLEAN_PROPERTY_CONTENT_INVALID = 0x00010000;
Svetoslav3577a282013-06-06 14:09:10 -0700633
Mady Mellore8608912015-06-05 09:02:55 -0700634 private static final int BOOLEAN_PROPERTY_CONTEXT_CLICKABLE = 0x00020000;
Mady Mellore82067b2015-04-30 09:58:35 -0700635
Casey Burkhardt2d80ae42016-01-31 12:52:23 -0800636 private static final int BOOLEAN_PROPERTY_IMPORTANCE = 0x0040000;
637
Phil Weaver1e6ecc62017-11-07 15:28:21 -0800638 private static final int BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE = 0x0080000;
639
Phil Weaver776afc22016-12-21 10:55:13 -0800640 private static final int BOOLEAN_PROPERTY_IS_SHOWING_HINT = 0x0100000;
641
Phil Weaver6290fb592018-01-08 17:42:18 -0800642 private static final int BOOLEAN_PROPERTY_IS_HEADING = 0x0200000;
643
Svetoslav Ganov02107852011-10-03 17:06:56 -0700644 /**
645 * Bits that provide the id of a virtual descendant of a view.
646 */
647 private static final long VIRTUAL_DESCENDANT_ID_MASK = 0xffffffff00000000L;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700648 /**
649 * Bit shift of {@link #VIRTUAL_DESCENDANT_ID_MASK} to get to the id for a
650 * virtual descendant of a view. Such a descendant does not exist in the view
651 * hierarchy and is only reported via the accessibility APIs.
652 */
653 private static final int VIRTUAL_DESCENDANT_ID_SHIFT = 32;
654
Phil Weaver62d20fa2016-09-15 11:05:55 -0700655 private static AtomicInteger sNumInstancesInUse;
Phil Weaverb010b122016-08-17 17:47:48 -0700656
Svetoslav Ganov02107852011-10-03 17:06:56 -0700657 /**
Phil Weavere1951292017-08-18 17:56:04 +0000658 * Gets the accessibility view id which identifies a View in the view three.
Svetoslav Ganov02107852011-10-03 17:06:56 -0700659 *
660 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}.
661 * @return The accessibility view id part of the node id.
662 *
663 * @hide
664 */
665 public static int getAccessibilityViewId(long accessibilityNodeId) {
666 return (int) accessibilityNodeId;
667 }
668
669 /**
670 * Gets the virtual descendant id which identifies an imaginary view in a
671 * containing View.
672 *
673 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}.
674 * @return The virtual view id part of the node id.
675 *
676 * @hide
677 */
678 public static int getVirtualDescendantId(long accessibilityNodeId) {
679 return (int) ((accessibilityNodeId & VIRTUAL_DESCENDANT_ID_MASK)
680 >> VIRTUAL_DESCENDANT_ID_SHIFT);
681 }
682
683 /**
684 * Makes a node id by shifting the <code>virtualDescendantId</code>
685 * by {@link #VIRTUAL_DESCENDANT_ID_SHIFT} and taking
686 * the bitwise or with the <code>accessibilityViewId</code>.
687 *
688 * @param accessibilityViewId A View accessibility id.
689 * @param virtualDescendantId A virtual descendant id.
690 * @return The node id.
691 *
692 * @hide
693 */
694 public static long makeNodeId(int accessibilityViewId, int virtualDescendantId) {
695 return (((long) virtualDescendantId) << VIRTUAL_DESCENDANT_ID_SHIFT) | accessibilityViewId;
696 }
697
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700698 // Housekeeping.
699 private static final int MAX_POOL_SIZE = 50;
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -0800700 private static final SynchronizedPool<AccessibilityNodeInfo> sPool =
Alan Viverette23f44322015-04-06 16:04:56 -0700701 new SynchronizedPool<>(MAX_POOL_SIZE);
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -0800702
Eugene Susla0eb2b6e2017-05-15 14:06:32 -0700703 private static final AccessibilityNodeInfo DEFAULT = new AccessibilityNodeInfo();
704
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700705 private boolean mSealed;
706
707 // Data.
Phil Weaver23161e72017-04-19 12:16:36 -0700708 private int mWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
Phil Weaverf00cd142017-03-03 13:44:00 -0800709 private long mSourceNodeId = UNDEFINED_NODE_ID;
710 private long mParentNodeId = UNDEFINED_NODE_ID;
711 private long mLabelForId = UNDEFINED_NODE_ID;
712 private long mLabeledById = UNDEFINED_NODE_ID;
713 private long mTraversalBefore = UNDEFINED_NODE_ID;
714 private long mTraversalAfter = UNDEFINED_NODE_ID;
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800715
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700716 private int mBooleanProperties;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700717 private final Rect mBoundsInParent = new Rect();
718 private final Rect mBoundsInScreen = new Rect();
Phil Weaver1f222542016-01-08 11:49:32 -0800719 private int mDrawingOrderInParent;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700720
721 private CharSequence mPackageName;
722 private CharSequence mClassName;
Phil Weaver193520e2016-12-13 09:39:06 -0800723 // Hidden, unparceled value used to hold the original value passed to setText
724 private CharSequence mOriginalText;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700725 private CharSequence mText;
Phil Weaver776afc22016-12-21 10:55:13 -0800726 private CharSequence mHintText;
Alan Viverettefccbff52014-07-07 15:06:14 -0700727 private CharSequence mError;
Phil Weaver9f26b3d2018-01-04 10:04:37 -0800728 private CharSequence mPaneTitle;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700729 private CharSequence mContentDescription;
Phil Weaverd89905f2018-01-10 08:28:04 -0800730 private CharSequence mTooltipText;
Svetoslav9fa1ee52013-04-22 12:43:03 -0700731 private String mViewIdResourceName;
Phil Weaverc2e28932016-12-08 12:29:25 -0800732 private ArrayList<String> mExtraDataKeys;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700733
Alan Viverettef0aed092013-11-06 15:33:03 -0800734 private LongArray mChildNodeIds;
Kristian Monsen74bc1942014-04-29 11:00:17 -0700735 private ArrayList<AccessibilityAction> mActions;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700736
Alan Viverette029942f2014-08-12 14:55:56 -0700737 private int mMaxTextLength = -1;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700738 private int mMovementGranularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700739
Svetoslav8e3feb12014-02-24 13:46:47 -0800740 private int mTextSelectionStart = UNDEFINED_SELECTION_INDEX;
741 private int mTextSelectionEnd = UNDEFINED_SELECTION_INDEX;
Svetoslav6254f482013-06-04 17:22:14 -0700742 private int mInputType = InputType.TYPE_NULL;
Alan Viverette77e9a282013-09-12 17:16:09 -0700743 private int mLiveRegion = View.ACCESSIBILITY_LIVE_REGION_NONE;
Svetoslav6254f482013-06-04 17:22:14 -0700744
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -0700745 private Bundle mExtras;
Svetoslavbcc46a02013-02-06 11:56:00 -0800746
Svetoslav8e3feb12014-02-24 13:46:47 -0800747 private int mConnectionId = UNDEFINED_CONNECTION_ID;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700748
Svetoslav3577a282013-06-06 14:09:10 -0700749 private RangeInfo mRangeInfo;
750 private CollectionInfo mCollectionInfo;
751 private CollectionItemInfo mCollectionItemInfo;
752
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700753 /**
754 * Hide constructor from clients.
755 */
756 private AccessibilityNodeInfo() {
757 /* do nothing */
758 }
759
760 /**
761 * Sets the source.
Svetoslav Ganov02107852011-10-03 17:06:56 -0700762 * <p>
763 * <strong>Note:</strong> Cannot be called from an
764 * {@link android.accessibilityservice.AccessibilityService}.
765 * This class is made immutable before being delivered to an AccessibilityService.
766 * </p>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700767 *
768 * @param source The info source.
769 */
770 public void setSource(View source) {
Phil Weaverf00cd142017-03-03 13:44:00 -0800771 setSource(source, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov02107852011-10-03 17:06:56 -0700772 }
773
774 /**
775 * Sets the source to be a virtual descendant of the given <code>root</code>.
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700776 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
Svetoslav Ganov02107852011-10-03 17:06:56 -0700777 * is set as the source.
778 * <p>
779 * A virtual descendant is an imaginary View that is reported as a part of the view
780 * hierarchy for accessibility purposes. This enables custom views that draw complex
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700781 * content to report themselves as a tree of virtual views, thus conveying their
Svetoslav Ganov02107852011-10-03 17:06:56 -0700782 * logical structure.
783 * </p>
784 * <p>
785 * <strong>Note:</strong> Cannot be called from an
786 * {@link android.accessibilityservice.AccessibilityService}.
787 * This class is made immutable before being delivered to an AccessibilityService.
788 * </p>
789 *
790 * @param root The root of the virtual subtree.
791 * @param virtualDescendantId The id of the virtual descendant.
792 */
793 public void setSource(View root, int virtualDescendantId) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700794 enforceNotSealed();
Svetoslav8e3feb12014-02-24 13:46:47 -0800795 mWindowId = (root != null) ? root.getAccessibilityWindowId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700796 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -0800797 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700798 mSourceNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700799 }
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700800
Svetoslav Ganov42138042012-03-20 11:51:39 -0700801 /**
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700802 * Find the view that has the specified focus type. The search starts from
Svetoslav Ganov42138042012-03-20 11:51:39 -0700803 * the view represented by this node info.
804 *
805 * @param focus The focus to find. One of {@link #FOCUS_INPUT} or
806 * {@link #FOCUS_ACCESSIBILITY}.
807 * @return The node info of the focused view or null.
808 *
809 * @see #FOCUS_INPUT
810 * @see #FOCUS_ACCESSIBILITY
811 */
812 public AccessibilityNodeInfo findFocus(int focus) {
813 enforceSealed();
Svetoslav Ganov2ef69052012-06-04 08:55:16 -0700814 enforceValidFocusType(focus);
Svetoslav Ganov42138042012-03-20 11:51:39 -0700815 if (!canPerformRequestOverConnection(mSourceNodeId)) {
816 return null;
817 }
818 return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId, mWindowId,
819 mSourceNodeId, focus);
820 }
821
822 /**
823 * Searches for the nearest view in the specified direction that can take
824 * the input focus.
825 *
826 * @param direction The direction. Can be one of:
827 * {@link View#FOCUS_DOWN},
828 * {@link View#FOCUS_UP},
829 * {@link View#FOCUS_LEFT},
830 * {@link View#FOCUS_RIGHT},
831 * {@link View#FOCUS_FORWARD},
Svetoslav Ganov8ffe8b32012-06-15 10:31:31 -0700832 * {@link View#FOCUS_BACKWARD}.
Svetoslav Ganov42138042012-03-20 11:51:39 -0700833 *
834 * @return The node info for the view that can take accessibility focus.
835 */
836 public AccessibilityNodeInfo focusSearch(int direction) {
837 enforceSealed();
Svetoslav Ganov2ef69052012-06-04 08:55:16 -0700838 enforceValidFocusDirection(direction);
Svetoslav Ganov42138042012-03-20 11:51:39 -0700839 if (!canPerformRequestOverConnection(mSourceNodeId)) {
840 return null;
841 }
842 return AccessibilityInteractionClient.getInstance().focusSearch(mConnectionId, mWindowId,
843 mSourceNodeId, direction);
844 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700845
846 /**
847 * Gets the id of the window from which the info comes from.
848 *
849 * @return The window id.
850 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700851 public int getWindowId() {
Svetoslav Ganov02107852011-10-03 17:06:56 -0700852 return mWindowId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700853 }
854
855 /**
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800856 * Refreshes this info with the latest state of the view it represents.
857 * <p>
858 * <strong>Note:</strong> If this method returns false this info is obsolete
859 * since it represents a view that is no longer in the view tree and should
860 * be recycled.
861 * </p>
Svetoslav6254f482013-06-04 17:22:14 -0700862 *
863 * @param bypassCache Whether to bypass the cache.
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800864 * @return Whether the refresh succeeded.
Svetoslav6254f482013-06-04 17:22:14 -0700865 *
866 * @hide
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800867 */
Phil Weaverc2e28932016-12-08 12:29:25 -0800868 public boolean refresh(Bundle arguments, boolean bypassCache) {
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800869 enforceSealed();
870 if (!canPerformRequestOverConnection(mSourceNodeId)) {
871 return false;
872 }
873 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
874 AccessibilityNodeInfo refreshedInfo = client.findAccessibilityNodeInfoByAccessibilityId(
Phil Weaverc2e28932016-12-08 12:29:25 -0800875 mConnectionId, mWindowId, mSourceNodeId, bypassCache, 0, arguments);
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800876 if (refreshedInfo == null) {
877 return false;
878 }
Phil Weavercc797d52017-08-21 12:45:11 -0700879 // Hard-to-reproduce bugs seem to be due to some tools recycling a node on another
880 // thread. If that happens, the init will re-seal the node, which then is in a bad state
881 // when it is obtained. Enforce sealing again before we init to fail when a node has been
882 // recycled during a refresh to catch such errors earlier.
883 enforceSealed();
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800884 init(refreshedInfo);
885 refreshedInfo.recycle();
886 return true;
887 }
888
889 /**
Svetoslav6254f482013-06-04 17:22:14 -0700890 * Refreshes this info with the latest state of the view it represents.
Phil Weaverc2e28932016-12-08 12:29:25 -0800891 *
892 * @return {@code true} if the refresh succeeded. {@code false} if the {@link View} represented
893 * by this node is no longer in the view tree (and thus this node is obsolete and should be
894 * recycled).
Svetoslav6254f482013-06-04 17:22:14 -0700895 */
896 public boolean refresh() {
Phil Weaverc2e28932016-12-08 12:29:25 -0800897 return refresh(null, true);
898 }
899
900 /**
901 * Refreshes this info with the latest state of the view it represents, and request new
902 * data be added by the View.
903 *
904 * @param extraDataKey A bitmask of the extra data requested. Data that must be requested
905 * with this mechanism is generally expensive to retrieve, so should only be
906 * requested when needed. See
907 * {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY} and
908 * {@link #getAvailableExtraData()}.
909 * @param args A bundle of arguments for the request. These depend on the particular request.
910 *
911 * @return {@code true} if the refresh succeeded. {@code false} if the {@link View} represented
912 * by this node is no longer in the view tree (and thus this node is obsolete and should be
913 * recycled).
914 */
915 public boolean refreshWithExtraData(String extraDataKey, Bundle args) {
916 args.putString(EXTRA_DATA_REQUESTED_KEY, extraDataKey);
917 return refresh(args, true);
Svetoslav6254f482013-06-04 17:22:14 -0700918 }
919
920 /**
Alan Viverettef0aed092013-11-06 15:33:03 -0800921 * Returns the array containing the IDs of this node's children.
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800922 *
923 * @hide
924 */
Alan Viverettef0aed092013-11-06 15:33:03 -0800925 public LongArray getChildNodeIds() {
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800926 return mChildNodeIds;
927 }
928
929 /**
Alan Viverettef0aed092013-11-06 15:33:03 -0800930 * Returns the id of the child at the specified index.
931 *
932 * @throws IndexOutOfBoundsException when index &lt; 0 || index &gt;=
933 * getChildCount()
934 * @hide
935 */
936 public long getChildId(int index) {
937 if (mChildNodeIds == null) {
938 throw new IndexOutOfBoundsException();
939 }
940 return mChildNodeIds.get(index);
941 }
942
943 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700944 * Gets the number of children.
945 *
946 * @return The child count.
947 */
948 public int getChildCount() {
Alan Viverettef0aed092013-11-06 15:33:03 -0800949 return mChildNodeIds == null ? 0 : mChildNodeIds.size();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700950 }
951
952 /**
953 * Get the child at given index.
954 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700955 * <strong>Note:</strong> It is a client responsibility to recycle the
956 * received info by calling {@link AccessibilityNodeInfo#recycle()}
957 * to avoid creating of multiple instances.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700958 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700959 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700960 * @param index The child index.
961 * @return The child node.
962 *
963 * @throws IllegalStateException If called outside of an AccessibilityService.
964 *
965 */
966 public AccessibilityNodeInfo getChild(int index) {
967 enforceSealed();
Alan Viverettef0aed092013-11-06 15:33:03 -0800968 if (mChildNodeIds == null) {
969 return null;
970 }
Svetoslav Ganov02107852011-10-03 17:06:56 -0700971 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700972 return null;
973 }
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800974 final long childId = mChildNodeIds.get(index);
Svetoslav Ganov8bd69612011-08-23 13:40:30 -0700975 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800976 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId,
Phil Weaverc2e28932016-12-08 12:29:25 -0800977 childId, false, FLAG_PREFETCH_DESCENDANTS, null);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700978 }
979
980 /**
981 * Adds a child.
982 * <p>
Svetoslav Ganov02107852011-10-03 17:06:56 -0700983 * <strong>Note:</strong> Cannot be called from an
984 * {@link android.accessibilityservice.AccessibilityService}.
985 * This class is made immutable before being delivered to an AccessibilityService.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700986 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700987 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700988 * @param child The child.
989 *
990 * @throws IllegalStateException If called from an AccessibilityService.
991 */
992 public void addChild(View child) {
Phil Weaverf00cd142017-03-03 13:44:00 -0800993 addChildInternal(child, AccessibilityNodeProvider.HOST_VIEW_ID, true);
Alan Viverettef0aed092013-11-06 15:33:03 -0800994 }
995
996 /**
997 * Unchecked version of {@link #addChild(View)} that does not verify
998 * uniqueness. For framework use only.
999 *
1000 * @hide
1001 */
1002 public void addChildUnchecked(View child) {
Phil Weaverf00cd142017-03-03 13:44:00 -08001003 addChildInternal(child, AccessibilityNodeProvider.HOST_VIEW_ID, false);
Alan Viverettef0aed092013-11-06 15:33:03 -08001004 }
1005
1006 /**
1007 * Removes a child. If the child was not previously added to the node,
1008 * calling this method has no effect.
1009 * <p>
1010 * <strong>Note:</strong> Cannot be called from an
1011 * {@link android.accessibilityservice.AccessibilityService}.
1012 * This class is made immutable before being delivered to an AccessibilityService.
1013 * </p>
1014 *
1015 * @param child The child.
1016 * @return true if the child was present
1017 *
1018 * @throws IllegalStateException If called from an AccessibilityService.
1019 */
1020 public boolean removeChild(View child) {
Phil Weaverf00cd142017-03-03 13:44:00 -08001021 return removeChild(child, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov02107852011-10-03 17:06:56 -07001022 }
1023
1024 /**
1025 * Adds a virtual child which is a descendant of the given <code>root</code>.
Svetoslav Ganov71b4e712011-10-25 11:31:31 -07001026 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
Svetoslav Ganov02107852011-10-03 17:06:56 -07001027 * is added as a child.
1028 * <p>
1029 * A virtual descendant is an imaginary View that is reported as a part of the view
1030 * hierarchy for accessibility purposes. This enables custom views that draw complex
1031 * content to report them selves as a tree of virtual views, thus conveying their
1032 * logical structure.
1033 * </p>
1034 *
1035 * @param root The root of the virtual subtree.
1036 * @param virtualDescendantId The id of the virtual child.
1037 */
1038 public void addChild(View root, int virtualDescendantId) {
Alan Viverettef0aed092013-11-06 15:33:03 -08001039 addChildInternal(root, virtualDescendantId, true);
1040 }
1041
1042 private void addChildInternal(View root, int virtualDescendantId, boolean checked) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001043 enforceNotSealed();
Alan Viverettef0aed092013-11-06 15:33:03 -08001044 if (mChildNodeIds == null) {
1045 mChildNodeIds = new LongArray();
1046 }
Svetoslav Ganov02107852011-10-03 17:06:56 -07001047 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -08001048 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -07001049 final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Alan Viverettef0aed092013-11-06 15:33:03 -08001050 // If we're checking uniqueness and the ID already exists, abort.
1051 if (checked && mChildNodeIds.indexOf(childNodeId) >= 0) {
1052 return;
1053 }
1054 mChildNodeIds.add(childNodeId);
1055 }
1056
1057 /**
1058 * Removes a virtual child which is a descendant of the given
1059 * <code>root</code>. If the child was not previously added to the node,
1060 * calling this method has no effect.
1061 *
1062 * @param root The root of the virtual subtree.
1063 * @param virtualDescendantId The id of the virtual child.
1064 * @return true if the child was present
1065 * @see #addChild(View, int)
1066 */
1067 public boolean removeChild(View root, int virtualDescendantId) {
1068 enforceNotSealed();
1069 final LongArray childIds = mChildNodeIds;
1070 if (childIds == null) {
1071 return false;
1072 }
1073 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -08001074 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Alan Viverettef0aed092013-11-06 15:33:03 -08001075 final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1076 final int index = childIds.indexOf(childNodeId);
1077 if (index < 0) {
1078 return false;
1079 }
1080 childIds.remove(index);
1081 return true;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001082 }
1083
1084 /**
1085 * Gets the actions that can be performed on the node.
Kristian Monsen74bc1942014-04-29 11:00:17 -07001086 */
1087 public List<AccessibilityAction> getActionList() {
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07001088 return CollectionUtils.emptyIfNull(mActions);
Kristian Monsen74bc1942014-04-29 11:00:17 -07001089 }
1090
1091 /**
1092 * Gets the actions that can be performed on the node.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001093 *
1094 * @return The bit mask of with actions.
1095 *
1096 * @see AccessibilityNodeInfo#ACTION_FOCUS
1097 * @see AccessibilityNodeInfo#ACTION_CLEAR_FOCUS
1098 * @see AccessibilityNodeInfo#ACTION_SELECT
1099 * @see AccessibilityNodeInfo#ACTION_CLEAR_SELECTION
Svetoslav Ganova1dc7612012-05-10 04:14:53 -07001100 * @see AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS
1101 * @see AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS
1102 * @see AccessibilityNodeInfo#ACTION_CLICK
1103 * @see AccessibilityNodeInfo#ACTION_LONG_CLICK
1104 * @see AccessibilityNodeInfo#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
1105 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
1106 * @see AccessibilityNodeInfo#ACTION_NEXT_HTML_ELEMENT
1107 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_HTML_ELEMENT
1108 * @see AccessibilityNodeInfo#ACTION_SCROLL_FORWARD
1109 * @see AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD
Kristian Monsen74bc1942014-04-29 11:00:17 -07001110 *
1111 * @deprecated Use {@link #getActionList()}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001112 */
Kristian Monsen74bc1942014-04-29 11:00:17 -07001113 @Deprecated
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001114 public int getActions() {
Kristian Monsen74bc1942014-04-29 11:00:17 -07001115 int returnValue = 0;
1116
1117 if (mActions == null) {
1118 return returnValue;
1119 }
1120
1121 final int actionSize = mActions.size();
1122 for (int i = 0; i < actionSize; i++) {
1123 int actionId = mActions.get(i).getId();
1124 if (actionId <= LAST_LEGACY_STANDARD_ACTION) {
1125 returnValue |= actionId;
1126 }
1127 }
1128
1129 return returnValue;
1130 }
1131
1132 /**
1133 * Adds an action that can be performed on the node.
1134 * <p>
1135 * To add a standard action use the static constants on {@link AccessibilityAction}.
1136 * To add a custom action create a new {@link AccessibilityAction} by passing in a
1137 * resource id from your application as the action id and an optional label that
1138 * describes the action. To override one of the standard actions use as the action
1139 * id of a standard action id such as {@link #ACTION_CLICK} and an optional label that
1140 * describes the action.
1141 * </p>
1142 * <p>
1143 * <strong>Note:</strong> Cannot be called from an
1144 * {@link android.accessibilityservice.AccessibilityService}.
1145 * This class is made immutable before being delivered to an AccessibilityService.
1146 * </p>
1147 *
1148 * @param action The action.
1149 *
1150 * @throws IllegalStateException If called from an AccessibilityService.
1151 */
1152 public void addAction(AccessibilityAction action) {
1153 enforceNotSealed();
1154
Alan Viverettec921f272015-05-14 12:26:49 -07001155 addActionUnchecked(action);
1156 }
1157
1158 private void addActionUnchecked(AccessibilityAction action) {
Kristian Monsen74bc1942014-04-29 11:00:17 -07001159 if (action == null) {
1160 return;
1161 }
1162
1163 if (mActions == null) {
Alan Viverette23f44322015-04-06 16:04:56 -07001164 mActions = new ArrayList<>();
Kristian Monsen74bc1942014-04-29 11:00:17 -07001165 }
1166
1167 mActions.remove(action);
1168 mActions.add(action);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001169 }
1170
1171 /**
1172 * Adds an action that can be performed on the node.
1173 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001174 * <strong>Note:</strong> Cannot be called from an
1175 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001176 * This class is made immutable before being delivered to an AccessibilityService.
1177 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001178 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001179 * @param action The action.
1180 *
1181 * @throws IllegalStateException If called from an AccessibilityService.
Kristian Monsen74bc1942014-04-29 11:00:17 -07001182 * @throws IllegalArgumentException If the argument is not one of the standard actions.
1183 *
1184 * @deprecated This has been deprecated for {@link #addAction(AccessibilityAction)}
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001185 */
Kristian Monsen74bc1942014-04-29 11:00:17 -07001186 @Deprecated
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001187 public void addAction(int action) {
1188 enforceNotSealed();
Kristian Monsen74bc1942014-04-29 11:00:17 -07001189
Kristian Monsen8d5f3fa2014-05-20 13:16:19 -07001190 if ((action & ACTION_TYPE_MASK) != 0) {
1191 throw new IllegalArgumentException("Action is not a combination of the standard " +
1192 "actions: " + action);
Kristian Monsen74bc1942014-04-29 11:00:17 -07001193 }
1194
Eugene Susla554edd32017-05-24 16:49:59 -07001195 addStandardActions(action);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001196 }
1197
1198 /**
Alan Viverettef0aed092013-11-06 15:33:03 -08001199 * Removes an action that can be performed on the node. If the action was
1200 * not already added to the node, calling this method has no effect.
1201 * <p>
1202 * <strong>Note:</strong> Cannot be called from an
1203 * {@link android.accessibilityservice.AccessibilityService}.
1204 * This class is made immutable before being delivered to an AccessibilityService.
1205 * </p>
1206 *
Kristian Monsen74bc1942014-04-29 11:00:17 -07001207 * @param action The action to be removed.
1208 *
1209 * @throws IllegalStateException If called from an AccessibilityService.
1210 * @deprecated Use {@link #removeAction(AccessibilityAction)}
1211 */
1212 @Deprecated
1213 public void removeAction(int action) {
1214 enforceNotSealed();
1215
1216 removeAction(getActionSingleton(action));
1217 }
1218
1219 /**
1220 * Removes an action that can be performed on the node. If the action was
1221 * not already added to the node, calling this method has no effect.
1222 * <p>
1223 * <strong>Note:</strong> Cannot be called from an
1224 * {@link android.accessibilityservice.AccessibilityService}.
1225 * This class is made immutable before being delivered to an AccessibilityService.
1226 * </p>
1227 *
1228 * @param action The action to be removed.
1229 * @return The action removed from the list of actions.
Alan Viverettef0aed092013-11-06 15:33:03 -08001230 *
1231 * @throws IllegalStateException If called from an AccessibilityService.
1232 */
Kristian Monsen74bc1942014-04-29 11:00:17 -07001233 public boolean removeAction(AccessibilityAction action) {
Alan Viverettef0aed092013-11-06 15:33:03 -08001234 enforceNotSealed();
Kristian Monsen74bc1942014-04-29 11:00:17 -07001235
1236 if (mActions == null || action == null) {
1237 return false;
1238 }
1239
1240 return mActions.remove(action);
Alan Viverettef0aed092013-11-06 15:33:03 -08001241 }
1242
1243 /**
Phil Weaverf00cd142017-03-03 13:44:00 -08001244 * Removes all actions.
1245 *
1246 * @hide
1247 */
1248 public void removeAllActions() {
1249 if (mActions != null) {
1250 mActions.clear();
1251 }
1252 }
1253
1254 /**
Svetoslav6c702902014-10-09 18:40:56 -07001255 * Gets the node before which this one is visited during traversal. A screen-reader
1256 * must visit the content of this node before the content of the one it precedes.
1257 *
1258 * @return The succeeding node if such or <code>null</code>.
1259 *
1260 * @see #setTraversalBefore(android.view.View)
1261 * @see #setTraversalBefore(android.view.View, int)
1262 */
1263 public AccessibilityNodeInfo getTraversalBefore() {
1264 enforceSealed();
1265 return getNodeForAccessibilityId(mTraversalBefore);
1266 }
1267
1268 /**
1269 * Sets the view before whose node this one should be visited during traversal. A
1270 * screen-reader must visit the content of this node before the content of the one
1271 * it precedes.
1272 * <p>
1273 * <strong>Note:</strong> Cannot be called from an
1274 * {@link android.accessibilityservice.AccessibilityService}.
1275 * This class is made immutable before being delivered to an AccessibilityService.
1276 * </p>
1277 *
1278 * @param view The view providing the preceding node.
1279 *
1280 * @see #getTraversalBefore()
1281 */
1282 public void setTraversalBefore(View view) {
Phil Weaverf00cd142017-03-03 13:44:00 -08001283 setTraversalBefore(view, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav6c702902014-10-09 18:40:56 -07001284 }
1285
1286 /**
1287 * Sets the node before which this one is visited during traversal. A screen-reader
1288 * must visit the content of this node before the content of the one it precedes.
1289 * The successor is a virtual descendant of the given <code>root</code>. If
1290 * <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root is set
1291 * as the successor.
1292 * <p>
1293 * A virtual descendant is an imaginary View that is reported as a part of the view
1294 * hierarchy for accessibility purposes. This enables custom views that draw complex
1295 * content to report them selves as a tree of virtual views, thus conveying their
1296 * logical structure.
1297 * </p>
1298 * <p>
1299 * <strong>Note:</strong> Cannot be called from an
1300 * {@link android.accessibilityservice.AccessibilityService}.
1301 * This class is made immutable before being delivered to an AccessibilityService.
1302 * </p>
1303 *
1304 * @param root The root of the virtual subtree.
1305 * @param virtualDescendantId The id of the virtual descendant.
1306 */
1307 public void setTraversalBefore(View root, int virtualDescendantId) {
1308 enforceNotSealed();
1309 final int rootAccessibilityViewId = (root != null)
1310 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
1311 mTraversalBefore = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1312 }
1313
1314 /**
1315 * Gets the node after which this one is visited in accessibility traversal.
1316 * A screen-reader must visit the content of the other node before the content
1317 * of this one.
1318 *
1319 * @return The succeeding node if such or <code>null</code>.
1320 *
1321 * @see #setTraversalAfter(android.view.View)
1322 * @see #setTraversalAfter(android.view.View, int)
1323 */
1324 public AccessibilityNodeInfo getTraversalAfter() {
1325 enforceSealed();
1326 return getNodeForAccessibilityId(mTraversalAfter);
1327 }
1328
1329 /**
1330 * Sets the view whose node is visited after this one in accessibility traversal.
1331 * A screen-reader must visit the content of the other node before the content
1332 * of this one.
1333 * <p>
1334 * <strong>Note:</strong> Cannot be called from an
1335 * {@link android.accessibilityservice.AccessibilityService}.
1336 * This class is made immutable before being delivered to an AccessibilityService.
1337 * </p>
1338 *
1339 * @param view The previous view.
1340 *
1341 * @see #getTraversalAfter()
1342 */
1343 public void setTraversalAfter(View view) {
Phil Weaverf00cd142017-03-03 13:44:00 -08001344 setTraversalAfter(view, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav6c702902014-10-09 18:40:56 -07001345 }
1346
1347 /**
1348 * Sets the node after which this one is visited in accessibility traversal.
1349 * A screen-reader must visit the content of the other node before the content
1350 * of this one. If <code>virtualDescendantId</code> equals to {@link View#NO_ID}
1351 * the root is set as the predecessor.
1352 * <p>
1353 * A virtual descendant is an imaginary View that is reported as a part of the view
1354 * hierarchy for accessibility purposes. This enables custom views that draw complex
1355 * content to report them selves as a tree of virtual views, thus conveying their
1356 * logical structure.
1357 * </p>
1358 * <p>
1359 * <strong>Note:</strong> Cannot be called from an
1360 * {@link android.accessibilityservice.AccessibilityService}.
1361 * This class is made immutable before being delivered to an AccessibilityService.
1362 * </p>
1363 *
1364 * @param root The root of the virtual subtree.
1365 * @param virtualDescendantId The id of the virtual descendant.
1366 */
1367 public void setTraversalAfter(View root, int virtualDescendantId) {
1368 enforceNotSealed();
1369 final int rootAccessibilityViewId = (root != null)
1370 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
1371 mTraversalAfter = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1372 }
1373
1374 /**
Phil Weaverc2e28932016-12-08 12:29:25 -08001375 * Get the extra data available for this node.
1376 * <p>
1377 * Some data that is useful for some accessibility services is expensive to compute, and would
1378 * place undue overhead on apps to compute all the time. That data can be requested with
1379 * {@link #refreshWithExtraData(String, Bundle)}.
1380 *
1381 * @return An unmodifiable list of keys corresponding to extra data that can be requested.
1382 * @see #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY
1383 */
1384 public List<String> getAvailableExtraData() {
1385 if (mExtraDataKeys != null) {
1386 return Collections.unmodifiableList(mExtraDataKeys);
1387 } else {
1388 return EMPTY_LIST;
1389 }
1390 }
1391
1392 /**
1393 * Set the extra data available for this node.
1394 * <p>
1395 * <strong>Note:</strong> When a {@code View} passes in a non-empty list, it promises that
1396 * it will populate the node's extras with corresponding pieces of information in
1397 * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)}.
1398 * <p>
1399 * <strong>Note:</strong> Cannot be called from an
1400 * {@link android.accessibilityservice.AccessibilityService}.
1401 * This class is made immutable before being delivered to an AccessibilityService.
1402 *
1403 * @param extraDataKeys A list of types of extra data that are available.
1404 * @see #getAvailableExtraData()
1405 *
1406 * @throws IllegalStateException If called from an AccessibilityService.
1407 */
1408 public void setAvailableExtraData(List<String> extraDataKeys) {
1409 enforceNotSealed();
1410 mExtraDataKeys = new ArrayList<>(extraDataKeys);
1411 }
1412
1413 /**
Alan Viverette029942f2014-08-12 14:55:56 -07001414 * Sets the maximum text length, or -1 for no limit.
1415 * <p>
1416 * Typically used to indicate that an editable text field has a limit on
1417 * the number of characters entered.
1418 * <p>
1419 * <strong>Note:</strong> Cannot be called from an
1420 * {@link android.accessibilityservice.AccessibilityService}.
1421 * This class is made immutable before being delivered to an AccessibilityService.
1422 *
1423 * @param max The maximum text length.
1424 * @see #getMaxTextLength()
1425 *
1426 * @throws IllegalStateException If called from an AccessibilityService.
1427 */
1428 public void setMaxTextLength(int max) {
1429 enforceNotSealed();
1430 mMaxTextLength = max;
1431 }
1432
1433 /**
1434 * Returns the maximum text length for this node.
1435 *
1436 * @return The maximum text length, or -1 for no limit.
1437 * @see #setMaxTextLength(int)
1438 */
1439 public int getMaxTextLength() {
1440 return mMaxTextLength;
1441 }
1442
1443 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001444 * Sets the movement granularities for traversing the text of this node.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001445 * <p>
1446 * <strong>Note:</strong> Cannot be called from an
1447 * {@link android.accessibilityservice.AccessibilityService}.
1448 * This class is made immutable before being delivered to an AccessibilityService.
1449 * </p>
1450 *
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07001451 * @param granularities The bit mask with granularities.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001452 *
1453 * @throws IllegalStateException If called from an AccessibilityService.
1454 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001455 public void setMovementGranularities(int granularities) {
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001456 enforceNotSealed();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001457 mMovementGranularities = granularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001458 }
1459
1460 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001461 * Gets the movement granularities for traversing the text of this node.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001462 *
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07001463 * @return The bit mask with granularities.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001464 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001465 public int getMovementGranularities() {
1466 return mMovementGranularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001467 }
1468
1469 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001470 * Performs an action on the node.
1471 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001472 * <strong>Note:</strong> An action can be performed only if the request is made
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001473 * from an {@link android.accessibilityservice.AccessibilityService}.
1474 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001475 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001476 * @param action The action to perform.
1477 * @return True if the action was performed.
1478 *
1479 * @throws IllegalStateException If called outside of an AccessibilityService.
1480 */
1481 public boolean performAction(int action) {
1482 enforceSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -07001483 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001484 return false;
1485 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -07001486 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001487 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
1488 action, null);
1489 }
1490
1491 /**
1492 * Performs an action on the node.
1493 * <p>
1494 * <strong>Note:</strong> An action can be performed only if the request is made
1495 * from an {@link android.accessibilityservice.AccessibilityService}.
1496 * </p>
1497 *
1498 * @param action The action to perform.
1499 * @param arguments A bundle with additional arguments.
1500 * @return True if the action was performed.
1501 *
1502 * @throws IllegalStateException If called outside of an AccessibilityService.
1503 */
1504 public boolean performAction(int action, Bundle arguments) {
1505 enforceSealed();
1506 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1507 return false;
1508 }
1509 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1510 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
1511 action, arguments);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001512 }
1513
1514 /**
1515 * Finds {@link AccessibilityNodeInfo}s by text. The match is case
Svetoslav Ganov86398bd2011-06-21 17:38:43 -07001516 * insensitive containment. The search is relative to this info i.e.
1517 * this info is the root of the traversed tree.
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07001518 *
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001519 * <p>
1520 * <strong>Note:</strong> It is a client responsibility to recycle the
1521 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1522 * to avoid creating of multiple instances.
1523 * </p>
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001524 *
1525 * @param text The searched text.
1526 * @return A list of node info.
1527 */
1528 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text) {
1529 enforceSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -07001530 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganov86398bd2011-06-21 17:38:43 -07001531 return Collections.emptyList();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001532 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -07001533 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganov79311c42012-01-17 20:24:26 -08001534 return client.findAccessibilityNodeInfosByText(mConnectionId, mWindowId, mSourceNodeId,
1535 text);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001536 }
1537
1538 /**
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001539 * Finds {@link AccessibilityNodeInfo}s by the fully qualified view id's resource
1540 * name where a fully qualified id is of the from "package:id/id_resource_name".
1541 * For example, if the target application's package is "foo.bar" and the id
1542 * resource name is "baz", the fully qualified resource id is "foo.bar:id/baz".
1543 *
1544 * <p>
1545 * <strong>Note:</strong> It is a client responsibility to recycle the
1546 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1547 * to avoid creating of multiple instances.
1548 * </p>
1549 * <p>
1550 * <strong>Note:</strong> The primary usage of this API is for UI test automation
1551 * and in order to report the fully qualified view id if an {@link AccessibilityNodeInfo}
1552 * the client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
Svetoslav14ff9962013-01-29 03:21:37 -08001553 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001554 * </p>
1555 *
1556 * @param viewId The fully qualified resource name of the view id to find.
1557 * @return A list of node info.
1558 */
1559 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId(String viewId) {
1560 enforceSealed();
1561 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1562 return Collections.emptyList();
1563 }
1564 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1565 return client.findAccessibilityNodeInfosByViewId(mConnectionId, mWindowId, mSourceNodeId,
1566 viewId);
1567 }
1568
1569 /**
Svetoslav8e3feb12014-02-24 13:46:47 -08001570 * Gets the window to which this node belongs.
1571 *
1572 * @return The window.
1573 *
1574 * @see android.accessibilityservice.AccessibilityService#getWindows()
1575 */
1576 public AccessibilityWindowInfo getWindow() {
1577 enforceSealed();
1578 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1579 return null;
1580 }
1581 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1582 return client.getWindow(mConnectionId, mWindowId);
1583 }
1584
1585 /**
Svetoslav Ganov00aabf72011-07-21 11:35:03 -07001586 * Gets the parent.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001587 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001588 * <strong>Note:</strong> It is a client responsibility to recycle the
1589 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1590 * to avoid creating of multiple instances.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001591 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001592 *
Svetoslav Ganov00aabf72011-07-21 11:35:03 -07001593 * @return The parent.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001594 */
1595 public AccessibilityNodeInfo getParent() {
1596 enforceSealed();
Svetoslav6c702902014-10-09 18:40:56 -07001597 return getNodeForAccessibilityId(mParentNodeId);
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -08001598 }
1599
1600 /**
1601 * @return The parent node id.
1602 *
1603 * @hide
1604 */
1605 public long getParentNodeId() {
1606 return mParentNodeId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001607 }
1608
1609 /**
1610 * Sets the parent.
1611 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001612 * <strong>Note:</strong> Cannot be called from an
1613 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001614 * This class is made immutable before being delivered to an AccessibilityService.
1615 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001616 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001617 * @param parent The parent.
1618 *
1619 * @throws IllegalStateException If called from an AccessibilityService.
1620 */
1621 public void setParent(View parent) {
Phil Weaverf00cd142017-03-03 13:44:00 -08001622 setParent(parent, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov02107852011-10-03 17:06:56 -07001623 }
1624
1625 /**
1626 * Sets the parent to be a virtual descendant of the given <code>root</code>.
1627 * If <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root
1628 * is set as the parent.
1629 * <p>
1630 * A virtual descendant is an imaginary View that is reported as a part of the view
1631 * hierarchy for accessibility purposes. This enables custom views that draw complex
1632 * content to report them selves as a tree of virtual views, thus conveying their
1633 * logical structure.
1634 * </p>
1635 * <p>
1636 * <strong>Note:</strong> Cannot be called from an
1637 * {@link android.accessibilityservice.AccessibilityService}.
1638 * This class is made immutable before being delivered to an AccessibilityService.
1639 * </p>
1640 *
1641 * @param root The root of the virtual subtree.
1642 * @param virtualDescendantId The id of the virtual descendant.
1643 */
1644 public void setParent(View root, int virtualDescendantId) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001645 enforceNotSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -07001646 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -08001647 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -07001648 mParentNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001649 }
1650
1651 /**
1652 * Gets the node bounds in parent coordinates.
1653 *
1654 * @param outBounds The output node bounds.
1655 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001656 public void getBoundsInParent(Rect outBounds) {
1657 outBounds.set(mBoundsInParent.left, mBoundsInParent.top,
1658 mBoundsInParent.right, mBoundsInParent.bottom);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001659 }
1660
1661 /**
1662 * Sets the node bounds in parent coordinates.
1663 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001664 * <strong>Note:</strong> Cannot be called from an
1665 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001666 * This class is made immutable before being delivered to an AccessibilityService.
1667 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001668 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001669 * @param bounds The node bounds.
1670 *
1671 * @throws IllegalStateException If called from an AccessibilityService.
1672 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001673 public void setBoundsInParent(Rect bounds) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001674 enforceNotSealed();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001675 mBoundsInParent.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
1676 }
1677
1678 /**
1679 * Gets the node bounds in screen coordinates.
1680 *
1681 * @param outBounds The output node bounds.
1682 */
1683 public void getBoundsInScreen(Rect outBounds) {
1684 outBounds.set(mBoundsInScreen.left, mBoundsInScreen.top,
1685 mBoundsInScreen.right, mBoundsInScreen.bottom);
1686 }
1687
1688 /**
Alan Viverettea7ea65e2015-05-15 11:30:21 -07001689 * Returns the actual rect containing the node bounds in screen coordinates.
1690 *
1691 * @hide Not safe to expose outside the framework.
1692 */
1693 public Rect getBoundsInScreen() {
1694 return mBoundsInScreen;
1695 }
1696
1697 /**
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001698 * Sets the node bounds in screen coordinates.
1699 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001700 * <strong>Note:</strong> Cannot be called from an
1701 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001702 * This class is made immutable before being delivered to an AccessibilityService.
1703 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001704 *
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001705 * @param bounds The node bounds.
1706 *
1707 * @throws IllegalStateException If called from an AccessibilityService.
1708 */
1709 public void setBoundsInScreen(Rect bounds) {
1710 enforceNotSealed();
1711 mBoundsInScreen.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001712 }
1713
1714 /**
1715 * Gets whether this node is checkable.
1716 *
1717 * @return True if the node is checkable.
1718 */
1719 public boolean isCheckable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001720 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001721 }
1722
1723 /**
1724 * Sets whether this node is checkable.
1725 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001726 * <strong>Note:</strong> Cannot be called from an
1727 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001728 * This class is made immutable before being delivered to an AccessibilityService.
1729 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001730 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001731 * @param checkable True if the node is checkable.
1732 *
1733 * @throws IllegalStateException If called from an AccessibilityService.
1734 */
1735 public void setCheckable(boolean checkable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001736 setBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE, checkable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001737 }
1738
1739 /**
1740 * Gets whether this node is checked.
1741 *
1742 * @return True if the node is checked.
1743 */
1744 public boolean isChecked() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001745 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001746 }
1747
1748 /**
1749 * Sets whether this node is checked.
1750 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001751 * <strong>Note:</strong> Cannot be called from an
1752 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001753 * This class is made immutable before being delivered to an AccessibilityService.
1754 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001755 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001756 * @param checked True if the node is checked.
1757 *
1758 * @throws IllegalStateException If called from an AccessibilityService.
1759 */
1760 public void setChecked(boolean checked) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001761 setBooleanProperty(BOOLEAN_PROPERTY_CHECKED, checked);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001762 }
1763
1764 /**
1765 * Gets whether this node is focusable.
1766 *
1767 * @return True if the node is focusable.
1768 */
1769 public boolean isFocusable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001770 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001771 }
1772
1773 /**
1774 * Sets whether this node is focusable.
1775 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001776 * <strong>Note:</strong> Cannot be called from an
1777 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001778 * This class is made immutable before being delivered to an AccessibilityService.
1779 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001780 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001781 * @param focusable True if the node is focusable.
1782 *
1783 * @throws IllegalStateException If called from an AccessibilityService.
1784 */
1785 public void setFocusable(boolean focusable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001786 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE, focusable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001787 }
1788
1789 /**
1790 * Gets whether this node is focused.
1791 *
1792 * @return True if the node is focused.
1793 */
1794 public boolean isFocused() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001795 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001796 }
1797
1798 /**
1799 * Sets whether this node is focused.
1800 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001801 * <strong>Note:</strong> Cannot be called from an
1802 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001803 * This class is made immutable before being delivered to an AccessibilityService.
1804 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001805 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001806 * @param focused True if the node is focused.
1807 *
1808 * @throws IllegalStateException If called from an AccessibilityService.
1809 */
1810 public void setFocused(boolean focused) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001811 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSED, focused);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001812 }
1813
1814 /**
Alan Viverette1579edc2015-04-01 13:23:06 -07001815 * Gets whether this node is visible to the user.
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001816 *
1817 * @return Whether the node is visible to the user.
1818 */
1819 public boolean isVisibleToUser() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001820 return getBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001821 }
1822
1823 /**
1824 * Sets whether this node is visible to the user.
1825 * <p>
1826 * <strong>Note:</strong> Cannot be called from an
1827 * {@link android.accessibilityservice.AccessibilityService}.
1828 * This class is made immutable before being delivered to an AccessibilityService.
1829 * </p>
1830 *
1831 * @param visibleToUser Whether the node is visible to the user.
1832 *
1833 * @throws IllegalStateException If called from an AccessibilityService.
1834 */
1835 public void setVisibleToUser(boolean visibleToUser) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001836 setBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER, visibleToUser);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001837 }
1838
1839 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -07001840 * Gets whether this node is accessibility focused.
1841 *
1842 * @return True if the node is accessibility focused.
1843 */
1844 public boolean isAccessibilityFocused() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001845 return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED);
Svetoslav Ganov42138042012-03-20 11:51:39 -07001846 }
1847
1848 /**
1849 * Sets whether this node is accessibility focused.
1850 * <p>
1851 * <strong>Note:</strong> Cannot be called from an
1852 * {@link android.accessibilityservice.AccessibilityService}.
1853 * This class is made immutable before being delivered to an AccessibilityService.
1854 * </p>
1855 *
1856 * @param focused True if the node is accessibility focused.
1857 *
1858 * @throws IllegalStateException If called from an AccessibilityService.
1859 */
1860 public void setAccessibilityFocused(boolean focused) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001861 setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED, focused);
Svetoslav Ganov42138042012-03-20 11:51:39 -07001862 }
1863
1864 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001865 * Gets whether this node is selected.
1866 *
1867 * @return True if the node is selected.
1868 */
1869 public boolean isSelected() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001870 return getBooleanProperty(BOOLEAN_PROPERTY_SELECTED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001871 }
1872
1873 /**
1874 * Sets whether this node is selected.
1875 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001876 * <strong>Note:</strong> Cannot be called from an
1877 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001878 * This class is made immutable before being delivered to an AccessibilityService.
1879 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001880 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001881 * @param selected True if the node is selected.
1882 *
1883 * @throws IllegalStateException If called from an AccessibilityService.
1884 */
1885 public void setSelected(boolean selected) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001886 setBooleanProperty(BOOLEAN_PROPERTY_SELECTED, selected);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001887 }
1888
1889 /**
1890 * Gets whether this node is clickable.
1891 *
1892 * @return True if the node is clickable.
1893 */
1894 public boolean isClickable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001895 return getBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001896 }
1897
1898 /**
1899 * Sets whether this node is clickable.
1900 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001901 * <strong>Note:</strong> Cannot be called from an
1902 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001903 * This class is made immutable before being delivered to an AccessibilityService.
1904 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001905 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001906 * @param clickable True if the node is clickable.
1907 *
1908 * @throws IllegalStateException If called from an AccessibilityService.
1909 */
1910 public void setClickable(boolean clickable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001911 setBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE, clickable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001912 }
1913
1914 /**
1915 * Gets whether this node is long clickable.
1916 *
1917 * @return True if the node is long clickable.
1918 */
1919 public boolean isLongClickable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001920 return getBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001921 }
1922
1923 /**
1924 * Sets whether this node is long clickable.
1925 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001926 * <strong>Note:</strong> Cannot be called from an
1927 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001928 * This class is made immutable before being delivered to an AccessibilityService.
1929 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001930 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001931 * @param longClickable True if the node is long clickable.
1932 *
1933 * @throws IllegalStateException If called from an AccessibilityService.
1934 */
1935 public void setLongClickable(boolean longClickable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001936 setBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE, longClickable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001937 }
1938
1939 /**
1940 * Gets whether this node is enabled.
1941 *
1942 * @return True if the node is enabled.
1943 */
1944 public boolean isEnabled() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001945 return getBooleanProperty(BOOLEAN_PROPERTY_ENABLED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001946 }
1947
1948 /**
1949 * Sets whether this node is enabled.
1950 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001951 * <strong>Note:</strong> Cannot be called from an
1952 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001953 * This class is made immutable before being delivered to an AccessibilityService.
1954 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001955 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001956 * @param enabled True if the node is enabled.
1957 *
1958 * @throws IllegalStateException If called from an AccessibilityService.
1959 */
1960 public void setEnabled(boolean enabled) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001961 setBooleanProperty(BOOLEAN_PROPERTY_ENABLED, enabled);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001962 }
1963
1964 /**
1965 * Gets whether this node is a password.
1966 *
1967 * @return True if the node is a password.
1968 */
1969 public boolean isPassword() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001970 return getBooleanProperty(BOOLEAN_PROPERTY_PASSWORD);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001971 }
1972
1973 /**
1974 * Sets whether this node is a password.
1975 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001976 * <strong>Note:</strong> Cannot be called from an
1977 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001978 * This class is made immutable before being delivered to an AccessibilityService.
1979 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001980 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001981 * @param password True if the node is a password.
1982 *
1983 * @throws IllegalStateException If called from an AccessibilityService.
1984 */
1985 public void setPassword(boolean password) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001986 setBooleanProperty(BOOLEAN_PROPERTY_PASSWORD, password);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001987 }
1988
1989 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -07001990 * Gets if the node is scrollable.
1991 *
1992 * @return True if the node is scrollable, false otherwise.
1993 */
1994 public boolean isScrollable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001995 return getBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE);
Svetoslav Ganova0156172011-06-26 17:55:44 -07001996 }
1997
1998 /**
1999 * Sets if the node is scrollable.
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002000 * <p>
2001 * <strong>Note:</strong> Cannot be called from an
2002 * {@link android.accessibilityservice.AccessibilityService}.
2003 * This class is made immutable before being delivered to an AccessibilityService.
2004 * </p>
Svetoslav Ganova0156172011-06-26 17:55:44 -07002005 *
2006 * @param scrollable True if the node is scrollable, false otherwise.
2007 *
2008 * @throws IllegalStateException If called from an AccessibilityService.
2009 */
2010 public void setScrollable(boolean scrollable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08002011 setBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE, scrollable);
2012 }
2013
2014 /**
2015 * Gets if the node is editable.
2016 *
2017 * @return True if the node is editable, false otherwise.
2018 */
2019 public boolean isEditable() {
2020 return getBooleanProperty(BOOLEAN_PROPERTY_EDITABLE);
2021 }
2022
2023 /**
2024 * Sets whether this node is editable.
2025 * <p>
2026 * <strong>Note:</strong> Cannot be called from an
2027 * {@link android.accessibilityservice.AccessibilityService}.
2028 * This class is made immutable before being delivered to an AccessibilityService.
2029 * </p>
2030 *
2031 * @param editable True if the node is editable.
2032 *
2033 * @throws IllegalStateException If called from an AccessibilityService.
2034 */
2035 public void setEditable(boolean editable) {
2036 setBooleanProperty(BOOLEAN_PROPERTY_EDITABLE, editable);
Svetoslav Ganova0156172011-06-26 17:55:44 -07002037 }
2038
2039 /**
Phil Weaver9f26b3d2018-01-04 10:04:37 -08002040 * If this node represents a visually distinct region of the screen that may update separately
2041 * from the rest of the window, it is considered a pane. Set the pane title to indicate that
2042 * the node is a pane, and to provide a title for it.
2043 * <p>
2044 * <strong>Note:</strong> Cannot be called from an
2045 * {@link android.accessibilityservice.AccessibilityService}.
2046 * This class is made immutable before being delivered to an AccessibilityService.
2047 * </p>
2048 * @param paneTitle The title of the pane represented by this node.
2049 */
2050 public void setPaneTitle(@Nullable CharSequence paneTitle) {
2051 enforceNotSealed();
2052 mPaneTitle = (paneTitle == null)
2053 ? null : paneTitle.subSequence(0, paneTitle.length());
2054 }
2055
2056 /**
2057 * Get the title of the pane represented by this node.
2058 *
2059 * @return The title of the pane represented by this node, or {@code null} if this node does
2060 * not represent a pane.
2061 */
2062 public @Nullable CharSequence getPaneTitle() {
2063 return mPaneTitle;
2064 }
2065
2066 /**
Phil Weaver1f222542016-01-08 11:49:32 -08002067 * Get the drawing order of the view corresponding it this node.
2068 * <p>
2069 * Drawing order is determined only within the node's parent, so this index is only relative
2070 * to its siblings.
2071 * <p>
2072 * In some cases, the drawing order is essentially simultaneous, so it is possible for two
2073 * siblings to return the same value. It is also possible that values will be skipped.
2074 *
2075 * @return The drawing position of the view corresponding to this node relative to its siblings.
2076 */
2077 public int getDrawingOrder() {
2078 return mDrawingOrderInParent;
2079 }
2080
2081 /**
2082 * Set the drawing order of the view corresponding it this node.
2083 *
2084 * <p>
2085 * <strong>Note:</strong> Cannot be called from an
2086 * {@link android.accessibilityservice.AccessibilityService}.
2087 * This class is made immutable before being delivered to an AccessibilityService.
2088 * </p>
2089 * @param drawingOrderInParent
2090 * @throws IllegalStateException If called from an AccessibilityService.
2091 */
2092 public void setDrawingOrder(int drawingOrderInParent) {
2093 enforceNotSealed();
2094 mDrawingOrderInParent = drawingOrderInParent;
2095 }
2096
2097 /**
Svetoslav3577a282013-06-06 14:09:10 -07002098 * Gets the collection info if the node is a collection. A collection
2099 * child is always a collection item.
2100 *
2101 * @return The collection info.
2102 */
2103 public CollectionInfo getCollectionInfo() {
2104 return mCollectionInfo;
2105 }
2106
2107 /**
2108 * Sets the collection info if the node is a collection. A collection
2109 * child is always a collection item.
2110 * <p>
2111 * <strong>Note:</strong> Cannot be called from an
2112 * {@link android.accessibilityservice.AccessibilityService}.
2113 * This class is made immutable before being delivered to an AccessibilityService.
2114 * </p>
2115 *
2116 * @param collectionInfo The collection info.
2117 */
2118 public void setCollectionInfo(CollectionInfo collectionInfo) {
2119 enforceNotSealed();
2120 mCollectionInfo = collectionInfo;
2121 }
2122
2123 /**
2124 * Gets the collection item info if the node is a collection item. A collection
2125 * item is always a child of a collection.
2126 *
2127 * @return The collection item info.
2128 */
2129 public CollectionItemInfo getCollectionItemInfo() {
2130 return mCollectionItemInfo;
2131 }
2132
2133 /**
2134 * Sets the collection item info if the node is a collection item. A collection
2135 * item is always a child of a collection.
2136 * <p>
2137 * <strong>Note:</strong> Cannot be called from an
2138 * {@link android.accessibilityservice.AccessibilityService}.
2139 * This class is made immutable before being delivered to an AccessibilityService.
2140 * </p>
Svetoslav3577a282013-06-06 14:09:10 -07002141 */
2142 public void setCollectionItemInfo(CollectionItemInfo collectionItemInfo) {
2143 enforceNotSealed();
2144 mCollectionItemInfo = collectionItemInfo;
2145 }
2146
2147 /**
2148 * Gets the range info if this node is a range.
2149 *
2150 * @return The range.
2151 */
2152 public RangeInfo getRangeInfo() {
2153 return mRangeInfo;
2154 }
2155
2156 /**
2157 * Sets the range info if this node is a range.
2158 * <p>
2159 * <strong>Note:</strong> Cannot be called from an
2160 * {@link android.accessibilityservice.AccessibilityService}.
2161 * This class is made immutable before being delivered to an AccessibilityService.
2162 * </p>
2163 *
2164 * @param rangeInfo The range info.
2165 */
2166 public void setRangeInfo(RangeInfo rangeInfo) {
2167 enforceNotSealed();
2168 mRangeInfo = rangeInfo;
2169 }
2170
2171 /**
2172 * Gets if the content of this node is invalid. For example,
2173 * a date is not well-formed.
2174 *
2175 * @return If the node content is invalid.
2176 */
2177 public boolean isContentInvalid() {
2178 return getBooleanProperty(BOOLEAN_PROPERTY_CONTENT_INVALID);
2179 }
2180
2181 /**
2182 * Sets if the content of this node is invalid. For example,
2183 * a date is not well-formed.
2184 * <p>
2185 * <strong>Note:</strong> Cannot be called from an
2186 * {@link android.accessibilityservice.AccessibilityService}.
2187 * This class is made immutable before being delivered to an AccessibilityService.
2188 * </p>
2189 *
2190 * @param contentInvalid If the node content is invalid.
2191 */
2192 public void setContentInvalid(boolean contentInvalid) {
2193 setBooleanProperty(BOOLEAN_PROPERTY_CONTENT_INVALID, contentInvalid);
2194 }
2195
2196 /**
Mady Mellore8608912015-06-05 09:02:55 -07002197 * Gets whether this node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07002198 *
Mady Mellore8608912015-06-05 09:02:55 -07002199 * @return True if the node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07002200 */
Mady Mellore8608912015-06-05 09:02:55 -07002201 public boolean isContextClickable() {
2202 return getBooleanProperty(BOOLEAN_PROPERTY_CONTEXT_CLICKABLE);
Mady Mellore82067b2015-04-30 09:58:35 -07002203 }
2204
2205 /**
Mady Mellore8608912015-06-05 09:02:55 -07002206 * Sets whether this node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07002207 * <p>
2208 * <strong>Note:</strong> Cannot be called from an
2209 * {@link android.accessibilityservice.AccessibilityService}. This class is made immutable
2210 * before being delivered to an AccessibilityService.
2211 * </p>
2212 *
Mady Mellore8608912015-06-05 09:02:55 -07002213 * @param contextClickable True if the node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07002214 * @throws IllegalStateException If called from an AccessibilityService.
2215 */
Mady Mellore8608912015-06-05 09:02:55 -07002216 public void setContextClickable(boolean contextClickable) {
2217 setBooleanProperty(BOOLEAN_PROPERTY_CONTEXT_CLICKABLE, contextClickable);
Mady Mellore82067b2015-04-30 09:58:35 -07002218 }
2219
2220 /**
Alan Viverette77e9a282013-09-12 17:16:09 -07002221 * Gets the node's live region mode.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002222 * <p>
Alan Viverette77e9a282013-09-12 17:16:09 -07002223 * A live region is a node that contains information that is important for
2224 * the user and when it changes the user should be notified. For example,
2225 * in a login screen with a TextView that displays an "incorrect password"
2226 * notification, that view should be marked as a live region with mode
2227 * {@link View#ACCESSIBILITY_LIVE_REGION_POLITE}.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002228 * <p>
Alan Viverette77e9a282013-09-12 17:16:09 -07002229 * It is the responsibility of the accessibility service to monitor
2230 * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} events indicating
2231 * changes to live region nodes and their children.
Svetoslav3577a282013-06-06 14:09:10 -07002232 *
Alan Viverette77e9a282013-09-12 17:16:09 -07002233 * @return The live region mode, or
2234 * {@link View#ACCESSIBILITY_LIVE_REGION_NONE} if the view is not a
2235 * live region.
2236 * @see android.view.View#getAccessibilityLiveRegion()
Svetoslav3577a282013-06-06 14:09:10 -07002237 */
Alan Viverette77e9a282013-09-12 17:16:09 -07002238 public int getLiveRegion() {
2239 return mLiveRegion;
Svetoslav3577a282013-06-06 14:09:10 -07002240 }
2241
2242 /**
Alan Viverette77e9a282013-09-12 17:16:09 -07002243 * Sets the node's live region mode.
Svetoslav3577a282013-06-06 14:09:10 -07002244 * <p>
Alan Viverette77e9a282013-09-12 17:16:09 -07002245 * <strong>Note:</strong> Cannot be called from an
2246 * {@link android.accessibilityservice.AccessibilityService}. This class is
2247 * made immutable before being delivered to an AccessibilityService.
Svetoslav3577a282013-06-06 14:09:10 -07002248 *
Alan Viverette77e9a282013-09-12 17:16:09 -07002249 * @param mode The live region mode, or
2250 * {@link View#ACCESSIBILITY_LIVE_REGION_NONE} if the view is not a
2251 * live region.
2252 * @see android.view.View#setAccessibilityLiveRegion(int)
Svetoslav3577a282013-06-06 14:09:10 -07002253 */
Alan Viverette77e9a282013-09-12 17:16:09 -07002254 public void setLiveRegion(int mode) {
2255 enforceNotSealed();
2256 mLiveRegion = mode;
Svetoslav3577a282013-06-06 14:09:10 -07002257 }
2258
2259 /**
2260 * Gets if the node is a multi line editable text.
2261 *
2262 * @return True if the node is multi line.
2263 */
2264 public boolean isMultiLine() {
2265 return getBooleanProperty(BOOLEAN_PROPERTY_MULTI_LINE);
2266 }
2267
2268 /**
2269 * Sets if the node is a multi line editable text.
2270 * <p>
2271 * <strong>Note:</strong> Cannot be called from an
2272 * {@link android.accessibilityservice.AccessibilityService}.
2273 * This class is made immutable before being delivered to an AccessibilityService.
2274 * </p>
2275 *
2276 * @param multiLine True if the node is multi line.
2277 */
2278 public void setMultiLine(boolean multiLine) {
Svetoslav3577a282013-06-06 14:09:10 -07002279 setBooleanProperty(BOOLEAN_PROPERTY_MULTI_LINE, multiLine);
2280 }
2281
2282 /**
2283 * Gets if this node opens a popup or a dialog.
2284 *
2285 * @return If the the node opens a popup.
2286 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002287 public boolean canOpenPopup() {
Svetoslav3577a282013-06-06 14:09:10 -07002288 return getBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP);
2289 }
2290
2291 /**
2292 * Sets if this node opens a popup or a dialog.
2293 * <p>
2294 * <strong>Note:</strong> Cannot be called from an
2295 * {@link android.accessibilityservice.AccessibilityService}.
2296 * This class is made immutable before being delivered to an AccessibilityService.
2297 * </p>
2298 *
2299 * @param opensPopup If the the node opens a popup.
2300 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002301 public void setCanOpenPopup(boolean opensPopup) {
Phil Weavere1951292017-08-18 17:56:04 +00002302 enforceNotSealed();
Svetoslav3577a282013-06-06 14:09:10 -07002303 setBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP, opensPopup);
2304 }
2305
2306 /**
Svetoslav3577a282013-06-06 14:09:10 -07002307 * Gets if the node can be dismissed.
2308 *
2309 * @return If the node can be dismissed.
2310 */
2311 public boolean isDismissable() {
2312 return getBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE);
2313 }
2314
2315 /**
2316 * Sets if the node can be dismissed.
2317 * <p>
2318 * <strong>Note:</strong> Cannot be called from an
2319 * {@link android.accessibilityservice.AccessibilityService}.
2320 * This class is made immutable before being delivered to an AccessibilityService.
2321 * </p>
2322 *
2323 * @param dismissable If the node can be dismissed.
2324 */
2325 public void setDismissable(boolean dismissable) {
Svetoslav3577a282013-06-06 14:09:10 -07002326 setBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE, dismissable);
2327 }
2328
2329 /**
Casey Burkhardt2d80ae42016-01-31 12:52:23 -08002330 * Returns whether the node originates from a view considered important for accessibility.
2331 *
2332 * @return {@code true} if the node originates from a view considered important for
2333 * accessibility, {@code false} otherwise
2334 *
2335 * @see View#isImportantForAccessibility()
2336 */
2337 public boolean isImportantForAccessibility() {
2338 return getBooleanProperty(BOOLEAN_PROPERTY_IMPORTANCE);
2339 }
2340
2341 /**
2342 * Sets whether the node is considered important for accessibility.
2343 * <p>
2344 * <strong>Note:</strong> Cannot be called from an
2345 * {@link android.accessibilityservice.AccessibilityService}.
2346 * This class is made immutable before being delivered to an AccessibilityService.
2347 * </p>
2348 *
2349 * @param important {@code true} if the node is considered important for accessibility,
2350 * {@code false} otherwise
2351 */
2352 public void setImportantForAccessibility(boolean important) {
2353 setBooleanProperty(BOOLEAN_PROPERTY_IMPORTANCE, important);
2354 }
2355
2356 /**
Phil Weaver1e6ecc62017-11-07 15:28:21 -08002357 * Returns whether the node is explicitly marked as a focusable unit by a screen reader. Note
2358 * that {@code false} indicates that it is not explicitly marked, not that the node is not
Phil Weaver75dce7c2017-12-15 17:48:33 -08002359 * a focusable unit. Screen readers should generally use other signals, such as
Phil Weaver1e6ecc62017-11-07 15:28:21 -08002360 * {@link #isFocusable()}, or the presence of text in a node, to determine what should receive
2361 * focus.
2362 *
2363 * @return {@code true} if the node is specifically marked as a focusable unit for screen
2364 * readers, {@code false} otherwise.
2365 *
2366 * @see View#isScreenReaderFocusable()
2367 */
2368 public boolean isScreenReaderFocusable() {
2369 return getBooleanProperty(BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE);
2370 }
2371
2372 /**
2373 * Sets whether the node should be considered a focusable unit by a screen reader.
2374 * <p>
2375 * <strong>Note:</strong> Cannot be called from an
2376 * {@link android.accessibilityservice.AccessibilityService}.
2377 * This class is made immutable before being delivered to an AccessibilityService.
2378 * </p>
2379 *
2380 * @param screenReaderFocusable {@code true} if the node is a focusable unit for screen readers,
2381 * {@code false} otherwise.
2382 */
2383 public void setScreenReaderFocusable(boolean screenReaderFocusable) {
2384 setBooleanProperty(BOOLEAN_PROPERTY_SCREEN_READER_FOCUSABLE, screenReaderFocusable);
2385 }
2386
2387 /**
Phil Weaver776afc22016-12-21 10:55:13 -08002388 * Returns whether the node's text represents a hint for the user to enter text. It should only
2389 * be {@code true} if the node has editable text.
2390 *
2391 * @return {@code true} if the text in the node represents a hint to the user, {@code false}
2392 * otherwise.
2393 */
2394 public boolean isShowingHintText() {
2395 return getBooleanProperty(BOOLEAN_PROPERTY_IS_SHOWING_HINT);
2396 }
2397
2398 /**
2399 * Sets whether the node's text represents a hint for the user to enter text. It should only
2400 * be {@code true} if the node has editable text.
2401 * <p>
2402 * <strong>Note:</strong> Cannot be called from an
2403 * {@link android.accessibilityservice.AccessibilityService}.
2404 * This class is made immutable before being delivered to an AccessibilityService.
2405 * </p>
2406 *
2407 * @param showingHintText {@code true} if the text in the node represents a hint to the user,
2408 * {@code false} otherwise.
2409 */
2410 public void setShowingHintText(boolean showingHintText) {
2411 setBooleanProperty(BOOLEAN_PROPERTY_IS_SHOWING_HINT, showingHintText);
2412 }
2413
2414 /**
Phil Weaver6290fb592018-01-08 17:42:18 -08002415 * Returns whether node represents a heading.
2416 *
2417 * @return {@code true} if the node is a heading, {@code false} otherwise.
2418 */
2419 public boolean isHeading() {
2420 return getBooleanProperty(BOOLEAN_PROPERTY_IS_HEADING);
2421 }
2422
2423 /**
2424 * Sets whether the node represents a heading.
2425 *
2426 * <p>
2427 * <strong>Note:</strong> Cannot be called from an
2428 * {@link android.accessibilityservice.AccessibilityService}.
2429 * This class is made immutable before being delivered to an AccessibilityService.
2430 * </p>
2431 *
2432 * @param isHeading {@code true} if the node is a heading, {@code false} otherwise.
2433 */
2434 public void setHeading(boolean isHeading) {
2435 setBooleanProperty(BOOLEAN_PROPERTY_IS_HEADING, isHeading);
2436 }
2437
2438 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002439 * Gets the package this node comes from.
2440 *
2441 * @return The package name.
2442 */
2443 public CharSequence getPackageName() {
2444 return mPackageName;
2445 }
2446
2447 /**
2448 * Sets the package this node comes from.
2449 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002450 * <strong>Note:</strong> Cannot be called from an
2451 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002452 * This class is made immutable before being delivered to an AccessibilityService.
2453 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002454 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002455 * @param packageName The package name.
2456 *
2457 * @throws IllegalStateException If called from an AccessibilityService.
2458 */
2459 public void setPackageName(CharSequence packageName) {
2460 enforceNotSealed();
2461 mPackageName = packageName;
2462 }
2463
2464 /**
2465 * Gets the class this node comes from.
2466 *
2467 * @return The class name.
2468 */
2469 public CharSequence getClassName() {
2470 return mClassName;
2471 }
2472
2473 /**
2474 * Sets the class this node comes from.
2475 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002476 * <strong>Note:</strong> Cannot be called from an
2477 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002478 * This class is made immutable before being delivered to an AccessibilityService.
2479 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002480 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002481 * @param className The class name.
2482 *
2483 * @throws IllegalStateException If called from an AccessibilityService.
2484 */
2485 public void setClassName(CharSequence className) {
2486 enforceNotSealed();
2487 mClassName = className;
2488 }
2489
2490 /**
2491 * Gets the text of this node.
Phil Weaver193520e2016-12-13 09:39:06 -08002492 * <p>
2493 * <strong>Note:</strong> If the text contains {@link ClickableSpan}s or {@link URLSpan}s,
2494 * these spans will have been replaced with ones whose {@link ClickableSpan#onClick(View)}
2495 * can be called from an {@link AccessibilityService}. When called from a service, the
2496 * {@link View} argument is ignored and the corresponding span will be found on the view that
2497 * this {@code AccessibilityNodeInfo} represents and called with that view as its argument.
2498 * <p>
2499 * This treatment of {@link ClickableSpan}s means that the text returned from this method may
2500 * different slightly one passed to {@link #setText(CharSequence)}, although they will be
2501 * equivalent according to {@link TextUtils#equals(CharSequence, CharSequence)}. The
2502 * {@link ClickableSpan#onClick(View)} of any spans, however, will generally not work outside
2503 * of an accessibility service.
2504 * </p>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002505 *
2506 * @return The text.
2507 */
2508 public CharSequence getText() {
Phil Weaver193520e2016-12-13 09:39:06 -08002509 // Attach this node to any spans that need it
2510 if (mText instanceof Spanned) {
2511 Spanned spanned = (Spanned) mText;
2512 AccessibilityClickableSpan[] clickableSpans =
2513 spanned.getSpans(0, mText.length(), AccessibilityClickableSpan.class);
2514 for (int i = 0; i < clickableSpans.length; i++) {
Phil Weaver23161e72017-04-19 12:16:36 -07002515 clickableSpans[i].copyConnectionDataFrom(this);
Phil Weaver193520e2016-12-13 09:39:06 -08002516 }
2517 AccessibilityURLSpan[] urlSpans =
2518 spanned.getSpans(0, mText.length(), AccessibilityURLSpan.class);
2519 for (int i = 0; i < urlSpans.length; i++) {
Phil Weaver23161e72017-04-19 12:16:36 -07002520 urlSpans[i].copyConnectionDataFrom(this);
Phil Weaver193520e2016-12-13 09:39:06 -08002521 }
2522 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002523 return mText;
2524 }
2525
2526 /**
Phil Weaver193520e2016-12-13 09:39:06 -08002527 * Get the text passed to setText before any changes to the spans.
2528 * @hide
2529 */
2530 public CharSequence getOriginalText() {
2531 return mOriginalText;
2532 }
2533
2534 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002535 * Sets the text of this node.
2536 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002537 * <strong>Note:</strong> Cannot be called from an
2538 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002539 * This class is made immutable before being delivered to an AccessibilityService.
2540 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002541 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002542 * @param text The text.
2543 *
2544 * @throws IllegalStateException If called from an AccessibilityService.
2545 */
2546 public void setText(CharSequence text) {
2547 enforceNotSealed();
Phil Weaver193520e2016-12-13 09:39:06 -08002548 mOriginalText = text;
2549 // Replace any ClickableSpans in mText with placeholders
2550 if (text instanceof Spanned) {
2551 ClickableSpan[] spans =
2552 ((Spanned) text).getSpans(0, text.length(), ClickableSpan.class);
2553 if (spans.length > 0) {
Phil Weaver0ebe6bd2017-02-21 16:24:31 -08002554 Spannable spannable = new SpannableStringBuilder(text);
Phil Weaver193520e2016-12-13 09:39:06 -08002555 for (int i = 0; i < spans.length; i++) {
2556 ClickableSpan span = spans[i];
2557 if ((span instanceof AccessibilityClickableSpan)
2558 || (span instanceof AccessibilityURLSpan)) {
2559 // We've already done enough
2560 break;
2561 }
2562 int spanToReplaceStart = spannable.getSpanStart(span);
2563 int spanToReplaceEnd = spannable.getSpanEnd(span);
2564 int spanToReplaceFlags = spannable.getSpanFlags(span);
2565 spannable.removeSpan(span);
2566 ClickableSpan replacementSpan = (span instanceof URLSpan)
2567 ? new AccessibilityURLSpan((URLSpan) span)
2568 : new AccessibilityClickableSpan(span.getId());
2569 spannable.setSpan(replacementSpan, spanToReplaceStart, spanToReplaceEnd,
2570 spanToReplaceFlags);
2571 }
2572 mText = spannable;
2573 return;
2574 }
2575 }
Phil Weaveref955ad2016-08-25 12:58:15 -07002576 mText = (text == null) ? null : text.subSequence(0, text.length());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002577 }
2578
2579 /**
Phil Weaver776afc22016-12-21 10:55:13 -08002580 * Gets the hint text of this node. Only applies to nodes where text can be entered.
2581 *
2582 * @return The hint text.
2583 */
2584 public CharSequence getHintText() {
2585 return mHintText;
2586 }
2587
2588 /**
2589 * Sets the hint text of this node. Only applies to nodes where text can be entered.
2590 * <p>
2591 * <strong>Note:</strong> Cannot be called from an
2592 * {@link android.accessibilityservice.AccessibilityService}.
2593 * This class is made immutable before being delivered to an AccessibilityService.
2594 * </p>
2595 *
2596 * @param hintText The hint text for this mode.
2597 *
2598 * @throws IllegalStateException If called from an AccessibilityService.
2599 */
2600 public void setHintText(CharSequence hintText) {
2601 enforceNotSealed();
2602 mHintText = (hintText == null) ? null : hintText.subSequence(0, hintText.length());
2603 }
2604
2605 /**
Alan Viverettefccbff52014-07-07 15:06:14 -07002606 * Sets the error text of this node.
2607 * <p>
2608 * <strong>Note:</strong> Cannot be called from an
2609 * {@link android.accessibilityservice.AccessibilityService}.
2610 * This class is made immutable before being delivered to an AccessibilityService.
2611 * </p>
2612 *
2613 * @param error The error text.
2614 *
2615 * @throws IllegalStateException If called from an AccessibilityService.
2616 */
2617 public void setError(CharSequence error) {
2618 enforceNotSealed();
Phil Weaveref955ad2016-08-25 12:58:15 -07002619 mError = (error == null) ? null : error.subSequence(0, error.length());
Alan Viverettefccbff52014-07-07 15:06:14 -07002620 }
2621
2622 /**
2623 * Gets the error text of this node.
2624 *
2625 * @return The error text.
2626 */
2627 public CharSequence getError() {
2628 return mError;
2629 }
2630
2631 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002632 * Gets the content description of this node.
2633 *
2634 * @return The content description.
2635 */
2636 public CharSequence getContentDescription() {
2637 return mContentDescription;
2638 }
2639
2640 /**
2641 * Sets the content description of this node.
2642 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002643 * <strong>Note:</strong> Cannot be called from an
2644 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002645 * This class is made immutable before being delivered to an AccessibilityService.
2646 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002647 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002648 * @param contentDescription The content description.
2649 *
2650 * @throws IllegalStateException If called from an AccessibilityService.
2651 */
2652 public void setContentDescription(CharSequence contentDescription) {
2653 enforceNotSealed();
Phil Weaveref955ad2016-08-25 12:58:15 -07002654 mContentDescription = (contentDescription == null) ? null
2655 : contentDescription.subSequence(0, contentDescription.length());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002656 }
2657
2658 /**
Phil Weaverd89905f2018-01-10 08:28:04 -08002659 * Gets the tooltip text of this node.
2660 *
2661 * @return The tooltip text.
2662 */
2663 @Nullable
2664 public CharSequence getTooltipText() {
2665 return mTooltipText;
2666 }
2667
2668 /**
2669 * Sets the tooltip text of this node.
2670 * <p>
2671 * <strong>Note:</strong> Cannot be called from an
2672 * {@link android.accessibilityservice.AccessibilityService}.
2673 * This class is made immutable before being delivered to an AccessibilityService.
2674 * </p>
2675 *
2676 * @param tooltipText The tooltip text.
2677 *
2678 * @throws IllegalStateException If called from an AccessibilityService.
2679 */
2680 public void setTooltipText(@Nullable CharSequence tooltipText) {
2681 enforceNotSealed();
2682 mTooltipText = (tooltipText == null) ? null
2683 : tooltipText.subSequence(0, tooltipText.length());
2684 }
2685
2686 /**
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002687 * Sets the view for which the view represented by this info serves as a
2688 * label for accessibility purposes.
2689 *
2690 * @param labeled The view for which this info serves as a label.
2691 */
2692 public void setLabelFor(View labeled) {
Phil Weaverf00cd142017-03-03 13:44:00 -08002693 setLabelFor(labeled, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002694 }
2695
2696 /**
2697 * Sets the view for which the view represented by this info serves as a
2698 * label for accessibility purposes. If <code>virtualDescendantId</code>
2699 * is {@link View#NO_ID} the root is set as the labeled.
2700 * <p>
2701 * A virtual descendant is an imaginary View that is reported as a part of the view
2702 * hierarchy for accessibility purposes. This enables custom views that draw complex
2703 * content to report themselves as a tree of virtual views, thus conveying their
2704 * logical structure.
2705 * </p>
2706 * <p>
2707 * <strong>Note:</strong> Cannot be called from an
2708 * {@link android.accessibilityservice.AccessibilityService}.
2709 * This class is made immutable before being delivered to an AccessibilityService.
2710 * </p>
2711 *
2712 * @param root The root whose virtual descendant serves as a label.
2713 * @param virtualDescendantId The id of the virtual descendant.
2714 */
2715 public void setLabelFor(View root, int virtualDescendantId) {
2716 enforceNotSealed();
2717 final int rootAccessibilityViewId = (root != null)
Svetoslav8e3feb12014-02-24 13:46:47 -08002718 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002719 mLabelForId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
2720 }
2721
2722 /**
2723 * Gets the node info for which the view represented by this info serves as
2724 * a label for accessibility purposes.
2725 * <p>
2726 * <strong>Note:</strong> It is a client responsibility to recycle the
2727 * received info by calling {@link AccessibilityNodeInfo#recycle()}
2728 * to avoid creating of multiple instances.
2729 * </p>
2730 *
2731 * @return The labeled info.
2732 */
2733 public AccessibilityNodeInfo getLabelFor() {
2734 enforceSealed();
Svetoslav6c702902014-10-09 18:40:56 -07002735 return getNodeForAccessibilityId(mLabelForId);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002736 }
2737
2738 /**
2739 * Sets the view which serves as the label of the view represented by
2740 * this info for accessibility purposes.
2741 *
2742 * @param label The view that labels this node's source.
2743 */
2744 public void setLabeledBy(View label) {
Phil Weaverf00cd142017-03-03 13:44:00 -08002745 setLabeledBy(label, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002746 }
2747
2748 /**
2749 * Sets the view which serves as the label of the view represented by
2750 * this info for accessibility purposes. If <code>virtualDescendantId</code>
2751 * is {@link View#NO_ID} the root is set as the label.
2752 * <p>
2753 * A virtual descendant is an imaginary View that is reported as a part of the view
2754 * hierarchy for accessibility purposes. This enables custom views that draw complex
2755 * content to report themselves as a tree of virtual views, thus conveying their
2756 * logical structure.
2757 * </p>
2758 * <p>
2759 * <strong>Note:</strong> Cannot be called from an
2760 * {@link android.accessibilityservice.AccessibilityService}.
2761 * This class is made immutable before being delivered to an AccessibilityService.
2762 * </p>
2763 *
2764 * @param root The root whose virtual descendant labels this node's source.
2765 * @param virtualDescendantId The id of the virtual descendant.
2766 */
2767 public void setLabeledBy(View root, int virtualDescendantId) {
2768 enforceNotSealed();
2769 final int rootAccessibilityViewId = (root != null)
Svetoslav8e3feb12014-02-24 13:46:47 -08002770 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002771 mLabeledById = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
2772 }
2773
2774 /**
2775 * Gets the node info which serves as the label of the view represented by
2776 * this info for accessibility purposes.
2777 * <p>
2778 * <strong>Note:</strong> It is a client responsibility to recycle the
2779 * received info by calling {@link AccessibilityNodeInfo#recycle()}
2780 * to avoid creating of multiple instances.
2781 * </p>
2782 *
2783 * @return The label.
2784 */
2785 public AccessibilityNodeInfo getLabeledBy() {
2786 enforceSealed();
Svetoslav6c702902014-10-09 18:40:56 -07002787 return getNodeForAccessibilityId(mLabeledById);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002788 }
2789
2790 /**
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002791 * Sets the fully qualified resource name of the source view's id.
2792 *
2793 * <p>
2794 * <strong>Note:</strong> Cannot be called from an
2795 * {@link android.accessibilityservice.AccessibilityService}.
2796 * This class is made immutable before being delivered to an AccessibilityService.
2797 * </p>
2798 *
Svetoslav92826452013-02-05 14:57:42 -08002799 * @param viewIdResName The id resource name.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002800 */
Svetoslav9fa1ee52013-04-22 12:43:03 -07002801 public void setViewIdResourceName(String viewIdResName) {
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002802 enforceNotSealed();
Svetoslav22431a32013-02-05 14:30:19 -08002803 mViewIdResourceName = viewIdResName;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002804 }
2805
2806 /**
2807 * Gets the fully qualified resource name of the source view's id.
2808 *
2809 * <p>
2810 * <strong>Note:</strong> The primary usage of this API is for UI test automation
2811 * and in order to report the source view id of an {@link AccessibilityNodeInfo} the
2812 * client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
Svetoslav14ff9962013-01-29 03:21:37 -08002813 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002814 * </p>
2815
2816 * @return The id resource name.
2817 */
Svetoslav9fa1ee52013-04-22 12:43:03 -07002818 public String getViewIdResourceName() {
Svetoslav22431a32013-02-05 14:30:19 -08002819 return mViewIdResourceName;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002820 }
2821
2822 /**
Phil Weaver40ded282016-01-25 15:49:02 -08002823 * Gets the text selection start or the cursor position.
2824 * <p>
2825 * If no text is selected, both this method and
2826 * {@link AccessibilityNodeInfo#getTextSelectionEnd()} return the same value:
2827 * the current location of the cursor.
2828 * </p>
Svetoslavbcc46a02013-02-06 11:56:00 -08002829 *
Phil Weaver40ded282016-01-25 15:49:02 -08002830 * @return The text selection start, the cursor location if there is no selection, or -1 if
2831 * there is no text selection and no cursor.
Svetoslavbcc46a02013-02-06 11:56:00 -08002832 */
2833 public int getTextSelectionStart() {
2834 return mTextSelectionStart;
2835 }
2836
2837 /**
Phil Weaver40ded282016-01-25 15:49:02 -08002838 * Gets the text selection end if text is selected.
2839 * <p>
2840 * If no text is selected, both this method and
2841 * {@link AccessibilityNodeInfo#getTextSelectionStart()} return the same value:
2842 * the current location of the cursor.
2843 * </p>
Svetoslavbcc46a02013-02-06 11:56:00 -08002844 *
Phil Weaver40ded282016-01-25 15:49:02 -08002845 * @return The text selection end, the cursor location if there is no selection, or -1 if
2846 * there is no text selection and no cursor.
Svetoslavbcc46a02013-02-06 11:56:00 -08002847 */
2848 public int getTextSelectionEnd() {
2849 return mTextSelectionEnd;
2850 }
2851
2852 /**
2853 * Sets the text selection start and end.
2854 * <p>
2855 * <strong>Note:</strong> Cannot be called from an
2856 * {@link android.accessibilityservice.AccessibilityService}.
2857 * This class is made immutable before being delivered to an AccessibilityService.
2858 * </p>
2859 *
2860 * @param start The text selection start.
2861 * @param end The text selection end.
2862 *
2863 * @throws IllegalStateException If called from an AccessibilityService.
2864 */
2865 public void setTextSelection(int start, int end) {
2866 enforceNotSealed();
2867 mTextSelectionStart = start;
2868 mTextSelectionEnd = end;
2869 }
2870
2871 /**
Svetoslav6254f482013-06-04 17:22:14 -07002872 * Gets the input type of the source as defined by {@link InputType}.
2873 *
2874 * @return The input type.
2875 */
2876 public int getInputType() {
2877 return mInputType;
2878 }
2879
2880 /**
2881 * Sets the input type of the source as defined by {@link InputType}.
2882 * <p>
2883 * <strong>Note:</strong> Cannot be called from an
2884 * {@link android.accessibilityservice.AccessibilityService}.
2885 * This class is made immutable before being delivered to an
2886 * AccessibilityService.
2887 * </p>
2888 *
2889 * @param inputType The input type.
2890 *
2891 * @throws IllegalStateException If called from an AccessibilityService.
2892 */
2893 public void setInputType(int inputType) {
Alan Viverettedf39cb92013-08-19 12:28:04 -07002894 enforceNotSealed();
Svetoslav6254f482013-06-04 17:22:14 -07002895 mInputType = inputType;
2896 }
2897
2898 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002899 * Gets an optional bundle with extra data. The bundle
Svetoslav6254f482013-06-04 17:22:14 -07002900 * is lazily created and never <code>null</code>.
2901 * <p>
2902 * <strong>Note:</strong> It is recommended to use the package
2903 * name of your application as a prefix for the keys to avoid
2904 * collisions which may confuse an accessibility service if the
2905 * same key has different meaning when emitted from different
2906 * applications.
2907 * </p>
2908 *
2909 * @return The bundle.
2910 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002911 public Bundle getExtras() {
2912 if (mExtras == null) {
2913 mExtras = new Bundle();
Svetoslav6254f482013-06-04 17:22:14 -07002914 }
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002915 return mExtras;
Svetoslav6254f482013-06-04 17:22:14 -07002916 }
2917
2918 /**
Phil Weaverc2e28932016-12-08 12:29:25 -08002919 * Check if a node has an extras bundle
2920 * @hide
2921 */
2922 public boolean hasExtras() {
2923 return mExtras != null;
2924 }
2925
2926 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002927 * Gets the value of a boolean property.
2928 *
2929 * @param property The property.
2930 * @return The value.
2931 */
2932 private boolean getBooleanProperty(int property) {
2933 return (mBooleanProperties & property) != 0;
2934 }
2935
2936 /**
2937 * Sets a boolean property.
2938 *
2939 * @param property The property.
2940 * @param value The value.
2941 *
2942 * @throws IllegalStateException If called from an AccessibilityService.
2943 */
2944 private void setBooleanProperty(int property, boolean value) {
2945 enforceNotSealed();
2946 if (value) {
2947 mBooleanProperties |= property;
2948 } else {
2949 mBooleanProperties &= ~property;
2950 }
2951 }
2952
2953 /**
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002954 * Sets the unique id of the IAccessibilityServiceConnection over which
2955 * this instance can send requests to the system.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002956 *
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002957 * @param connectionId The connection id.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002958 *
2959 * @hide
2960 */
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002961 public void setConnectionId(int connectionId) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002962 enforceNotSealed();
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002963 mConnectionId = connectionId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002964 }
2965
2966 /**
Phil Weaver23161e72017-04-19 12:16:36 -07002967 * Get the connection ID.
2968 *
2969 * @return The connection id
2970 *
2971 * @hide
2972 */
2973 public int getConnectionId() {
2974 return mConnectionId;
2975 }
2976
2977 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002978 * {@inheritDoc}
2979 */
Alan Viverettef0aed092013-11-06 15:33:03 -08002980 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002981 public int describeContents() {
2982 return 0;
2983 }
2984
2985 /**
Phil Weaverf00cd142017-03-03 13:44:00 -08002986 * Sets the id of the source node.
2987 *
2988 * @param sourceId The id.
2989 * @param windowId The window id.
2990 *
2991 * @hide
2992 */
2993 public void setSourceNodeId(long sourceId, int windowId) {
2994 enforceNotSealed();
2995 mSourceNodeId = sourceId;
2996 mWindowId = windowId;
2997 }
2998
2999 /**
Svetoslav Ganov79311c42012-01-17 20:24:26 -08003000 * Gets the id of the source node.
3001 *
3002 * @return The id.
3003 *
3004 * @hide
3005 */
3006 public long getSourceNodeId() {
3007 return mSourceNodeId;
3008 }
3009
3010 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003011 * Sets if this instance is sealed.
3012 *
3013 * @param sealed Whether is sealed.
3014 *
3015 * @hide
3016 */
3017 public void setSealed(boolean sealed) {
3018 mSealed = sealed;
3019 }
3020
3021 /**
3022 * Gets if this instance is sealed.
3023 *
3024 * @return Whether is sealed.
3025 *
3026 * @hide
3027 */
3028 public boolean isSealed() {
3029 return mSealed;
3030 }
3031
3032 /**
3033 * Enforces that this instance is sealed.
3034 *
3035 * @throws IllegalStateException If this instance is not sealed.
3036 *
3037 * @hide
3038 */
3039 protected void enforceSealed() {
3040 if (!isSealed()) {
3041 throw new IllegalStateException("Cannot perform this "
3042 + "action on a not sealed instance.");
3043 }
3044 }
3045
Svetoslav Ganov2ef69052012-06-04 08:55:16 -07003046 private void enforceValidFocusDirection(int direction) {
3047 switch (direction) {
3048 case View.FOCUS_DOWN:
3049 case View.FOCUS_UP:
3050 case View.FOCUS_LEFT:
3051 case View.FOCUS_RIGHT:
3052 case View.FOCUS_FORWARD:
3053 case View.FOCUS_BACKWARD:
Svetoslav Ganov2ef69052012-06-04 08:55:16 -07003054 return;
3055 default:
3056 throw new IllegalArgumentException("Unknown direction: " + direction);
3057 }
3058 }
3059
3060 private void enforceValidFocusType(int focusType) {
3061 switch (focusType) {
3062 case FOCUS_INPUT:
3063 case FOCUS_ACCESSIBILITY:
3064 return;
3065 default:
3066 throw new IllegalArgumentException("Unknown focus type: " + focusType);
3067 }
3068 }
3069
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003070 /**
3071 * Enforces that this instance is not sealed.
3072 *
3073 * @throws IllegalStateException If this instance is sealed.
3074 *
3075 * @hide
3076 */
3077 protected void enforceNotSealed() {
3078 if (isSealed()) {
3079 throw new IllegalStateException("Cannot perform this "
Ken Wakasaf76a50c2012-03-09 19:56:35 +09003080 + "action on a sealed instance.");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003081 }
3082 }
3083
3084 /**
3085 * Returns a cached instance if such is available otherwise a new one
3086 * and sets the source.
3087 *
Svetoslav Ganov02107852011-10-03 17:06:56 -07003088 * @param source The source view.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003089 * @return An instance.
3090 *
3091 * @see #setSource(View)
3092 */
3093 public static AccessibilityNodeInfo obtain(View source) {
3094 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
3095 info.setSource(source);
3096 return info;
3097 }
3098
3099 /**
Svetoslav Ganov02107852011-10-03 17:06:56 -07003100 * Returns a cached instance if such is available otherwise a new one
3101 * and sets the source.
3102 *
3103 * @param root The root of the virtual subtree.
3104 * @param virtualDescendantId The id of the virtual descendant.
3105 * @return An instance.
3106 *
3107 * @see #setSource(View, int)
3108 */
3109 public static AccessibilityNodeInfo obtain(View root, int virtualDescendantId) {
3110 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
3111 info.setSource(root, virtualDescendantId);
3112 return info;
3113 }
3114
3115 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003116 * Returns a cached instance if such is available otherwise a new one.
3117 *
3118 * @return An instance.
3119 */
3120 public static AccessibilityNodeInfo obtain() {
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -08003121 AccessibilityNodeInfo info = sPool.acquire();
Phil Weaver62d20fa2016-09-15 11:05:55 -07003122 if (sNumInstancesInUse != null) {
3123 sNumInstancesInUse.incrementAndGet();
3124 }
Phil Weavere1951292017-08-18 17:56:04 +00003125 return (info != null) ? info : new AccessibilityNodeInfo();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003126 }
3127
3128 /**
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003129 * Returns a cached instance if such is available or a new one is
3130 * create. The returned instance is initialized from the given
3131 * <code>info</code>.
3132 *
3133 * @param info The other info.
3134 * @return An instance.
3135 */
3136 public static AccessibilityNodeInfo obtain(AccessibilityNodeInfo info) {
3137 AccessibilityNodeInfo infoClone = AccessibilityNodeInfo.obtain();
3138 infoClone.init(info);
3139 return infoClone;
3140 }
3141
3142 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003143 * Return an instance back to be reused.
3144 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003145 * <strong>Note:</strong> You must not touch the object after calling this function.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003146 *
3147 * @throws IllegalStateException If the info is already recycled.
3148 */
3149 public void recycle() {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003150 clear();
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -08003151 sPool.release(this);
Phil Weaver62d20fa2016-09-15 11:05:55 -07003152 if (sNumInstancesInUse != null) {
3153 sNumInstancesInUse.decrementAndGet();
3154 }
Phil Weaverb010b122016-08-17 17:47:48 -07003155 }
3156
3157 /**
Phil Weaver62d20fa2016-09-15 11:05:55 -07003158 * Specify a counter that will be incremented on obtain() and decremented on recycle()
Phil Weaverb010b122016-08-17 17:47:48 -07003159 *
3160 * @hide
3161 */
Phil Weaver62d20fa2016-09-15 11:05:55 -07003162 @TestApi
3163 public static void setNumInstancesInUseCounter(AtomicInteger counter) {
3164 sNumInstancesInUse = counter;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003165 }
3166
3167 /**
3168 * {@inheritDoc}
3169 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003170 * <strong>Note:</strong> After the instance is written to a parcel it
3171 * is recycled. You must not touch the object after calling this function.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003172 * </p>
3173 */
Alan Viverettef0aed092013-11-06 15:33:03 -08003174 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003175 public void writeToParcel(Parcel parcel, int flags) {
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003176 // Write bit set of indices of fields with values differing from default
3177 long nonDefaultFields = 0;
3178 int fieldIndex = 0; // index of the current field
3179 if (isSealed() != DEFAULT.isSealed()) nonDefaultFields |= bitAt(fieldIndex);
3180 fieldIndex++;
3181 if (mSourceNodeId != DEFAULT.mSourceNodeId) nonDefaultFields |= bitAt(fieldIndex);
3182 fieldIndex++;
3183 if (mWindowId != DEFAULT.mWindowId) nonDefaultFields |= bitAt(fieldIndex);
3184 fieldIndex++;
3185 if (mParentNodeId != DEFAULT.mParentNodeId) nonDefaultFields |= bitAt(fieldIndex);
3186 fieldIndex++;
3187 if (mLabelForId != DEFAULT.mLabelForId) nonDefaultFields |= bitAt(fieldIndex);
3188 fieldIndex++;
3189 if (mLabeledById != DEFAULT.mLabeledById) nonDefaultFields |= bitAt(fieldIndex);
3190 fieldIndex++;
3191 if (mTraversalBefore != DEFAULT.mTraversalBefore) nonDefaultFields |= bitAt(fieldIndex);
3192 fieldIndex++;
3193 if (mTraversalAfter != DEFAULT.mTraversalAfter) nonDefaultFields |= bitAt(fieldIndex);
3194 fieldIndex++;
3195 if (mConnectionId != DEFAULT.mConnectionId) nonDefaultFields |= bitAt(fieldIndex);
3196 fieldIndex++;
3197 if (!Objects.equals(mChildNodeIds, DEFAULT.mChildNodeIds)) {
3198 nonDefaultFields |= bitAt(fieldIndex);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003199 }
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003200 fieldIndex++;
3201 if (!Objects.equals(mBoundsInParent, DEFAULT.mBoundsInParent)) {
3202 nonDefaultFields |= bitAt(fieldIndex);
3203 }
3204 fieldIndex++;
3205 if (!Objects.equals(mBoundsInScreen, DEFAULT.mBoundsInScreen)) {
3206 nonDefaultFields |= bitAt(fieldIndex);
3207 }
3208 fieldIndex++;
3209 if (!Objects.equals(mActions, DEFAULT.mActions)) nonDefaultFields |= bitAt(fieldIndex);
3210 fieldIndex++;
3211 if (mMaxTextLength != DEFAULT.mMaxTextLength) nonDefaultFields |= bitAt(fieldIndex);
3212 fieldIndex++;
3213 if (mMovementGranularities != DEFAULT.mMovementGranularities) {
3214 nonDefaultFields |= bitAt(fieldIndex);
3215 }
3216 fieldIndex++;
3217 if (mBooleanProperties != DEFAULT.mBooleanProperties) nonDefaultFields |= bitAt(fieldIndex);
3218 fieldIndex++;
3219 if (!Objects.equals(mPackageName, DEFAULT.mPackageName)) {
3220 nonDefaultFields |= bitAt(fieldIndex);
3221 }
3222 fieldIndex++;
3223 if (!Objects.equals(mClassName, DEFAULT.mClassName)) nonDefaultFields |= bitAt(fieldIndex);
3224 fieldIndex++;
3225 if (!Objects.equals(mText, DEFAULT.mText)) nonDefaultFields |= bitAt(fieldIndex);
3226 fieldIndex++;
3227 if (!Objects.equals(mHintText, DEFAULT.mHintText)) {
3228 nonDefaultFields |= bitAt(fieldIndex);
3229 }
3230 fieldIndex++;
3231 if (!Objects.equals(mError, DEFAULT.mError)) nonDefaultFields |= bitAt(fieldIndex);
3232 fieldIndex++;
3233 if (!Objects.equals(mContentDescription, DEFAULT.mContentDescription)) {
3234 nonDefaultFields |= bitAt(fieldIndex);
3235 }
3236 fieldIndex++;
Phil Weaver9f26b3d2018-01-04 10:04:37 -08003237 if (!Objects.equals(mPaneTitle, DEFAULT.mPaneTitle)) {
3238 nonDefaultFields |= bitAt(fieldIndex);
3239 }
3240 fieldIndex++;
Phil Weaverd89905f2018-01-10 08:28:04 -08003241 if (!Objects.equals(mTooltipText, DEFAULT.mTooltipText)) {
3242 nonDefaultFields |= bitAt(fieldIndex);
3243 }
3244 fieldIndex++;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003245 if (!Objects.equals(mViewIdResourceName, DEFAULT.mViewIdResourceName)) {
3246 nonDefaultFields |= bitAt(fieldIndex);
3247 }
3248 fieldIndex++;
3249 if (mTextSelectionStart != DEFAULT.mTextSelectionStart) {
3250 nonDefaultFields |= bitAt(fieldIndex);
3251 }
3252 fieldIndex++;
3253 if (mTextSelectionEnd != DEFAULT.mTextSelectionEnd) {
3254 nonDefaultFields |= bitAt(fieldIndex);
3255 }
3256 fieldIndex++;
3257 if (mInputType != DEFAULT.mInputType) nonDefaultFields |= bitAt(fieldIndex);
3258 fieldIndex++;
3259 if (mLiveRegion != DEFAULT.mLiveRegion) nonDefaultFields |= bitAt(fieldIndex);
3260 fieldIndex++;
3261 if (mDrawingOrderInParent != DEFAULT.mDrawingOrderInParent) {
3262 nonDefaultFields |= bitAt(fieldIndex);
3263 }
3264 fieldIndex++;
3265 if (!Objects.equals(mExtraDataKeys, DEFAULT.mExtraDataKeys)) {
3266 nonDefaultFields |= bitAt(fieldIndex);
3267 }
3268 fieldIndex++;
3269 if (!Objects.equals(mExtras, DEFAULT.mExtras)) nonDefaultFields |= bitAt(fieldIndex);
3270 fieldIndex++;
3271 if (!Objects.equals(mRangeInfo, DEFAULT.mRangeInfo)) nonDefaultFields |= bitAt(fieldIndex);
3272 fieldIndex++;
3273 if (!Objects.equals(mCollectionInfo, DEFAULT.mCollectionInfo)) {
3274 nonDefaultFields |= bitAt(fieldIndex);
3275 }
3276 fieldIndex++;
3277 if (!Objects.equals(mCollectionItemInfo, DEFAULT.mCollectionItemInfo)) {
3278 nonDefaultFields |= bitAt(fieldIndex);
3279 }
3280 int totalFields = fieldIndex;
3281 parcel.writeLong(nonDefaultFields);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003282
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003283 fieldIndex = 0;
3284 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(isSealed() ? 1 : 0);
3285 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mSourceNodeId);
3286 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mWindowId);
3287 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mParentNodeId);
3288 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mLabelForId);
3289 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mLabeledById);
3290 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mTraversalBefore);
3291 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mTraversalAfter);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07003292
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003293 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mConnectionId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003294
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003295 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3296 final LongArray childIds = mChildNodeIds;
3297 if (childIds == null) {
3298 parcel.writeInt(0);
3299 } else {
3300 final int childIdsSize = childIds.size();
3301 parcel.writeInt(childIdsSize);
3302 for (int i = 0; i < childIdsSize; i++) {
3303 parcel.writeLong(childIds.get(i));
Kristian Monsen74bc1942014-04-29 11:00:17 -07003304 }
3305 }
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003306 }
Kristian Monsen74bc1942014-04-29 11:00:17 -07003307
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003308 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3309 parcel.writeInt(mBoundsInParent.top);
3310 parcel.writeInt(mBoundsInParent.bottom);
3311 parcel.writeInt(mBoundsInParent.left);
3312 parcel.writeInt(mBoundsInParent.right);
3313 }
3314
3315 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3316 parcel.writeInt(mBoundsInScreen.top);
3317 parcel.writeInt(mBoundsInScreen.bottom);
3318 parcel.writeInt(mBoundsInScreen.left);
3319 parcel.writeInt(mBoundsInScreen.right);
3320 }
3321
3322 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3323 if (mActions != null && !mActions.isEmpty()) {
3324 final int actionCount = mActions.size();
3325
Eugene Susla554edd32017-05-24 16:49:59 -07003326 int nonStandardActionCount = 0;
3327 int defaultStandardActions = 0;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003328 for (int i = 0; i < actionCount; i++) {
3329 AccessibilityAction action = mActions.get(i);
Eugene Susla554edd32017-05-24 16:49:59 -07003330 if (isDefaultStandardAction(action)) {
3331 defaultStandardActions |= action.mSerializationFlag;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003332 } else {
Eugene Susla554edd32017-05-24 16:49:59 -07003333 nonStandardActionCount++;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003334 }
Kristian Monsen74bc1942014-04-29 11:00:17 -07003335 }
Eugene Susla554edd32017-05-24 16:49:59 -07003336 parcel.writeInt(defaultStandardActions);
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003337
Eugene Susla554edd32017-05-24 16:49:59 -07003338 parcel.writeInt(nonStandardActionCount);
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003339 for (int i = 0; i < actionCount; i++) {
3340 AccessibilityAction action = mActions.get(i);
Eugene Susla554edd32017-05-24 16:49:59 -07003341 if (!isDefaultStandardAction(action)) {
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003342 parcel.writeInt(action.getId());
3343 parcel.writeCharSequence(action.getLabel());
3344 }
3345 }
3346 } else {
3347 parcel.writeInt(0);
3348 parcel.writeInt(0);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003349 }
Kristian Monsen74bc1942014-04-29 11:00:17 -07003350 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003351
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003352 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mMaxTextLength);
3353 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mMovementGranularities);
3354 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mBooleanProperties);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003355
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003356 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mPackageName);
3357 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mClassName);
3358 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mText);
3359 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mHintText);
3360 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mError);
3361 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3362 parcel.writeCharSequence(mContentDescription);
Phil Weaverc2e28932016-12-08 12:29:25 -08003363 }
Phil Weaver9f26b3d2018-01-04 10:04:37 -08003364 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mPaneTitle);
Phil Weaverd89905f2018-01-10 08:28:04 -08003365 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mTooltipText);
3366
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003367 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeString(mViewIdResourceName);
Svetoslav6254f482013-06-04 17:22:14 -07003368
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003369 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mTextSelectionStart);
3370 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mTextSelectionEnd);
3371 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mInputType);
3372 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mLiveRegion);
3373 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mDrawingOrderInParent);
Svetoslavbcc46a02013-02-06 11:56:00 -08003374
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003375 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeStringList(mExtraDataKeys);
3376
3377 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeBundle(mExtras);
3378
3379 if (isBitSet(nonDefaultFields, fieldIndex++)) {
Svetoslav3577a282013-06-06 14:09:10 -07003380 parcel.writeInt(mRangeInfo.getType());
3381 parcel.writeFloat(mRangeInfo.getMin());
3382 parcel.writeFloat(mRangeInfo.getMax());
3383 parcel.writeFloat(mRangeInfo.getCurrent());
Svetoslav3577a282013-06-06 14:09:10 -07003384 }
3385
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003386 if (isBitSet(nonDefaultFields, fieldIndex++)) {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003387 parcel.writeInt(mCollectionInfo.getRowCount());
3388 parcel.writeInt(mCollectionInfo.getColumnCount());
Svetoslav3577a282013-06-06 14:09:10 -07003389 parcel.writeInt(mCollectionInfo.isHierarchical() ? 1 : 0);
Alan Viverette76769ae2014-02-12 16:38:10 -08003390 parcel.writeInt(mCollectionInfo.getSelectionMode());
Svetoslav3577a282013-06-06 14:09:10 -07003391 }
3392
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003393 if (isBitSet(nonDefaultFields, fieldIndex++)) {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003394 parcel.writeInt(mCollectionItemInfo.getRowIndex());
3395 parcel.writeInt(mCollectionItemInfo.getRowSpan());
Alan Viverettefaeac962015-06-01 09:03:27 -07003396 parcel.writeInt(mCollectionItemInfo.getColumnIndex());
3397 parcel.writeInt(mCollectionItemInfo.getColumnSpan());
Svetoslav3577a282013-06-06 14:09:10 -07003398 parcel.writeInt(mCollectionItemInfo.isHeading() ? 1 : 0);
Alan Viverette76769ae2014-02-12 16:38:10 -08003399 parcel.writeInt(mCollectionItemInfo.isSelected() ? 1 : 0);
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003400 }
3401
3402 if (DEBUG) {
3403 fieldIndex--;
3404 if (totalFields != fieldIndex) {
3405 throw new IllegalStateException("Number of fields mismatch: " + totalFields
3406 + " vs " + fieldIndex);
3407 }
Svetoslav3577a282013-06-06 14:09:10 -07003408 }
3409
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003410 // Since instances of this class are fetched via synchronous i.e. blocking
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003411 // calls in IPCs we always recycle as soon as the instance is marshaled.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003412 recycle();
3413 }
3414
3415 /**
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003416 * Initializes this instance from another one.
3417 *
3418 * @param other The other instance.
3419 */
3420 private void init(AccessibilityNodeInfo other) {
3421 mSealed = other.mSealed;
Svetoslav Ganov02107852011-10-03 17:06:56 -07003422 mSourceNodeId = other.mSourceNodeId;
3423 mParentNodeId = other.mParentNodeId;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07003424 mLabelForId = other.mLabelForId;
3425 mLabeledById = other.mLabeledById;
Svetoslav6c702902014-10-09 18:40:56 -07003426 mTraversalBefore = other.mTraversalBefore;
3427 mTraversalAfter = other.mTraversalAfter;
Svetoslav Ganov02107852011-10-03 17:06:56 -07003428 mWindowId = other.mWindowId;
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08003429 mConnectionId = other.mConnectionId;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003430 mBoundsInParent.set(other.mBoundsInParent);
3431 mBoundsInScreen.set(other.mBoundsInScreen);
3432 mPackageName = other.mPackageName;
3433 mClassName = other.mClassName;
3434 mText = other.mText;
Phil Weaver776afc22016-12-21 10:55:13 -08003435 mHintText = other.mHintText;
Alan Viverettefccbff52014-07-07 15:06:14 -07003436 mError = other.mError;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003437 mContentDescription = other.mContentDescription;
Phil Weaver9f26b3d2018-01-04 10:04:37 -08003438 mPaneTitle = other.mPaneTitle;
Phil Weaverd89905f2018-01-10 08:28:04 -08003439 mTooltipText = other.mTooltipText;
Svetoslav22431a32013-02-05 14:30:19 -08003440 mViewIdResourceName = other.mViewIdResourceName;
Kristian Monsen74bc1942014-04-29 11:00:17 -07003441
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003442 if (mActions != null) mActions.clear();
Kristian Monsen74bc1942014-04-29 11:00:17 -07003443 final ArrayList<AccessibilityAction> otherActions = other.mActions;
3444 if (otherActions != null && otherActions.size() > 0) {
3445 if (mActions == null) {
3446 mActions = new ArrayList(otherActions);
3447 } else {
Kristian Monsen74bc1942014-04-29 11:00:17 -07003448 mActions.addAll(other.mActions);
3449 }
3450 }
3451
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003452 mBooleanProperties = other.mBooleanProperties;
Alan Viverette029942f2014-08-12 14:55:56 -07003453 mMaxTextLength = other.mMaxTextLength;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003454 mMovementGranularities = other.mMovementGranularities;
Alan Viverettef0aed092013-11-06 15:33:03 -08003455
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003456
3457 if (mChildNodeIds != null) mChildNodeIds.clear();
Alan Viverettef0aed092013-11-06 15:33:03 -08003458 final LongArray otherChildNodeIds = other.mChildNodeIds;
3459 if (otherChildNodeIds != null && otherChildNodeIds.size() > 0) {
3460 if (mChildNodeIds == null) {
3461 mChildNodeIds = otherChildNodeIds.clone();
3462 } else {
3463 mChildNodeIds.addAll(otherChildNodeIds);
3464 }
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003465 }
Alan Viverettef0aed092013-11-06 15:33:03 -08003466
Svetoslavbcc46a02013-02-06 11:56:00 -08003467 mTextSelectionStart = other.mTextSelectionStart;
3468 mTextSelectionEnd = other.mTextSelectionEnd;
Svetoslav6254f482013-06-04 17:22:14 -07003469 mInputType = other.mInputType;
Alan Viverette77e9a282013-09-12 17:16:09 -07003470 mLiveRegion = other.mLiveRegion;
Phil Weaver1f222542016-01-08 11:49:32 -08003471 mDrawingOrderInParent = other.mDrawingOrderInParent;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003472
Phil Weaverc2e28932016-12-08 12:29:25 -08003473 mExtraDataKeys = other.mExtraDataKeys;
3474
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003475 mExtras = other.mExtras != null ? new Bundle(other.mExtras) : null;
3476
3477 if (mRangeInfo != null) mRangeInfo.recycle();
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07003478 mRangeInfo = (other.mRangeInfo != null)
3479 ? RangeInfo.obtain(other.mRangeInfo) : null;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003480 if (mCollectionInfo != null) mCollectionInfo.recycle();
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07003481 mCollectionInfo = (other.mCollectionInfo != null)
3482 ? CollectionInfo.obtain(other.mCollectionInfo) : null;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003483 if (mCollectionItemInfo != null) mCollectionItemInfo.recycle();
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07003484 mCollectionItemInfo = (other.mCollectionItemInfo != null)
3485 ? CollectionItemInfo.obtain(other.mCollectionItemInfo) : null;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003486 }
3487
3488 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003489 * Creates a new instance from a {@link Parcel}.
3490 *
3491 * @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}.
3492 */
3493 private void initFromParcel(Parcel parcel) {
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003494 // Bit mask of non-default-valued field indices
3495 long nonDefaultFields = parcel.readLong();
3496 int fieldIndex = 0;
3497 final boolean sealed = isBitSet(nonDefaultFields, fieldIndex++)
3498 ? (parcel.readInt() == 1)
3499 : DEFAULT.mSealed;
3500 if (isBitSet(nonDefaultFields, fieldIndex++)) mSourceNodeId = parcel.readLong();
3501 if (isBitSet(nonDefaultFields, fieldIndex++)) mWindowId = parcel.readInt();
3502 if (isBitSet(nonDefaultFields, fieldIndex++)) mParentNodeId = parcel.readLong();
3503 if (isBitSet(nonDefaultFields, fieldIndex++)) mLabelForId = parcel.readLong();
3504 if (isBitSet(nonDefaultFields, fieldIndex++)) mLabeledById = parcel.readLong();
3505 if (isBitSet(nonDefaultFields, fieldIndex++)) mTraversalBefore = parcel.readLong();
3506 if (isBitSet(nonDefaultFields, fieldIndex++)) mTraversalAfter = parcel.readLong();
Svetoslav6c702902014-10-09 18:40:56 -07003507
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003508 if (isBitSet(nonDefaultFields, fieldIndex++)) mConnectionId = parcel.readInt();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003509
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003510 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3511 final int childrenSize = parcel.readInt();
3512 if (childrenSize <= 0) {
3513 mChildNodeIds = null;
3514 } else {
3515 mChildNodeIds = new LongArray(childrenSize);
3516 for (int i = 0; i < childrenSize; i++) {
3517 final long childId = parcel.readLong();
3518 mChildNodeIds.add(childId);
3519 }
Alan Viverettef0aed092013-11-06 15:33:03 -08003520 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003521 }
3522
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003523 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3524 mBoundsInParent.top = parcel.readInt();
3525 mBoundsInParent.bottom = parcel.readInt();
3526 mBoundsInParent.left = parcel.readInt();
3527 mBoundsInParent.right = parcel.readInt();
Kristian Monsen74bc1942014-04-29 11:00:17 -07003528 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003529
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003530 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3531 mBoundsInScreen.top = parcel.readInt();
3532 mBoundsInScreen.bottom = parcel.readInt();
3533 mBoundsInScreen.left = parcel.readInt();
3534 mBoundsInScreen.right = parcel.readInt();
Phil Weaverc2e28932016-12-08 12:29:25 -08003535 }
3536
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003537 if (isBitSet(nonDefaultFields, fieldIndex++)) {
Eugene Susla554edd32017-05-24 16:49:59 -07003538 final int standardActions = parcel.readInt();
3539 addStandardActions(standardActions);
3540 final int nonStandardActionCount = parcel.readInt();
3541 for (int i = 0; i < nonStandardActionCount; i++) {
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003542 final AccessibilityAction action = new AccessibilityAction(
3543 parcel.readInt(), parcel.readCharSequence());
3544 addActionUnchecked(action);
3545 }
Svetoslav6254f482013-06-04 17:22:14 -07003546 }
Svetoslav3577a282013-06-06 14:09:10 -07003547
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003548 if (isBitSet(nonDefaultFields, fieldIndex++)) mMaxTextLength = parcel.readInt();
3549 if (isBitSet(nonDefaultFields, fieldIndex++)) mMovementGranularities = parcel.readInt();
3550 if (isBitSet(nonDefaultFields, fieldIndex++)) mBooleanProperties = parcel.readInt();
Svetoslav3577a282013-06-06 14:09:10 -07003551
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003552 if (isBitSet(nonDefaultFields, fieldIndex++)) mPackageName = parcel.readCharSequence();
3553 if (isBitSet(nonDefaultFields, fieldIndex++)) mClassName = parcel.readCharSequence();
3554 if (isBitSet(nonDefaultFields, fieldIndex++)) mText = parcel.readCharSequence();
3555 if (isBitSet(nonDefaultFields, fieldIndex++)) mHintText = parcel.readCharSequence();
3556 if (isBitSet(nonDefaultFields, fieldIndex++)) mError = parcel.readCharSequence();
3557 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3558 mContentDescription = parcel.readCharSequence();
Svetoslav3577a282013-06-06 14:09:10 -07003559 }
Phil Weaver9f26b3d2018-01-04 10:04:37 -08003560 if (isBitSet(nonDefaultFields, fieldIndex++)) mPaneTitle = parcel.readString();
Phil Weaverd89905f2018-01-10 08:28:04 -08003561 if (isBitSet(nonDefaultFields, fieldIndex++)) mTooltipText = parcel.readCharSequence();
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003562 if (isBitSet(nonDefaultFields, fieldIndex++)) mViewIdResourceName = parcel.readString();
Svetoslav3577a282013-06-06 14:09:10 -07003563
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003564 if (isBitSet(nonDefaultFields, fieldIndex++)) mTextSelectionStart = parcel.readInt();
3565 if (isBitSet(nonDefaultFields, fieldIndex++)) mTextSelectionEnd = parcel.readInt();
3566
3567 if (isBitSet(nonDefaultFields, fieldIndex++)) mInputType = parcel.readInt();
3568 if (isBitSet(nonDefaultFields, fieldIndex++)) mLiveRegion = parcel.readInt();
3569 if (isBitSet(nonDefaultFields, fieldIndex++)) mDrawingOrderInParent = parcel.readInt();
3570
3571 mExtraDataKeys = isBitSet(nonDefaultFields, fieldIndex++)
3572 ? parcel.createStringArrayList()
3573 : null;
3574
3575 mExtras = isBitSet(nonDefaultFields, fieldIndex++)
3576 ? parcel.readBundle()
3577 : null;
3578
3579 if (mRangeInfo != null) mRangeInfo.recycle();
3580 mRangeInfo = isBitSet(nonDefaultFields, fieldIndex++)
3581 ? RangeInfo.obtain(
3582 parcel.readInt(),
3583 parcel.readFloat(),
3584 parcel.readFloat(),
3585 parcel.readFloat())
3586 : null;
3587
3588 if (mCollectionInfo != null) mCollectionInfo.recycle();
3589 mCollectionInfo = isBitSet(nonDefaultFields, fieldIndex++)
3590 ? CollectionInfo.obtain(
3591 parcel.readInt(),
3592 parcel.readInt(),
3593 parcel.readInt() == 1,
3594 parcel.readInt())
3595 : null;
3596
3597 if (mCollectionItemInfo != null) mCollectionItemInfo.recycle();
3598 mCollectionItemInfo = isBitSet(nonDefaultFields, fieldIndex++)
3599 ? CollectionItemInfo.obtain(
3600 parcel.readInt(),
3601 parcel.readInt(),
3602 parcel.readInt(),
3603 parcel.readInt(),
3604 parcel.readInt() == 1,
3605 parcel.readInt() == 1)
3606 : null;
Maxim Bogatov2f55a3f2015-06-09 15:00:44 -07003607
3608 mSealed = sealed;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003609 }
3610
3611 /**
3612 * Clears the state of this instance.
3613 */
3614 private void clear() {
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003615 init(DEFAULT);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003616 }
3617
Eugene Susla554edd32017-05-24 16:49:59 -07003618 private static boolean isDefaultStandardAction(AccessibilityAction action) {
3619 return action.mSerializationFlag != -1 && TextUtils.isEmpty(action.getLabel());
Kristian Monsen74bc1942014-04-29 11:00:17 -07003620 }
3621
3622 private static AccessibilityAction getActionSingleton(int actionId) {
3623 final int actions = AccessibilityAction.sStandardActions.size();
3624 for (int i = 0; i < actions; i++) {
3625 AccessibilityAction currentAction = AccessibilityAction.sStandardActions.valueAt(i);
3626 if (actionId == currentAction.getId()) {
3627 return currentAction;
3628 }
3629 }
3630
3631 return null;
3632 }
3633
Eugene Susla554edd32017-05-24 16:49:59 -07003634 private static AccessibilityAction getActionSingletonBySerializationFlag(int flag) {
3635 final int actions = AccessibilityAction.sStandardActions.size();
3636 for (int i = 0; i < actions; i++) {
3637 AccessibilityAction currentAction = AccessibilityAction.sStandardActions.valueAt(i);
3638 if (flag == currentAction.mSerializationFlag) {
3639 return currentAction;
3640 }
3641 }
3642
3643 return null;
3644 }
3645
3646 private void addStandardActions(int serializationIdMask) {
3647 int remainingIds = serializationIdMask;
Kristian Monsen74bc1942014-04-29 11:00:17 -07003648 while (remainingIds > 0) {
3649 final int id = 1 << Integer.numberOfTrailingZeros(remainingIds);
3650 remainingIds &= ~id;
Eugene Susla554edd32017-05-24 16:49:59 -07003651 AccessibilityAction action = getActionSingletonBySerializationFlag(id);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003652 addAction(action);
3653 }
3654 }
3655
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003656 /**
3657 * Gets the human readable action symbolic name.
3658 *
3659 * @param action The action.
3660 * @return The symbolic name.
3661 */
3662 private static String getActionSymbolicName(int action) {
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003663 switch (action) {
3664 case ACTION_FOCUS:
3665 return "ACTION_FOCUS";
3666 case ACTION_CLEAR_FOCUS:
3667 return "ACTION_CLEAR_FOCUS";
3668 case ACTION_SELECT:
3669 return "ACTION_SELECT";
3670 case ACTION_CLEAR_SELECTION:
3671 return "ACTION_CLEAR_SELECTION";
Svetoslav Ganove9bda152012-04-30 16:55:21 -07003672 case ACTION_CLICK:
3673 return "ACTION_CLICK";
3674 case ACTION_LONG_CLICK:
3675 return "ACTION_LONG_CLICK";
3676 case ACTION_ACCESSIBILITY_FOCUS:
3677 return "ACTION_ACCESSIBILITY_FOCUS";
3678 case ACTION_CLEAR_ACCESSIBILITY_FOCUS:
3679 return "ACTION_CLEAR_ACCESSIBILITY_FOCUS";
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003680 case ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
3681 return "ACTION_NEXT_AT_MOVEMENT_GRANULARITY";
3682 case ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY:
3683 return "ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY";
Svetoslav Ganove9bda152012-04-30 16:55:21 -07003684 case ACTION_NEXT_HTML_ELEMENT:
3685 return "ACTION_NEXT_HTML_ELEMENT";
3686 case ACTION_PREVIOUS_HTML_ELEMENT:
3687 return "ACTION_PREVIOUS_HTML_ELEMENT";
Svetoslav Ganova1dc7612012-05-10 04:14:53 -07003688 case ACTION_SCROLL_FORWARD:
3689 return "ACTION_SCROLL_FORWARD";
3690 case ACTION_SCROLL_BACKWARD:
3691 return "ACTION_SCROLL_BACKWARD";
Svetoslav Ganov242724e2013-02-01 14:42:18 -08003692 case ACTION_CUT:
3693 return "ACTION_CUT";
3694 case ACTION_COPY:
3695 return "ACTION_COPY";
3696 case ACTION_PASTE:
3697 return "ACTION_PASTE";
3698 case ACTION_SET_SELECTION:
3699 return "ACTION_SET_SELECTION";
Steven Dao103a577c2015-10-12 17:35:59 -07003700 case ACTION_EXPAND:
3701 return "ACTION_EXPAND";
3702 case ACTION_COLLAPSE:
3703 return "ACTION_COLLAPSE";
3704 case ACTION_DISMISS:
3705 return "ACTION_DISMISS";
3706 case ACTION_SET_TEXT:
3707 return "ACTION_SET_TEXT";
3708 case R.id.accessibilityActionShowOnScreen:
3709 return "ACTION_SHOW_ON_SCREEN";
3710 case R.id.accessibilityActionScrollToPosition:
3711 return "ACTION_SCROLL_TO_POSITION";
3712 case R.id.accessibilityActionScrollUp:
3713 return "ACTION_SCROLL_UP";
3714 case R.id.accessibilityActionScrollLeft:
3715 return "ACTION_SCROLL_LEFT";
3716 case R.id.accessibilityActionScrollDown:
3717 return "ACTION_SCROLL_DOWN";
3718 case R.id.accessibilityActionScrollRight:
3719 return "ACTION_SCROLL_RIGHT";
3720 case R.id.accessibilityActionSetProgress:
3721 return "ACTION_SET_PROGRESS";
3722 case R.id.accessibilityActionContextClick:
3723 return "ACTION_CONTEXT_CLICK";
Phil Weaverd89905f2018-01-10 08:28:04 -08003724 case R.id.accessibilityActionShowTooltip:
3725 return "ACTION_SHOW_TOOLTIP";
3726 case R.id.accessibilityActionHideTooltip:
3727 return "ACTION_HIDE_TOOLTIP";
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003728 default:
Steven Dao103a577c2015-10-12 17:35:59 -07003729 return "ACTION_UNKNOWN";
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003730 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003731 }
3732
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003733 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003734 * Gets the human readable movement granularity symbolic name.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003735 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003736 * @param granularity The granularity.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003737 * @return The symbolic name.
3738 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003739 private static String getMovementGranularitySymbolicName(int granularity) {
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003740 switch (granularity) {
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003741 case MOVEMENT_GRANULARITY_CHARACTER:
3742 return "MOVEMENT_GRANULARITY_CHARACTER";
3743 case MOVEMENT_GRANULARITY_WORD:
3744 return "MOVEMENT_GRANULARITY_WORD";
3745 case MOVEMENT_GRANULARITY_LINE:
3746 return "MOVEMENT_GRANULARITY_LINE";
3747 case MOVEMENT_GRANULARITY_PARAGRAPH:
3748 return "MOVEMENT_GRANULARITY_PARAGRAPH";
3749 case MOVEMENT_GRANULARITY_PAGE:
3750 return "MOVEMENT_GRANULARITY_PAGE";
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003751 default:
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003752 throw new IllegalArgumentException("Unknown movement granularity: " + granularity);
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003753 }
3754 }
3755
Svetoslav Ganov02107852011-10-03 17:06:56 -07003756 private boolean canPerformRequestOverConnection(long accessibilityNodeId) {
Phil Weaver23161e72017-04-19 12:16:36 -07003757 return ((mWindowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)
3758 && (getAccessibilityViewId(accessibilityNodeId) != UNDEFINED_ITEM_ID)
3759 && (mConnectionId != UNDEFINED_CONNECTION_ID));
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07003760 }
3761
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003762 @Override
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07003763 public boolean equals(Object object) {
3764 if (this == object) {
3765 return true;
3766 }
3767 if (object == null) {
3768 return false;
3769 }
3770 if (getClass() != object.getClass()) {
3771 return false;
3772 }
3773 AccessibilityNodeInfo other = (AccessibilityNodeInfo) object;
Svetoslav Ganov02107852011-10-03 17:06:56 -07003774 if (mSourceNodeId != other.mSourceNodeId) {
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07003775 return false;
3776 }
Svetoslav Ganov02107852011-10-03 17:06:56 -07003777 if (mWindowId != other.mWindowId) {
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07003778 return false;
3779 }
3780 return true;
3781 }
3782
3783 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003784 public int hashCode() {
3785 final int prime = 31;
3786 int result = 1;
Svetoslav Ganov02107852011-10-03 17:06:56 -07003787 result = prime * result + getAccessibilityViewId(mSourceNodeId);
3788 result = prime * result + getVirtualDescendantId(mSourceNodeId);
3789 result = prime * result + mWindowId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003790 return result;
3791 }
3792
3793 @Override
3794 public String toString() {
3795 StringBuilder builder = new StringBuilder();
3796 builder.append(super.toString());
3797
3798 if (DEBUG) {
Svetoslav8e3feb12014-02-24 13:46:47 -08003799 builder.append("; sourceNodeId: " + mSourceNodeId);
Felipe Lemeac645ba2017-12-08 14:04:28 -08003800 builder.append("; windowId: " + mWindowId);
3801 builder.append("; accessibilityViewId: ").append(getAccessibilityViewId(mSourceNodeId));
3802 builder.append("; virtualDescendantId: ").append(getVirtualDescendantId(mSourceNodeId));
Svetoslav Ganov02107852011-10-03 17:06:56 -07003803 builder.append("; mParentNodeId: " + mParentNodeId);
Svetoslav6c702902014-10-09 18:40:56 -07003804 builder.append("; traversalBefore: ").append(mTraversalBefore);
3805 builder.append("; traversalAfter: ").append(mTraversalAfter);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003806
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003807 int granularities = mMovementGranularities;
3808 builder.append("; MovementGranularities: [");
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003809 while (granularities != 0) {
3810 final int granularity = 1 << Integer.numberOfTrailingZeros(granularities);
3811 granularities &= ~granularity;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003812 builder.append(getMovementGranularitySymbolicName(granularity));
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003813 if (granularities != 0) {
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003814 builder.append(", ");
3815 }
3816 }
3817 builder.append("]");
3818
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003819 builder.append("; childAccessibilityIds: [");
Alan Viverettef0aed092013-11-06 15:33:03 -08003820 final LongArray childIds = mChildNodeIds;
3821 if (childIds != null) {
3822 for (int i = 0, count = childIds.size(); i < count; i++) {
3823 builder.append(childIds.get(i));
3824 if (i < count - 1) {
3825 builder.append(", ");
3826 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003827 }
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003828 }
3829 builder.append("]");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003830 }
3831
Felipe Lemeac645ba2017-12-08 14:04:28 -08003832 builder.append("; boundsInParent: ").append(mBoundsInParent);
3833 builder.append("; boundsInScreen: ").append(mBoundsInScreen);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003834
3835 builder.append("; packageName: ").append(mPackageName);
3836 builder.append("; className: ").append(mClassName);
3837 builder.append("; text: ").append(mText);
Alan Viverettefccbff52014-07-07 15:06:14 -07003838 builder.append("; error: ").append(mError);
Alan Viverette029942f2014-08-12 14:55:56 -07003839 builder.append("; maxTextLength: ").append(mMaxTextLength);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003840 builder.append("; contentDescription: ").append(mContentDescription);
Phil Weaverd89905f2018-01-10 08:28:04 -08003841 builder.append("; tooltipText: ").append(mTooltipText);
Svetoslav22431a32013-02-05 14:30:19 -08003842 builder.append("; viewIdResName: ").append(mViewIdResourceName);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003843
3844 builder.append("; checkable: ").append(isCheckable());
3845 builder.append("; checked: ").append(isChecked());
3846 builder.append("; focusable: ").append(isFocusable());
3847 builder.append("; focused: ").append(isFocused());
3848 builder.append("; selected: ").append(isSelected());
3849 builder.append("; clickable: ").append(isClickable());
3850 builder.append("; longClickable: ").append(isLongClickable());
Mady Mellore8608912015-06-05 09:02:55 -07003851 builder.append("; contextClickable: ").append(isContextClickable());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003852 builder.append("; enabled: ").append(isEnabled());
3853 builder.append("; password: ").append(isPassword());
Kristian Monsen74bc1942014-04-29 11:00:17 -07003854 builder.append("; scrollable: ").append(isScrollable());
Phil Weaver4d3eec412016-09-01 16:28:34 -07003855 builder.append("; importantForAccessibility: ").append(isImportantForAccessibility());
Kristian Monsen74bc1942014-04-29 11:00:17 -07003856 builder.append("; actions: ").append(mActions);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003857
3858 return builder.toString();
3859 }
3860
Svetoslav6c702902014-10-09 18:40:56 -07003861 private AccessibilityNodeInfo getNodeForAccessibilityId(long accessibilityId) {
3862 if (!canPerformRequestOverConnection(accessibilityId)) {
3863 return null;
3864 }
3865 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
3866 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
3867 mWindowId, accessibilityId, false, FLAG_PREFETCH_PREDECESSORS
Phil Weaverc2e28932016-12-08 12:29:25 -08003868 | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS, null);
Svetoslav6c702902014-10-09 18:40:56 -07003869 }
3870
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003871 /**
Kristian Monsen74bc1942014-04-29 11:00:17 -07003872 * A class defining an action that can be performed on an {@link AccessibilityNodeInfo}.
3873 * Each action has a unique id that is mandatory and optional data.
3874 * <p>
3875 * There are three categories of actions:
3876 * <ul>
3877 * <li><strong>Standard actions</strong> - These are actions that are reported and
3878 * handled by the standard UI widgets in the platform. For each standard action
3879 * there is a static constant defined in this class, e.g. {@link #ACTION_FOCUS}.
Phil Weaver426361c2017-02-22 13:06:25 -08003880 * These actions will have {@code null} labels.
Kristian Monsen74bc1942014-04-29 11:00:17 -07003881 * </li>
3882 * <li><strong>Custom actions action</strong> - These are actions that are reported
3883 * and handled by custom widgets. i.e. ones that are not part of the UI toolkit. For
3884 * example, an application may define a custom action for clearing the user history.
3885 * </li>
3886 * <li><strong>Overriden standard actions</strong> - These are actions that override
3887 * standard actions to customize them. For example, an app may add a label to the
Casey Burkhardt7ef48be2016-01-31 11:51:09 -08003888 * standard {@link #ACTION_CLICK} action to announce that this action clears browsing history.
Kristian Monsen74bc1942014-04-29 11:00:17 -07003889 * </ul>
3890 * </p>
Casey Burkhardt7ef48be2016-01-31 11:51:09 -08003891 * <p>
3892 * Actions are typically added to an {@link AccessibilityNodeInfo} by using
3893 * {@link AccessibilityNodeInfo#addAction(AccessibilityAction)} within
3894 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} and are performed
3895 * within {@link View#performAccessibilityAction(int, Bundle)}.
3896 * </p>
3897 * <p class="note">
3898 * <strong>Note:</strong> Views which support these actions should invoke
3899 * {@link View#setImportantForAccessibility(int)} with
3900 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_YES} to ensure an {@link AccessibilityService}
3901 * can discover the set of supported actions.
3902 * </p>
Kristian Monsen74bc1942014-04-29 11:00:17 -07003903 */
3904 public static final class AccessibilityAction {
3905
Eugene Susla554edd32017-05-24 16:49:59 -07003906 /** @hide */
3907 public static final ArraySet<AccessibilityAction> sStandardActions = new ArraySet<>();
3908
Kristian Monsen74bc1942014-04-29 11:00:17 -07003909 /**
3910 * Action that gives input focus to the node.
3911 */
3912 public static final AccessibilityAction ACTION_FOCUS =
Eugene Susla554edd32017-05-24 16:49:59 -07003913 new AccessibilityAction(AccessibilityNodeInfo.ACTION_FOCUS);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003914
3915 /**
3916 * Action that clears input focus of the node.
3917 */
3918 public static final AccessibilityAction ACTION_CLEAR_FOCUS =
Eugene Susla554edd32017-05-24 16:49:59 -07003919 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003920
3921 /**
3922 * Action that selects the node.
3923 */
3924 public static final AccessibilityAction ACTION_SELECT =
Eugene Susla554edd32017-05-24 16:49:59 -07003925 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SELECT);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003926
3927 /**
3928 * Action that deselects the node.
3929 */
3930 public static final AccessibilityAction ACTION_CLEAR_SELECTION =
Eugene Susla554edd32017-05-24 16:49:59 -07003931 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003932
3933 /**
3934 * Action that clicks on the node info.
3935 */
3936 public static final AccessibilityAction ACTION_CLICK =
Eugene Susla554edd32017-05-24 16:49:59 -07003937 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003938
3939 /**
3940 * Action that long clicks on the node.
3941 */
3942 public static final AccessibilityAction ACTION_LONG_CLICK =
Eugene Susla554edd32017-05-24 16:49:59 -07003943 new AccessibilityAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003944
3945 /**
3946 * Action that gives accessibility focus to the node.
3947 */
3948 public static final AccessibilityAction ACTION_ACCESSIBILITY_FOCUS =
Eugene Susla554edd32017-05-24 16:49:59 -07003949 new AccessibilityAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003950
3951 /**
3952 * Action that clears accessibility focus of the node.
3953 */
3954 public static final AccessibilityAction ACTION_CLEAR_ACCESSIBILITY_FOCUS =
Eugene Susla554edd32017-05-24 16:49:59 -07003955 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003956
3957 /**
3958 * Action that requests to go to the next entity in this node's text
3959 * at a given movement granularity. For example, move to the next character,
3960 * word, etc.
3961 * <p>
3962 * <strong>Arguments:</strong>
3963 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3964 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT},
3965 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3966 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
3967 * <strong>Example:</strong> Move to the previous character and do not extend selection.
3968 * <code><pre><p>
3969 * Bundle arguments = new Bundle();
3970 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
3971 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
3972 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
3973 * false);
3974 * info.performAction(AccessibilityAction.ACTION_NEXT_AT_MOVEMENT_GRANULARITY.getId(),
3975 * arguments);
3976 * </code></pre></p>
3977 * </p>
3978 *
3979 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3980 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3981 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3982 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3983 *
3984 * @see AccessibilityNodeInfo#setMovementGranularities(int)
3985 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3986 * @see AccessibilityNodeInfo#getMovementGranularities()
3987 * AccessibilityNodeInfo.getMovementGranularities()
3988 *
3989 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_CHARACTER
3990 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
3991 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_WORD
3992 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
3993 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_LINE
3994 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
3995 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PARAGRAPH
3996 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
3997 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PAGE
3998 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE
3999 */
4000 public static final AccessibilityAction ACTION_NEXT_AT_MOVEMENT_GRANULARITY =
Eugene Susla554edd32017-05-24 16:49:59 -07004001 new AccessibilityAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004002
4003 /**
4004 * Action that requests to go to the previous entity in this node's text
4005 * at a given movement granularity. For example, move to the next character,
4006 * word, etc.
4007 * <p>
4008 * <strong>Arguments:</strong>
4009 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
4010 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT},
4011 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
4012 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
4013 * <strong>Example:</strong> Move to the next character and do not extend selection.
4014 * <code><pre><p>
4015 * Bundle arguments = new Bundle();
4016 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
4017 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
4018 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
4019 * false);
4020 * info.performAction(AccessibilityAction.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY.getId(),
4021 * arguments);
4022 * </code></pre></p>
4023 * </p>
4024 *
4025 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
4026 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
4027 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
4028 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
4029 *
4030 * @see AccessibilityNodeInfo#setMovementGranularities(int)
4031 * AccessibilityNodeInfo.setMovementGranularities(int)
4032 * @see AccessibilityNodeInfo#getMovementGranularities()
4033 * AccessibilityNodeInfo.getMovementGranularities()
4034 *
4035 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_CHARACTER
4036 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
4037 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_WORD
4038 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
4039 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_LINE
4040 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
4041 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PARAGRAPH
4042 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
4043 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PAGE
4044 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE
4045 */
4046 public static final AccessibilityAction ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY =
4047 new AccessibilityAction(
Eugene Susla554edd32017-05-24 16:49:59 -07004048 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004049
4050 /**
4051 * Action to move to the next HTML element of a given type. For example, move
4052 * to the BUTTON, INPUT, TABLE, etc.
4053 * <p>
4054 * <strong>Arguments:</strong>
4055 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_HTML_ELEMENT_STRING
4056 * AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
4057 * <strong>Example:</strong>
4058 * <code><pre><p>
4059 * Bundle arguments = new Bundle();
4060 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
4061 * info.performAction(AccessibilityAction.ACTION_NEXT_HTML_ELEMENT.getId(), arguments);
4062 * </code></pre></p>
4063 * </p>
4064 */
4065 public static final AccessibilityAction ACTION_NEXT_HTML_ELEMENT =
Eugene Susla554edd32017-05-24 16:49:59 -07004066 new AccessibilityAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004067
4068 /**
4069 * Action to move to the previous HTML element of a given type. For example, move
4070 * to the BUTTON, INPUT, TABLE, etc.
4071 * <p>
4072 * <strong>Arguments:</strong>
4073 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_HTML_ELEMENT_STRING
4074 * AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
4075 * <strong>Example:</strong>
4076 * <code><pre><p>
4077 * Bundle arguments = new Bundle();
4078 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
4079 * info.performAction(AccessibilityAction.ACTION_PREVIOUS_HTML_ELEMENT.getId(), arguments);
4080 * </code></pre></p>
4081 * </p>
4082 */
4083 public static final AccessibilityAction ACTION_PREVIOUS_HTML_ELEMENT =
Eugene Susla554edd32017-05-24 16:49:59 -07004084 new AccessibilityAction(AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004085
4086 /**
4087 * Action to scroll the node content forward.
4088 */
4089 public static final AccessibilityAction ACTION_SCROLL_FORWARD =
Eugene Susla554edd32017-05-24 16:49:59 -07004090 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004091
4092 /**
4093 * Action to scroll the node content backward.
4094 */
4095 public static final AccessibilityAction ACTION_SCROLL_BACKWARD =
Eugene Susla554edd32017-05-24 16:49:59 -07004096 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004097
4098 /**
4099 * Action to copy the current selection to the clipboard.
4100 */
4101 public static final AccessibilityAction ACTION_COPY =
Eugene Susla554edd32017-05-24 16:49:59 -07004102 new AccessibilityAction(AccessibilityNodeInfo.ACTION_COPY);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004103
4104 /**
4105 * Action to paste the current clipboard content.
4106 */
4107 public static final AccessibilityAction ACTION_PASTE =
Eugene Susla554edd32017-05-24 16:49:59 -07004108 new AccessibilityAction(AccessibilityNodeInfo.ACTION_PASTE);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004109
4110 /**
4111 * Action to cut the current selection and place it to the clipboard.
4112 */
4113 public static final AccessibilityAction ACTION_CUT =
Eugene Susla554edd32017-05-24 16:49:59 -07004114 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CUT);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004115
4116 /**
4117 * Action to set the selection. Performing this action with no arguments
4118 * clears the selection.
4119 * <p>
4120 * <strong>Arguments:</strong>
4121 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_START_INT
4122 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT},
4123 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_END_INT
4124 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT}<br>
4125 * <strong>Example:</strong>
4126 * <code><pre><p>
4127 * Bundle arguments = new Bundle();
4128 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1);
4129 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 2);
4130 * info.performAction(AccessibilityAction.ACTION_SET_SELECTION.getId(), arguments);
4131 * </code></pre></p>
4132 * </p>
4133 *
4134 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_START_INT
4135 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT
4136 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_END_INT
4137 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT
4138 */
4139 public static final AccessibilityAction ACTION_SET_SELECTION =
Eugene Susla554edd32017-05-24 16:49:59 -07004140 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004141
4142 /**
4143 * Action to expand an expandable node.
4144 */
4145 public static final AccessibilityAction ACTION_EXPAND =
Eugene Susla554edd32017-05-24 16:49:59 -07004146 new AccessibilityAction(AccessibilityNodeInfo.ACTION_EXPAND);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004147
4148 /**
4149 * Action to collapse an expandable node.
4150 */
4151 public static final AccessibilityAction ACTION_COLLAPSE =
Eugene Susla554edd32017-05-24 16:49:59 -07004152 new AccessibilityAction(AccessibilityNodeInfo.ACTION_COLLAPSE);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004153
4154 /**
4155 * Action to dismiss a dismissable node.
4156 */
4157 public static final AccessibilityAction ACTION_DISMISS =
Eugene Susla554edd32017-05-24 16:49:59 -07004158 new AccessibilityAction(AccessibilityNodeInfo.ACTION_DISMISS);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004159
4160 /**
4161 * Action that sets the text of the node. Performing the action without argument,
4162 * using <code> null</code> or empty {@link CharSequence} will clear the text. This
4163 * action will also put the cursor at the end of text.
4164 * <p>
4165 * <strong>Arguments:</strong>
4166 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE
4167 * AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br>
4168 * <strong>Example:</strong>
4169 * <code><pre><p>
4170 * Bundle arguments = new Bundle();
4171 * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
4172 * "android");
4173 * info.performAction(AccessibilityAction.ACTION_SET_TEXT.getId(), arguments);
4174 * </code></pre></p>
4175 */
4176 public static final AccessibilityAction ACTION_SET_TEXT =
Eugene Susla554edd32017-05-24 16:49:59 -07004177 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SET_TEXT);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004178
Alan Viverette26c44ee2015-03-25 14:54:13 -07004179 /**
4180 * Action that requests the node make its bounding rectangle visible
4181 * on the screen, scrolling if necessary just enough.
4182 *
4183 * @see View#requestRectangleOnScreen(Rect)
4184 */
4185 public static final AccessibilityAction ACTION_SHOW_ON_SCREEN =
Eugene Susla554edd32017-05-24 16:49:59 -07004186 new AccessibilityAction(R.id.accessibilityActionShowOnScreen);
Alan Viverette26c44ee2015-03-25 14:54:13 -07004187
Alan Viverette23f44322015-04-06 16:04:56 -07004188 /**
4189 * Action that scrolls the node to make the specified collection
4190 * position visible on screen.
4191 * <p>
4192 * <strong>Arguments:</strong>
4193 * <ul>
4194 * <li>{@link AccessibilityNodeInfo#ACTION_ARGUMENT_ROW_INT}</li>
4195 * <li>{@link AccessibilityNodeInfo#ACTION_ARGUMENT_COLUMN_INT}</li>
4196 * <ul>
4197 *
4198 * @see AccessibilityNodeInfo#getCollectionInfo()
4199 */
4200 public static final AccessibilityAction ACTION_SCROLL_TO_POSITION =
Eugene Susla554edd32017-05-24 16:49:59 -07004201 new AccessibilityAction(R.id.accessibilityActionScrollToPosition);
Alan Viverette23f44322015-04-06 16:04:56 -07004202
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004203 /**
4204 * Action to scroll the node content up.
4205 */
4206 public static final AccessibilityAction ACTION_SCROLL_UP =
Eugene Susla554edd32017-05-24 16:49:59 -07004207 new AccessibilityAction(R.id.accessibilityActionScrollUp);
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004208
4209 /**
4210 * Action to scroll the node content left.
4211 */
4212 public static final AccessibilityAction ACTION_SCROLL_LEFT =
Eugene Susla554edd32017-05-24 16:49:59 -07004213 new AccessibilityAction(R.id.accessibilityActionScrollLeft);
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004214
4215 /**
4216 * Action to scroll the node content down.
4217 */
4218 public static final AccessibilityAction ACTION_SCROLL_DOWN =
Eugene Susla554edd32017-05-24 16:49:59 -07004219 new AccessibilityAction(R.id.accessibilityActionScrollDown);
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004220
4221 /**
4222 * Action to scroll the node content right.
4223 */
Maxim Bogatov32e59d52015-04-30 16:57:33 -07004224 public static final AccessibilityAction ACTION_SCROLL_RIGHT =
Eugene Susla554edd32017-05-24 16:49:59 -07004225 new AccessibilityAction(R.id.accessibilityActionScrollRight);
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004226
Mady Mellord2744002015-04-30 16:17:16 -07004227 /**
Mady Mellore8608912015-06-05 09:02:55 -07004228 * Action that context clicks the node.
Mady Mellore82067b2015-04-30 09:58:35 -07004229 */
Mady Mellore8608912015-06-05 09:02:55 -07004230 public static final AccessibilityAction ACTION_CONTEXT_CLICK =
Eugene Susla554edd32017-05-24 16:49:59 -07004231 new AccessibilityAction(R.id.accessibilityActionContextClick);
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004232
Maxim Bogatov32e59d52015-04-30 16:57:33 -07004233 /**
4234 * Action that sets progress between {@link RangeInfo#getMin() RangeInfo.getMin()} and
4235 * {@link RangeInfo#getMax() RangeInfo.getMax()}. It should use the same value type as
4236 * {@link RangeInfo#getType() RangeInfo.getType()}
4237 * <p>
4238 * <strong>Arguments:</strong>
4239 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_PROGRESS_VALUE}
4240 *
4241 * @see RangeInfo
4242 */
4243 public static final AccessibilityAction ACTION_SET_PROGRESS =
Eugene Susla554edd32017-05-24 16:49:59 -07004244 new AccessibilityAction(R.id.accessibilityActionSetProgress);
Maxim Bogatov32e59d52015-04-30 16:57:33 -07004245
Phil Weaverf00cd142017-03-03 13:44:00 -08004246 /**
4247 * Action to move a window to a new location.
4248 * <p>
4249 * <strong>Arguments:</strong>
4250 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVE_WINDOW_X}
4251 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVE_WINDOW_Y}
4252 */
4253 public static final AccessibilityAction ACTION_MOVE_WINDOW =
Eugene Susla554edd32017-05-24 16:49:59 -07004254 new AccessibilityAction(R.id.accessibilityActionMoveWindow);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004255
Phil Weaverd89905f2018-01-10 08:28:04 -08004256 /**
4257 * Action to show a tooltip. A node should expose this action only for views with tooltip
4258 * text that but are not currently showing a tooltip.
4259 */
4260 public static final AccessibilityAction ACTION_SHOW_TOOLTIP =
4261 new AccessibilityAction(R.id.accessibilityActionShowTooltip);
4262
4263 /**
4264 * Action to hide a tooltip. A node should expose this action only for views that are
4265 * currently showing a tooltip.
4266 */
4267 public static final AccessibilityAction ACTION_HIDE_TOOLTIP =
4268 new AccessibilityAction(R.id.accessibilityActionHideTooltip);
4269
Kristian Monsen74bc1942014-04-29 11:00:17 -07004270 private final int mActionId;
4271 private final CharSequence mLabel;
4272
Eugene Susla554edd32017-05-24 16:49:59 -07004273 /** @hide */
4274 public int mSerializationFlag = -1;
4275
Kristian Monsen74bc1942014-04-29 11:00:17 -07004276 /**
4277 * Creates a new AccessibilityAction. For adding a standard action without a specific label,
4278 * use the static constants.
4279 *
4280 * You can also override the description for one the standard actions. Below is an example
4281 * how to override the standard click action by adding a custom label:
4282 * <pre>
4283 * AccessibilityAction action = new AccessibilityAction(
Phil Weaverc3791292016-09-12 11:06:49 -07004284 * AccessibilityAction.ACTION_CLICK.getId(), getLocalizedLabel());
Kristian Monsen74bc1942014-04-29 11:00:17 -07004285 * node.addAction(action);
4286 * </pre>
4287 *
4288 * @param actionId The id for this action. This should either be one of the
4289 * standard actions or a specific action for your app. In that case it is
4290 * required to use a resource identifier.
4291 * @param label The label for the new AccessibilityAction.
4292 */
4293 public AccessibilityAction(int actionId, @Nullable CharSequence label) {
Svetoslav5c4cd182014-05-21 14:53:16 -07004294 if ((actionId & ACTION_TYPE_MASK) == 0 && Integer.bitCount(actionId) != 1) {
Kristian Monsen74bc1942014-04-29 11:00:17 -07004295 throw new IllegalArgumentException("Invalid standard action id");
4296 }
4297
Kristian Monsen74bc1942014-04-29 11:00:17 -07004298 mActionId = actionId;
4299 mLabel = label;
4300 }
4301
4302 /**
Eugene Susla554edd32017-05-24 16:49:59 -07004303 * Constructor for a {@link #sStandardActions standard} action
4304 */
4305 private AccessibilityAction(int standardActionId) {
4306 this(standardActionId, null);
4307
4308 mSerializationFlag = (int) bitAt(sStandardActions.size());
4309 sStandardActions.add(this);
4310 }
4311
4312 /**
Kristian Monsen74bc1942014-04-29 11:00:17 -07004313 * Gets the id for this action.
4314 *
4315 * @return The action id.
4316 */
4317 public int getId() {
4318 return mActionId;
4319 }
4320
4321 /**
4322 * Gets the label for this action. Its purpose is to describe the
4323 * action to user.
4324 *
4325 * @return The label.
4326 */
4327 public CharSequence getLabel() {
4328 return mLabel;
4329 }
4330
4331 @Override
4332 public int hashCode() {
4333 return mActionId;
4334 }
4335
4336 @Override
4337 public boolean equals(Object other) {
4338 if (other == null) {
4339 return false;
4340 }
4341
4342 if (other == this) {
4343 return true;
4344 }
4345
4346 if (getClass() != other.getClass()) {
4347 return false;
4348 }
4349
4350 return mActionId == ((AccessibilityAction)other).mActionId;
4351 }
4352
4353 @Override
4354 public String toString() {
4355 return "AccessibilityAction: " + getActionSymbolicName(mActionId) + " - " + mLabel;
4356 }
4357 }
4358
4359 /**
Svetoslav3577a282013-06-06 14:09:10 -07004360 * Class with information if a node is a range. Use
Phil Weaver764152b2016-07-19 11:32:27 -07004361 * {@link RangeInfo#obtain(int, float, float, float)} to get an instance. Recycling is
4362 * handled by the {@link AccessibilityNodeInfo} to which this object is attached.
Svetoslav3577a282013-06-06 14:09:10 -07004363 */
4364 public static final class RangeInfo {
4365 private static final int MAX_POOL_SIZE = 10;
4366
4367 /** Range type: integer. */
4368 public static final int RANGE_TYPE_INT = 0;
4369 /** Range type: float. */
4370 public static final int RANGE_TYPE_FLOAT = 1;
4371 /** Range type: percent with values from zero to one.*/
4372 public static final int RANGE_TYPE_PERCENT = 2;
4373
4374 private static final SynchronizedPool<RangeInfo> sPool =
4375 new SynchronizedPool<AccessibilityNodeInfo.RangeInfo>(MAX_POOL_SIZE);
4376
4377 private int mType;
4378 private float mMin;
4379 private float mMax;
4380 private float mCurrent;
4381
4382 /**
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004383 * Obtains a pooled instance that is a clone of another one.
4384 *
4385 * @param other The instance to clone.
4386 *
4387 * @hide
4388 */
4389 public static RangeInfo obtain(RangeInfo other) {
4390 return obtain(other.mType, other.mMin, other.mMax, other.mCurrent);
4391 }
4392
4393 /**
Svetoslav3577a282013-06-06 14:09:10 -07004394 * Obtains a pooled instance.
4395 *
4396 * @param type The type of the range.
Phil Weaver79e44192016-12-19 14:24:49 -08004397 * @param min The minimum value. Use {@code Float.NEGATIVE_INFINITY} if the range has no
4398 * minimum.
4399 * @param max The maximum value. Use {@code Float.POSITIVE_INFINITY} if the range has no
4400 * maximum.
Svetoslav3577a282013-06-06 14:09:10 -07004401 * @param current The current value.
4402 */
4403 public static RangeInfo obtain(int type, float min, float max, float current) {
4404 RangeInfo info = sPool.acquire();
Steven Dao24142812016-04-13 15:25:09 -07004405 if (info == null) {
4406 return new RangeInfo(type, min, max, current);
4407 }
4408
4409 info.mType = type;
4410 info.mMin = min;
4411 info.mMax = max;
4412 info.mCurrent = current;
4413 return info;
Svetoslav3577a282013-06-06 14:09:10 -07004414 }
4415
4416 /**
4417 * Creates a new range.
4418 *
4419 * @param type The type of the range.
Phil Weaver79e44192016-12-19 14:24:49 -08004420 * @param min The minimum value. Use {@code Float.NEGATIVE_INFINITY} if the range has no
4421 * minimum.
4422 * @param max The maximum value. Use {@code Float.POSITIVE_INFINITY} if the range has no
4423 * maximum.
Svetoslav3577a282013-06-06 14:09:10 -07004424 * @param current The current value.
4425 */
4426 private RangeInfo(int type, float min, float max, float current) {
4427 mType = type;
4428 mMin = min;
4429 mMax = max;
4430 mCurrent = current;
4431 }
4432
4433 /**
4434 * Gets the range type.
4435 *
4436 * @return The range type.
4437 *
4438 * @see #RANGE_TYPE_INT
4439 * @see #RANGE_TYPE_FLOAT
4440 * @see #RANGE_TYPE_PERCENT
4441 */
4442 public int getType() {
4443 return mType;
4444 }
4445
4446 /**
Phil Weaver79e44192016-12-19 14:24:49 -08004447 * Gets the minimum value.
Svetoslav3577a282013-06-06 14:09:10 -07004448 *
Phil Weaver79e44192016-12-19 14:24:49 -08004449 * @return The minimum value, or {@code Float.NEGATIVE_INFINITY} if no minimum exists.
Svetoslav3577a282013-06-06 14:09:10 -07004450 */
4451 public float getMin() {
4452 return mMin;
4453 }
4454
4455 /**
Phil Weaver79e44192016-12-19 14:24:49 -08004456 * Gets the maximum value.
Svetoslav3577a282013-06-06 14:09:10 -07004457 *
Phil Weaver79e44192016-12-19 14:24:49 -08004458 * @return The maximum value, or {@code Float.POSITIVE_INFINITY} if no maximum exists.
Svetoslav3577a282013-06-06 14:09:10 -07004459 */
4460 public float getMax() {
4461 return mMax;
4462 }
4463
4464 /**
4465 * Gets the current value.
4466 *
4467 * @return The current value.
4468 */
4469 public float getCurrent() {
4470 return mCurrent;
4471 }
4472
4473 /**
4474 * Recycles this instance.
4475 */
4476 void recycle() {
4477 clear();
4478 sPool.release(this);
4479 }
4480
4481 private void clear() {
4482 mType = 0;
4483 mMin = 0;
4484 mMax = 0;
4485 mCurrent = 0;
4486 }
4487 }
4488
4489 /**
4490 * Class with information if a node is a collection. Use
Phil Weaver764152b2016-07-19 11:32:27 -07004491 * {@link CollectionInfo#obtain(int, int, boolean)} to get an instance. Recycling is
4492 * handled by the {@link AccessibilityNodeInfo} to which this object is attached.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004493 * <p>
4494 * A collection of items has rows and columns and may be hierarchical.
4495 * For example, a horizontal list is a collection with one column, as
4496 * many rows as the list items, and is not hierarchical; A table is a
4497 * collection with several rows, several columns, and is not hierarchical;
4498 * A vertical tree is a hierarchical collection with one column and
4499 * as many rows as the first level children.
4500 * </p>
Svetoslav3577a282013-06-06 14:09:10 -07004501 */
4502 public static final class CollectionInfo {
Alan Viverette76769ae2014-02-12 16:38:10 -08004503 /** Selection mode where items are not selectable. */
4504 public static final int SELECTION_MODE_NONE = 0;
4505
4506 /** Selection mode where a single item may be selected. */
4507 public static final int SELECTION_MODE_SINGLE = 1;
4508
4509 /** Selection mode where multiple items may be selected. */
4510 public static final int SELECTION_MODE_MULTIPLE = 2;
4511
Svetoslav3577a282013-06-06 14:09:10 -07004512 private static final int MAX_POOL_SIZE = 20;
4513
4514 private static final SynchronizedPool<CollectionInfo> sPool =
Alan Viverette23f44322015-04-06 16:04:56 -07004515 new SynchronizedPool<>(MAX_POOL_SIZE);
Svetoslav3577a282013-06-06 14:09:10 -07004516
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004517 private int mRowCount;
4518 private int mColumnCount;
Svetoslav3577a282013-06-06 14:09:10 -07004519 private boolean mHierarchical;
Alan Viverette76769ae2014-02-12 16:38:10 -08004520 private int mSelectionMode;
Svetoslav3577a282013-06-06 14:09:10 -07004521
4522 /**
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004523 * Obtains a pooled instance that is a clone of another one.
4524 *
4525 * @param other The instance to clone.
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004526 * @hide
4527 */
4528 public static CollectionInfo obtain(CollectionInfo other) {
Alan Viverette76769ae2014-02-12 16:38:10 -08004529 return CollectionInfo.obtain(other.mRowCount, other.mColumnCount, other.mHierarchical,
4530 other.mSelectionMode);
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004531 }
4532
4533 /**
Svetoslav3577a282013-06-06 14:09:10 -07004534 * Obtains a pooled instance.
4535 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004536 * @param rowCount The number of rows.
4537 * @param columnCount The number of columns.
Svetoslav3577a282013-06-06 14:09:10 -07004538 * @param hierarchical Whether the collection is hierarchical.
4539 */
Alan Viverette76769ae2014-02-12 16:38:10 -08004540 public static CollectionInfo obtain(int rowCount, int columnCount,
4541 boolean hierarchical) {
4542 return obtain(rowCount, columnCount, hierarchical, SELECTION_MODE_NONE);
4543 }
4544
4545 /**
4546 * Obtains a pooled instance.
4547 *
4548 * @param rowCount The number of rows.
4549 * @param columnCount The number of columns.
4550 * @param hierarchical Whether the collection is hierarchical.
4551 * @param selectionMode The collection's selection mode, one of:
4552 * <ul>
4553 * <li>{@link #SELECTION_MODE_NONE}
4554 * <li>{@link #SELECTION_MODE_SINGLE}
4555 * <li>{@link #SELECTION_MODE_MULTIPLE}
4556 * </ul>
4557 */
4558 public static CollectionInfo obtain(int rowCount, int columnCount,
4559 boolean hierarchical, int selectionMode) {
4560 final CollectionInfo info = sPool.acquire();
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004561 if (info == null) {
Alan Viverette76769ae2014-02-12 16:38:10 -08004562 return new CollectionInfo(rowCount, columnCount, hierarchical, selectionMode);
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004563 }
4564
4565 info.mRowCount = rowCount;
4566 info.mColumnCount = columnCount;
4567 info.mHierarchical = hierarchical;
Alan Viverette76769ae2014-02-12 16:38:10 -08004568 info.mSelectionMode = selectionMode;
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004569 return info;
Svetoslav3577a282013-06-06 14:09:10 -07004570 }
4571
4572 /**
4573 * Creates a new instance.
4574 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004575 * @param rowCount The number of rows.
4576 * @param columnCount The number of columns.
Svetoslav3577a282013-06-06 14:09:10 -07004577 * @param hierarchical Whether the collection is hierarchical.
Alan Viverette76769ae2014-02-12 16:38:10 -08004578 * @param selectionMode The collection's selection mode.
Svetoslav3577a282013-06-06 14:09:10 -07004579 */
Alan Viverette76769ae2014-02-12 16:38:10 -08004580 private CollectionInfo(int rowCount, int columnCount, boolean hierarchical,
4581 int selectionMode) {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004582 mRowCount = rowCount;
4583 mColumnCount = columnCount;
Svetoslav3577a282013-06-06 14:09:10 -07004584 mHierarchical = hierarchical;
Alan Viverette76769ae2014-02-12 16:38:10 -08004585 mSelectionMode = selectionMode;
Svetoslav3577a282013-06-06 14:09:10 -07004586 }
4587
4588 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004589 * Gets the number of rows.
Svetoslav3577a282013-06-06 14:09:10 -07004590 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004591 * @return The row count.
Svetoslav3577a282013-06-06 14:09:10 -07004592 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004593 public int getRowCount() {
4594 return mRowCount;
Svetoslav3577a282013-06-06 14:09:10 -07004595 }
4596
4597 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004598 * Gets the number of columns.
Svetoslav3577a282013-06-06 14:09:10 -07004599 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004600 * @return The column count.
Svetoslav3577a282013-06-06 14:09:10 -07004601 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004602 public int getColumnCount() {
4603 return mColumnCount;
Svetoslav3577a282013-06-06 14:09:10 -07004604 }
4605
4606 /**
4607 * Gets if the collection is a hierarchically ordered.
4608 *
4609 * @return Whether the collection is hierarchical.
4610 */
4611 public boolean isHierarchical() {
4612 return mHierarchical;
4613 }
4614
4615 /**
Alan Viverette76769ae2014-02-12 16:38:10 -08004616 * Gets the collection's selection mode.
4617 *
4618 * @return The collection's selection mode, one of:
4619 * <ul>
4620 * <li>{@link #SELECTION_MODE_NONE}
4621 * <li>{@link #SELECTION_MODE_SINGLE}
4622 * <li>{@link #SELECTION_MODE_MULTIPLE}
4623 * </ul>
4624 */
4625 public int getSelectionMode() {
4626 return mSelectionMode;
4627 }
4628
4629 /**
Svetoslav3577a282013-06-06 14:09:10 -07004630 * Recycles this instance.
4631 */
4632 void recycle() {
4633 clear();
4634 sPool.release(this);
4635 }
4636
4637 private void clear() {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004638 mRowCount = 0;
4639 mColumnCount = 0;
Svetoslav3577a282013-06-06 14:09:10 -07004640 mHierarchical = false;
Alan Viverette76769ae2014-02-12 16:38:10 -08004641 mSelectionMode = SELECTION_MODE_NONE;
Svetoslav3577a282013-06-06 14:09:10 -07004642 }
4643 }
4644
4645 /**
4646 * Class with information if a node is a collection item. Use
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004647 * {@link CollectionItemInfo#obtain(int, int, int, int, boolean)}
Phil Weaver764152b2016-07-19 11:32:27 -07004648 * to get an instance. Recycling is handled by the {@link AccessibilityNodeInfo} to which this
4649 * object is attached.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004650 * <p>
4651 * A collection item is contained in a collection, it starts at
4652 * a given row and column in the collection, and spans one or
4653 * more rows and columns. For example, a header of two related
4654 * table columns starts at the first row and the first column,
4655 * spans one row and two columns.
4656 * </p>
Svetoslav3577a282013-06-06 14:09:10 -07004657 */
4658 public static final class CollectionItemInfo {
4659 private static final int MAX_POOL_SIZE = 20;
4660
4661 private static final SynchronizedPool<CollectionItemInfo> sPool =
Alan Viverette23f44322015-04-06 16:04:56 -07004662 new SynchronizedPool<>(MAX_POOL_SIZE);
Svetoslav3577a282013-06-06 14:09:10 -07004663
4664 /**
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004665 * Obtains a pooled instance that is a clone of another one.
4666 *
4667 * @param other The instance to clone.
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004668 * @hide
4669 */
4670 public static CollectionItemInfo obtain(CollectionItemInfo other) {
Alan Viverette76769ae2014-02-12 16:38:10 -08004671 return CollectionItemInfo.obtain(other.mRowIndex, other.mRowSpan, other.mColumnIndex,
4672 other.mColumnSpan, other.mHeading, other.mSelected);
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004673 }
4674
4675 /**
Svetoslav3577a282013-06-06 14:09:10 -07004676 * Obtains a pooled instance.
4677 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004678 * @param rowIndex The row index at which the item is located.
4679 * @param rowSpan The number of rows the item spans.
4680 * @param columnIndex The column index at which the item is located.
4681 * @param columnSpan The number of columns the item spans.
Phil Weaver6290fb592018-01-08 17:42:18 -08004682 * @param heading Whether the item is a heading. (Prefer
4683 * {@link AccessibilityNodeInfo#setHeading(boolean)}).
Svetoslav3577a282013-06-06 14:09:10 -07004684 */
Alan Viverette76769ae2014-02-12 16:38:10 -08004685 public static CollectionItemInfo obtain(int rowIndex, int rowSpan,
4686 int columnIndex, int columnSpan, boolean heading) {
4687 return obtain(rowIndex, rowSpan, columnIndex, columnSpan, heading, false);
4688 }
4689
4690 /**
4691 * Obtains a pooled instance.
4692 *
4693 * @param rowIndex The row index at which the item is located.
4694 * @param rowSpan The number of rows the item spans.
4695 * @param columnIndex The column index at which the item is located.
4696 * @param columnSpan The number of columns the item spans.
Phil Weaver6290fb592018-01-08 17:42:18 -08004697 * @param heading Whether the item is a heading. (Prefer
4698 * {@link AccessibilityNodeInfo#setHeading(boolean)})
Alan Viverette76769ae2014-02-12 16:38:10 -08004699 * @param selected Whether the item is selected.
4700 */
4701 public static CollectionItemInfo obtain(int rowIndex, int rowSpan,
4702 int columnIndex, int columnSpan, boolean heading, boolean selected) {
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004703 final CollectionItemInfo info = sPool.acquire();
4704 if (info == null) {
Alan Viverette76769ae2014-02-12 16:38:10 -08004705 return new CollectionItemInfo(
4706 rowIndex, rowSpan, columnIndex, columnSpan, heading, selected);
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004707 }
4708
4709 info.mRowIndex = rowIndex;
4710 info.mRowSpan = rowSpan;
4711 info.mColumnIndex = columnIndex;
4712 info.mColumnSpan = columnSpan;
4713 info.mHeading = heading;
Alan Viverette76769ae2014-02-12 16:38:10 -08004714 info.mSelected = selected;
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004715 return info;
Svetoslav3577a282013-06-06 14:09:10 -07004716 }
4717
4718 private boolean mHeading;
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004719 private int mColumnIndex;
4720 private int mRowIndex;
4721 private int mColumnSpan;
4722 private int mRowSpan;
Alan Viverette76769ae2014-02-12 16:38:10 -08004723 private boolean mSelected;
Svetoslav3577a282013-06-06 14:09:10 -07004724
4725 /**
4726 * Creates a new instance.
4727 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004728 * @param rowIndex The row index at which the item is located.
4729 * @param rowSpan The number of rows the item spans.
4730 * @param columnIndex The column index at which the item is located.
4731 * @param columnSpan The number of columns the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07004732 * @param heading Whether the item is a heading.
4733 */
Alan Viverette76769ae2014-02-12 16:38:10 -08004734 private CollectionItemInfo(int rowIndex, int rowSpan, int columnIndex, int columnSpan,
4735 boolean heading, boolean selected) {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004736 mRowIndex = rowIndex;
4737 mRowSpan = rowSpan;
4738 mColumnIndex = columnIndex;
4739 mColumnSpan = columnSpan;
Svetoslav3577a282013-06-06 14:09:10 -07004740 mHeading = heading;
Alan Viverette76769ae2014-02-12 16:38:10 -08004741 mSelected = selected;
Svetoslav3577a282013-06-06 14:09:10 -07004742 }
4743
4744 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004745 * Gets the column index at which the item is located.
Svetoslav3577a282013-06-06 14:09:10 -07004746 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004747 * @return The column index.
Svetoslav3577a282013-06-06 14:09:10 -07004748 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004749 public int getColumnIndex() {
4750 return mColumnIndex;
Svetoslav3577a282013-06-06 14:09:10 -07004751 }
4752
4753 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004754 * Gets the row index at which the item is located.
Svetoslav3577a282013-06-06 14:09:10 -07004755 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004756 * @return The row index.
Svetoslav3577a282013-06-06 14:09:10 -07004757 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004758 public int getRowIndex() {
4759 return mRowIndex;
Svetoslav3577a282013-06-06 14:09:10 -07004760 }
4761
4762 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004763 * Gets the number of columns the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07004764 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004765 * @return The column span.
Svetoslav3577a282013-06-06 14:09:10 -07004766 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004767 public int getColumnSpan() {
4768 return mColumnSpan;
Svetoslav3577a282013-06-06 14:09:10 -07004769 }
4770
4771 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004772 * Gets the number of rows the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07004773 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004774 * @return The row span.
Svetoslav3577a282013-06-06 14:09:10 -07004775 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004776 public int getRowSpan() {
4777 return mRowSpan;
Svetoslav3577a282013-06-06 14:09:10 -07004778 }
4779
4780 /**
4781 * Gets if the collection item is a heading. For example, section
4782 * heading, table header, etc.
4783 *
4784 * @return If the item is a heading.
Phil Weaver6290fb592018-01-08 17:42:18 -08004785 * @deprecated Use {@link AccessibilityNodeInfo#isHeading()}
Svetoslav3577a282013-06-06 14:09:10 -07004786 */
4787 public boolean isHeading() {
4788 return mHeading;
4789 }
4790
4791 /**
Alan Viverette76769ae2014-02-12 16:38:10 -08004792 * Gets if the collection item is selected.
4793 *
4794 * @return If the item is selected.
4795 */
4796 public boolean isSelected() {
4797 return mSelected;
4798 }
4799
4800 /**
Svetoslav3577a282013-06-06 14:09:10 -07004801 * Recycles this instance.
4802 */
4803 void recycle() {
4804 clear();
4805 sPool.release(this);
4806 }
4807
4808 private void clear() {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004809 mColumnIndex = 0;
4810 mColumnSpan = 0;
4811 mRowIndex = 0;
4812 mRowSpan = 0;
Svetoslav3577a282013-06-06 14:09:10 -07004813 mHeading = false;
Alan Viverette76769ae2014-02-12 16:38:10 -08004814 mSelected = false;
Svetoslav3577a282013-06-06 14:09:10 -07004815 }
4816 }
4817
4818 /**
Alan Viverettef0aed092013-11-06 15:33:03 -08004819 * @see android.os.Parcelable.Creator
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004820 */
4821 public static final Parcelable.Creator<AccessibilityNodeInfo> CREATOR =
4822 new Parcelable.Creator<AccessibilityNodeInfo>() {
Alan Viverettef0aed092013-11-06 15:33:03 -08004823 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004824 public AccessibilityNodeInfo createFromParcel(Parcel parcel) {
4825 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
4826 info.initFromParcel(parcel);
4827 return info;
4828 }
4829
Alan Viverettef0aed092013-11-06 15:33:03 -08004830 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004831 public AccessibilityNodeInfo[] newArray(int size) {
4832 return new AccessibilityNodeInfo[size];
4833 }
4834 };
4835}