blob: 53efe1833db1cac5aed3d246c70ac74236ad5a8f [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 Weaver776afc22016-12-21 10:55:13 -0800638 private static final int BOOLEAN_PROPERTY_IS_SHOWING_HINT = 0x0100000;
639
Svetoslav Ganov02107852011-10-03 17:06:56 -0700640 /**
641 * Bits that provide the id of a virtual descendant of a view.
642 */
643 private static final long VIRTUAL_DESCENDANT_ID_MASK = 0xffffffff00000000L;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700644 /**
645 * Bit shift of {@link #VIRTUAL_DESCENDANT_ID_MASK} to get to the id for a
646 * virtual descendant of a view. Such a descendant does not exist in the view
647 * hierarchy and is only reported via the accessibility APIs.
648 */
649 private static final int VIRTUAL_DESCENDANT_ID_SHIFT = 32;
650
Phil Weaver62d20fa2016-09-15 11:05:55 -0700651 private static AtomicInteger sNumInstancesInUse;
Phil Weaverb010b122016-08-17 17:47:48 -0700652
Svetoslav Ganov02107852011-10-03 17:06:56 -0700653 /**
654 * Gets the accessibility view id which identifies a View in the view three.
655 *
656 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}.
657 * @return The accessibility view id part of the node id.
658 *
659 * @hide
660 */
661 public static int getAccessibilityViewId(long accessibilityNodeId) {
662 return (int) accessibilityNodeId;
663 }
664
665 /**
666 * Gets the virtual descendant id which identifies an imaginary view in a
667 * containing View.
668 *
669 * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}.
670 * @return The virtual view id part of the node id.
671 *
672 * @hide
673 */
674 public static int getVirtualDescendantId(long accessibilityNodeId) {
675 return (int) ((accessibilityNodeId & VIRTUAL_DESCENDANT_ID_MASK)
676 >> VIRTUAL_DESCENDANT_ID_SHIFT);
677 }
678
679 /**
680 * Makes a node id by shifting the <code>virtualDescendantId</code>
681 * by {@link #VIRTUAL_DESCENDANT_ID_SHIFT} and taking
682 * the bitwise or with the <code>accessibilityViewId</code>.
683 *
684 * @param accessibilityViewId A View accessibility id.
685 * @param virtualDescendantId A virtual descendant id.
686 * @return The node id.
687 *
688 * @hide
689 */
690 public static long makeNodeId(int accessibilityViewId, int virtualDescendantId) {
691 return (((long) virtualDescendantId) << VIRTUAL_DESCENDANT_ID_SHIFT) | accessibilityViewId;
692 }
693
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700694 // Housekeeping.
695 private static final int MAX_POOL_SIZE = 50;
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -0800696 private static final SynchronizedPool<AccessibilityNodeInfo> sPool =
Alan Viverette23f44322015-04-06 16:04:56 -0700697 new SynchronizedPool<>(MAX_POOL_SIZE);
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -0800698
Eugene Susla0eb2b6e2017-05-15 14:06:32 -0700699 private static final AccessibilityNodeInfo DEFAULT = new AccessibilityNodeInfo();
700
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700701 private boolean mSealed;
702
703 // Data.
Phil Weaver23161e72017-04-19 12:16:36 -0700704 private int mWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
Phil Weaverf00cd142017-03-03 13:44:00 -0800705 private long mSourceNodeId = UNDEFINED_NODE_ID;
706 private long mParentNodeId = UNDEFINED_NODE_ID;
707 private long mLabelForId = UNDEFINED_NODE_ID;
708 private long mLabeledById = UNDEFINED_NODE_ID;
709 private long mTraversalBefore = UNDEFINED_NODE_ID;
710 private long mTraversalAfter = UNDEFINED_NODE_ID;
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800711
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700712 private int mBooleanProperties;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700713 private final Rect mBoundsInParent = new Rect();
714 private final Rect mBoundsInScreen = new Rect();
Phil Weaver1f222542016-01-08 11:49:32 -0800715 private int mDrawingOrderInParent;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700716
717 private CharSequence mPackageName;
718 private CharSequence mClassName;
Phil Weaver193520e2016-12-13 09:39:06 -0800719 // Hidden, unparceled value used to hold the original value passed to setText
720 private CharSequence mOriginalText;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700721 private CharSequence mText;
Phil Weaver776afc22016-12-21 10:55:13 -0800722 private CharSequence mHintText;
Alan Viverettefccbff52014-07-07 15:06:14 -0700723 private CharSequence mError;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700724 private CharSequence mContentDescription;
Svetoslav9fa1ee52013-04-22 12:43:03 -0700725 private String mViewIdResourceName;
Phil Weaverc2e28932016-12-08 12:29:25 -0800726 private ArrayList<String> mExtraDataKeys;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700727
Alan Viverettef0aed092013-11-06 15:33:03 -0800728 private LongArray mChildNodeIds;
Kristian Monsen74bc1942014-04-29 11:00:17 -0700729 private ArrayList<AccessibilityAction> mActions;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700730
Alan Viverette029942f2014-08-12 14:55:56 -0700731 private int mMaxTextLength = -1;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -0700732 private int mMovementGranularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -0700733
Svetoslav8e3feb12014-02-24 13:46:47 -0800734 private int mTextSelectionStart = UNDEFINED_SELECTION_INDEX;
735 private int mTextSelectionEnd = UNDEFINED_SELECTION_INDEX;
Svetoslav6254f482013-06-04 17:22:14 -0700736 private int mInputType = InputType.TYPE_NULL;
Alan Viverette77e9a282013-09-12 17:16:09 -0700737 private int mLiveRegion = View.ACCESSIBILITY_LIVE_REGION_NONE;
Svetoslav6254f482013-06-04 17:22:14 -0700738
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -0700739 private Bundle mExtras;
Svetoslavbcc46a02013-02-06 11:56:00 -0800740
Svetoslav8e3feb12014-02-24 13:46:47 -0800741 private int mConnectionId = UNDEFINED_CONNECTION_ID;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700742
Svetoslav3577a282013-06-06 14:09:10 -0700743 private RangeInfo mRangeInfo;
744 private CollectionInfo mCollectionInfo;
745 private CollectionItemInfo mCollectionItemInfo;
746
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700747 /**
748 * Hide constructor from clients.
749 */
750 private AccessibilityNodeInfo() {
751 /* do nothing */
752 }
753
754 /**
755 * Sets the source.
Svetoslav Ganov02107852011-10-03 17:06:56 -0700756 * <p>
757 * <strong>Note:</strong> Cannot be called from an
758 * {@link android.accessibilityservice.AccessibilityService}.
759 * This class is made immutable before being delivered to an AccessibilityService.
760 * </p>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700761 *
762 * @param source The info source.
763 */
764 public void setSource(View source) {
Phil Weaverf00cd142017-03-03 13:44:00 -0800765 setSource(source, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov02107852011-10-03 17:06:56 -0700766 }
767
768 /**
769 * Sets the source to be a virtual descendant of the given <code>root</code>.
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700770 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
Svetoslav Ganov02107852011-10-03 17:06:56 -0700771 * is set as the source.
772 * <p>
773 * A virtual descendant is an imaginary View that is reported as a part of the view
774 * hierarchy for accessibility purposes. This enables custom views that draw complex
Svetoslav Ganov71b4e712011-10-25 11:31:31 -0700775 * content to report themselves as a tree of virtual views, thus conveying their
Svetoslav Ganov02107852011-10-03 17:06:56 -0700776 * logical structure.
777 * </p>
778 * <p>
779 * <strong>Note:</strong> Cannot be called from an
780 * {@link android.accessibilityservice.AccessibilityService}.
781 * This class is made immutable before being delivered to an AccessibilityService.
782 * </p>
783 *
784 * @param root The root of the virtual subtree.
785 * @param virtualDescendantId The id of the virtual descendant.
786 */
787 public void setSource(View root, int virtualDescendantId) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700788 enforceNotSealed();
Svetoslav8e3feb12014-02-24 13:46:47 -0800789 mWindowId = (root != null) ? root.getAccessibilityWindowId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700790 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -0800791 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700792 mSourceNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700793 }
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700794
Svetoslav Ganov42138042012-03-20 11:51:39 -0700795 /**
Svetoslav Ganov005b83b2012-04-16 18:17:17 -0700796 * Find the view that has the specified focus type. The search starts from
Svetoslav Ganov42138042012-03-20 11:51:39 -0700797 * the view represented by this node info.
798 *
799 * @param focus The focus to find. One of {@link #FOCUS_INPUT} or
800 * {@link #FOCUS_ACCESSIBILITY}.
801 * @return The node info of the focused view or null.
802 *
803 * @see #FOCUS_INPUT
804 * @see #FOCUS_ACCESSIBILITY
805 */
806 public AccessibilityNodeInfo findFocus(int focus) {
807 enforceSealed();
Svetoslav Ganov2ef69052012-06-04 08:55:16 -0700808 enforceValidFocusType(focus);
Svetoslav Ganov42138042012-03-20 11:51:39 -0700809 if (!canPerformRequestOverConnection(mSourceNodeId)) {
810 return null;
811 }
812 return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId, mWindowId,
813 mSourceNodeId, focus);
814 }
815
816 /**
817 * Searches for the nearest view in the specified direction that can take
818 * the input focus.
819 *
820 * @param direction The direction. Can be one of:
821 * {@link View#FOCUS_DOWN},
822 * {@link View#FOCUS_UP},
823 * {@link View#FOCUS_LEFT},
824 * {@link View#FOCUS_RIGHT},
825 * {@link View#FOCUS_FORWARD},
Svetoslav Ganov8ffe8b32012-06-15 10:31:31 -0700826 * {@link View#FOCUS_BACKWARD}.
Svetoslav Ganov42138042012-03-20 11:51:39 -0700827 *
828 * @return The node info for the view that can take accessibility focus.
829 */
830 public AccessibilityNodeInfo focusSearch(int direction) {
831 enforceSealed();
Svetoslav Ganov2ef69052012-06-04 08:55:16 -0700832 enforceValidFocusDirection(direction);
Svetoslav Ganov42138042012-03-20 11:51:39 -0700833 if (!canPerformRequestOverConnection(mSourceNodeId)) {
834 return null;
835 }
836 return AccessibilityInteractionClient.getInstance().focusSearch(mConnectionId, mWindowId,
837 mSourceNodeId, direction);
838 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700839
840 /**
841 * Gets the id of the window from which the info comes from.
842 *
843 * @return The window id.
844 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700845 public int getWindowId() {
Svetoslav Ganov02107852011-10-03 17:06:56 -0700846 return mWindowId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700847 }
848
849 /**
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800850 * Refreshes this info with the latest state of the view it represents.
851 * <p>
852 * <strong>Note:</strong> If this method returns false this info is obsolete
853 * since it represents a view that is no longer in the view tree and should
854 * be recycled.
855 * </p>
Svetoslav6254f482013-06-04 17:22:14 -0700856 *
857 * @param bypassCache Whether to bypass the cache.
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800858 * @return Whether the refresh succeeded.
Svetoslav6254f482013-06-04 17:22:14 -0700859 *
860 * @hide
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800861 */
Phil Weaverc2e28932016-12-08 12:29:25 -0800862 public boolean refresh(Bundle arguments, boolean bypassCache) {
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800863 enforceSealed();
864 if (!canPerformRequestOverConnection(mSourceNodeId)) {
865 return false;
866 }
867 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
868 AccessibilityNodeInfo refreshedInfo = client.findAccessibilityNodeInfoByAccessibilityId(
Phil Weaverc2e28932016-12-08 12:29:25 -0800869 mConnectionId, mWindowId, mSourceNodeId, bypassCache, 0, arguments);
Svetoslav Ganov0b0afb42012-12-03 16:51:53 -0800870 if (refreshedInfo == null) {
871 return false;
872 }
873 init(refreshedInfo);
874 refreshedInfo.recycle();
875 return true;
876 }
877
878 /**
Svetoslav6254f482013-06-04 17:22:14 -0700879 * Refreshes this info with the latest state of the view it represents.
Phil Weaverc2e28932016-12-08 12:29:25 -0800880 *
881 * @return {@code true} if the refresh succeeded. {@code false} if the {@link View} represented
882 * by this node is no longer in the view tree (and thus this node is obsolete and should be
883 * recycled).
Svetoslav6254f482013-06-04 17:22:14 -0700884 */
885 public boolean refresh() {
Phil Weaverc2e28932016-12-08 12:29:25 -0800886 return refresh(null, true);
887 }
888
889 /**
890 * Refreshes this info with the latest state of the view it represents, and request new
891 * data be added by the View.
892 *
893 * @param extraDataKey A bitmask of the extra data requested. Data that must be requested
894 * with this mechanism is generally expensive to retrieve, so should only be
895 * requested when needed. See
896 * {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY} and
897 * {@link #getAvailableExtraData()}.
898 * @param args A bundle of arguments for the request. These depend on the particular request.
899 *
900 * @return {@code true} if the refresh succeeded. {@code false} if the {@link View} represented
901 * by this node is no longer in the view tree (and thus this node is obsolete and should be
902 * recycled).
903 */
904 public boolean refreshWithExtraData(String extraDataKey, Bundle args) {
905 args.putString(EXTRA_DATA_REQUESTED_KEY, extraDataKey);
906 return refresh(args, true);
Svetoslav6254f482013-06-04 17:22:14 -0700907 }
908
909 /**
Alan Viverettef0aed092013-11-06 15:33:03 -0800910 * Returns the array containing the IDs of this node's children.
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800911 *
912 * @hide
913 */
Alan Viverettef0aed092013-11-06 15:33:03 -0800914 public LongArray getChildNodeIds() {
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800915 return mChildNodeIds;
916 }
917
918 /**
Alan Viverettef0aed092013-11-06 15:33:03 -0800919 * Returns the id of the child at the specified index.
920 *
921 * @throws IndexOutOfBoundsException when index &lt; 0 || index &gt;=
922 * getChildCount()
923 * @hide
924 */
925 public long getChildId(int index) {
926 if (mChildNodeIds == null) {
927 throw new IndexOutOfBoundsException();
928 }
929 return mChildNodeIds.get(index);
930 }
931
932 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700933 * Gets the number of children.
934 *
935 * @return The child count.
936 */
937 public int getChildCount() {
Alan Viverettef0aed092013-11-06 15:33:03 -0800938 return mChildNodeIds == null ? 0 : mChildNodeIds.size();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700939 }
940
941 /**
942 * Get the child at given index.
943 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700944 * <strong>Note:</strong> It is a client responsibility to recycle the
945 * received info by calling {@link AccessibilityNodeInfo#recycle()}
946 * to avoid creating of multiple instances.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700947 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700948 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700949 * @param index The child index.
950 * @return The child node.
951 *
952 * @throws IllegalStateException If called outside of an AccessibilityService.
953 *
954 */
955 public AccessibilityNodeInfo getChild(int index) {
956 enforceSealed();
Alan Viverettef0aed092013-11-06 15:33:03 -0800957 if (mChildNodeIds == null) {
958 return null;
959 }
Svetoslav Ganov02107852011-10-03 17:06:56 -0700960 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700961 return null;
962 }
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800963 final long childId = mChildNodeIds.get(index);
Svetoslav Ganov8bd69612011-08-23 13:40:30 -0700964 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800965 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId,
Phil Weaverc2e28932016-12-08 12:29:25 -0800966 childId, false, FLAG_PREFETCH_DESCENDANTS, null);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700967 }
968
969 /**
970 * Adds a child.
971 * <p>
Svetoslav Ganov02107852011-10-03 17:06:56 -0700972 * <strong>Note:</strong> Cannot be called from an
973 * {@link android.accessibilityservice.AccessibilityService}.
974 * This class is made immutable before being delivered to an AccessibilityService.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700975 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700976 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700977 * @param child The child.
978 *
979 * @throws IllegalStateException If called from an AccessibilityService.
980 */
981 public void addChild(View child) {
Phil Weaverf00cd142017-03-03 13:44:00 -0800982 addChildInternal(child, AccessibilityNodeProvider.HOST_VIEW_ID, true);
Alan Viverettef0aed092013-11-06 15:33:03 -0800983 }
984
985 /**
986 * Unchecked version of {@link #addChild(View)} that does not verify
987 * uniqueness. For framework use only.
988 *
989 * @hide
990 */
991 public void addChildUnchecked(View child) {
Phil Weaverf00cd142017-03-03 13:44:00 -0800992 addChildInternal(child, AccessibilityNodeProvider.HOST_VIEW_ID, false);
Alan Viverettef0aed092013-11-06 15:33:03 -0800993 }
994
995 /**
996 * Removes a child. If the child was not previously added to the node,
997 * calling this method has no effect.
998 * <p>
999 * <strong>Note:</strong> Cannot be called from an
1000 * {@link android.accessibilityservice.AccessibilityService}.
1001 * This class is made immutable before being delivered to an AccessibilityService.
1002 * </p>
1003 *
1004 * @param child The child.
1005 * @return true if the child was present
1006 *
1007 * @throws IllegalStateException If called from an AccessibilityService.
1008 */
1009 public boolean removeChild(View child) {
Phil Weaverf00cd142017-03-03 13:44:00 -08001010 return removeChild(child, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov02107852011-10-03 17:06:56 -07001011 }
1012
1013 /**
1014 * Adds a virtual child which is a descendant of the given <code>root</code>.
Svetoslav Ganov71b4e712011-10-25 11:31:31 -07001015 * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
Svetoslav Ganov02107852011-10-03 17:06:56 -07001016 * is added as a child.
1017 * <p>
1018 * A virtual descendant is an imaginary View that is reported as a part of the view
1019 * hierarchy for accessibility purposes. This enables custom views that draw complex
1020 * content to report them selves as a tree of virtual views, thus conveying their
1021 * logical structure.
1022 * </p>
1023 *
1024 * @param root The root of the virtual subtree.
1025 * @param virtualDescendantId The id of the virtual child.
1026 */
1027 public void addChild(View root, int virtualDescendantId) {
Alan Viverettef0aed092013-11-06 15:33:03 -08001028 addChildInternal(root, virtualDescendantId, true);
1029 }
1030
1031 private void addChildInternal(View root, int virtualDescendantId, boolean checked) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001032 enforceNotSealed();
Alan Viverettef0aed092013-11-06 15:33:03 -08001033 if (mChildNodeIds == null) {
1034 mChildNodeIds = new LongArray();
1035 }
Svetoslav Ganov02107852011-10-03 17:06:56 -07001036 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -08001037 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -07001038 final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Alan Viverettef0aed092013-11-06 15:33:03 -08001039 // If we're checking uniqueness and the ID already exists, abort.
1040 if (checked && mChildNodeIds.indexOf(childNodeId) >= 0) {
1041 return;
1042 }
1043 mChildNodeIds.add(childNodeId);
1044 }
1045
1046 /**
1047 * Removes a virtual child which is a descendant of the given
1048 * <code>root</code>. If the child was not previously added to the node,
1049 * calling this method has no effect.
1050 *
1051 * @param root The root of the virtual subtree.
1052 * @param virtualDescendantId The id of the virtual child.
1053 * @return true if the child was present
1054 * @see #addChild(View, int)
1055 */
1056 public boolean removeChild(View root, int virtualDescendantId) {
1057 enforceNotSealed();
1058 final LongArray childIds = mChildNodeIds;
1059 if (childIds == null) {
1060 return false;
1061 }
1062 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -08001063 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Alan Viverettef0aed092013-11-06 15:33:03 -08001064 final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1065 final int index = childIds.indexOf(childNodeId);
1066 if (index < 0) {
1067 return false;
1068 }
1069 childIds.remove(index);
1070 return true;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001071 }
1072
1073 /**
1074 * Gets the actions that can be performed on the node.
Kristian Monsen74bc1942014-04-29 11:00:17 -07001075 */
1076 public List<AccessibilityAction> getActionList() {
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07001077 return CollectionUtils.emptyIfNull(mActions);
Kristian Monsen74bc1942014-04-29 11:00:17 -07001078 }
1079
1080 /**
1081 * Gets the actions that can be performed on the node.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001082 *
1083 * @return The bit mask of with actions.
1084 *
1085 * @see AccessibilityNodeInfo#ACTION_FOCUS
1086 * @see AccessibilityNodeInfo#ACTION_CLEAR_FOCUS
1087 * @see AccessibilityNodeInfo#ACTION_SELECT
1088 * @see AccessibilityNodeInfo#ACTION_CLEAR_SELECTION
Svetoslav Ganova1dc7612012-05-10 04:14:53 -07001089 * @see AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS
1090 * @see AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS
1091 * @see AccessibilityNodeInfo#ACTION_CLICK
1092 * @see AccessibilityNodeInfo#ACTION_LONG_CLICK
1093 * @see AccessibilityNodeInfo#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
1094 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
1095 * @see AccessibilityNodeInfo#ACTION_NEXT_HTML_ELEMENT
1096 * @see AccessibilityNodeInfo#ACTION_PREVIOUS_HTML_ELEMENT
1097 * @see AccessibilityNodeInfo#ACTION_SCROLL_FORWARD
1098 * @see AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD
Kristian Monsen74bc1942014-04-29 11:00:17 -07001099 *
1100 * @deprecated Use {@link #getActionList()}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001101 */
Kristian Monsen74bc1942014-04-29 11:00:17 -07001102 @Deprecated
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001103 public int getActions() {
Kristian Monsen74bc1942014-04-29 11:00:17 -07001104 int returnValue = 0;
1105
1106 if (mActions == null) {
1107 return returnValue;
1108 }
1109
1110 final int actionSize = mActions.size();
1111 for (int i = 0; i < actionSize; i++) {
1112 int actionId = mActions.get(i).getId();
1113 if (actionId <= LAST_LEGACY_STANDARD_ACTION) {
1114 returnValue |= actionId;
1115 }
1116 }
1117
1118 return returnValue;
1119 }
1120
1121 /**
1122 * Adds an action that can be performed on the node.
1123 * <p>
1124 * To add a standard action use the static constants on {@link AccessibilityAction}.
1125 * To add a custom action create a new {@link AccessibilityAction} by passing in a
1126 * resource id from your application as the action id and an optional label that
1127 * describes the action. To override one of the standard actions use as the action
1128 * id of a standard action id such as {@link #ACTION_CLICK} and an optional label that
1129 * describes the action.
1130 * </p>
1131 * <p>
1132 * <strong>Note:</strong> Cannot be called from an
1133 * {@link android.accessibilityservice.AccessibilityService}.
1134 * This class is made immutable before being delivered to an AccessibilityService.
1135 * </p>
1136 *
1137 * @param action The action.
1138 *
1139 * @throws IllegalStateException If called from an AccessibilityService.
1140 */
1141 public void addAction(AccessibilityAction action) {
1142 enforceNotSealed();
1143
Alan Viverettec921f272015-05-14 12:26:49 -07001144 addActionUnchecked(action);
1145 }
1146
1147 private void addActionUnchecked(AccessibilityAction action) {
Kristian Monsen74bc1942014-04-29 11:00:17 -07001148 if (action == null) {
1149 return;
1150 }
1151
1152 if (mActions == null) {
Alan Viverette23f44322015-04-06 16:04:56 -07001153 mActions = new ArrayList<>();
Kristian Monsen74bc1942014-04-29 11:00:17 -07001154 }
1155
1156 mActions.remove(action);
1157 mActions.add(action);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001158 }
1159
1160 /**
1161 * Adds an action that can be performed on the node.
1162 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001163 * <strong>Note:</strong> Cannot be called from an
1164 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001165 * This class is made immutable before being delivered to an AccessibilityService.
1166 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001167 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001168 * @param action The action.
1169 *
1170 * @throws IllegalStateException If called from an AccessibilityService.
Kristian Monsen74bc1942014-04-29 11:00:17 -07001171 * @throws IllegalArgumentException If the argument is not one of the standard actions.
1172 *
1173 * @deprecated This has been deprecated for {@link #addAction(AccessibilityAction)}
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001174 */
Kristian Monsen74bc1942014-04-29 11:00:17 -07001175 @Deprecated
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001176 public void addAction(int action) {
1177 enforceNotSealed();
Kristian Monsen74bc1942014-04-29 11:00:17 -07001178
Kristian Monsen8d5f3fa2014-05-20 13:16:19 -07001179 if ((action & ACTION_TYPE_MASK) != 0) {
1180 throw new IllegalArgumentException("Action is not a combination of the standard " +
1181 "actions: " + action);
Kristian Monsen74bc1942014-04-29 11:00:17 -07001182 }
1183
Eugene Susla554edd32017-05-24 16:49:59 -07001184 addStandardActions(action);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001185 }
1186
1187 /**
Alan Viverettef0aed092013-11-06 15:33:03 -08001188 * Removes an action that can be performed on the node. If the action was
1189 * not already added to the node, calling this method has no effect.
1190 * <p>
1191 * <strong>Note:</strong> Cannot be called from an
1192 * {@link android.accessibilityservice.AccessibilityService}.
1193 * This class is made immutable before being delivered to an AccessibilityService.
1194 * </p>
1195 *
Kristian Monsen74bc1942014-04-29 11:00:17 -07001196 * @param action The action to be removed.
1197 *
1198 * @throws IllegalStateException If called from an AccessibilityService.
1199 * @deprecated Use {@link #removeAction(AccessibilityAction)}
1200 */
1201 @Deprecated
1202 public void removeAction(int action) {
1203 enforceNotSealed();
1204
1205 removeAction(getActionSingleton(action));
1206 }
1207
1208 /**
1209 * Removes an action that can be performed on the node. If the action was
1210 * not already added to the node, calling this method has no effect.
1211 * <p>
1212 * <strong>Note:</strong> Cannot be called from an
1213 * {@link android.accessibilityservice.AccessibilityService}.
1214 * This class is made immutable before being delivered to an AccessibilityService.
1215 * </p>
1216 *
1217 * @param action The action to be removed.
1218 * @return The action removed from the list of actions.
Alan Viverettef0aed092013-11-06 15:33:03 -08001219 *
1220 * @throws IllegalStateException If called from an AccessibilityService.
1221 */
Kristian Monsen74bc1942014-04-29 11:00:17 -07001222 public boolean removeAction(AccessibilityAction action) {
Alan Viverettef0aed092013-11-06 15:33:03 -08001223 enforceNotSealed();
Kristian Monsen74bc1942014-04-29 11:00:17 -07001224
1225 if (mActions == null || action == null) {
1226 return false;
1227 }
1228
1229 return mActions.remove(action);
Alan Viverettef0aed092013-11-06 15:33:03 -08001230 }
1231
1232 /**
Phil Weaverf00cd142017-03-03 13:44:00 -08001233 * Removes all actions.
1234 *
1235 * @hide
1236 */
1237 public void removeAllActions() {
1238 if (mActions != null) {
1239 mActions.clear();
1240 }
1241 }
1242
1243 /**
Svetoslav6c702902014-10-09 18:40:56 -07001244 * Gets the node before which this one is visited during traversal. A screen-reader
1245 * must visit the content of this node before the content of the one it precedes.
1246 *
1247 * @return The succeeding node if such or <code>null</code>.
1248 *
1249 * @see #setTraversalBefore(android.view.View)
1250 * @see #setTraversalBefore(android.view.View, int)
1251 */
1252 public AccessibilityNodeInfo getTraversalBefore() {
1253 enforceSealed();
1254 return getNodeForAccessibilityId(mTraversalBefore);
1255 }
1256
1257 /**
1258 * Sets the view before whose node this one should be visited during traversal. A
1259 * screen-reader must visit the content of this node before the content of the one
1260 * it precedes.
1261 * <p>
1262 * <strong>Note:</strong> Cannot be called from an
1263 * {@link android.accessibilityservice.AccessibilityService}.
1264 * This class is made immutable before being delivered to an AccessibilityService.
1265 * </p>
1266 *
1267 * @param view The view providing the preceding node.
1268 *
1269 * @see #getTraversalBefore()
1270 */
1271 public void setTraversalBefore(View view) {
Phil Weaverf00cd142017-03-03 13:44:00 -08001272 setTraversalBefore(view, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav6c702902014-10-09 18:40:56 -07001273 }
1274
1275 /**
1276 * Sets the node before which this one is visited during traversal. A screen-reader
1277 * must visit the content of this node before the content of the one it precedes.
1278 * The successor is a virtual descendant of the given <code>root</code>. If
1279 * <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root is set
1280 * as the successor.
1281 * <p>
1282 * A virtual descendant is an imaginary View that is reported as a part of the view
1283 * hierarchy for accessibility purposes. This enables custom views that draw complex
1284 * content to report them selves as a tree of virtual views, thus conveying their
1285 * logical structure.
1286 * </p>
1287 * <p>
1288 * <strong>Note:</strong> Cannot be called from an
1289 * {@link android.accessibilityservice.AccessibilityService}.
1290 * This class is made immutable before being delivered to an AccessibilityService.
1291 * </p>
1292 *
1293 * @param root The root of the virtual subtree.
1294 * @param virtualDescendantId The id of the virtual descendant.
1295 */
1296 public void setTraversalBefore(View root, int virtualDescendantId) {
1297 enforceNotSealed();
1298 final int rootAccessibilityViewId = (root != null)
1299 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
1300 mTraversalBefore = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1301 }
1302
1303 /**
1304 * Gets the node after which this one is visited in accessibility traversal.
1305 * A screen-reader must visit the content of the other node before the content
1306 * of this one.
1307 *
1308 * @return The succeeding node if such or <code>null</code>.
1309 *
1310 * @see #setTraversalAfter(android.view.View)
1311 * @see #setTraversalAfter(android.view.View, int)
1312 */
1313 public AccessibilityNodeInfo getTraversalAfter() {
1314 enforceSealed();
1315 return getNodeForAccessibilityId(mTraversalAfter);
1316 }
1317
1318 /**
1319 * Sets the view whose node is visited after this one in accessibility traversal.
1320 * A screen-reader must visit the content of the other node before the content
1321 * of this one.
1322 * <p>
1323 * <strong>Note:</strong> Cannot be called from an
1324 * {@link android.accessibilityservice.AccessibilityService}.
1325 * This class is made immutable before being delivered to an AccessibilityService.
1326 * </p>
1327 *
1328 * @param view The previous view.
1329 *
1330 * @see #getTraversalAfter()
1331 */
1332 public void setTraversalAfter(View view) {
Phil Weaverf00cd142017-03-03 13:44:00 -08001333 setTraversalAfter(view, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav6c702902014-10-09 18:40:56 -07001334 }
1335
1336 /**
1337 * Sets the node after which this one is visited in accessibility traversal.
1338 * A screen-reader must visit the content of the other node before the content
1339 * of this one. If <code>virtualDescendantId</code> equals to {@link View#NO_ID}
1340 * the root is set as the predecessor.
1341 * <p>
1342 * A virtual descendant is an imaginary View that is reported as a part of the view
1343 * hierarchy for accessibility purposes. This enables custom views that draw complex
1344 * content to report them selves as a tree of virtual views, thus conveying their
1345 * logical structure.
1346 * </p>
1347 * <p>
1348 * <strong>Note:</strong> Cannot be called from an
1349 * {@link android.accessibilityservice.AccessibilityService}.
1350 * This class is made immutable before being delivered to an AccessibilityService.
1351 * </p>
1352 *
1353 * @param root The root of the virtual subtree.
1354 * @param virtualDescendantId The id of the virtual descendant.
1355 */
1356 public void setTraversalAfter(View root, int virtualDescendantId) {
1357 enforceNotSealed();
1358 final int rootAccessibilityViewId = (root != null)
1359 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
1360 mTraversalAfter = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
1361 }
1362
1363 /**
Phil Weaverc2e28932016-12-08 12:29:25 -08001364 * Get the extra data available for this node.
1365 * <p>
1366 * Some data that is useful for some accessibility services is expensive to compute, and would
1367 * place undue overhead on apps to compute all the time. That data can be requested with
1368 * {@link #refreshWithExtraData(String, Bundle)}.
1369 *
1370 * @return An unmodifiable list of keys corresponding to extra data that can be requested.
1371 * @see #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY
1372 */
1373 public List<String> getAvailableExtraData() {
1374 if (mExtraDataKeys != null) {
1375 return Collections.unmodifiableList(mExtraDataKeys);
1376 } else {
1377 return EMPTY_LIST;
1378 }
1379 }
1380
1381 /**
1382 * Set the extra data available for this node.
1383 * <p>
1384 * <strong>Note:</strong> When a {@code View} passes in a non-empty list, it promises that
1385 * it will populate the node's extras with corresponding pieces of information in
1386 * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)}.
1387 * <p>
1388 * <strong>Note:</strong> Cannot be called from an
1389 * {@link android.accessibilityservice.AccessibilityService}.
1390 * This class is made immutable before being delivered to an AccessibilityService.
1391 *
1392 * @param extraDataKeys A list of types of extra data that are available.
1393 * @see #getAvailableExtraData()
1394 *
1395 * @throws IllegalStateException If called from an AccessibilityService.
1396 */
1397 public void setAvailableExtraData(List<String> extraDataKeys) {
1398 enforceNotSealed();
1399 mExtraDataKeys = new ArrayList<>(extraDataKeys);
1400 }
1401
1402 /**
Alan Viverette029942f2014-08-12 14:55:56 -07001403 * Sets the maximum text length, or -1 for no limit.
1404 * <p>
1405 * Typically used to indicate that an editable text field has a limit on
1406 * the number of characters entered.
1407 * <p>
1408 * <strong>Note:</strong> Cannot be called from an
1409 * {@link android.accessibilityservice.AccessibilityService}.
1410 * This class is made immutable before being delivered to an AccessibilityService.
1411 *
1412 * @param max The maximum text length.
1413 * @see #getMaxTextLength()
1414 *
1415 * @throws IllegalStateException If called from an AccessibilityService.
1416 */
1417 public void setMaxTextLength(int max) {
1418 enforceNotSealed();
1419 mMaxTextLength = max;
1420 }
1421
1422 /**
1423 * Returns the maximum text length for this node.
1424 *
1425 * @return The maximum text length, or -1 for no limit.
1426 * @see #setMaxTextLength(int)
1427 */
1428 public int getMaxTextLength() {
1429 return mMaxTextLength;
1430 }
1431
1432 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001433 * Sets the movement granularities for traversing the text of this node.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001434 * <p>
1435 * <strong>Note:</strong> Cannot be called from an
1436 * {@link android.accessibilityservice.AccessibilityService}.
1437 * This class is made immutable before being delivered to an AccessibilityService.
1438 * </p>
1439 *
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07001440 * @param granularities The bit mask with granularities.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001441 *
1442 * @throws IllegalStateException If called from an AccessibilityService.
1443 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001444 public void setMovementGranularities(int granularities) {
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001445 enforceNotSealed();
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001446 mMovementGranularities = granularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001447 }
1448
1449 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001450 * Gets the movement granularities for traversing the text of this node.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001451 *
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07001452 * @return The bit mask with granularities.
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001453 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07001454 public int getMovementGranularities() {
1455 return mMovementGranularities;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001456 }
1457
1458 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001459 * Performs an action on the node.
1460 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001461 * <strong>Note:</strong> An action can be performed only if the request is made
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001462 * from an {@link android.accessibilityservice.AccessibilityService}.
1463 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001464 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001465 * @param action The action to perform.
1466 * @return True if the action was performed.
1467 *
1468 * @throws IllegalStateException If called outside of an AccessibilityService.
1469 */
1470 public boolean performAction(int action) {
1471 enforceSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -07001472 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001473 return false;
1474 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -07001475 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07001476 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
1477 action, null);
1478 }
1479
1480 /**
1481 * Performs an action on the node.
1482 * <p>
1483 * <strong>Note:</strong> An action can be performed only if the request is made
1484 * from an {@link android.accessibilityservice.AccessibilityService}.
1485 * </p>
1486 *
1487 * @param action The action to perform.
1488 * @param arguments A bundle with additional arguments.
1489 * @return True if the action was performed.
1490 *
1491 * @throws IllegalStateException If called outside of an AccessibilityService.
1492 */
1493 public boolean performAction(int action, Bundle arguments) {
1494 enforceSealed();
1495 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1496 return false;
1497 }
1498 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1499 return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId,
1500 action, arguments);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001501 }
1502
1503 /**
1504 * Finds {@link AccessibilityNodeInfo}s by text. The match is case
Svetoslav Ganov86398bd2011-06-21 17:38:43 -07001505 * insensitive containment. The search is relative to this info i.e.
1506 * this info is the root of the traversed tree.
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07001507 *
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001508 * <p>
1509 * <strong>Note:</strong> It is a client responsibility to recycle the
1510 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1511 * to avoid creating of multiple instances.
1512 * </p>
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001513 *
1514 * @param text The searched text.
1515 * @return A list of node info.
1516 */
1517 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text) {
1518 enforceSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -07001519 if (!canPerformRequestOverConnection(mSourceNodeId)) {
Svetoslav Ganov86398bd2011-06-21 17:38:43 -07001520 return Collections.emptyList();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001521 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -07001522 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganov79311c42012-01-17 20:24:26 -08001523 return client.findAccessibilityNodeInfosByText(mConnectionId, mWindowId, mSourceNodeId,
1524 text);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001525 }
1526
1527 /**
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001528 * Finds {@link AccessibilityNodeInfo}s by the fully qualified view id's resource
1529 * name where a fully qualified id is of the from "package:id/id_resource_name".
1530 * For example, if the target application's package is "foo.bar" and the id
1531 * resource name is "baz", the fully qualified resource id is "foo.bar:id/baz".
1532 *
1533 * <p>
1534 * <strong>Note:</strong> It is a client responsibility to recycle the
1535 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1536 * to avoid creating of multiple instances.
1537 * </p>
1538 * <p>
1539 * <strong>Note:</strong> The primary usage of this API is for UI test automation
1540 * and in order to report the fully qualified view id if an {@link AccessibilityNodeInfo}
1541 * the client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
Svetoslav14ff9962013-01-29 03:21:37 -08001542 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001543 * </p>
1544 *
1545 * @param viewId The fully qualified resource name of the view id to find.
1546 * @return A list of node info.
1547 */
1548 public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId(String viewId) {
1549 enforceSealed();
1550 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1551 return Collections.emptyList();
1552 }
1553 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1554 return client.findAccessibilityNodeInfosByViewId(mConnectionId, mWindowId, mSourceNodeId,
1555 viewId);
1556 }
1557
1558 /**
Svetoslav8e3feb12014-02-24 13:46:47 -08001559 * Gets the window to which this node belongs.
1560 *
1561 * @return The window.
1562 *
1563 * @see android.accessibilityservice.AccessibilityService#getWindows()
1564 */
1565 public AccessibilityWindowInfo getWindow() {
1566 enforceSealed();
1567 if (!canPerformRequestOverConnection(mSourceNodeId)) {
1568 return null;
1569 }
1570 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
1571 return client.getWindow(mConnectionId, mWindowId);
1572 }
1573
1574 /**
Svetoslav Ganov00aabf72011-07-21 11:35:03 -07001575 * Gets the parent.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001576 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001577 * <strong>Note:</strong> It is a client responsibility to recycle the
1578 * received info by calling {@link AccessibilityNodeInfo#recycle()}
1579 * to avoid creating of multiple instances.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001580 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001581 *
Svetoslav Ganov00aabf72011-07-21 11:35:03 -07001582 * @return The parent.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001583 */
1584 public AccessibilityNodeInfo getParent() {
1585 enforceSealed();
Svetoslav6c702902014-10-09 18:40:56 -07001586 return getNodeForAccessibilityId(mParentNodeId);
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -08001587 }
1588
1589 /**
1590 * @return The parent node id.
1591 *
1592 * @hide
1593 */
1594 public long getParentNodeId() {
1595 return mParentNodeId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001596 }
1597
1598 /**
1599 * Sets the parent.
1600 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001601 * <strong>Note:</strong> Cannot be called from an
1602 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001603 * This class is made immutable before being delivered to an AccessibilityService.
1604 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001605 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001606 * @param parent The parent.
1607 *
1608 * @throws IllegalStateException If called from an AccessibilityService.
1609 */
1610 public void setParent(View parent) {
Phil Weaverf00cd142017-03-03 13:44:00 -08001611 setParent(parent, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov02107852011-10-03 17:06:56 -07001612 }
1613
1614 /**
1615 * Sets the parent to be a virtual descendant of the given <code>root</code>.
1616 * If <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root
1617 * is set as the parent.
1618 * <p>
1619 * A virtual descendant is an imaginary View that is reported as a part of the view
1620 * hierarchy for accessibility purposes. This enables custom views that draw complex
1621 * content to report them selves as a tree of virtual views, thus conveying their
1622 * logical structure.
1623 * </p>
1624 * <p>
1625 * <strong>Note:</strong> Cannot be called from an
1626 * {@link android.accessibilityservice.AccessibilityService}.
1627 * This class is made immutable before being delivered to an AccessibilityService.
1628 * </p>
1629 *
1630 * @param root The root of the virtual subtree.
1631 * @param virtualDescendantId The id of the virtual descendant.
1632 */
1633 public void setParent(View root, int virtualDescendantId) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001634 enforceNotSealed();
Svetoslav Ganov02107852011-10-03 17:06:56 -07001635 final int rootAccessibilityViewId =
Svetoslav8e3feb12014-02-24 13:46:47 -08001636 (root != null) ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov02107852011-10-03 17:06:56 -07001637 mParentNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001638 }
1639
1640 /**
1641 * Gets the node bounds in parent coordinates.
1642 *
1643 * @param outBounds The output node bounds.
1644 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001645 public void getBoundsInParent(Rect outBounds) {
1646 outBounds.set(mBoundsInParent.left, mBoundsInParent.top,
1647 mBoundsInParent.right, mBoundsInParent.bottom);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001648 }
1649
1650 /**
1651 * Sets the node bounds in parent coordinates.
1652 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001653 * <strong>Note:</strong> Cannot be called from an
1654 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001655 * This class is made immutable before being delivered to an AccessibilityService.
1656 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001657 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001658 * @param bounds The node bounds.
1659 *
1660 * @throws IllegalStateException If called from an AccessibilityService.
1661 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001662 public void setBoundsInParent(Rect bounds) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001663 enforceNotSealed();
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001664 mBoundsInParent.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
1665 }
1666
1667 /**
1668 * Gets the node bounds in screen coordinates.
1669 *
1670 * @param outBounds The output node bounds.
1671 */
1672 public void getBoundsInScreen(Rect outBounds) {
1673 outBounds.set(mBoundsInScreen.left, mBoundsInScreen.top,
1674 mBoundsInScreen.right, mBoundsInScreen.bottom);
1675 }
1676
1677 /**
Alan Viverettea7ea65e2015-05-15 11:30:21 -07001678 * Returns the actual rect containing the node bounds in screen coordinates.
1679 *
1680 * @hide Not safe to expose outside the framework.
1681 */
1682 public Rect getBoundsInScreen() {
1683 return mBoundsInScreen;
1684 }
1685
1686 /**
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001687 * Sets the node bounds in screen coordinates.
1688 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001689 * <strong>Note:</strong> Cannot be called from an
1690 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001691 * This class is made immutable before being delivered to an AccessibilityService.
1692 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001693 *
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07001694 * @param bounds The node bounds.
1695 *
1696 * @throws IllegalStateException If called from an AccessibilityService.
1697 */
1698 public void setBoundsInScreen(Rect bounds) {
1699 enforceNotSealed();
1700 mBoundsInScreen.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001701 }
1702
1703 /**
1704 * Gets whether this node is checkable.
1705 *
1706 * @return True if the node is checkable.
1707 */
1708 public boolean isCheckable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001709 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001710 }
1711
1712 /**
1713 * Sets whether this node is checkable.
1714 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001715 * <strong>Note:</strong> Cannot be called from an
1716 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001717 * This class is made immutable before being delivered to an AccessibilityService.
1718 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001719 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001720 * @param checkable True if the node is checkable.
1721 *
1722 * @throws IllegalStateException If called from an AccessibilityService.
1723 */
1724 public void setCheckable(boolean checkable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001725 setBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE, checkable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001726 }
1727
1728 /**
1729 * Gets whether this node is checked.
1730 *
1731 * @return True if the node is checked.
1732 */
1733 public boolean isChecked() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001734 return getBooleanProperty(BOOLEAN_PROPERTY_CHECKED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001735 }
1736
1737 /**
1738 * Sets whether this node is checked.
1739 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001740 * <strong>Note:</strong> Cannot be called from an
1741 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001742 * This class is made immutable before being delivered to an AccessibilityService.
1743 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001744 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001745 * @param checked True if the node is checked.
1746 *
1747 * @throws IllegalStateException If called from an AccessibilityService.
1748 */
1749 public void setChecked(boolean checked) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001750 setBooleanProperty(BOOLEAN_PROPERTY_CHECKED, checked);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001751 }
1752
1753 /**
1754 * Gets whether this node is focusable.
1755 *
1756 * @return True if the node is focusable.
1757 */
1758 public boolean isFocusable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001759 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001760 }
1761
1762 /**
1763 * Sets whether this node is focusable.
1764 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001765 * <strong>Note:</strong> Cannot be called from an
1766 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001767 * This class is made immutable before being delivered to an AccessibilityService.
1768 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001769 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001770 * @param focusable True if the node is focusable.
1771 *
1772 * @throws IllegalStateException If called from an AccessibilityService.
1773 */
1774 public void setFocusable(boolean focusable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001775 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE, focusable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001776 }
1777
1778 /**
1779 * Gets whether this node is focused.
1780 *
1781 * @return True if the node is focused.
1782 */
1783 public boolean isFocused() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001784 return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001785 }
1786
1787 /**
1788 * Sets whether this node is focused.
1789 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001790 * <strong>Note:</strong> Cannot be called from an
1791 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001792 * This class is made immutable before being delivered to an AccessibilityService.
1793 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001794 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001795 * @param focused True if the node is focused.
1796 *
1797 * @throws IllegalStateException If called from an AccessibilityService.
1798 */
1799 public void setFocused(boolean focused) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001800 setBooleanProperty(BOOLEAN_PROPERTY_FOCUSED, focused);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001801 }
1802
1803 /**
Alan Viverette1579edc2015-04-01 13:23:06 -07001804 * Gets whether this node is visible to the user.
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001805 *
1806 * @return Whether the node is visible to the user.
1807 */
1808 public boolean isVisibleToUser() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001809 return getBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001810 }
1811
1812 /**
1813 * Sets whether this node is visible to the user.
1814 * <p>
1815 * <strong>Note:</strong> Cannot be called from an
1816 * {@link android.accessibilityservice.AccessibilityService}.
1817 * This class is made immutable before being delivered to an AccessibilityService.
1818 * </p>
1819 *
1820 * @param visibleToUser Whether the node is visible to the user.
1821 *
1822 * @throws IllegalStateException If called from an AccessibilityService.
1823 */
1824 public void setVisibleToUser(boolean visibleToUser) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001825 setBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER, visibleToUser);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07001826 }
1827
1828 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -07001829 * Gets whether this node is accessibility focused.
1830 *
1831 * @return True if the node is accessibility focused.
1832 */
1833 public boolean isAccessibilityFocused() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001834 return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED);
Svetoslav Ganov42138042012-03-20 11:51:39 -07001835 }
1836
1837 /**
1838 * Sets whether this node is accessibility focused.
1839 * <p>
1840 * <strong>Note:</strong> Cannot be called from an
1841 * {@link android.accessibilityservice.AccessibilityService}.
1842 * This class is made immutable before being delivered to an AccessibilityService.
1843 * </p>
1844 *
1845 * @param focused True if the node is accessibility focused.
1846 *
1847 * @throws IllegalStateException If called from an AccessibilityService.
1848 */
1849 public void setAccessibilityFocused(boolean focused) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001850 setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED, focused);
Svetoslav Ganov42138042012-03-20 11:51:39 -07001851 }
1852
1853 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001854 * Gets whether this node is selected.
1855 *
1856 * @return True if the node is selected.
1857 */
1858 public boolean isSelected() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001859 return getBooleanProperty(BOOLEAN_PROPERTY_SELECTED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001860 }
1861
1862 /**
1863 * Sets whether this node is selected.
1864 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001865 * <strong>Note:</strong> Cannot be called from an
1866 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001867 * This class is made immutable before being delivered to an AccessibilityService.
1868 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001869 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001870 * @param selected True if the node is selected.
1871 *
1872 * @throws IllegalStateException If called from an AccessibilityService.
1873 */
1874 public void setSelected(boolean selected) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001875 setBooleanProperty(BOOLEAN_PROPERTY_SELECTED, selected);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001876 }
1877
1878 /**
1879 * Gets whether this node is clickable.
1880 *
1881 * @return True if the node is clickable.
1882 */
1883 public boolean isClickable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001884 return getBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001885 }
1886
1887 /**
1888 * Sets whether this node is clickable.
1889 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001890 * <strong>Note:</strong> Cannot be called from an
1891 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001892 * This class is made immutable before being delivered to an AccessibilityService.
1893 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001894 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001895 * @param clickable True if the node is clickable.
1896 *
1897 * @throws IllegalStateException If called from an AccessibilityService.
1898 */
1899 public void setClickable(boolean clickable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001900 setBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE, clickable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001901 }
1902
1903 /**
1904 * Gets whether this node is long clickable.
1905 *
1906 * @return True if the node is long clickable.
1907 */
1908 public boolean isLongClickable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001909 return getBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001910 }
1911
1912 /**
1913 * Sets whether this node is long clickable.
1914 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001915 * <strong>Note:</strong> Cannot be called from an
1916 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001917 * This class is made immutable before being delivered to an AccessibilityService.
1918 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001919 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001920 * @param longClickable True if the node is long clickable.
1921 *
1922 * @throws IllegalStateException If called from an AccessibilityService.
1923 */
1924 public void setLongClickable(boolean longClickable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001925 setBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE, longClickable);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001926 }
1927
1928 /**
1929 * Gets whether this node is enabled.
1930 *
1931 * @return True if the node is enabled.
1932 */
1933 public boolean isEnabled() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001934 return getBooleanProperty(BOOLEAN_PROPERTY_ENABLED);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001935 }
1936
1937 /**
1938 * Sets whether this node is enabled.
1939 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001940 * <strong>Note:</strong> Cannot be called from an
1941 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001942 * This class is made immutable before being delivered to an AccessibilityService.
1943 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001944 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001945 * @param enabled True if the node is enabled.
1946 *
1947 * @throws IllegalStateException If called from an AccessibilityService.
1948 */
1949 public void setEnabled(boolean enabled) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001950 setBooleanProperty(BOOLEAN_PROPERTY_ENABLED, enabled);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001951 }
1952
1953 /**
1954 * Gets whether this node is a password.
1955 *
1956 * @return True if the node is a password.
1957 */
1958 public boolean isPassword() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001959 return getBooleanProperty(BOOLEAN_PROPERTY_PASSWORD);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001960 }
1961
1962 /**
1963 * Sets whether this node is a password.
1964 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001965 * <strong>Note:</strong> Cannot be called from an
1966 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001967 * This class is made immutable before being delivered to an AccessibilityService.
1968 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001969 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001970 * @param password True if the node is a password.
1971 *
1972 * @throws IllegalStateException If called from an AccessibilityService.
1973 */
1974 public void setPassword(boolean password) {
Svetoslavbcc46a02013-02-06 11:56:00 -08001975 setBooleanProperty(BOOLEAN_PROPERTY_PASSWORD, password);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001976 }
1977
1978 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -07001979 * Gets if the node is scrollable.
1980 *
1981 * @return True if the node is scrollable, false otherwise.
1982 */
1983 public boolean isScrollable() {
Svetoslavbcc46a02013-02-06 11:56:00 -08001984 return getBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE);
Svetoslav Ganova0156172011-06-26 17:55:44 -07001985 }
1986
1987 /**
1988 * Sets if the node is scrollable.
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07001989 * <p>
1990 * <strong>Note:</strong> Cannot be called from an
1991 * {@link android.accessibilityservice.AccessibilityService}.
1992 * This class is made immutable before being delivered to an AccessibilityService.
1993 * </p>
Svetoslav Ganova0156172011-06-26 17:55:44 -07001994 *
1995 * @param scrollable True if the node is scrollable, false otherwise.
1996 *
1997 * @throws IllegalStateException If called from an AccessibilityService.
1998 */
1999 public void setScrollable(boolean scrollable) {
Svetoslavbcc46a02013-02-06 11:56:00 -08002000 setBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE, scrollable);
2001 }
2002
2003 /**
2004 * Gets if the node is editable.
2005 *
2006 * @return True if the node is editable, false otherwise.
2007 */
2008 public boolean isEditable() {
2009 return getBooleanProperty(BOOLEAN_PROPERTY_EDITABLE);
2010 }
2011
2012 /**
2013 * Sets whether this node is editable.
2014 * <p>
2015 * <strong>Note:</strong> Cannot be called from an
2016 * {@link android.accessibilityservice.AccessibilityService}.
2017 * This class is made immutable before being delivered to an AccessibilityService.
2018 * </p>
2019 *
2020 * @param editable True if the node is editable.
2021 *
2022 * @throws IllegalStateException If called from an AccessibilityService.
2023 */
2024 public void setEditable(boolean editable) {
2025 setBooleanProperty(BOOLEAN_PROPERTY_EDITABLE, editable);
Svetoslav Ganova0156172011-06-26 17:55:44 -07002026 }
2027
2028 /**
Phil Weaver1f222542016-01-08 11:49:32 -08002029 * Get the drawing order of the view corresponding it this node.
2030 * <p>
2031 * Drawing order is determined only within the node's parent, so this index is only relative
2032 * to its siblings.
2033 * <p>
2034 * In some cases, the drawing order is essentially simultaneous, so it is possible for two
2035 * siblings to return the same value. It is also possible that values will be skipped.
2036 *
2037 * @return The drawing position of the view corresponding to this node relative to its siblings.
2038 */
2039 public int getDrawingOrder() {
2040 return mDrawingOrderInParent;
2041 }
2042
2043 /**
2044 * Set the drawing order of the view corresponding it this node.
2045 *
2046 * <p>
2047 * <strong>Note:</strong> Cannot be called from an
2048 * {@link android.accessibilityservice.AccessibilityService}.
2049 * This class is made immutable before being delivered to an AccessibilityService.
2050 * </p>
2051 * @param drawingOrderInParent
2052 * @throws IllegalStateException If called from an AccessibilityService.
2053 */
2054 public void setDrawingOrder(int drawingOrderInParent) {
2055 enforceNotSealed();
2056 mDrawingOrderInParent = drawingOrderInParent;
2057 }
2058
2059 /**
Svetoslav3577a282013-06-06 14:09:10 -07002060 * Gets the collection info if the node is a collection. A collection
2061 * child is always a collection item.
2062 *
2063 * @return The collection info.
2064 */
2065 public CollectionInfo getCollectionInfo() {
2066 return mCollectionInfo;
2067 }
2068
2069 /**
2070 * Sets the collection info if the node is a collection. A collection
2071 * child is always a collection item.
2072 * <p>
2073 * <strong>Note:</strong> Cannot be called from an
2074 * {@link android.accessibilityservice.AccessibilityService}.
2075 * This class is made immutable before being delivered to an AccessibilityService.
2076 * </p>
2077 *
2078 * @param collectionInfo The collection info.
2079 */
2080 public void setCollectionInfo(CollectionInfo collectionInfo) {
2081 enforceNotSealed();
2082 mCollectionInfo = collectionInfo;
2083 }
2084
2085 /**
2086 * Gets the collection item info if the node is a collection item. A collection
2087 * item is always a child of a collection.
2088 *
2089 * @return The collection item info.
2090 */
2091 public CollectionItemInfo getCollectionItemInfo() {
2092 return mCollectionItemInfo;
2093 }
2094
2095 /**
2096 * Sets the collection item info if the node is a collection item. A collection
2097 * item is always a child of a collection.
2098 * <p>
2099 * <strong>Note:</strong> Cannot be called from an
2100 * {@link android.accessibilityservice.AccessibilityService}.
2101 * This class is made immutable before being delivered to an AccessibilityService.
2102 * </p>
Svetoslav3577a282013-06-06 14:09:10 -07002103 */
2104 public void setCollectionItemInfo(CollectionItemInfo collectionItemInfo) {
2105 enforceNotSealed();
2106 mCollectionItemInfo = collectionItemInfo;
2107 }
2108
2109 /**
2110 * Gets the range info if this node is a range.
2111 *
2112 * @return The range.
2113 */
2114 public RangeInfo getRangeInfo() {
2115 return mRangeInfo;
2116 }
2117
2118 /**
2119 * Sets the range info if this node is a range.
2120 * <p>
2121 * <strong>Note:</strong> Cannot be called from an
2122 * {@link android.accessibilityservice.AccessibilityService}.
2123 * This class is made immutable before being delivered to an AccessibilityService.
2124 * </p>
2125 *
2126 * @param rangeInfo The range info.
2127 */
2128 public void setRangeInfo(RangeInfo rangeInfo) {
2129 enforceNotSealed();
2130 mRangeInfo = rangeInfo;
2131 }
2132
2133 /**
2134 * Gets if the content of this node is invalid. For example,
2135 * a date is not well-formed.
2136 *
2137 * @return If the node content is invalid.
2138 */
2139 public boolean isContentInvalid() {
2140 return getBooleanProperty(BOOLEAN_PROPERTY_CONTENT_INVALID);
2141 }
2142
2143 /**
2144 * Sets if the content of this node is invalid. For example,
2145 * a date is not well-formed.
2146 * <p>
2147 * <strong>Note:</strong> Cannot be called from an
2148 * {@link android.accessibilityservice.AccessibilityService}.
2149 * This class is made immutable before being delivered to an AccessibilityService.
2150 * </p>
2151 *
2152 * @param contentInvalid If the node content is invalid.
2153 */
2154 public void setContentInvalid(boolean contentInvalid) {
2155 setBooleanProperty(BOOLEAN_PROPERTY_CONTENT_INVALID, contentInvalid);
2156 }
2157
2158 /**
Mady Mellore8608912015-06-05 09:02:55 -07002159 * Gets whether this node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07002160 *
Mady Mellore8608912015-06-05 09:02:55 -07002161 * @return True if the node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07002162 */
Mady Mellore8608912015-06-05 09:02:55 -07002163 public boolean isContextClickable() {
2164 return getBooleanProperty(BOOLEAN_PROPERTY_CONTEXT_CLICKABLE);
Mady Mellore82067b2015-04-30 09:58:35 -07002165 }
2166
2167 /**
Mady Mellore8608912015-06-05 09:02:55 -07002168 * Sets whether this node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07002169 * <p>
2170 * <strong>Note:</strong> Cannot be called from an
2171 * {@link android.accessibilityservice.AccessibilityService}. This class is made immutable
2172 * before being delivered to an AccessibilityService.
2173 * </p>
2174 *
Mady Mellore8608912015-06-05 09:02:55 -07002175 * @param contextClickable True if the node is context clickable.
Mady Mellore82067b2015-04-30 09:58:35 -07002176 * @throws IllegalStateException If called from an AccessibilityService.
2177 */
Mady Mellore8608912015-06-05 09:02:55 -07002178 public void setContextClickable(boolean contextClickable) {
2179 setBooleanProperty(BOOLEAN_PROPERTY_CONTEXT_CLICKABLE, contextClickable);
Mady Mellore82067b2015-04-30 09:58:35 -07002180 }
2181
2182 /**
Alan Viverette77e9a282013-09-12 17:16:09 -07002183 * Gets the node's live region mode.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002184 * <p>
Alan Viverette77e9a282013-09-12 17:16:09 -07002185 * A live region is a node that contains information that is important for
2186 * the user and when it changes the user should be notified. For example,
2187 * in a login screen with a TextView that displays an "incorrect password"
2188 * notification, that view should be marked as a live region with mode
2189 * {@link View#ACCESSIBILITY_LIVE_REGION_POLITE}.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002190 * <p>
Alan Viverette77e9a282013-09-12 17:16:09 -07002191 * It is the responsibility of the accessibility service to monitor
2192 * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} events indicating
2193 * changes to live region nodes and their children.
Svetoslav3577a282013-06-06 14:09:10 -07002194 *
Alan Viverette77e9a282013-09-12 17:16:09 -07002195 * @return The live region mode, or
2196 * {@link View#ACCESSIBILITY_LIVE_REGION_NONE} if the view is not a
2197 * live region.
2198 * @see android.view.View#getAccessibilityLiveRegion()
Svetoslav3577a282013-06-06 14:09:10 -07002199 */
Alan Viverette77e9a282013-09-12 17:16:09 -07002200 public int getLiveRegion() {
2201 return mLiveRegion;
Svetoslav3577a282013-06-06 14:09:10 -07002202 }
2203
2204 /**
Alan Viverette77e9a282013-09-12 17:16:09 -07002205 * Sets the node's live region mode.
Svetoslav3577a282013-06-06 14:09:10 -07002206 * <p>
Alan Viverette77e9a282013-09-12 17:16:09 -07002207 * <strong>Note:</strong> Cannot be called from an
2208 * {@link android.accessibilityservice.AccessibilityService}. This class is
2209 * made immutable before being delivered to an AccessibilityService.
Svetoslav3577a282013-06-06 14:09:10 -07002210 *
Alan Viverette77e9a282013-09-12 17:16:09 -07002211 * @param mode The live region mode, or
2212 * {@link View#ACCESSIBILITY_LIVE_REGION_NONE} if the view is not a
2213 * live region.
2214 * @see android.view.View#setAccessibilityLiveRegion(int)
Svetoslav3577a282013-06-06 14:09:10 -07002215 */
Alan Viverette77e9a282013-09-12 17:16:09 -07002216 public void setLiveRegion(int mode) {
2217 enforceNotSealed();
2218 mLiveRegion = mode;
Svetoslav3577a282013-06-06 14:09:10 -07002219 }
2220
2221 /**
2222 * Gets if the node is a multi line editable text.
2223 *
2224 * @return True if the node is multi line.
2225 */
2226 public boolean isMultiLine() {
2227 return getBooleanProperty(BOOLEAN_PROPERTY_MULTI_LINE);
2228 }
2229
2230 /**
2231 * Sets if the node is a multi line editable text.
2232 * <p>
2233 * <strong>Note:</strong> Cannot be called from an
2234 * {@link android.accessibilityservice.AccessibilityService}.
2235 * This class is made immutable before being delivered to an AccessibilityService.
2236 * </p>
2237 *
2238 * @param multiLine True if the node is multi line.
2239 */
2240 public void setMultiLine(boolean multiLine) {
Svetoslav3577a282013-06-06 14:09:10 -07002241 setBooleanProperty(BOOLEAN_PROPERTY_MULTI_LINE, multiLine);
2242 }
2243
2244 /**
2245 * Gets if this node opens a popup or a dialog.
2246 *
2247 * @return If the the node opens a popup.
2248 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002249 public boolean canOpenPopup() {
Svetoslav3577a282013-06-06 14:09:10 -07002250 return getBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP);
2251 }
2252
2253 /**
2254 * Sets if this node opens a popup or a dialog.
2255 * <p>
2256 * <strong>Note:</strong> Cannot be called from an
2257 * {@link android.accessibilityservice.AccessibilityService}.
2258 * This class is made immutable before being delivered to an AccessibilityService.
2259 * </p>
2260 *
2261 * @param opensPopup If the the node opens a popup.
2262 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002263 public void setCanOpenPopup(boolean opensPopup) {
2264 enforceNotSealed();
Svetoslav3577a282013-06-06 14:09:10 -07002265 setBooleanProperty(BOOLEAN_PROPERTY_OPENS_POPUP, opensPopup);
2266 }
2267
2268 /**
Svetoslav3577a282013-06-06 14:09:10 -07002269 * Gets if the node can be dismissed.
2270 *
2271 * @return If the node can be dismissed.
2272 */
2273 public boolean isDismissable() {
2274 return getBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE);
2275 }
2276
2277 /**
2278 * Sets if the node can be dismissed.
2279 * <p>
2280 * <strong>Note:</strong> Cannot be called from an
2281 * {@link android.accessibilityservice.AccessibilityService}.
2282 * This class is made immutable before being delivered to an AccessibilityService.
2283 * </p>
2284 *
2285 * @param dismissable If the node can be dismissed.
2286 */
2287 public void setDismissable(boolean dismissable) {
Svetoslav3577a282013-06-06 14:09:10 -07002288 setBooleanProperty(BOOLEAN_PROPERTY_DISMISSABLE, dismissable);
2289 }
2290
2291 /**
Casey Burkhardt2d80ae42016-01-31 12:52:23 -08002292 * Returns whether the node originates from a view considered important for accessibility.
2293 *
2294 * @return {@code true} if the node originates from a view considered important for
2295 * accessibility, {@code false} otherwise
2296 *
2297 * @see View#isImportantForAccessibility()
2298 */
2299 public boolean isImportantForAccessibility() {
2300 return getBooleanProperty(BOOLEAN_PROPERTY_IMPORTANCE);
2301 }
2302
2303 /**
2304 * Sets whether the node is considered important for accessibility.
2305 * <p>
2306 * <strong>Note:</strong> Cannot be called from an
2307 * {@link android.accessibilityservice.AccessibilityService}.
2308 * This class is made immutable before being delivered to an AccessibilityService.
2309 * </p>
2310 *
2311 * @param important {@code true} if the node is considered important for accessibility,
2312 * {@code false} otherwise
2313 */
2314 public void setImportantForAccessibility(boolean important) {
2315 setBooleanProperty(BOOLEAN_PROPERTY_IMPORTANCE, important);
2316 }
2317
2318 /**
Phil Weaver776afc22016-12-21 10:55:13 -08002319 * Returns whether the node's text represents a hint for the user to enter text. It should only
2320 * be {@code true} if the node has editable text.
2321 *
2322 * @return {@code true} if the text in the node represents a hint to the user, {@code false}
2323 * otherwise.
2324 */
2325 public boolean isShowingHintText() {
2326 return getBooleanProperty(BOOLEAN_PROPERTY_IS_SHOWING_HINT);
2327 }
2328
2329 /**
2330 * Sets whether the node's text represents a hint for the user to enter text. It should only
2331 * be {@code true} if the node has editable text.
2332 * <p>
2333 * <strong>Note:</strong> Cannot be called from an
2334 * {@link android.accessibilityservice.AccessibilityService}.
2335 * This class is made immutable before being delivered to an AccessibilityService.
2336 * </p>
2337 *
2338 * @param showingHintText {@code true} if the text in the node represents a hint to the user,
2339 * {@code false} otherwise.
2340 */
2341 public void setShowingHintText(boolean showingHintText) {
2342 setBooleanProperty(BOOLEAN_PROPERTY_IS_SHOWING_HINT, showingHintText);
2343 }
2344
2345 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002346 * Gets the package this node comes from.
2347 *
2348 * @return The package name.
2349 */
2350 public CharSequence getPackageName() {
2351 return mPackageName;
2352 }
2353
2354 /**
2355 * Sets the package this node comes from.
2356 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002357 * <strong>Note:</strong> Cannot be called from an
2358 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002359 * This class is made immutable before being delivered to an AccessibilityService.
2360 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002361 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002362 * @param packageName The package name.
2363 *
2364 * @throws IllegalStateException If called from an AccessibilityService.
2365 */
2366 public void setPackageName(CharSequence packageName) {
2367 enforceNotSealed();
2368 mPackageName = packageName;
2369 }
2370
2371 /**
2372 * Gets the class this node comes from.
2373 *
2374 * @return The class name.
2375 */
2376 public CharSequence getClassName() {
2377 return mClassName;
2378 }
2379
2380 /**
2381 * Sets the class this node comes from.
2382 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002383 * <strong>Note:</strong> Cannot be called from an
2384 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002385 * This class is made immutable before being delivered to an AccessibilityService.
2386 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002387 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002388 * @param className The class name.
2389 *
2390 * @throws IllegalStateException If called from an AccessibilityService.
2391 */
2392 public void setClassName(CharSequence className) {
2393 enforceNotSealed();
2394 mClassName = className;
2395 }
2396
2397 /**
2398 * Gets the text of this node.
Phil Weaver193520e2016-12-13 09:39:06 -08002399 * <p>
2400 * <strong>Note:</strong> If the text contains {@link ClickableSpan}s or {@link URLSpan}s,
2401 * these spans will have been replaced with ones whose {@link ClickableSpan#onClick(View)}
2402 * can be called from an {@link AccessibilityService}. When called from a service, the
2403 * {@link View} argument is ignored and the corresponding span will be found on the view that
2404 * this {@code AccessibilityNodeInfo} represents and called with that view as its argument.
2405 * <p>
2406 * This treatment of {@link ClickableSpan}s means that the text returned from this method may
2407 * different slightly one passed to {@link #setText(CharSequence)}, although they will be
2408 * equivalent according to {@link TextUtils#equals(CharSequence, CharSequence)}. The
2409 * {@link ClickableSpan#onClick(View)} of any spans, however, will generally not work outside
2410 * of an accessibility service.
2411 * </p>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002412 *
2413 * @return The text.
2414 */
2415 public CharSequence getText() {
Phil Weaver193520e2016-12-13 09:39:06 -08002416 // Attach this node to any spans that need it
2417 if (mText instanceof Spanned) {
2418 Spanned spanned = (Spanned) mText;
2419 AccessibilityClickableSpan[] clickableSpans =
2420 spanned.getSpans(0, mText.length(), AccessibilityClickableSpan.class);
2421 for (int i = 0; i < clickableSpans.length; i++) {
Phil Weaver23161e72017-04-19 12:16:36 -07002422 clickableSpans[i].copyConnectionDataFrom(this);
Phil Weaver193520e2016-12-13 09:39:06 -08002423 }
2424 AccessibilityURLSpan[] urlSpans =
2425 spanned.getSpans(0, mText.length(), AccessibilityURLSpan.class);
2426 for (int i = 0; i < urlSpans.length; i++) {
Phil Weaver23161e72017-04-19 12:16:36 -07002427 urlSpans[i].copyConnectionDataFrom(this);
Phil Weaver193520e2016-12-13 09:39:06 -08002428 }
2429 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002430 return mText;
2431 }
2432
2433 /**
Phil Weaver193520e2016-12-13 09:39:06 -08002434 * Get the text passed to setText before any changes to the spans.
2435 * @hide
2436 */
2437 public CharSequence getOriginalText() {
2438 return mOriginalText;
2439 }
2440
2441 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002442 * Sets the text of this node.
2443 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002444 * <strong>Note:</strong> Cannot be called from an
2445 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002446 * This class is made immutable before being delivered to an AccessibilityService.
2447 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002448 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002449 * @param text The text.
2450 *
2451 * @throws IllegalStateException If called from an AccessibilityService.
2452 */
2453 public void setText(CharSequence text) {
2454 enforceNotSealed();
Phil Weaver193520e2016-12-13 09:39:06 -08002455 mOriginalText = text;
2456 // Replace any ClickableSpans in mText with placeholders
2457 if (text instanceof Spanned) {
2458 ClickableSpan[] spans =
2459 ((Spanned) text).getSpans(0, text.length(), ClickableSpan.class);
2460 if (spans.length > 0) {
Phil Weaver0ebe6bd2017-02-21 16:24:31 -08002461 Spannable spannable = new SpannableStringBuilder(text);
Phil Weaver193520e2016-12-13 09:39:06 -08002462 for (int i = 0; i < spans.length; i++) {
2463 ClickableSpan span = spans[i];
2464 if ((span instanceof AccessibilityClickableSpan)
2465 || (span instanceof AccessibilityURLSpan)) {
2466 // We've already done enough
2467 break;
2468 }
2469 int spanToReplaceStart = spannable.getSpanStart(span);
2470 int spanToReplaceEnd = spannable.getSpanEnd(span);
2471 int spanToReplaceFlags = spannable.getSpanFlags(span);
2472 spannable.removeSpan(span);
2473 ClickableSpan replacementSpan = (span instanceof URLSpan)
2474 ? new AccessibilityURLSpan((URLSpan) span)
2475 : new AccessibilityClickableSpan(span.getId());
2476 spannable.setSpan(replacementSpan, spanToReplaceStart, spanToReplaceEnd,
2477 spanToReplaceFlags);
2478 }
2479 mText = spannable;
2480 return;
2481 }
2482 }
Phil Weaveref955ad2016-08-25 12:58:15 -07002483 mText = (text == null) ? null : text.subSequence(0, text.length());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002484 }
2485
2486 /**
Phil Weaver776afc22016-12-21 10:55:13 -08002487 * Gets the hint text of this node. Only applies to nodes where text can be entered.
2488 *
2489 * @return The hint text.
2490 */
2491 public CharSequence getHintText() {
2492 return mHintText;
2493 }
2494
2495 /**
2496 * Sets the hint text of this node. Only applies to nodes where text can be entered.
2497 * <p>
2498 * <strong>Note:</strong> Cannot be called from an
2499 * {@link android.accessibilityservice.AccessibilityService}.
2500 * This class is made immutable before being delivered to an AccessibilityService.
2501 * </p>
2502 *
2503 * @param hintText The hint text for this mode.
2504 *
2505 * @throws IllegalStateException If called from an AccessibilityService.
2506 */
2507 public void setHintText(CharSequence hintText) {
2508 enforceNotSealed();
2509 mHintText = (hintText == null) ? null : hintText.subSequence(0, hintText.length());
2510 }
2511
2512 /**
Alan Viverettefccbff52014-07-07 15:06:14 -07002513 * Sets the error text of this node.
2514 * <p>
2515 * <strong>Note:</strong> Cannot be called from an
2516 * {@link android.accessibilityservice.AccessibilityService}.
2517 * This class is made immutable before being delivered to an AccessibilityService.
2518 * </p>
2519 *
2520 * @param error The error text.
2521 *
2522 * @throws IllegalStateException If called from an AccessibilityService.
2523 */
2524 public void setError(CharSequence error) {
2525 enforceNotSealed();
Phil Weaveref955ad2016-08-25 12:58:15 -07002526 mError = (error == null) ? null : error.subSequence(0, error.length());
Alan Viverettefccbff52014-07-07 15:06:14 -07002527 }
2528
2529 /**
2530 * Gets the error text of this node.
2531 *
2532 * @return The error text.
2533 */
2534 public CharSequence getError() {
2535 return mError;
2536 }
2537
2538 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002539 * Gets the content description of this node.
2540 *
2541 * @return The content description.
2542 */
2543 public CharSequence getContentDescription() {
2544 return mContentDescription;
2545 }
2546
2547 /**
2548 * Sets the content description of this node.
2549 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002550 * <strong>Note:</strong> Cannot be called from an
2551 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002552 * This class is made immutable before being delivered to an AccessibilityService.
2553 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07002554 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002555 * @param contentDescription The content description.
2556 *
2557 * @throws IllegalStateException If called from an AccessibilityService.
2558 */
2559 public void setContentDescription(CharSequence contentDescription) {
2560 enforceNotSealed();
Phil Weaveref955ad2016-08-25 12:58:15 -07002561 mContentDescription = (contentDescription == null) ? null
2562 : contentDescription.subSequence(0, contentDescription.length());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002563 }
2564
2565 /**
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002566 * Sets the view for which the view represented by this info serves as a
2567 * label for accessibility purposes.
2568 *
2569 * @param labeled The view for which this info serves as a label.
2570 */
2571 public void setLabelFor(View labeled) {
Phil Weaverf00cd142017-03-03 13:44:00 -08002572 setLabelFor(labeled, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002573 }
2574
2575 /**
2576 * Sets the view for which the view represented by this info serves as a
2577 * label for accessibility purposes. If <code>virtualDescendantId</code>
2578 * is {@link View#NO_ID} the root is set as the labeled.
2579 * <p>
2580 * A virtual descendant is an imaginary View that is reported as a part of the view
2581 * hierarchy for accessibility purposes. This enables custom views that draw complex
2582 * content to report themselves as a tree of virtual views, thus conveying their
2583 * logical structure.
2584 * </p>
2585 * <p>
2586 * <strong>Note:</strong> Cannot be called from an
2587 * {@link android.accessibilityservice.AccessibilityService}.
2588 * This class is made immutable before being delivered to an AccessibilityService.
2589 * </p>
2590 *
2591 * @param root The root whose virtual descendant serves as a label.
2592 * @param virtualDescendantId The id of the virtual descendant.
2593 */
2594 public void setLabelFor(View root, int virtualDescendantId) {
2595 enforceNotSealed();
2596 final int rootAccessibilityViewId = (root != null)
Svetoslav8e3feb12014-02-24 13:46:47 -08002597 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002598 mLabelForId = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
2599 }
2600
2601 /**
2602 * Gets the node info for which the view represented by this info serves as
2603 * a label for accessibility purposes.
2604 * <p>
2605 * <strong>Note:</strong> It is a client responsibility to recycle the
2606 * received info by calling {@link AccessibilityNodeInfo#recycle()}
2607 * to avoid creating of multiple instances.
2608 * </p>
2609 *
2610 * @return The labeled info.
2611 */
2612 public AccessibilityNodeInfo getLabelFor() {
2613 enforceSealed();
Svetoslav6c702902014-10-09 18:40:56 -07002614 return getNodeForAccessibilityId(mLabelForId);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002615 }
2616
2617 /**
2618 * Sets the view which serves as the label of the view represented by
2619 * this info for accessibility purposes.
2620 *
2621 * @param label The view that labels this node's source.
2622 */
2623 public void setLabeledBy(View label) {
Phil Weaverf00cd142017-03-03 13:44:00 -08002624 setLabeledBy(label, AccessibilityNodeProvider.HOST_VIEW_ID);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002625 }
2626
2627 /**
2628 * Sets the view which serves as the label of the view represented by
2629 * this info for accessibility purposes. If <code>virtualDescendantId</code>
2630 * is {@link View#NO_ID} the root is set as the label.
2631 * <p>
2632 * A virtual descendant is an imaginary View that is reported as a part of the view
2633 * hierarchy for accessibility purposes. This enables custom views that draw complex
2634 * content to report themselves as a tree of virtual views, thus conveying their
2635 * logical structure.
2636 * </p>
2637 * <p>
2638 * <strong>Note:</strong> Cannot be called from an
2639 * {@link android.accessibilityservice.AccessibilityService}.
2640 * This class is made immutable before being delivered to an AccessibilityService.
2641 * </p>
2642 *
2643 * @param root The root whose virtual descendant labels this node's source.
2644 * @param virtualDescendantId The id of the virtual descendant.
2645 */
2646 public void setLabeledBy(View root, int virtualDescendantId) {
2647 enforceNotSealed();
2648 final int rootAccessibilityViewId = (root != null)
Svetoslav8e3feb12014-02-24 13:46:47 -08002649 ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002650 mLabeledById = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
2651 }
2652
2653 /**
2654 * Gets the node info which serves as the label of the view represented by
2655 * this info for accessibility purposes.
2656 * <p>
2657 * <strong>Note:</strong> It is a client responsibility to recycle the
2658 * received info by calling {@link AccessibilityNodeInfo#recycle()}
2659 * to avoid creating of multiple instances.
2660 * </p>
2661 *
2662 * @return The label.
2663 */
2664 public AccessibilityNodeInfo getLabeledBy() {
2665 enforceSealed();
Svetoslav6c702902014-10-09 18:40:56 -07002666 return getNodeForAccessibilityId(mLabeledById);
Svetoslav Ganov33aef982012-09-13 12:49:03 -07002667 }
2668
2669 /**
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002670 * Sets the fully qualified resource name of the source view's id.
2671 *
2672 * <p>
2673 * <strong>Note:</strong> Cannot be called from an
2674 * {@link android.accessibilityservice.AccessibilityService}.
2675 * This class is made immutable before being delivered to an AccessibilityService.
2676 * </p>
2677 *
Svetoslav92826452013-02-05 14:57:42 -08002678 * @param viewIdResName The id resource name.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002679 */
Svetoslav9fa1ee52013-04-22 12:43:03 -07002680 public void setViewIdResourceName(String viewIdResName) {
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002681 enforceNotSealed();
Svetoslav22431a32013-02-05 14:30:19 -08002682 mViewIdResourceName = viewIdResName;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002683 }
2684
2685 /**
2686 * Gets the fully qualified resource name of the source view's id.
2687 *
2688 * <p>
2689 * <strong>Note:</strong> The primary usage of this API is for UI test automation
2690 * and in order to report the source view id of an {@link AccessibilityNodeInfo} the
2691 * client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
Svetoslav14ff9962013-01-29 03:21:37 -08002692 * flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002693 * </p>
2694
2695 * @return The id resource name.
2696 */
Svetoslav9fa1ee52013-04-22 12:43:03 -07002697 public String getViewIdResourceName() {
Svetoslav22431a32013-02-05 14:30:19 -08002698 return mViewIdResourceName;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002699 }
2700
2701 /**
Phil Weaver40ded282016-01-25 15:49:02 -08002702 * Gets the text selection start or the cursor position.
2703 * <p>
2704 * If no text is selected, both this method and
2705 * {@link AccessibilityNodeInfo#getTextSelectionEnd()} return the same value:
2706 * the current location of the cursor.
2707 * </p>
Svetoslavbcc46a02013-02-06 11:56:00 -08002708 *
Phil Weaver40ded282016-01-25 15:49:02 -08002709 * @return The text selection start, the cursor location if there is no selection, or -1 if
2710 * there is no text selection and no cursor.
Svetoslavbcc46a02013-02-06 11:56:00 -08002711 */
2712 public int getTextSelectionStart() {
2713 return mTextSelectionStart;
2714 }
2715
2716 /**
Phil Weaver40ded282016-01-25 15:49:02 -08002717 * Gets the text selection end if text is selected.
2718 * <p>
2719 * If no text is selected, both this method and
2720 * {@link AccessibilityNodeInfo#getTextSelectionStart()} return the same value:
2721 * the current location of the cursor.
2722 * </p>
Svetoslavbcc46a02013-02-06 11:56:00 -08002723 *
Phil Weaver40ded282016-01-25 15:49:02 -08002724 * @return The text selection end, the cursor location if there is no selection, or -1 if
2725 * there is no text selection and no cursor.
Svetoslavbcc46a02013-02-06 11:56:00 -08002726 */
2727 public int getTextSelectionEnd() {
2728 return mTextSelectionEnd;
2729 }
2730
2731 /**
2732 * Sets the text selection start and end.
2733 * <p>
2734 * <strong>Note:</strong> Cannot be called from an
2735 * {@link android.accessibilityservice.AccessibilityService}.
2736 * This class is made immutable before being delivered to an AccessibilityService.
2737 * </p>
2738 *
2739 * @param start The text selection start.
2740 * @param end The text selection end.
2741 *
2742 * @throws IllegalStateException If called from an AccessibilityService.
2743 */
2744 public void setTextSelection(int start, int end) {
2745 enforceNotSealed();
2746 mTextSelectionStart = start;
2747 mTextSelectionEnd = end;
2748 }
2749
2750 /**
Svetoslav6254f482013-06-04 17:22:14 -07002751 * Gets the input type of the source as defined by {@link InputType}.
2752 *
2753 * @return The input type.
2754 */
2755 public int getInputType() {
2756 return mInputType;
2757 }
2758
2759 /**
2760 * Sets the input type of the source as defined by {@link InputType}.
2761 * <p>
2762 * <strong>Note:</strong> Cannot be called from an
2763 * {@link android.accessibilityservice.AccessibilityService}.
2764 * This class is made immutable before being delivered to an
2765 * AccessibilityService.
2766 * </p>
2767 *
2768 * @param inputType The input type.
2769 *
2770 * @throws IllegalStateException If called from an AccessibilityService.
2771 */
2772 public void setInputType(int inputType) {
Alan Viverettedf39cb92013-08-19 12:28:04 -07002773 enforceNotSealed();
Svetoslav6254f482013-06-04 17:22:14 -07002774 mInputType = inputType;
2775 }
2776
2777 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002778 * Gets an optional bundle with extra data. The bundle
Svetoslav6254f482013-06-04 17:22:14 -07002779 * is lazily created and never <code>null</code>.
2780 * <p>
2781 * <strong>Note:</strong> It is recommended to use the package
2782 * name of your application as a prefix for the keys to avoid
2783 * collisions which may confuse an accessibility service if the
2784 * same key has different meaning when emitted from different
2785 * applications.
2786 * </p>
2787 *
2788 * @return The bundle.
2789 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002790 public Bundle getExtras() {
2791 if (mExtras == null) {
2792 mExtras = new Bundle();
Svetoslav6254f482013-06-04 17:22:14 -07002793 }
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07002794 return mExtras;
Svetoslav6254f482013-06-04 17:22:14 -07002795 }
2796
2797 /**
Phil Weaverc2e28932016-12-08 12:29:25 -08002798 * Check if a node has an extras bundle
2799 * @hide
2800 */
2801 public boolean hasExtras() {
2802 return mExtras != null;
2803 }
2804
2805 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002806 * Gets the value of a boolean property.
2807 *
2808 * @param property The property.
2809 * @return The value.
2810 */
2811 private boolean getBooleanProperty(int property) {
2812 return (mBooleanProperties & property) != 0;
2813 }
2814
2815 /**
2816 * Sets a boolean property.
2817 *
2818 * @param property The property.
2819 * @param value The value.
2820 *
2821 * @throws IllegalStateException If called from an AccessibilityService.
2822 */
2823 private void setBooleanProperty(int property, boolean value) {
2824 enforceNotSealed();
2825 if (value) {
2826 mBooleanProperties |= property;
2827 } else {
2828 mBooleanProperties &= ~property;
2829 }
2830 }
2831
2832 /**
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002833 * Sets the unique id of the IAccessibilityServiceConnection over which
2834 * this instance can send requests to the system.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002835 *
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002836 * @param connectionId The connection id.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002837 *
2838 * @hide
2839 */
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002840 public void setConnectionId(int connectionId) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07002841 enforceNotSealed();
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08002842 mConnectionId = connectionId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002843 }
2844
2845 /**
Phil Weaver23161e72017-04-19 12:16:36 -07002846 * Get the connection ID.
2847 *
2848 * @return The connection id
2849 *
2850 * @hide
2851 */
2852 public int getConnectionId() {
2853 return mConnectionId;
2854 }
2855
2856 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002857 * {@inheritDoc}
2858 */
Alan Viverettef0aed092013-11-06 15:33:03 -08002859 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002860 public int describeContents() {
2861 return 0;
2862 }
2863
2864 /**
Phil Weaverf00cd142017-03-03 13:44:00 -08002865 * Sets the id of the source node.
2866 *
2867 * @param sourceId The id.
2868 * @param windowId The window id.
2869 *
2870 * @hide
2871 */
2872 public void setSourceNodeId(long sourceId, int windowId) {
2873 enforceNotSealed();
2874 mSourceNodeId = sourceId;
2875 mWindowId = windowId;
2876 }
2877
2878 /**
Svetoslav Ganov79311c42012-01-17 20:24:26 -08002879 * Gets the id of the source node.
2880 *
2881 * @return The id.
2882 *
2883 * @hide
2884 */
2885 public long getSourceNodeId() {
2886 return mSourceNodeId;
2887 }
2888
2889 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002890 * Sets if this instance is sealed.
2891 *
2892 * @param sealed Whether is sealed.
2893 *
2894 * @hide
2895 */
2896 public void setSealed(boolean sealed) {
2897 mSealed = sealed;
2898 }
2899
2900 /**
2901 * Gets if this instance is sealed.
2902 *
2903 * @return Whether is sealed.
2904 *
2905 * @hide
2906 */
2907 public boolean isSealed() {
2908 return mSealed;
2909 }
2910
2911 /**
2912 * Enforces that this instance is sealed.
2913 *
2914 * @throws IllegalStateException If this instance is not sealed.
2915 *
2916 * @hide
2917 */
2918 protected void enforceSealed() {
2919 if (!isSealed()) {
2920 throw new IllegalStateException("Cannot perform this "
2921 + "action on a not sealed instance.");
2922 }
2923 }
2924
Svetoslav Ganov2ef69052012-06-04 08:55:16 -07002925 private void enforceValidFocusDirection(int direction) {
2926 switch (direction) {
2927 case View.FOCUS_DOWN:
2928 case View.FOCUS_UP:
2929 case View.FOCUS_LEFT:
2930 case View.FOCUS_RIGHT:
2931 case View.FOCUS_FORWARD:
2932 case View.FOCUS_BACKWARD:
Svetoslav Ganov2ef69052012-06-04 08:55:16 -07002933 return;
2934 default:
2935 throw new IllegalArgumentException("Unknown direction: " + direction);
2936 }
2937 }
2938
2939 private void enforceValidFocusType(int focusType) {
2940 switch (focusType) {
2941 case FOCUS_INPUT:
2942 case FOCUS_ACCESSIBILITY:
2943 return;
2944 default:
2945 throw new IllegalArgumentException("Unknown focus type: " + focusType);
2946 }
2947 }
2948
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002949 /**
2950 * Enforces that this instance is not sealed.
2951 *
2952 * @throws IllegalStateException If this instance is sealed.
2953 *
2954 * @hide
2955 */
2956 protected void enforceNotSealed() {
2957 if (isSealed()) {
2958 throw new IllegalStateException("Cannot perform this "
Ken Wakasaf76a50c2012-03-09 19:56:35 +09002959 + "action on a sealed instance.");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002960 }
2961 }
2962
2963 /**
2964 * Returns a cached instance if such is available otherwise a new one
2965 * and sets the source.
2966 *
Svetoslav Ganov02107852011-10-03 17:06:56 -07002967 * @param source The source view.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002968 * @return An instance.
2969 *
2970 * @see #setSource(View)
2971 */
2972 public static AccessibilityNodeInfo obtain(View source) {
2973 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
2974 info.setSource(source);
2975 return info;
2976 }
2977
2978 /**
Svetoslav Ganov02107852011-10-03 17:06:56 -07002979 * Returns a cached instance if such is available otherwise a new one
2980 * and sets the source.
2981 *
2982 * @param root The root of the virtual subtree.
2983 * @param virtualDescendantId The id of the virtual descendant.
2984 * @return An instance.
2985 *
2986 * @see #setSource(View, int)
2987 */
2988 public static AccessibilityNodeInfo obtain(View root, int virtualDescendantId) {
2989 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
2990 info.setSource(root, virtualDescendantId);
2991 return info;
2992 }
2993
2994 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07002995 * Returns a cached instance if such is available otherwise a new one.
2996 *
2997 * @return An instance.
2998 */
2999 public static AccessibilityNodeInfo obtain() {
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -08003000 AccessibilityNodeInfo info = sPool.acquire();
Phil Weaver62d20fa2016-09-15 11:05:55 -07003001 if (sNumInstancesInUse != null) {
3002 sNumInstancesInUse.incrementAndGet();
3003 }
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -08003004 return (info != null) ? info : new AccessibilityNodeInfo();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003005 }
3006
3007 /**
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003008 * Returns a cached instance if such is available or a new one is
3009 * create. The returned instance is initialized from the given
3010 * <code>info</code>.
3011 *
3012 * @param info The other info.
3013 * @return An instance.
3014 */
3015 public static AccessibilityNodeInfo obtain(AccessibilityNodeInfo info) {
3016 AccessibilityNodeInfo infoClone = AccessibilityNodeInfo.obtain();
3017 infoClone.init(info);
3018 return infoClone;
3019 }
3020
3021 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003022 * Return an instance back to be reused.
3023 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003024 * <strong>Note:</strong> You must not touch the object after calling this function.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003025 *
3026 * @throws IllegalStateException If the info is already recycled.
3027 */
3028 public void recycle() {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003029 clear();
Svetoslav Ganovf4782ec2012-11-28 09:11:41 -08003030 sPool.release(this);
Phil Weaver62d20fa2016-09-15 11:05:55 -07003031 if (sNumInstancesInUse != null) {
3032 sNumInstancesInUse.decrementAndGet();
3033 }
Phil Weaverb010b122016-08-17 17:47:48 -07003034 }
3035
3036 /**
Phil Weaver62d20fa2016-09-15 11:05:55 -07003037 * Specify a counter that will be incremented on obtain() and decremented on recycle()
Phil Weaverb010b122016-08-17 17:47:48 -07003038 *
3039 * @hide
3040 */
Phil Weaver62d20fa2016-09-15 11:05:55 -07003041 @TestApi
3042 public static void setNumInstancesInUseCounter(AtomicInteger counter) {
3043 sNumInstancesInUse = counter;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003044 }
3045
3046 /**
3047 * {@inheritDoc}
3048 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003049 * <strong>Note:</strong> After the instance is written to a parcel it
3050 * is recycled. You must not touch the object after calling this function.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003051 * </p>
3052 */
Alan Viverettef0aed092013-11-06 15:33:03 -08003053 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003054 public void writeToParcel(Parcel parcel, int flags) {
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003055 // Write bit set of indices of fields with values differing from default
3056 long nonDefaultFields = 0;
3057 int fieldIndex = 0; // index of the current field
3058 if (isSealed() != DEFAULT.isSealed()) nonDefaultFields |= bitAt(fieldIndex);
3059 fieldIndex++;
3060 if (mSourceNodeId != DEFAULT.mSourceNodeId) nonDefaultFields |= bitAt(fieldIndex);
3061 fieldIndex++;
3062 if (mWindowId != DEFAULT.mWindowId) nonDefaultFields |= bitAt(fieldIndex);
3063 fieldIndex++;
3064 if (mParentNodeId != DEFAULT.mParentNodeId) nonDefaultFields |= bitAt(fieldIndex);
3065 fieldIndex++;
3066 if (mLabelForId != DEFAULT.mLabelForId) nonDefaultFields |= bitAt(fieldIndex);
3067 fieldIndex++;
3068 if (mLabeledById != DEFAULT.mLabeledById) nonDefaultFields |= bitAt(fieldIndex);
3069 fieldIndex++;
3070 if (mTraversalBefore != DEFAULT.mTraversalBefore) nonDefaultFields |= bitAt(fieldIndex);
3071 fieldIndex++;
3072 if (mTraversalAfter != DEFAULT.mTraversalAfter) nonDefaultFields |= bitAt(fieldIndex);
3073 fieldIndex++;
3074 if (mConnectionId != DEFAULT.mConnectionId) nonDefaultFields |= bitAt(fieldIndex);
3075 fieldIndex++;
3076 if (!Objects.equals(mChildNodeIds, DEFAULT.mChildNodeIds)) {
3077 nonDefaultFields |= bitAt(fieldIndex);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003078 }
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003079 fieldIndex++;
3080 if (!Objects.equals(mBoundsInParent, DEFAULT.mBoundsInParent)) {
3081 nonDefaultFields |= bitAt(fieldIndex);
3082 }
3083 fieldIndex++;
3084 if (!Objects.equals(mBoundsInScreen, DEFAULT.mBoundsInScreen)) {
3085 nonDefaultFields |= bitAt(fieldIndex);
3086 }
3087 fieldIndex++;
3088 if (!Objects.equals(mActions, DEFAULT.mActions)) nonDefaultFields |= bitAt(fieldIndex);
3089 fieldIndex++;
3090 if (mMaxTextLength != DEFAULT.mMaxTextLength) nonDefaultFields |= bitAt(fieldIndex);
3091 fieldIndex++;
3092 if (mMovementGranularities != DEFAULT.mMovementGranularities) {
3093 nonDefaultFields |= bitAt(fieldIndex);
3094 }
3095 fieldIndex++;
3096 if (mBooleanProperties != DEFAULT.mBooleanProperties) nonDefaultFields |= bitAt(fieldIndex);
3097 fieldIndex++;
3098 if (!Objects.equals(mPackageName, DEFAULT.mPackageName)) {
3099 nonDefaultFields |= bitAt(fieldIndex);
3100 }
3101 fieldIndex++;
3102 if (!Objects.equals(mClassName, DEFAULT.mClassName)) nonDefaultFields |= bitAt(fieldIndex);
3103 fieldIndex++;
3104 if (!Objects.equals(mText, DEFAULT.mText)) nonDefaultFields |= bitAt(fieldIndex);
3105 fieldIndex++;
3106 if (!Objects.equals(mHintText, DEFAULT.mHintText)) {
3107 nonDefaultFields |= bitAt(fieldIndex);
3108 }
3109 fieldIndex++;
3110 if (!Objects.equals(mError, DEFAULT.mError)) nonDefaultFields |= bitAt(fieldIndex);
3111 fieldIndex++;
3112 if (!Objects.equals(mContentDescription, DEFAULT.mContentDescription)) {
3113 nonDefaultFields |= bitAt(fieldIndex);
3114 }
3115 fieldIndex++;
3116 if (!Objects.equals(mViewIdResourceName, DEFAULT.mViewIdResourceName)) {
3117 nonDefaultFields |= bitAt(fieldIndex);
3118 }
3119 fieldIndex++;
3120 if (mTextSelectionStart != DEFAULT.mTextSelectionStart) {
3121 nonDefaultFields |= bitAt(fieldIndex);
3122 }
3123 fieldIndex++;
3124 if (mTextSelectionEnd != DEFAULT.mTextSelectionEnd) {
3125 nonDefaultFields |= bitAt(fieldIndex);
3126 }
3127 fieldIndex++;
3128 if (mInputType != DEFAULT.mInputType) nonDefaultFields |= bitAt(fieldIndex);
3129 fieldIndex++;
3130 if (mLiveRegion != DEFAULT.mLiveRegion) nonDefaultFields |= bitAt(fieldIndex);
3131 fieldIndex++;
3132 if (mDrawingOrderInParent != DEFAULT.mDrawingOrderInParent) {
3133 nonDefaultFields |= bitAt(fieldIndex);
3134 }
3135 fieldIndex++;
3136 if (!Objects.equals(mExtraDataKeys, DEFAULT.mExtraDataKeys)) {
3137 nonDefaultFields |= bitAt(fieldIndex);
3138 }
3139 fieldIndex++;
3140 if (!Objects.equals(mExtras, DEFAULT.mExtras)) nonDefaultFields |= bitAt(fieldIndex);
3141 fieldIndex++;
3142 if (!Objects.equals(mRangeInfo, DEFAULT.mRangeInfo)) nonDefaultFields |= bitAt(fieldIndex);
3143 fieldIndex++;
3144 if (!Objects.equals(mCollectionInfo, DEFAULT.mCollectionInfo)) {
3145 nonDefaultFields |= bitAt(fieldIndex);
3146 }
3147 fieldIndex++;
3148 if (!Objects.equals(mCollectionItemInfo, DEFAULT.mCollectionItemInfo)) {
3149 nonDefaultFields |= bitAt(fieldIndex);
3150 }
3151 int totalFields = fieldIndex;
3152 parcel.writeLong(nonDefaultFields);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003153
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003154 fieldIndex = 0;
3155 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(isSealed() ? 1 : 0);
3156 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mSourceNodeId);
3157 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mWindowId);
3158 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mParentNodeId);
3159 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mLabelForId);
3160 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mLabeledById);
3161 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mTraversalBefore);
3162 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeLong(mTraversalAfter);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07003163
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003164 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mConnectionId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003165
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003166 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3167 final LongArray childIds = mChildNodeIds;
3168 if (childIds == null) {
3169 parcel.writeInt(0);
3170 } else {
3171 final int childIdsSize = childIds.size();
3172 parcel.writeInt(childIdsSize);
3173 for (int i = 0; i < childIdsSize; i++) {
3174 parcel.writeLong(childIds.get(i));
Kristian Monsen74bc1942014-04-29 11:00:17 -07003175 }
3176 }
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003177 }
Kristian Monsen74bc1942014-04-29 11:00:17 -07003178
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003179 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3180 parcel.writeInt(mBoundsInParent.top);
3181 parcel.writeInt(mBoundsInParent.bottom);
3182 parcel.writeInt(mBoundsInParent.left);
3183 parcel.writeInt(mBoundsInParent.right);
3184 }
3185
3186 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3187 parcel.writeInt(mBoundsInScreen.top);
3188 parcel.writeInt(mBoundsInScreen.bottom);
3189 parcel.writeInt(mBoundsInScreen.left);
3190 parcel.writeInt(mBoundsInScreen.right);
3191 }
3192
3193 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3194 if (mActions != null && !mActions.isEmpty()) {
3195 final int actionCount = mActions.size();
3196
Eugene Susla554edd32017-05-24 16:49:59 -07003197 int nonStandardActionCount = 0;
3198 int defaultStandardActions = 0;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003199 for (int i = 0; i < actionCount; i++) {
3200 AccessibilityAction action = mActions.get(i);
Eugene Susla554edd32017-05-24 16:49:59 -07003201 if (isDefaultStandardAction(action)) {
3202 defaultStandardActions |= action.mSerializationFlag;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003203 } else {
Eugene Susla554edd32017-05-24 16:49:59 -07003204 nonStandardActionCount++;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003205 }
Kristian Monsen74bc1942014-04-29 11:00:17 -07003206 }
Eugene Susla554edd32017-05-24 16:49:59 -07003207 parcel.writeInt(defaultStandardActions);
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003208
Eugene Susla554edd32017-05-24 16:49:59 -07003209 parcel.writeInt(nonStandardActionCount);
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003210 for (int i = 0; i < actionCount; i++) {
3211 AccessibilityAction action = mActions.get(i);
Eugene Susla554edd32017-05-24 16:49:59 -07003212 if (!isDefaultStandardAction(action)) {
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003213 parcel.writeInt(action.getId());
3214 parcel.writeCharSequence(action.getLabel());
3215 }
3216 }
3217 } else {
3218 parcel.writeInt(0);
3219 parcel.writeInt(0);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003220 }
Kristian Monsen74bc1942014-04-29 11:00:17 -07003221 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003222
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003223 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mMaxTextLength);
3224 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mMovementGranularities);
3225 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mBooleanProperties);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003226
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003227 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mPackageName);
3228 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mClassName);
3229 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mText);
3230 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mHintText);
3231 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mError);
3232 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3233 parcel.writeCharSequence(mContentDescription);
Phil Weaverc2e28932016-12-08 12:29:25 -08003234 }
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003235 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeString(mViewIdResourceName);
Svetoslav6254f482013-06-04 17:22:14 -07003236
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003237 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mTextSelectionStart);
3238 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mTextSelectionEnd);
3239 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mInputType);
3240 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mLiveRegion);
3241 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mDrawingOrderInParent);
Svetoslavbcc46a02013-02-06 11:56:00 -08003242
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003243 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeStringList(mExtraDataKeys);
3244
3245 if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeBundle(mExtras);
3246
3247 if (isBitSet(nonDefaultFields, fieldIndex++)) {
Svetoslav3577a282013-06-06 14:09:10 -07003248 parcel.writeInt(mRangeInfo.getType());
3249 parcel.writeFloat(mRangeInfo.getMin());
3250 parcel.writeFloat(mRangeInfo.getMax());
3251 parcel.writeFloat(mRangeInfo.getCurrent());
Svetoslav3577a282013-06-06 14:09:10 -07003252 }
3253
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003254 if (isBitSet(nonDefaultFields, fieldIndex++)) {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003255 parcel.writeInt(mCollectionInfo.getRowCount());
3256 parcel.writeInt(mCollectionInfo.getColumnCount());
Svetoslav3577a282013-06-06 14:09:10 -07003257 parcel.writeInt(mCollectionInfo.isHierarchical() ? 1 : 0);
Alan Viverette76769ae2014-02-12 16:38:10 -08003258 parcel.writeInt(mCollectionInfo.getSelectionMode());
Svetoslav3577a282013-06-06 14:09:10 -07003259 }
3260
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003261 if (isBitSet(nonDefaultFields, fieldIndex++)) {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07003262 parcel.writeInt(mCollectionItemInfo.getRowIndex());
3263 parcel.writeInt(mCollectionItemInfo.getRowSpan());
Alan Viverettefaeac962015-06-01 09:03:27 -07003264 parcel.writeInt(mCollectionItemInfo.getColumnIndex());
3265 parcel.writeInt(mCollectionItemInfo.getColumnSpan());
Svetoslav3577a282013-06-06 14:09:10 -07003266 parcel.writeInt(mCollectionItemInfo.isHeading() ? 1 : 0);
Alan Viverette76769ae2014-02-12 16:38:10 -08003267 parcel.writeInt(mCollectionItemInfo.isSelected() ? 1 : 0);
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003268 }
3269
3270 if (DEBUG) {
3271 fieldIndex--;
3272 if (totalFields != fieldIndex) {
3273 throw new IllegalStateException("Number of fields mismatch: " + totalFields
3274 + " vs " + fieldIndex);
3275 }
Svetoslav3577a282013-06-06 14:09:10 -07003276 }
3277
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003278 // Since instances of this class are fetched via synchronous i.e. blocking
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003279 // calls in IPCs we always recycle as soon as the instance is marshaled.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003280 recycle();
3281 }
3282
3283 /**
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003284 * Initializes this instance from another one.
3285 *
3286 * @param other The other instance.
3287 */
3288 private void init(AccessibilityNodeInfo other) {
3289 mSealed = other.mSealed;
Svetoslav Ganov02107852011-10-03 17:06:56 -07003290 mSourceNodeId = other.mSourceNodeId;
3291 mParentNodeId = other.mParentNodeId;
Svetoslav Ganov33aef982012-09-13 12:49:03 -07003292 mLabelForId = other.mLabelForId;
3293 mLabeledById = other.mLabeledById;
Svetoslav6c702902014-10-09 18:40:56 -07003294 mTraversalBefore = other.mTraversalBefore;
3295 mTraversalAfter = other.mTraversalAfter;
Svetoslav Ganov02107852011-10-03 17:06:56 -07003296 mWindowId = other.mWindowId;
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -08003297 mConnectionId = other.mConnectionId;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003298 mBoundsInParent.set(other.mBoundsInParent);
3299 mBoundsInScreen.set(other.mBoundsInScreen);
3300 mPackageName = other.mPackageName;
3301 mClassName = other.mClassName;
3302 mText = other.mText;
Phil Weaver776afc22016-12-21 10:55:13 -08003303 mHintText = other.mHintText;
Alan Viverettefccbff52014-07-07 15:06:14 -07003304 mError = other.mError;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003305 mContentDescription = other.mContentDescription;
Svetoslav22431a32013-02-05 14:30:19 -08003306 mViewIdResourceName = other.mViewIdResourceName;
Kristian Monsen74bc1942014-04-29 11:00:17 -07003307
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003308 if (mActions != null) mActions.clear();
Kristian Monsen74bc1942014-04-29 11:00:17 -07003309 final ArrayList<AccessibilityAction> otherActions = other.mActions;
3310 if (otherActions != null && otherActions.size() > 0) {
3311 if (mActions == null) {
3312 mActions = new ArrayList(otherActions);
3313 } else {
Kristian Monsen74bc1942014-04-29 11:00:17 -07003314 mActions.addAll(other.mActions);
3315 }
3316 }
3317
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003318 mBooleanProperties = other.mBooleanProperties;
Alan Viverette029942f2014-08-12 14:55:56 -07003319 mMaxTextLength = other.mMaxTextLength;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003320 mMovementGranularities = other.mMovementGranularities;
Alan Viverettef0aed092013-11-06 15:33:03 -08003321
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003322
3323 if (mChildNodeIds != null) mChildNodeIds.clear();
Alan Viverettef0aed092013-11-06 15:33:03 -08003324 final LongArray otherChildNodeIds = other.mChildNodeIds;
3325 if (otherChildNodeIds != null && otherChildNodeIds.size() > 0) {
3326 if (mChildNodeIds == null) {
3327 mChildNodeIds = otherChildNodeIds.clone();
3328 } else {
3329 mChildNodeIds.addAll(otherChildNodeIds);
3330 }
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003331 }
Alan Viverettef0aed092013-11-06 15:33:03 -08003332
Svetoslavbcc46a02013-02-06 11:56:00 -08003333 mTextSelectionStart = other.mTextSelectionStart;
3334 mTextSelectionEnd = other.mTextSelectionEnd;
Svetoslav6254f482013-06-04 17:22:14 -07003335 mInputType = other.mInputType;
Alan Viverette77e9a282013-09-12 17:16:09 -07003336 mLiveRegion = other.mLiveRegion;
Phil Weaver1f222542016-01-08 11:49:32 -08003337 mDrawingOrderInParent = other.mDrawingOrderInParent;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003338
Phil Weaverc2e28932016-12-08 12:29:25 -08003339 mExtraDataKeys = other.mExtraDataKeys;
3340
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003341 mExtras = other.mExtras != null ? new Bundle(other.mExtras) : null;
3342
3343 if (mRangeInfo != null) mRangeInfo.recycle();
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07003344 mRangeInfo = (other.mRangeInfo != null)
3345 ? RangeInfo.obtain(other.mRangeInfo) : null;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003346 if (mCollectionInfo != null) mCollectionInfo.recycle();
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07003347 mCollectionInfo = (other.mCollectionInfo != null)
3348 ? CollectionInfo.obtain(other.mCollectionInfo) : null;
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003349 if (mCollectionItemInfo != null) mCollectionItemInfo.recycle();
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07003350 mCollectionItemInfo = (other.mCollectionItemInfo != null)
3351 ? CollectionItemInfo.obtain(other.mCollectionItemInfo) : null;
Svetoslav Ganov35bfede2011-07-14 17:57:06 -07003352 }
3353
3354 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003355 * Creates a new instance from a {@link Parcel}.
3356 *
3357 * @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}.
3358 */
3359 private void initFromParcel(Parcel parcel) {
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003360 // Bit mask of non-default-valued field indices
3361 long nonDefaultFields = parcel.readLong();
3362 int fieldIndex = 0;
3363 final boolean sealed = isBitSet(nonDefaultFields, fieldIndex++)
3364 ? (parcel.readInt() == 1)
3365 : DEFAULT.mSealed;
3366 if (isBitSet(nonDefaultFields, fieldIndex++)) mSourceNodeId = parcel.readLong();
3367 if (isBitSet(nonDefaultFields, fieldIndex++)) mWindowId = parcel.readInt();
3368 if (isBitSet(nonDefaultFields, fieldIndex++)) mParentNodeId = parcel.readLong();
3369 if (isBitSet(nonDefaultFields, fieldIndex++)) mLabelForId = parcel.readLong();
3370 if (isBitSet(nonDefaultFields, fieldIndex++)) mLabeledById = parcel.readLong();
3371 if (isBitSet(nonDefaultFields, fieldIndex++)) mTraversalBefore = parcel.readLong();
3372 if (isBitSet(nonDefaultFields, fieldIndex++)) mTraversalAfter = parcel.readLong();
Svetoslav6c702902014-10-09 18:40:56 -07003373
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003374 if (isBitSet(nonDefaultFields, fieldIndex++)) mConnectionId = parcel.readInt();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003375
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003376 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3377 final int childrenSize = parcel.readInt();
3378 if (childrenSize <= 0) {
3379 mChildNodeIds = null;
3380 } else {
3381 mChildNodeIds = new LongArray(childrenSize);
3382 for (int i = 0; i < childrenSize; i++) {
3383 final long childId = parcel.readLong();
3384 mChildNodeIds.add(childId);
3385 }
Alan Viverettef0aed092013-11-06 15:33:03 -08003386 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003387 }
3388
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003389 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3390 mBoundsInParent.top = parcel.readInt();
3391 mBoundsInParent.bottom = parcel.readInt();
3392 mBoundsInParent.left = parcel.readInt();
3393 mBoundsInParent.right = parcel.readInt();
Kristian Monsen74bc1942014-04-29 11:00:17 -07003394 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003395
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003396 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3397 mBoundsInScreen.top = parcel.readInt();
3398 mBoundsInScreen.bottom = parcel.readInt();
3399 mBoundsInScreen.left = parcel.readInt();
3400 mBoundsInScreen.right = parcel.readInt();
Phil Weaverc2e28932016-12-08 12:29:25 -08003401 }
3402
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003403 if (isBitSet(nonDefaultFields, fieldIndex++)) {
Eugene Susla554edd32017-05-24 16:49:59 -07003404 final int standardActions = parcel.readInt();
3405 addStandardActions(standardActions);
3406 final int nonStandardActionCount = parcel.readInt();
3407 for (int i = 0; i < nonStandardActionCount; i++) {
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003408 final AccessibilityAction action = new AccessibilityAction(
3409 parcel.readInt(), parcel.readCharSequence());
3410 addActionUnchecked(action);
3411 }
Svetoslav6254f482013-06-04 17:22:14 -07003412 }
Svetoslav3577a282013-06-06 14:09:10 -07003413
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003414 if (isBitSet(nonDefaultFields, fieldIndex++)) mMaxTextLength = parcel.readInt();
3415 if (isBitSet(nonDefaultFields, fieldIndex++)) mMovementGranularities = parcel.readInt();
3416 if (isBitSet(nonDefaultFields, fieldIndex++)) mBooleanProperties = parcel.readInt();
Svetoslav3577a282013-06-06 14:09:10 -07003417
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003418 if (isBitSet(nonDefaultFields, fieldIndex++)) mPackageName = parcel.readCharSequence();
3419 if (isBitSet(nonDefaultFields, fieldIndex++)) mClassName = parcel.readCharSequence();
3420 if (isBitSet(nonDefaultFields, fieldIndex++)) mText = parcel.readCharSequence();
3421 if (isBitSet(nonDefaultFields, fieldIndex++)) mHintText = parcel.readCharSequence();
3422 if (isBitSet(nonDefaultFields, fieldIndex++)) mError = parcel.readCharSequence();
3423 if (isBitSet(nonDefaultFields, fieldIndex++)) {
3424 mContentDescription = parcel.readCharSequence();
Svetoslav3577a282013-06-06 14:09:10 -07003425 }
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003426 if (isBitSet(nonDefaultFields, fieldIndex++)) mViewIdResourceName = parcel.readString();
Svetoslav3577a282013-06-06 14:09:10 -07003427
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003428 if (isBitSet(nonDefaultFields, fieldIndex++)) mTextSelectionStart = parcel.readInt();
3429 if (isBitSet(nonDefaultFields, fieldIndex++)) mTextSelectionEnd = parcel.readInt();
3430
3431 if (isBitSet(nonDefaultFields, fieldIndex++)) mInputType = parcel.readInt();
3432 if (isBitSet(nonDefaultFields, fieldIndex++)) mLiveRegion = parcel.readInt();
3433 if (isBitSet(nonDefaultFields, fieldIndex++)) mDrawingOrderInParent = parcel.readInt();
3434
3435 mExtraDataKeys = isBitSet(nonDefaultFields, fieldIndex++)
3436 ? parcel.createStringArrayList()
3437 : null;
3438
3439 mExtras = isBitSet(nonDefaultFields, fieldIndex++)
3440 ? parcel.readBundle()
3441 : null;
3442
3443 if (mRangeInfo != null) mRangeInfo.recycle();
3444 mRangeInfo = isBitSet(nonDefaultFields, fieldIndex++)
3445 ? RangeInfo.obtain(
3446 parcel.readInt(),
3447 parcel.readFloat(),
3448 parcel.readFloat(),
3449 parcel.readFloat())
3450 : null;
3451
3452 if (mCollectionInfo != null) mCollectionInfo.recycle();
3453 mCollectionInfo = isBitSet(nonDefaultFields, fieldIndex++)
3454 ? CollectionInfo.obtain(
3455 parcel.readInt(),
3456 parcel.readInt(),
3457 parcel.readInt() == 1,
3458 parcel.readInt())
3459 : null;
3460
3461 if (mCollectionItemInfo != null) mCollectionItemInfo.recycle();
3462 mCollectionItemInfo = isBitSet(nonDefaultFields, fieldIndex++)
3463 ? CollectionItemInfo.obtain(
3464 parcel.readInt(),
3465 parcel.readInt(),
3466 parcel.readInt(),
3467 parcel.readInt(),
3468 parcel.readInt() == 1,
3469 parcel.readInt() == 1)
3470 : null;
Maxim Bogatov2f55a3f2015-06-09 15:00:44 -07003471
3472 mSealed = sealed;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003473 }
3474
3475 /**
3476 * Clears the state of this instance.
3477 */
3478 private void clear() {
Eugene Susla0eb2b6e2017-05-15 14:06:32 -07003479 init(DEFAULT);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003480 }
3481
Eugene Susla554edd32017-05-24 16:49:59 -07003482 private static boolean isDefaultStandardAction(AccessibilityAction action) {
3483 return action.mSerializationFlag != -1 && TextUtils.isEmpty(action.getLabel());
Kristian Monsen74bc1942014-04-29 11:00:17 -07003484 }
3485
3486 private static AccessibilityAction getActionSingleton(int actionId) {
3487 final int actions = AccessibilityAction.sStandardActions.size();
3488 for (int i = 0; i < actions; i++) {
3489 AccessibilityAction currentAction = AccessibilityAction.sStandardActions.valueAt(i);
3490 if (actionId == currentAction.getId()) {
3491 return currentAction;
3492 }
3493 }
3494
3495 return null;
3496 }
3497
Eugene Susla554edd32017-05-24 16:49:59 -07003498 private static AccessibilityAction getActionSingletonBySerializationFlag(int flag) {
3499 final int actions = AccessibilityAction.sStandardActions.size();
3500 for (int i = 0; i < actions; i++) {
3501 AccessibilityAction currentAction = AccessibilityAction.sStandardActions.valueAt(i);
3502 if (flag == currentAction.mSerializationFlag) {
3503 return currentAction;
3504 }
3505 }
3506
3507 return null;
3508 }
3509
3510 private void addStandardActions(int serializationIdMask) {
3511 int remainingIds = serializationIdMask;
Kristian Monsen74bc1942014-04-29 11:00:17 -07003512 while (remainingIds > 0) {
3513 final int id = 1 << Integer.numberOfTrailingZeros(remainingIds);
3514 remainingIds &= ~id;
Eugene Susla554edd32017-05-24 16:49:59 -07003515 AccessibilityAction action = getActionSingletonBySerializationFlag(id);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003516 addAction(action);
3517 }
3518 }
3519
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003520 /**
3521 * Gets the human readable action symbolic name.
3522 *
3523 * @param action The action.
3524 * @return The symbolic name.
3525 */
3526 private static String getActionSymbolicName(int action) {
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003527 switch (action) {
3528 case ACTION_FOCUS:
3529 return "ACTION_FOCUS";
3530 case ACTION_CLEAR_FOCUS:
3531 return "ACTION_CLEAR_FOCUS";
3532 case ACTION_SELECT:
3533 return "ACTION_SELECT";
3534 case ACTION_CLEAR_SELECTION:
3535 return "ACTION_CLEAR_SELECTION";
Svetoslav Ganove9bda152012-04-30 16:55:21 -07003536 case ACTION_CLICK:
3537 return "ACTION_CLICK";
3538 case ACTION_LONG_CLICK:
3539 return "ACTION_LONG_CLICK";
3540 case ACTION_ACCESSIBILITY_FOCUS:
3541 return "ACTION_ACCESSIBILITY_FOCUS";
3542 case ACTION_CLEAR_ACCESSIBILITY_FOCUS:
3543 return "ACTION_CLEAR_ACCESSIBILITY_FOCUS";
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003544 case ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
3545 return "ACTION_NEXT_AT_MOVEMENT_GRANULARITY";
3546 case ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY:
3547 return "ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY";
Svetoslav Ganove9bda152012-04-30 16:55:21 -07003548 case ACTION_NEXT_HTML_ELEMENT:
3549 return "ACTION_NEXT_HTML_ELEMENT";
3550 case ACTION_PREVIOUS_HTML_ELEMENT:
3551 return "ACTION_PREVIOUS_HTML_ELEMENT";
Svetoslav Ganova1dc7612012-05-10 04:14:53 -07003552 case ACTION_SCROLL_FORWARD:
3553 return "ACTION_SCROLL_FORWARD";
3554 case ACTION_SCROLL_BACKWARD:
3555 return "ACTION_SCROLL_BACKWARD";
Svetoslav Ganov242724e2013-02-01 14:42:18 -08003556 case ACTION_CUT:
3557 return "ACTION_CUT";
3558 case ACTION_COPY:
3559 return "ACTION_COPY";
3560 case ACTION_PASTE:
3561 return "ACTION_PASTE";
3562 case ACTION_SET_SELECTION:
3563 return "ACTION_SET_SELECTION";
Steven Dao103a577c2015-10-12 17:35:59 -07003564 case ACTION_EXPAND:
3565 return "ACTION_EXPAND";
3566 case ACTION_COLLAPSE:
3567 return "ACTION_COLLAPSE";
3568 case ACTION_DISMISS:
3569 return "ACTION_DISMISS";
3570 case ACTION_SET_TEXT:
3571 return "ACTION_SET_TEXT";
3572 case R.id.accessibilityActionShowOnScreen:
3573 return "ACTION_SHOW_ON_SCREEN";
3574 case R.id.accessibilityActionScrollToPosition:
3575 return "ACTION_SCROLL_TO_POSITION";
3576 case R.id.accessibilityActionScrollUp:
3577 return "ACTION_SCROLL_UP";
3578 case R.id.accessibilityActionScrollLeft:
3579 return "ACTION_SCROLL_LEFT";
3580 case R.id.accessibilityActionScrollDown:
3581 return "ACTION_SCROLL_DOWN";
3582 case R.id.accessibilityActionScrollRight:
3583 return "ACTION_SCROLL_RIGHT";
3584 case R.id.accessibilityActionSetProgress:
3585 return "ACTION_SET_PROGRESS";
3586 case R.id.accessibilityActionContextClick:
3587 return "ACTION_CONTEXT_CLICK";
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -07003588 default:
Steven Dao103a577c2015-10-12 17:35:59 -07003589 return "ACTION_UNKNOWN";
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003590 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003591 }
3592
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003593 /**
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003594 * Gets the human readable movement granularity symbolic name.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003595 *
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003596 * @param granularity The granularity.
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003597 * @return The symbolic name.
3598 */
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003599 private static String getMovementGranularitySymbolicName(int granularity) {
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003600 switch (granularity) {
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003601 case MOVEMENT_GRANULARITY_CHARACTER:
3602 return "MOVEMENT_GRANULARITY_CHARACTER";
3603 case MOVEMENT_GRANULARITY_WORD:
3604 return "MOVEMENT_GRANULARITY_WORD";
3605 case MOVEMENT_GRANULARITY_LINE:
3606 return "MOVEMENT_GRANULARITY_LINE";
3607 case MOVEMENT_GRANULARITY_PARAGRAPH:
3608 return "MOVEMENT_GRANULARITY_PARAGRAPH";
3609 case MOVEMENT_GRANULARITY_PAGE:
3610 return "MOVEMENT_GRANULARITY_PAGE";
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003611 default:
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003612 throw new IllegalArgumentException("Unknown movement granularity: " + granularity);
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003613 }
3614 }
3615
Svetoslav Ganov02107852011-10-03 17:06:56 -07003616 private boolean canPerformRequestOverConnection(long accessibilityNodeId) {
Phil Weaver23161e72017-04-19 12:16:36 -07003617 return ((mWindowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)
3618 && (getAccessibilityViewId(accessibilityNodeId) != UNDEFINED_ITEM_ID)
3619 && (mConnectionId != UNDEFINED_CONNECTION_ID));
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07003620 }
3621
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003622 @Override
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07003623 public boolean equals(Object object) {
3624 if (this == object) {
3625 return true;
3626 }
3627 if (object == null) {
3628 return false;
3629 }
3630 if (getClass() != object.getClass()) {
3631 return false;
3632 }
3633 AccessibilityNodeInfo other = (AccessibilityNodeInfo) object;
Svetoslav Ganov02107852011-10-03 17:06:56 -07003634 if (mSourceNodeId != other.mSourceNodeId) {
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07003635 return false;
3636 }
Svetoslav Ganov02107852011-10-03 17:06:56 -07003637 if (mWindowId != other.mWindowId) {
Svetoslav Ganov8dffad62011-06-10 12:38:36 -07003638 return false;
3639 }
3640 return true;
3641 }
3642
3643 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003644 public int hashCode() {
3645 final int prime = 31;
3646 int result = 1;
Svetoslav Ganov02107852011-10-03 17:06:56 -07003647 result = prime * result + getAccessibilityViewId(mSourceNodeId);
3648 result = prime * result + getVirtualDescendantId(mSourceNodeId);
3649 result = prime * result + mWindowId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003650 return result;
3651 }
3652
3653 @Override
3654 public String toString() {
3655 StringBuilder builder = new StringBuilder();
3656 builder.append(super.toString());
3657
3658 if (DEBUG) {
Svetoslav8e3feb12014-02-24 13:46:47 -08003659 builder.append("; sourceNodeId: " + mSourceNodeId);
Svetoslav Ganov02107852011-10-03 17:06:56 -07003660 builder.append("; accessibilityViewId: " + getAccessibilityViewId(mSourceNodeId));
3661 builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId));
3662 builder.append("; mParentNodeId: " + mParentNodeId);
Svetoslav6c702902014-10-09 18:40:56 -07003663 builder.append("; traversalBefore: ").append(mTraversalBefore);
3664 builder.append("; traversalAfter: ").append(mTraversalAfter);
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003665
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003666 int granularities = mMovementGranularities;
3667 builder.append("; MovementGranularities: [");
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003668 while (granularities != 0) {
3669 final int granularity = 1 << Integer.numberOfTrailingZeros(granularities);
3670 granularities &= ~granularity;
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07003671 builder.append(getMovementGranularitySymbolicName(granularity));
Svetoslav Ganovb7ff3252012-04-24 18:40:07 -07003672 if (granularities != 0) {
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003673 builder.append(", ");
3674 }
3675 }
3676 builder.append("]");
3677
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003678 builder.append("; childAccessibilityIds: [");
Alan Viverettef0aed092013-11-06 15:33:03 -08003679 final LongArray childIds = mChildNodeIds;
3680 if (childIds != null) {
3681 for (int i = 0, count = childIds.size(); i < count; i++) {
3682 builder.append(childIds.get(i));
3683 if (i < count - 1) {
3684 builder.append(", ");
3685 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003686 }
Svetoslav Ganovaa780c12012-04-19 23:01:39 -07003687 }
3688 builder.append("]");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003689 }
3690
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07003691 builder.append("; boundsInParent: " + mBoundsInParent);
3692 builder.append("; boundsInScreen: " + mBoundsInScreen);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003693
3694 builder.append("; packageName: ").append(mPackageName);
3695 builder.append("; className: ").append(mClassName);
3696 builder.append("; text: ").append(mText);
Alan Viverettefccbff52014-07-07 15:06:14 -07003697 builder.append("; error: ").append(mError);
Alan Viverette029942f2014-08-12 14:55:56 -07003698 builder.append("; maxTextLength: ").append(mMaxTextLength);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003699 builder.append("; contentDescription: ").append(mContentDescription);
Svetoslav22431a32013-02-05 14:30:19 -08003700 builder.append("; viewIdResName: ").append(mViewIdResourceName);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003701
3702 builder.append("; checkable: ").append(isCheckable());
3703 builder.append("; checked: ").append(isChecked());
3704 builder.append("; focusable: ").append(isFocusable());
3705 builder.append("; focused: ").append(isFocused());
3706 builder.append("; selected: ").append(isSelected());
3707 builder.append("; clickable: ").append(isClickable());
3708 builder.append("; longClickable: ").append(isLongClickable());
Mady Mellore8608912015-06-05 09:02:55 -07003709 builder.append("; contextClickable: ").append(isContextClickable());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003710 builder.append("; enabled: ").append(isEnabled());
3711 builder.append("; password: ").append(isPassword());
Kristian Monsen74bc1942014-04-29 11:00:17 -07003712 builder.append("; scrollable: ").append(isScrollable());
Phil Weaver4d3eec412016-09-01 16:28:34 -07003713 builder.append("; importantForAccessibility: ").append(isImportantForAccessibility());
Kristian Monsen74bc1942014-04-29 11:00:17 -07003714 builder.append("; actions: ").append(mActions);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003715
3716 return builder.toString();
3717 }
3718
Svetoslav6c702902014-10-09 18:40:56 -07003719 private AccessibilityNodeInfo getNodeForAccessibilityId(long accessibilityId) {
3720 if (!canPerformRequestOverConnection(accessibilityId)) {
3721 return null;
3722 }
3723 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
3724 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
3725 mWindowId, accessibilityId, false, FLAG_PREFETCH_PREDECESSORS
Phil Weaverc2e28932016-12-08 12:29:25 -08003726 | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS, null);
Svetoslav6c702902014-10-09 18:40:56 -07003727 }
3728
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07003729 /**
Kristian Monsen74bc1942014-04-29 11:00:17 -07003730 * A class defining an action that can be performed on an {@link AccessibilityNodeInfo}.
3731 * Each action has a unique id that is mandatory and optional data.
3732 * <p>
3733 * There are three categories of actions:
3734 * <ul>
3735 * <li><strong>Standard actions</strong> - These are actions that are reported and
3736 * handled by the standard UI widgets in the platform. For each standard action
3737 * there is a static constant defined in this class, e.g. {@link #ACTION_FOCUS}.
Phil Weaver426361c2017-02-22 13:06:25 -08003738 * These actions will have {@code null} labels.
Kristian Monsen74bc1942014-04-29 11:00:17 -07003739 * </li>
3740 * <li><strong>Custom actions action</strong> - These are actions that are reported
3741 * and handled by custom widgets. i.e. ones that are not part of the UI toolkit. For
3742 * example, an application may define a custom action for clearing the user history.
3743 * </li>
3744 * <li><strong>Overriden standard actions</strong> - These are actions that override
3745 * standard actions to customize them. For example, an app may add a label to the
Casey Burkhardt7ef48be2016-01-31 11:51:09 -08003746 * standard {@link #ACTION_CLICK} action to announce that this action clears browsing history.
Kristian Monsen74bc1942014-04-29 11:00:17 -07003747 * </ul>
3748 * </p>
Casey Burkhardt7ef48be2016-01-31 11:51:09 -08003749 * <p>
3750 * Actions are typically added to an {@link AccessibilityNodeInfo} by using
3751 * {@link AccessibilityNodeInfo#addAction(AccessibilityAction)} within
3752 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} and are performed
3753 * within {@link View#performAccessibilityAction(int, Bundle)}.
3754 * </p>
3755 * <p class="note">
3756 * <strong>Note:</strong> Views which support these actions should invoke
3757 * {@link View#setImportantForAccessibility(int)} with
3758 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_YES} to ensure an {@link AccessibilityService}
3759 * can discover the set of supported actions.
3760 * </p>
Kristian Monsen74bc1942014-04-29 11:00:17 -07003761 */
3762 public static final class AccessibilityAction {
3763
Eugene Susla554edd32017-05-24 16:49:59 -07003764 /** @hide */
3765 public static final ArraySet<AccessibilityAction> sStandardActions = new ArraySet<>();
3766
Kristian Monsen74bc1942014-04-29 11:00:17 -07003767 /**
3768 * Action that gives input focus to the node.
3769 */
3770 public static final AccessibilityAction ACTION_FOCUS =
Eugene Susla554edd32017-05-24 16:49:59 -07003771 new AccessibilityAction(AccessibilityNodeInfo.ACTION_FOCUS);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003772
3773 /**
3774 * Action that clears input focus of the node.
3775 */
3776 public static final AccessibilityAction ACTION_CLEAR_FOCUS =
Eugene Susla554edd32017-05-24 16:49:59 -07003777 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003778
3779 /**
3780 * Action that selects the node.
3781 */
3782 public static final AccessibilityAction ACTION_SELECT =
Eugene Susla554edd32017-05-24 16:49:59 -07003783 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SELECT);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003784
3785 /**
3786 * Action that deselects the node.
3787 */
3788 public static final AccessibilityAction ACTION_CLEAR_SELECTION =
Eugene Susla554edd32017-05-24 16:49:59 -07003789 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003790
3791 /**
3792 * Action that clicks on the node info.
3793 */
3794 public static final AccessibilityAction ACTION_CLICK =
Eugene Susla554edd32017-05-24 16:49:59 -07003795 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003796
3797 /**
3798 * Action that long clicks on the node.
3799 */
3800 public static final AccessibilityAction ACTION_LONG_CLICK =
Eugene Susla554edd32017-05-24 16:49:59 -07003801 new AccessibilityAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003802
3803 /**
3804 * Action that gives accessibility focus to the node.
3805 */
3806 public static final AccessibilityAction ACTION_ACCESSIBILITY_FOCUS =
Eugene Susla554edd32017-05-24 16:49:59 -07003807 new AccessibilityAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003808
3809 /**
3810 * Action that clears accessibility focus of the node.
3811 */
3812 public static final AccessibilityAction ACTION_CLEAR_ACCESSIBILITY_FOCUS =
Eugene Susla554edd32017-05-24 16:49:59 -07003813 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003814
3815 /**
3816 * Action that requests to go to the next entity in this node's text
3817 * at a given movement granularity. For example, move to the next character,
3818 * word, etc.
3819 * <p>
3820 * <strong>Arguments:</strong>
3821 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3822 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT},
3823 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3824 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
3825 * <strong>Example:</strong> Move to the previous character and do not extend selection.
3826 * <code><pre><p>
3827 * Bundle arguments = new Bundle();
3828 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
3829 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
3830 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
3831 * false);
3832 * info.performAction(AccessibilityAction.ACTION_NEXT_AT_MOVEMENT_GRANULARITY.getId(),
3833 * arguments);
3834 * </code></pre></p>
3835 * </p>
3836 *
3837 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3838 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3839 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3840 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3841 *
3842 * @see AccessibilityNodeInfo#setMovementGranularities(int)
3843 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3844 * @see AccessibilityNodeInfo#getMovementGranularities()
3845 * AccessibilityNodeInfo.getMovementGranularities()
3846 *
3847 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_CHARACTER
3848 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
3849 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_WORD
3850 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
3851 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_LINE
3852 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
3853 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PARAGRAPH
3854 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
3855 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PAGE
3856 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE
3857 */
3858 public static final AccessibilityAction ACTION_NEXT_AT_MOVEMENT_GRANULARITY =
Eugene Susla554edd32017-05-24 16:49:59 -07003859 new AccessibilityAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003860
3861 /**
3862 * Action that requests to go to the previous entity in this node's text
3863 * at a given movement granularity. For example, move to the next character,
3864 * word, etc.
3865 * <p>
3866 * <strong>Arguments:</strong>
3867 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3868 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT},
3869 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3870 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
3871 * <strong>Example:</strong> Move to the next character and do not extend selection.
3872 * <code><pre><p>
3873 * Bundle arguments = new Bundle();
3874 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
3875 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
3876 * arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
3877 * false);
3878 * info.performAction(AccessibilityAction.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY.getId(),
3879 * arguments);
3880 * </code></pre></p>
3881 * </p>
3882 *
3883 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3884 * AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
3885 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3886 * AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
3887 *
3888 * @see AccessibilityNodeInfo#setMovementGranularities(int)
3889 * AccessibilityNodeInfo.setMovementGranularities(int)
3890 * @see AccessibilityNodeInfo#getMovementGranularities()
3891 * AccessibilityNodeInfo.getMovementGranularities()
3892 *
3893 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_CHARACTER
3894 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
3895 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_WORD
3896 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
3897 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_LINE
3898 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
3899 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PARAGRAPH
3900 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
3901 * @see AccessibilityNodeInfo#MOVEMENT_GRANULARITY_PAGE
3902 * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE
3903 */
3904 public static final AccessibilityAction ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY =
3905 new AccessibilityAction(
Eugene Susla554edd32017-05-24 16:49:59 -07003906 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003907
3908 /**
3909 * Action to move to the next HTML element of a given type. For example, move
3910 * to the BUTTON, INPUT, TABLE, etc.
3911 * <p>
3912 * <strong>Arguments:</strong>
3913 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_HTML_ELEMENT_STRING
3914 * AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
3915 * <strong>Example:</strong>
3916 * <code><pre><p>
3917 * Bundle arguments = new Bundle();
3918 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
3919 * info.performAction(AccessibilityAction.ACTION_NEXT_HTML_ELEMENT.getId(), arguments);
3920 * </code></pre></p>
3921 * </p>
3922 */
3923 public static final AccessibilityAction ACTION_NEXT_HTML_ELEMENT =
Eugene Susla554edd32017-05-24 16:49:59 -07003924 new AccessibilityAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003925
3926 /**
3927 * Action to move to the previous HTML element of a given type. For example, move
3928 * to the BUTTON, INPUT, TABLE, etc.
3929 * <p>
3930 * <strong>Arguments:</strong>
3931 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_HTML_ELEMENT_STRING
3932 * AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
3933 * <strong>Example:</strong>
3934 * <code><pre><p>
3935 * Bundle arguments = new Bundle();
3936 * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
3937 * info.performAction(AccessibilityAction.ACTION_PREVIOUS_HTML_ELEMENT.getId(), arguments);
3938 * </code></pre></p>
3939 * </p>
3940 */
3941 public static final AccessibilityAction ACTION_PREVIOUS_HTML_ELEMENT =
Eugene Susla554edd32017-05-24 16:49:59 -07003942 new AccessibilityAction(AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003943
3944 /**
3945 * Action to scroll the node content forward.
3946 */
3947 public static final AccessibilityAction ACTION_SCROLL_FORWARD =
Eugene Susla554edd32017-05-24 16:49:59 -07003948 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003949
3950 /**
3951 * Action to scroll the node content backward.
3952 */
3953 public static final AccessibilityAction ACTION_SCROLL_BACKWARD =
Eugene Susla554edd32017-05-24 16:49:59 -07003954 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003955
3956 /**
3957 * Action to copy the current selection to the clipboard.
3958 */
3959 public static final AccessibilityAction ACTION_COPY =
Eugene Susla554edd32017-05-24 16:49:59 -07003960 new AccessibilityAction(AccessibilityNodeInfo.ACTION_COPY);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003961
3962 /**
3963 * Action to paste the current clipboard content.
3964 */
3965 public static final AccessibilityAction ACTION_PASTE =
Eugene Susla554edd32017-05-24 16:49:59 -07003966 new AccessibilityAction(AccessibilityNodeInfo.ACTION_PASTE);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003967
3968 /**
3969 * Action to cut the current selection and place it to the clipboard.
3970 */
3971 public static final AccessibilityAction ACTION_CUT =
Eugene Susla554edd32017-05-24 16:49:59 -07003972 new AccessibilityAction(AccessibilityNodeInfo.ACTION_CUT);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003973
3974 /**
3975 * Action to set the selection. Performing this action with no arguments
3976 * clears the selection.
3977 * <p>
3978 * <strong>Arguments:</strong>
3979 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_START_INT
3980 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT},
3981 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_END_INT
3982 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT}<br>
3983 * <strong>Example:</strong>
3984 * <code><pre><p>
3985 * Bundle arguments = new Bundle();
3986 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1);
3987 * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 2);
3988 * info.performAction(AccessibilityAction.ACTION_SET_SELECTION.getId(), arguments);
3989 * </code></pre></p>
3990 * </p>
3991 *
3992 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_START_INT
3993 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT
3994 * @see AccessibilityNodeInfo#ACTION_ARGUMENT_SELECTION_END_INT
3995 * AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT
3996 */
3997 public static final AccessibilityAction ACTION_SET_SELECTION =
Eugene Susla554edd32017-05-24 16:49:59 -07003998 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
Kristian Monsen74bc1942014-04-29 11:00:17 -07003999
4000 /**
4001 * Action to expand an expandable node.
4002 */
4003 public static final AccessibilityAction ACTION_EXPAND =
Eugene Susla554edd32017-05-24 16:49:59 -07004004 new AccessibilityAction(AccessibilityNodeInfo.ACTION_EXPAND);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004005
4006 /**
4007 * Action to collapse an expandable node.
4008 */
4009 public static final AccessibilityAction ACTION_COLLAPSE =
Eugene Susla554edd32017-05-24 16:49:59 -07004010 new AccessibilityAction(AccessibilityNodeInfo.ACTION_COLLAPSE);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004011
4012 /**
4013 * Action to dismiss a dismissable node.
4014 */
4015 public static final AccessibilityAction ACTION_DISMISS =
Eugene Susla554edd32017-05-24 16:49:59 -07004016 new AccessibilityAction(AccessibilityNodeInfo.ACTION_DISMISS);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004017
4018 /**
4019 * Action that sets the text of the node. Performing the action without argument,
4020 * using <code> null</code> or empty {@link CharSequence} will clear the text. This
4021 * action will also put the cursor at the end of text.
4022 * <p>
4023 * <strong>Arguments:</strong>
4024 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE
4025 * AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br>
4026 * <strong>Example:</strong>
4027 * <code><pre><p>
4028 * Bundle arguments = new Bundle();
4029 * arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
4030 * "android");
4031 * info.performAction(AccessibilityAction.ACTION_SET_TEXT.getId(), arguments);
4032 * </code></pre></p>
4033 */
4034 public static final AccessibilityAction ACTION_SET_TEXT =
Eugene Susla554edd32017-05-24 16:49:59 -07004035 new AccessibilityAction(AccessibilityNodeInfo.ACTION_SET_TEXT);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004036
Alan Viverette26c44ee2015-03-25 14:54:13 -07004037 /**
4038 * Action that requests the node make its bounding rectangle visible
4039 * on the screen, scrolling if necessary just enough.
4040 *
4041 * @see View#requestRectangleOnScreen(Rect)
4042 */
4043 public static final AccessibilityAction ACTION_SHOW_ON_SCREEN =
Eugene Susla554edd32017-05-24 16:49:59 -07004044 new AccessibilityAction(R.id.accessibilityActionShowOnScreen);
Alan Viverette26c44ee2015-03-25 14:54:13 -07004045
Alan Viverette23f44322015-04-06 16:04:56 -07004046 /**
4047 * Action that scrolls the node to make the specified collection
4048 * position visible on screen.
4049 * <p>
4050 * <strong>Arguments:</strong>
4051 * <ul>
4052 * <li>{@link AccessibilityNodeInfo#ACTION_ARGUMENT_ROW_INT}</li>
4053 * <li>{@link AccessibilityNodeInfo#ACTION_ARGUMENT_COLUMN_INT}</li>
4054 * <ul>
4055 *
4056 * @see AccessibilityNodeInfo#getCollectionInfo()
4057 */
4058 public static final AccessibilityAction ACTION_SCROLL_TO_POSITION =
Eugene Susla554edd32017-05-24 16:49:59 -07004059 new AccessibilityAction(R.id.accessibilityActionScrollToPosition);
Alan Viverette23f44322015-04-06 16:04:56 -07004060
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004061 /**
4062 * Action to scroll the node content up.
4063 */
4064 public static final AccessibilityAction ACTION_SCROLL_UP =
Eugene Susla554edd32017-05-24 16:49:59 -07004065 new AccessibilityAction(R.id.accessibilityActionScrollUp);
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004066
4067 /**
4068 * Action to scroll the node content left.
4069 */
4070 public static final AccessibilityAction ACTION_SCROLL_LEFT =
Eugene Susla554edd32017-05-24 16:49:59 -07004071 new AccessibilityAction(R.id.accessibilityActionScrollLeft);
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004072
4073 /**
4074 * Action to scroll the node content down.
4075 */
4076 public static final AccessibilityAction ACTION_SCROLL_DOWN =
Eugene Susla554edd32017-05-24 16:49:59 -07004077 new AccessibilityAction(R.id.accessibilityActionScrollDown);
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004078
4079 /**
4080 * Action to scroll the node content right.
4081 */
Maxim Bogatov32e59d52015-04-30 16:57:33 -07004082 public static final AccessibilityAction ACTION_SCROLL_RIGHT =
Eugene Susla554edd32017-05-24 16:49:59 -07004083 new AccessibilityAction(R.id.accessibilityActionScrollRight);
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004084
Mady Mellord2744002015-04-30 16:17:16 -07004085 /**
Mady Mellore8608912015-06-05 09:02:55 -07004086 * Action that context clicks the node.
Mady Mellore82067b2015-04-30 09:58:35 -07004087 */
Mady Mellore8608912015-06-05 09:02:55 -07004088 public static final AccessibilityAction ACTION_CONTEXT_CLICK =
Eugene Susla554edd32017-05-24 16:49:59 -07004089 new AccessibilityAction(R.id.accessibilityActionContextClick);
Maxim Bogatovac6ffce2015-04-27 13:45:52 -07004090
Maxim Bogatov32e59d52015-04-30 16:57:33 -07004091 /**
4092 * Action that sets progress between {@link RangeInfo#getMin() RangeInfo.getMin()} and
4093 * {@link RangeInfo#getMax() RangeInfo.getMax()}. It should use the same value type as
4094 * {@link RangeInfo#getType() RangeInfo.getType()}
4095 * <p>
4096 * <strong>Arguments:</strong>
4097 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_PROGRESS_VALUE}
4098 *
4099 * @see RangeInfo
4100 */
4101 public static final AccessibilityAction ACTION_SET_PROGRESS =
Eugene Susla554edd32017-05-24 16:49:59 -07004102 new AccessibilityAction(R.id.accessibilityActionSetProgress);
Maxim Bogatov32e59d52015-04-30 16:57:33 -07004103
Phil Weaverf00cd142017-03-03 13:44:00 -08004104 /**
4105 * Action to move a window to a new location.
4106 * <p>
4107 * <strong>Arguments:</strong>
4108 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVE_WINDOW_X}
4109 * {@link AccessibilityNodeInfo#ACTION_ARGUMENT_MOVE_WINDOW_Y}
4110 */
4111 public static final AccessibilityAction ACTION_MOVE_WINDOW =
Eugene Susla554edd32017-05-24 16:49:59 -07004112 new AccessibilityAction(R.id.accessibilityActionMoveWindow);
Kristian Monsen74bc1942014-04-29 11:00:17 -07004113
4114 private final int mActionId;
4115 private final CharSequence mLabel;
4116
Eugene Susla554edd32017-05-24 16:49:59 -07004117 /** @hide */
4118 public int mSerializationFlag = -1;
4119
Kristian Monsen74bc1942014-04-29 11:00:17 -07004120 /**
4121 * Creates a new AccessibilityAction. For adding a standard action without a specific label,
4122 * use the static constants.
4123 *
4124 * You can also override the description for one the standard actions. Below is an example
4125 * how to override the standard click action by adding a custom label:
4126 * <pre>
4127 * AccessibilityAction action = new AccessibilityAction(
Phil Weaverc3791292016-09-12 11:06:49 -07004128 * AccessibilityAction.ACTION_CLICK.getId(), getLocalizedLabel());
Kristian Monsen74bc1942014-04-29 11:00:17 -07004129 * node.addAction(action);
4130 * </pre>
4131 *
4132 * @param actionId The id for this action. This should either be one of the
4133 * standard actions or a specific action for your app. In that case it is
4134 * required to use a resource identifier.
4135 * @param label The label for the new AccessibilityAction.
4136 */
4137 public AccessibilityAction(int actionId, @Nullable CharSequence label) {
Svetoslav5c4cd182014-05-21 14:53:16 -07004138 if ((actionId & ACTION_TYPE_MASK) == 0 && Integer.bitCount(actionId) != 1) {
Kristian Monsen74bc1942014-04-29 11:00:17 -07004139 throw new IllegalArgumentException("Invalid standard action id");
4140 }
4141
Kristian Monsen74bc1942014-04-29 11:00:17 -07004142 mActionId = actionId;
4143 mLabel = label;
4144 }
4145
4146 /**
Eugene Susla554edd32017-05-24 16:49:59 -07004147 * Constructor for a {@link #sStandardActions standard} action
4148 */
4149 private AccessibilityAction(int standardActionId) {
4150 this(standardActionId, null);
4151
4152 mSerializationFlag = (int) bitAt(sStandardActions.size());
4153 sStandardActions.add(this);
4154 }
4155
4156 /**
Kristian Monsen74bc1942014-04-29 11:00:17 -07004157 * Gets the id for this action.
4158 *
4159 * @return The action id.
4160 */
4161 public int getId() {
4162 return mActionId;
4163 }
4164
4165 /**
4166 * Gets the label for this action. Its purpose is to describe the
4167 * action to user.
4168 *
4169 * @return The label.
4170 */
4171 public CharSequence getLabel() {
4172 return mLabel;
4173 }
4174
4175 @Override
4176 public int hashCode() {
4177 return mActionId;
4178 }
4179
4180 @Override
4181 public boolean equals(Object other) {
4182 if (other == null) {
4183 return false;
4184 }
4185
4186 if (other == this) {
4187 return true;
4188 }
4189
4190 if (getClass() != other.getClass()) {
4191 return false;
4192 }
4193
4194 return mActionId == ((AccessibilityAction)other).mActionId;
4195 }
4196
4197 @Override
4198 public String toString() {
4199 return "AccessibilityAction: " + getActionSymbolicName(mActionId) + " - " + mLabel;
4200 }
4201 }
4202
4203 /**
Svetoslav3577a282013-06-06 14:09:10 -07004204 * Class with information if a node is a range. Use
Phil Weaver764152b2016-07-19 11:32:27 -07004205 * {@link RangeInfo#obtain(int, float, float, float)} to get an instance. Recycling is
4206 * handled by the {@link AccessibilityNodeInfo} to which this object is attached.
Svetoslav3577a282013-06-06 14:09:10 -07004207 */
4208 public static final class RangeInfo {
4209 private static final int MAX_POOL_SIZE = 10;
4210
4211 /** Range type: integer. */
4212 public static final int RANGE_TYPE_INT = 0;
4213 /** Range type: float. */
4214 public static final int RANGE_TYPE_FLOAT = 1;
4215 /** Range type: percent with values from zero to one.*/
4216 public static final int RANGE_TYPE_PERCENT = 2;
4217
4218 private static final SynchronizedPool<RangeInfo> sPool =
4219 new SynchronizedPool<AccessibilityNodeInfo.RangeInfo>(MAX_POOL_SIZE);
4220
4221 private int mType;
4222 private float mMin;
4223 private float mMax;
4224 private float mCurrent;
4225
4226 /**
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004227 * Obtains a pooled instance that is a clone of another one.
4228 *
4229 * @param other The instance to clone.
4230 *
4231 * @hide
4232 */
4233 public static RangeInfo obtain(RangeInfo other) {
4234 return obtain(other.mType, other.mMin, other.mMax, other.mCurrent);
4235 }
4236
4237 /**
Svetoslav3577a282013-06-06 14:09:10 -07004238 * Obtains a pooled instance.
4239 *
4240 * @param type The type of the range.
Phil Weaver79e44192016-12-19 14:24:49 -08004241 * @param min The minimum value. Use {@code Float.NEGATIVE_INFINITY} if the range has no
4242 * minimum.
4243 * @param max The maximum value. Use {@code Float.POSITIVE_INFINITY} if the range has no
4244 * maximum.
Svetoslav3577a282013-06-06 14:09:10 -07004245 * @param current The current value.
4246 */
4247 public static RangeInfo obtain(int type, float min, float max, float current) {
4248 RangeInfo info = sPool.acquire();
Steven Dao24142812016-04-13 15:25:09 -07004249 if (info == null) {
4250 return new RangeInfo(type, min, max, current);
4251 }
4252
4253 info.mType = type;
4254 info.mMin = min;
4255 info.mMax = max;
4256 info.mCurrent = current;
4257 return info;
Svetoslav3577a282013-06-06 14:09:10 -07004258 }
4259
4260 /**
4261 * Creates a new range.
4262 *
4263 * @param type The type of the range.
Phil Weaver79e44192016-12-19 14:24:49 -08004264 * @param min The minimum value. Use {@code Float.NEGATIVE_INFINITY} if the range has no
4265 * minimum.
4266 * @param max The maximum value. Use {@code Float.POSITIVE_INFINITY} if the range has no
4267 * maximum.
Svetoslav3577a282013-06-06 14:09:10 -07004268 * @param current The current value.
4269 */
4270 private RangeInfo(int type, float min, float max, float current) {
4271 mType = type;
4272 mMin = min;
4273 mMax = max;
4274 mCurrent = current;
4275 }
4276
4277 /**
4278 * Gets the range type.
4279 *
4280 * @return The range type.
4281 *
4282 * @see #RANGE_TYPE_INT
4283 * @see #RANGE_TYPE_FLOAT
4284 * @see #RANGE_TYPE_PERCENT
4285 */
4286 public int getType() {
4287 return mType;
4288 }
4289
4290 /**
Phil Weaver79e44192016-12-19 14:24:49 -08004291 * Gets the minimum value.
Svetoslav3577a282013-06-06 14:09:10 -07004292 *
Phil Weaver79e44192016-12-19 14:24:49 -08004293 * @return The minimum value, or {@code Float.NEGATIVE_INFINITY} if no minimum exists.
Svetoslav3577a282013-06-06 14:09:10 -07004294 */
4295 public float getMin() {
4296 return mMin;
4297 }
4298
4299 /**
Phil Weaver79e44192016-12-19 14:24:49 -08004300 * Gets the maximum value.
Svetoslav3577a282013-06-06 14:09:10 -07004301 *
Phil Weaver79e44192016-12-19 14:24:49 -08004302 * @return The maximum value, or {@code Float.POSITIVE_INFINITY} if no maximum exists.
Svetoslav3577a282013-06-06 14:09:10 -07004303 */
4304 public float getMax() {
4305 return mMax;
4306 }
4307
4308 /**
4309 * Gets the current value.
4310 *
4311 * @return The current value.
4312 */
4313 public float getCurrent() {
4314 return mCurrent;
4315 }
4316
4317 /**
4318 * Recycles this instance.
4319 */
4320 void recycle() {
4321 clear();
4322 sPool.release(this);
4323 }
4324
4325 private void clear() {
4326 mType = 0;
4327 mMin = 0;
4328 mMax = 0;
4329 mCurrent = 0;
4330 }
4331 }
4332
4333 /**
4334 * Class with information if a node is a collection. Use
Phil Weaver764152b2016-07-19 11:32:27 -07004335 * {@link CollectionInfo#obtain(int, int, boolean)} to get an instance. Recycling is
4336 * handled by the {@link AccessibilityNodeInfo} to which this object is attached.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004337 * <p>
4338 * A collection of items has rows and columns and may be hierarchical.
4339 * For example, a horizontal list is a collection with one column, as
4340 * many rows as the list items, and is not hierarchical; A table is a
4341 * collection with several rows, several columns, and is not hierarchical;
4342 * A vertical tree is a hierarchical collection with one column and
4343 * as many rows as the first level children.
4344 * </p>
Svetoslav3577a282013-06-06 14:09:10 -07004345 */
4346 public static final class CollectionInfo {
Alan Viverette76769ae2014-02-12 16:38:10 -08004347 /** Selection mode where items are not selectable. */
4348 public static final int SELECTION_MODE_NONE = 0;
4349
4350 /** Selection mode where a single item may be selected. */
4351 public static final int SELECTION_MODE_SINGLE = 1;
4352
4353 /** Selection mode where multiple items may be selected. */
4354 public static final int SELECTION_MODE_MULTIPLE = 2;
4355
Svetoslav3577a282013-06-06 14:09:10 -07004356 private static final int MAX_POOL_SIZE = 20;
4357
4358 private static final SynchronizedPool<CollectionInfo> sPool =
Alan Viverette23f44322015-04-06 16:04:56 -07004359 new SynchronizedPool<>(MAX_POOL_SIZE);
Svetoslav3577a282013-06-06 14:09:10 -07004360
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004361 private int mRowCount;
4362 private int mColumnCount;
Svetoslav3577a282013-06-06 14:09:10 -07004363 private boolean mHierarchical;
Alan Viverette76769ae2014-02-12 16:38:10 -08004364 private int mSelectionMode;
Svetoslav3577a282013-06-06 14:09:10 -07004365
4366 /**
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004367 * Obtains a pooled instance that is a clone of another one.
4368 *
4369 * @param other The instance to clone.
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004370 * @hide
4371 */
4372 public static CollectionInfo obtain(CollectionInfo other) {
Alan Viverette76769ae2014-02-12 16:38:10 -08004373 return CollectionInfo.obtain(other.mRowCount, other.mColumnCount, other.mHierarchical,
4374 other.mSelectionMode);
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004375 }
4376
4377 /**
Svetoslav3577a282013-06-06 14:09:10 -07004378 * Obtains a pooled instance.
4379 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004380 * @param rowCount The number of rows.
4381 * @param columnCount The number of columns.
Svetoslav3577a282013-06-06 14:09:10 -07004382 * @param hierarchical Whether the collection is hierarchical.
4383 */
Alan Viverette76769ae2014-02-12 16:38:10 -08004384 public static CollectionInfo obtain(int rowCount, int columnCount,
4385 boolean hierarchical) {
4386 return obtain(rowCount, columnCount, hierarchical, SELECTION_MODE_NONE);
4387 }
4388
4389 /**
4390 * Obtains a pooled instance.
4391 *
4392 * @param rowCount The number of rows.
4393 * @param columnCount The number of columns.
4394 * @param hierarchical Whether the collection is hierarchical.
4395 * @param selectionMode The collection's selection mode, one of:
4396 * <ul>
4397 * <li>{@link #SELECTION_MODE_NONE}
4398 * <li>{@link #SELECTION_MODE_SINGLE}
4399 * <li>{@link #SELECTION_MODE_MULTIPLE}
4400 * </ul>
4401 */
4402 public static CollectionInfo obtain(int rowCount, int columnCount,
4403 boolean hierarchical, int selectionMode) {
4404 final CollectionInfo info = sPool.acquire();
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004405 if (info == null) {
Alan Viverette76769ae2014-02-12 16:38:10 -08004406 return new CollectionInfo(rowCount, columnCount, hierarchical, selectionMode);
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004407 }
4408
4409 info.mRowCount = rowCount;
4410 info.mColumnCount = columnCount;
4411 info.mHierarchical = hierarchical;
Alan Viverette76769ae2014-02-12 16:38:10 -08004412 info.mSelectionMode = selectionMode;
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004413 return info;
Svetoslav3577a282013-06-06 14:09:10 -07004414 }
4415
4416 /**
4417 * Creates a new instance.
4418 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004419 * @param rowCount The number of rows.
4420 * @param columnCount The number of columns.
Svetoslav3577a282013-06-06 14:09:10 -07004421 * @param hierarchical Whether the collection is hierarchical.
Alan Viverette76769ae2014-02-12 16:38:10 -08004422 * @param selectionMode The collection's selection mode.
Svetoslav3577a282013-06-06 14:09:10 -07004423 */
Alan Viverette76769ae2014-02-12 16:38:10 -08004424 private CollectionInfo(int rowCount, int columnCount, boolean hierarchical,
4425 int selectionMode) {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004426 mRowCount = rowCount;
4427 mColumnCount = columnCount;
Svetoslav3577a282013-06-06 14:09:10 -07004428 mHierarchical = hierarchical;
Alan Viverette76769ae2014-02-12 16:38:10 -08004429 mSelectionMode = selectionMode;
Svetoslav3577a282013-06-06 14:09:10 -07004430 }
4431
4432 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004433 * Gets the number of rows.
Svetoslav3577a282013-06-06 14:09:10 -07004434 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004435 * @return The row count.
Svetoslav3577a282013-06-06 14:09:10 -07004436 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004437 public int getRowCount() {
4438 return mRowCount;
Svetoslav3577a282013-06-06 14:09:10 -07004439 }
4440
4441 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004442 * Gets the number of columns.
Svetoslav3577a282013-06-06 14:09:10 -07004443 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004444 * @return The column count.
Svetoslav3577a282013-06-06 14:09:10 -07004445 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004446 public int getColumnCount() {
4447 return mColumnCount;
Svetoslav3577a282013-06-06 14:09:10 -07004448 }
4449
4450 /**
4451 * Gets if the collection is a hierarchically ordered.
4452 *
4453 * @return Whether the collection is hierarchical.
4454 */
4455 public boolean isHierarchical() {
4456 return mHierarchical;
4457 }
4458
4459 /**
Alan Viverette76769ae2014-02-12 16:38:10 -08004460 * Gets the collection's selection mode.
4461 *
4462 * @return The collection's selection mode, one of:
4463 * <ul>
4464 * <li>{@link #SELECTION_MODE_NONE}
4465 * <li>{@link #SELECTION_MODE_SINGLE}
4466 * <li>{@link #SELECTION_MODE_MULTIPLE}
4467 * </ul>
4468 */
4469 public int getSelectionMode() {
4470 return mSelectionMode;
4471 }
4472
4473 /**
Svetoslav3577a282013-06-06 14:09:10 -07004474 * Recycles this instance.
4475 */
4476 void recycle() {
4477 clear();
4478 sPool.release(this);
4479 }
4480
4481 private void clear() {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004482 mRowCount = 0;
4483 mColumnCount = 0;
Svetoslav3577a282013-06-06 14:09:10 -07004484 mHierarchical = false;
Alan Viverette76769ae2014-02-12 16:38:10 -08004485 mSelectionMode = SELECTION_MODE_NONE;
Svetoslav3577a282013-06-06 14:09:10 -07004486 }
4487 }
4488
4489 /**
4490 * Class with information if a node is a collection item. Use
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004491 * {@link CollectionItemInfo#obtain(int, int, int, int, boolean)}
Phil Weaver764152b2016-07-19 11:32:27 -07004492 * to get an instance. Recycling is handled by the {@link AccessibilityNodeInfo} to which this
4493 * object is attached.
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004494 * <p>
4495 * A collection item is contained in a collection, it starts at
4496 * a given row and column in the collection, and spans one or
4497 * more rows and columns. For example, a header of two related
4498 * table columns starts at the first row and the first column,
4499 * spans one row and two columns.
4500 * </p>
Svetoslav3577a282013-06-06 14:09:10 -07004501 */
4502 public static final class CollectionItemInfo {
4503 private static final int MAX_POOL_SIZE = 20;
4504
4505 private static final SynchronizedPool<CollectionItemInfo> sPool =
Alan Viverette23f44322015-04-06 16:04:56 -07004506 new SynchronizedPool<>(MAX_POOL_SIZE);
Svetoslav3577a282013-06-06 14:09:10 -07004507
4508 /**
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004509 * Obtains a pooled instance that is a clone of another one.
4510 *
4511 * @param other The instance to clone.
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004512 * @hide
4513 */
4514 public static CollectionItemInfo obtain(CollectionItemInfo other) {
Alan Viverette76769ae2014-02-12 16:38:10 -08004515 return CollectionItemInfo.obtain(other.mRowIndex, other.mRowSpan, other.mColumnIndex,
4516 other.mColumnSpan, other.mHeading, other.mSelected);
Svetoslav Ganov6685f1b2013-09-09 13:36:43 -07004517 }
4518
4519 /**
Svetoslav3577a282013-06-06 14:09:10 -07004520 * Obtains a pooled instance.
4521 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004522 * @param rowIndex The row index at which the item is located.
4523 * @param rowSpan The number of rows the item spans.
4524 * @param columnIndex The column index at which the item is located.
4525 * @param columnSpan The number of columns the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07004526 * @param heading Whether the item is a heading.
4527 */
Alan Viverette76769ae2014-02-12 16:38:10 -08004528 public static CollectionItemInfo obtain(int rowIndex, int rowSpan,
4529 int columnIndex, int columnSpan, boolean heading) {
4530 return obtain(rowIndex, rowSpan, columnIndex, columnSpan, heading, false);
4531 }
4532
4533 /**
4534 * Obtains a pooled instance.
4535 *
4536 * @param rowIndex The row index at which the item is located.
4537 * @param rowSpan The number of rows the item spans.
4538 * @param columnIndex The column index at which the item is located.
4539 * @param columnSpan The number of columns the item spans.
4540 * @param heading Whether the item is a heading.
4541 * @param selected Whether the item is selected.
4542 */
4543 public static CollectionItemInfo obtain(int rowIndex, int rowSpan,
4544 int columnIndex, int columnSpan, boolean heading, boolean selected) {
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004545 final CollectionItemInfo info = sPool.acquire();
4546 if (info == null) {
Alan Viverette76769ae2014-02-12 16:38:10 -08004547 return new CollectionItemInfo(
4548 rowIndex, rowSpan, columnIndex, columnSpan, heading, selected);
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004549 }
4550
4551 info.mRowIndex = rowIndex;
4552 info.mRowSpan = rowSpan;
4553 info.mColumnIndex = columnIndex;
4554 info.mColumnSpan = columnSpan;
4555 info.mHeading = heading;
Alan Viverette76769ae2014-02-12 16:38:10 -08004556 info.mSelected = selected;
Alan Viverettecdd2edd2014-02-12 11:28:33 -08004557 return info;
Svetoslav3577a282013-06-06 14:09:10 -07004558 }
4559
4560 private boolean mHeading;
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004561 private int mColumnIndex;
4562 private int mRowIndex;
4563 private int mColumnSpan;
4564 private int mRowSpan;
Alan Viverette76769ae2014-02-12 16:38:10 -08004565 private boolean mSelected;
Svetoslav3577a282013-06-06 14:09:10 -07004566
4567 /**
4568 * Creates a new instance.
4569 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004570 * @param rowIndex The row index at which the item is located.
4571 * @param rowSpan The number of rows the item spans.
4572 * @param columnIndex The column index at which the item is located.
4573 * @param columnSpan The number of columns the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07004574 * @param heading Whether the item is a heading.
4575 */
Alan Viverette76769ae2014-02-12 16:38:10 -08004576 private CollectionItemInfo(int rowIndex, int rowSpan, int columnIndex, int columnSpan,
4577 boolean heading, boolean selected) {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004578 mRowIndex = rowIndex;
4579 mRowSpan = rowSpan;
4580 mColumnIndex = columnIndex;
4581 mColumnSpan = columnSpan;
Svetoslav3577a282013-06-06 14:09:10 -07004582 mHeading = heading;
Alan Viverette76769ae2014-02-12 16:38:10 -08004583 mSelected = selected;
Svetoslav3577a282013-06-06 14:09:10 -07004584 }
4585
4586 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004587 * Gets the column index at which the item is located.
Svetoslav3577a282013-06-06 14:09:10 -07004588 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004589 * @return The column index.
Svetoslav3577a282013-06-06 14:09:10 -07004590 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004591 public int getColumnIndex() {
4592 return mColumnIndex;
Svetoslav3577a282013-06-06 14:09:10 -07004593 }
4594
4595 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004596 * Gets the row index at which the item is located.
Svetoslav3577a282013-06-06 14:09:10 -07004597 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004598 * @return The row index.
Svetoslav3577a282013-06-06 14:09:10 -07004599 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004600 public int getRowIndex() {
4601 return mRowIndex;
Svetoslav3577a282013-06-06 14:09:10 -07004602 }
4603
4604 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004605 * Gets the number of columns the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07004606 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004607 * @return The column span.
Svetoslav3577a282013-06-06 14:09:10 -07004608 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004609 public int getColumnSpan() {
4610 return mColumnSpan;
Svetoslav3577a282013-06-06 14:09:10 -07004611 }
4612
4613 /**
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004614 * Gets the number of rows the item spans.
Svetoslav3577a282013-06-06 14:09:10 -07004615 *
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004616 * @return The row span.
Svetoslav3577a282013-06-06 14:09:10 -07004617 */
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004618 public int getRowSpan() {
4619 return mRowSpan;
Svetoslav3577a282013-06-06 14:09:10 -07004620 }
4621
4622 /**
4623 * Gets if the collection item is a heading. For example, section
4624 * heading, table header, etc.
4625 *
4626 * @return If the item is a heading.
4627 */
4628 public boolean isHeading() {
4629 return mHeading;
4630 }
4631
4632 /**
Alan Viverette76769ae2014-02-12 16:38:10 -08004633 * Gets if the collection item is selected.
4634 *
4635 * @return If the item is selected.
4636 */
4637 public boolean isSelected() {
4638 return mSelected;
4639 }
4640
4641 /**
Svetoslav3577a282013-06-06 14:09:10 -07004642 * Recycles this instance.
4643 */
4644 void recycle() {
4645 clear();
4646 sPool.release(this);
4647 }
4648
4649 private void clear() {
Svetoslav Ganovcb8ed392013-08-23 20:37:28 -07004650 mColumnIndex = 0;
4651 mColumnSpan = 0;
4652 mRowIndex = 0;
4653 mRowSpan = 0;
Svetoslav3577a282013-06-06 14:09:10 -07004654 mHeading = false;
Alan Viverette76769ae2014-02-12 16:38:10 -08004655 mSelected = false;
Svetoslav3577a282013-06-06 14:09:10 -07004656 }
4657 }
4658
4659 /**
Alan Viverettef0aed092013-11-06 15:33:03 -08004660 * @see android.os.Parcelable.Creator
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004661 */
4662 public static final Parcelable.Creator<AccessibilityNodeInfo> CREATOR =
4663 new Parcelable.Creator<AccessibilityNodeInfo>() {
Alan Viverettef0aed092013-11-06 15:33:03 -08004664 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004665 public AccessibilityNodeInfo createFromParcel(Parcel parcel) {
4666 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
4667 info.initFromParcel(parcel);
4668 return info;
4669 }
4670
Alan Viverettef0aed092013-11-06 15:33:03 -08004671 @Override
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004672 public AccessibilityNodeInfo[] newArray(int size) {
4673 return new AccessibilityNodeInfo[size];
4674 }
4675 };
4676}