Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package android.view.accessibility; |
| 18 | |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 19 | import android.graphics.Rect; |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 20 | import android.os.Bundle; |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 21 | import android.os.Parcel; |
| 22 | import android.os.Parcelable; |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 23 | import android.util.SparseLongArray; |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 24 | import android.view.View; |
| 25 | |
Svetoslav Ganov | eeee4d2 | 2011-06-10 20:51:30 -0700 | [diff] [blame] | 26 | import java.util.Collections; |
| 27 | import java.util.List; |
| 28 | |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 29 | /** |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 30 | * This class represents a node of the window content as well as actions that |
| 31 | * can be requested from its source. From the point of view of an |
| 32 | * {@link android.accessibilityservice.AccessibilityService} a window content is |
| 33 | * presented as tree of accessibility node info which may or may not map one-to-one |
| 34 | * to the view hierarchy. In other words, a custom view is free to report itself as |
| 35 | * a tree of accessibility node info. |
| 36 | * </p> |
| 37 | * <p> |
| 38 | * Once an accessibility node info is delivered to an accessibility service it is |
| 39 | * made immutable and calling a state mutation method generates an error. |
| 40 | * </p> |
| 41 | * <p> |
| 42 | * Please refer to {@link android.accessibilityservice.AccessibilityService} for |
| 43 | * details about how to obtain a handle to window content as a tree of accessibility |
| 44 | * node info as well as familiarizing with the security model. |
| 45 | * </p> |
Joe Fernandez | e1302ed | 2012-02-06 14:30:15 -0800 | [diff] [blame] | 46 | * <div class="special reference"> |
| 47 | * <h3>Developer Guides</h3> |
| 48 | * <p>For more information about making applications accessible, read the |
| 49 | * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a> |
| 50 | * developer guide.</p> |
| 51 | * </div> |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 52 | * |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 53 | * @see android.accessibilityservice.AccessibilityService |
| 54 | * @see AccessibilityEvent |
| 55 | * @see AccessibilityManager |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 56 | */ |
| 57 | public class AccessibilityNodeInfo implements Parcelable { |
| 58 | |
| 59 | private static final boolean DEBUG = false; |
| 60 | |
Svetoslav Ganov | 0d04e24 | 2012-02-21 13:46:36 -0800 | [diff] [blame] | 61 | /** @hide */ |
| 62 | public static final int UNDEFINED = -1; |
| 63 | |
| 64 | /** @hide */ |
| 65 | public static final long ROOT_NODE_ID = makeNodeId(UNDEFINED, UNDEFINED); |
| 66 | |
| 67 | /** @hide */ |
| 68 | public static final int ACTIVE_WINDOW_ID = UNDEFINED; |
Svetoslav Ganov | d116d7c | 2011-11-21 18:41:59 -0800 | [diff] [blame] | 69 | |
Svetoslav Ganov | 57c7fd5 | 2012-02-23 18:31:39 -0800 | [diff] [blame] | 70 | /** @hide */ |
| 71 | public static final int FLAG_PREFETCH_PREDECESSORS = 0x00000001; |
| 72 | |
| 73 | /** @hide */ |
| 74 | public static final int FLAG_PREFETCH_SIBLINGS = 0x00000002; |
| 75 | |
| 76 | /** @hide */ |
Svetoslav Ganov | 4213804 | 2012-03-20 11:51:39 -0700 | [diff] [blame] | 77 | public static final int FLAG_PREFETCH_DESCENDANTS = 0x00000004; |
| 78 | |
| 79 | /** @hide */ |
| 80 | public static final int INCLUDE_NOT_IMPORTANT_VIEWS = 0x00000008; |
Svetoslav Ganov | 57c7fd5 | 2012-02-23 18:31:39 -0800 | [diff] [blame] | 81 | |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 82 | // Actions. |
| 83 | |
| 84 | /** |
Svetoslav Ganov | 4213804 | 2012-03-20 11:51:39 -0700 | [diff] [blame] | 85 | * Action that gives input focus to the node. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 86 | */ |
Svetoslav Ganov | 005b83b | 2012-04-16 18:17:17 -0700 | [diff] [blame] | 87 | public static final int ACTION_FOCUS = 0x00000001; |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 88 | |
| 89 | /** |
Svetoslav Ganov | 4213804 | 2012-03-20 11:51:39 -0700 | [diff] [blame] | 90 | * Action that clears input focus of the node. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 91 | */ |
Svetoslav Ganov | 4213804 | 2012-03-20 11:51:39 -0700 | [diff] [blame] | 92 | public static final int ACTION_CLEAR_FOCUS = 0x00000002; |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 93 | |
| 94 | /** |
| 95 | * Action that selects the node. |
| 96 | */ |
Svetoslav Ganov | 4213804 | 2012-03-20 11:51:39 -0700 | [diff] [blame] | 97 | public static final int ACTION_SELECT = 0x00000004; |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 98 | |
| 99 | /** |
| 100 | * Action that unselects the node. |
| 101 | */ |
Svetoslav Ganov | 4213804 | 2012-03-20 11:51:39 -0700 | [diff] [blame] | 102 | public static final int ACTION_CLEAR_SELECTION = 0x00000008; |
| 103 | |
| 104 | /** |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 105 | * Action that long clicks on the node info. |
Svetoslav Ganov | 005b83b | 2012-04-16 18:17:17 -0700 | [diff] [blame] | 106 | */ |
| 107 | public static final int ACTION_CLICK = 0x00000010; |
| 108 | |
| 109 | /** |
| 110 | * Action that clicks on the node. |
| 111 | */ |
| 112 | public static final int ACTION_LONG_CLICK = 0x00000020; |
| 113 | |
| 114 | /** |
Svetoslav Ganov | 4213804 | 2012-03-20 11:51:39 -0700 | [diff] [blame] | 115 | * Action that gives accessibility focus to the node. |
| 116 | */ |
Svetoslav Ganov | 005b83b | 2012-04-16 18:17:17 -0700 | [diff] [blame] | 117 | public static final int ACTION_ACCESSIBILITY_FOCUS = 0x00000040; |
Svetoslav Ganov | 4213804 | 2012-03-20 11:51:39 -0700 | [diff] [blame] | 118 | |
| 119 | /** |
| 120 | * Action that clears accessibility focus of the node. |
| 121 | */ |
Svetoslav Ganov | 005b83b | 2012-04-16 18:17:17 -0700 | [diff] [blame] | 122 | public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 0x00000080; |
Svetoslav Ganov | 4213804 | 2012-03-20 11:51:39 -0700 | [diff] [blame] | 123 | |
| 124 | /** |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 125 | * Action that requests to go to the next entity in this node's text |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 126 | * at a given movement granularity. For example, move to the next character, |
| 127 | * word, etc. |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 128 | * <p> |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 129 | * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<br> |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 130 | * <strong>Example:</strong> |
| 131 | * <code><pre><p> |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 132 | * Bundle arguments = new Bundle(); |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 133 | * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT, |
| 134 | * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER); |
| 135 | * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments); |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 136 | * </code></pre></p> |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 137 | * </p> |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 138 | * |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 139 | * @see #setMovementGranularities(int) |
| 140 | * @see #getMovementGranularities() |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 141 | * |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 142 | * @see #MOVEMENT_GRANULARITY_CHARACTER |
| 143 | * @see #MOVEMENT_GRANULARITY_WORD |
| 144 | * @see #MOVEMENT_GRANULARITY_LINE |
| 145 | * @see #MOVEMENT_GRANULARITY_PARAGRAPH |
| 146 | * @see #MOVEMENT_GRANULARITY_PAGE |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 147 | */ |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 148 | public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 0x00000100; |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 149 | |
| 150 | /** |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 151 | * Action that requests to go to the previous entity in this node's text |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 152 | * at a given movement granularity. For example, move to the next character, |
| 153 | * word, etc. |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 154 | * <p> |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 155 | * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<br> |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 156 | * <strong>Example:</strong> |
| 157 | * <code><pre><p> |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 158 | * Bundle arguments = new Bundle(); |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 159 | * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT, |
| 160 | * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER); |
| 161 | * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, |
| 162 | * arguments); |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 163 | * </code></pre></p> |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 164 | * </p> |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 165 | * |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 166 | * @see #setMovementGranularities(int) |
| 167 | * @see #getMovementGranularities() |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 168 | * |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 169 | * @see #MOVEMENT_GRANULARITY_CHARACTER |
| 170 | * @see #MOVEMENT_GRANULARITY_WORD |
| 171 | * @see #MOVEMENT_GRANULARITY_LINE |
| 172 | * @see #MOVEMENT_GRANULARITY_PARAGRAPH |
| 173 | * @see #MOVEMENT_GRANULARITY_PAGE |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 174 | */ |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 175 | public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 0x00000200; |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 176 | |
| 177 | /** |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 178 | * Action to move to the next HTML element of a given type. For example, move |
| 179 | * to the BUTTON, INPUT, TABLE, etc. |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 180 | * <p> |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 181 | * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br> |
| 182 | * <strong>Example:</strong> |
| 183 | * <code><pre><p> |
| 184 | * Bundle arguments = new Bundle(); |
| 185 | * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON"); |
| 186 | * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, arguments); |
| 187 | * </code></pre></p> |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 188 | * </p> |
| 189 | */ |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 190 | public static final int ACTION_NEXT_HTML_ELEMENT = 0x00000400; |
| 191 | |
| 192 | /** |
| 193 | * Action to move to the previous HTML element of a given type. For example, move |
| 194 | * to the BUTTON, INPUT, TABLE, etc. |
| 195 | * <p> |
| 196 | * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br> |
| 197 | * <strong>Example:</strong> |
| 198 | * <code><pre><p> |
| 199 | * Bundle arguments = new Bundle(); |
| 200 | * arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON"); |
| 201 | * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT, arguments); |
| 202 | * </code></pre></p> |
| 203 | * </p> |
| 204 | */ |
| 205 | public static final int ACTION_PREVIOUS_HTML_ELEMENT = 0x00000800; |
| 206 | |
| 207 | /** |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 208 | * Argument for which movement granularity to be used when traversing the node text. |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 209 | * <p> |
| 210 | * <strong>Type:</strong> int<br> |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 211 | * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_MOVEMENT_GRANULARITY}, |
| 212 | * {@link #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY} |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 213 | * </p> |
| 214 | */ |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 215 | public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT = |
| 216 | "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT"; |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 217 | |
| 218 | /** |
| 219 | * Argument for which HTML element to get moving to the next/previous HTML element. |
| 220 | * <p> |
| 221 | * <strong>Type:</strong> String<br> |
| 222 | * <strong>Actions:</strong> {@link #ACTION_NEXT_HTML_ELEMENT}, |
| 223 | * {@link #ACTION_PREVIOUS_HTML_ELEMENT} |
| 224 | * </p> |
| 225 | */ |
| 226 | public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING = |
| 227 | "ACTION_ARGUMENT_HTML_ELEMENT_STRING"; |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 228 | |
| 229 | /** |
Svetoslav Ganov | 4213804 | 2012-03-20 11:51:39 -0700 | [diff] [blame] | 230 | * The input focus. |
| 231 | */ |
| 232 | public static final int FOCUS_INPUT = 1; |
| 233 | |
| 234 | /** |
| 235 | * The accessibility focus. |
| 236 | */ |
| 237 | public static final int FOCUS_ACCESSIBILITY = 2; |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 238 | |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 239 | // Movement granularities |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 240 | |
| 241 | /** |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 242 | * Movement granularity bit for traversing the text of a node by character. |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 243 | */ |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 244 | public static final int MOVEMENT_GRANULARITY_CHARACTER = 0x00000001; |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 245 | |
| 246 | /** |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 247 | * Movement granularity bit for traversing the text of a node by word. |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 248 | */ |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 249 | public static final int MOVEMENT_GRANULARITY_WORD = 0x00000002; |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 250 | |
| 251 | /** |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 252 | * Movement granularity bit for traversing the text of a node by line. |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 253 | */ |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 254 | public static final int MOVEMENT_GRANULARITY_LINE = 0x00000004; |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 255 | |
| 256 | /** |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 257 | * Movement granularity bit for traversing the text of a node by paragraph. |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 258 | */ |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 259 | public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 0x00000008; |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 260 | |
| 261 | /** |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 262 | * Movement granularity bit for traversing the text of a node by page. |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 263 | */ |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 264 | public static final int MOVEMENT_GRANULARITY_PAGE = 0x00000010; |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 265 | |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 266 | // Boolean attributes. |
| 267 | |
| 268 | private static final int PROPERTY_CHECKABLE = 0x00000001; |
| 269 | |
| 270 | private static final int PROPERTY_CHECKED = 0x00000002; |
| 271 | |
| 272 | private static final int PROPERTY_FOCUSABLE = 0x00000004; |
| 273 | |
| 274 | private static final int PROPERTY_FOCUSED = 0x00000008; |
| 275 | |
| 276 | private static final int PROPERTY_SELECTED = 0x00000010; |
| 277 | |
| 278 | private static final int PROPERTY_CLICKABLE = 0x00000020; |
| 279 | |
| 280 | private static final int PROPERTY_LONG_CLICKABLE = 0x00000040; |
| 281 | |
| 282 | private static final int PROPERTY_ENABLED = 0x00000080; |
| 283 | |
| 284 | private static final int PROPERTY_PASSWORD = 0x00000100; |
| 285 | |
Svetoslav Ganov | a015617 | 2011-06-26 17:55:44 -0700 | [diff] [blame] | 286 | private static final int PROPERTY_SCROLLABLE = 0x00000200; |
| 287 | |
Svetoslav Ganov | 4213804 | 2012-03-20 11:51:39 -0700 | [diff] [blame] | 288 | private static final int PROPERTY_ACCESSIBILITY_FOCUSED = 0x00000400; |
| 289 | |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 290 | /** |
| 291 | * Bits that provide the id of a virtual descendant of a view. |
| 292 | */ |
| 293 | private static final long VIRTUAL_DESCENDANT_ID_MASK = 0xffffffff00000000L; |
| 294 | |
| 295 | /** |
| 296 | * Bit shift of {@link #VIRTUAL_DESCENDANT_ID_MASK} to get to the id for a |
| 297 | * virtual descendant of a view. Such a descendant does not exist in the view |
| 298 | * hierarchy and is only reported via the accessibility APIs. |
| 299 | */ |
| 300 | private static final int VIRTUAL_DESCENDANT_ID_SHIFT = 32; |
| 301 | |
| 302 | /** |
| 303 | * Gets the accessibility view id which identifies a View in the view three. |
| 304 | * |
| 305 | * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}. |
| 306 | * @return The accessibility view id part of the node id. |
| 307 | * |
| 308 | * @hide |
| 309 | */ |
| 310 | public static int getAccessibilityViewId(long accessibilityNodeId) { |
| 311 | return (int) accessibilityNodeId; |
| 312 | } |
| 313 | |
| 314 | /** |
| 315 | * Gets the virtual descendant id which identifies an imaginary view in a |
| 316 | * containing View. |
| 317 | * |
| 318 | * @param accessibilityNodeId The id of an {@link AccessibilityNodeInfo}. |
| 319 | * @return The virtual view id part of the node id. |
| 320 | * |
| 321 | * @hide |
| 322 | */ |
| 323 | public static int getVirtualDescendantId(long accessibilityNodeId) { |
| 324 | return (int) ((accessibilityNodeId & VIRTUAL_DESCENDANT_ID_MASK) |
| 325 | >> VIRTUAL_DESCENDANT_ID_SHIFT); |
| 326 | } |
| 327 | |
| 328 | /** |
| 329 | * Makes a node id by shifting the <code>virtualDescendantId</code> |
| 330 | * by {@link #VIRTUAL_DESCENDANT_ID_SHIFT} and taking |
| 331 | * the bitwise or with the <code>accessibilityViewId</code>. |
| 332 | * |
| 333 | * @param accessibilityViewId A View accessibility id. |
| 334 | * @param virtualDescendantId A virtual descendant id. |
| 335 | * @return The node id. |
| 336 | * |
| 337 | * @hide |
| 338 | */ |
| 339 | public static long makeNodeId(int accessibilityViewId, int virtualDescendantId) { |
| 340 | return (((long) virtualDescendantId) << VIRTUAL_DESCENDANT_ID_SHIFT) | accessibilityViewId; |
| 341 | } |
| 342 | |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 343 | // Housekeeping. |
| 344 | private static final int MAX_POOL_SIZE = 50; |
| 345 | private static final Object sPoolLock = new Object(); |
| 346 | private static AccessibilityNodeInfo sPool; |
| 347 | private static int sPoolSize; |
| 348 | private AccessibilityNodeInfo mNext; |
| 349 | private boolean mIsInPool; |
| 350 | private boolean mSealed; |
| 351 | |
| 352 | // Data. |
Svetoslav Ganov | f3b4f31 | 2011-11-30 18:15:01 -0800 | [diff] [blame] | 353 | private int mWindowId = UNDEFINED; |
Svetoslav Ganov | 0d04e24 | 2012-02-21 13:46:36 -0800 | [diff] [blame] | 354 | private long mSourceNodeId = ROOT_NODE_ID; |
| 355 | private long mParentNodeId = ROOT_NODE_ID; |
Svetoslav Ganov | f3b4f31 | 2011-11-30 18:15:01 -0800 | [diff] [blame] | 356 | |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 357 | private int mBooleanProperties; |
Svetoslav Ganov | eeee4d2 | 2011-06-10 20:51:30 -0700 | [diff] [blame] | 358 | private final Rect mBoundsInParent = new Rect(); |
| 359 | private final Rect mBoundsInScreen = new Rect(); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 360 | |
| 361 | private CharSequence mPackageName; |
| 362 | private CharSequence mClassName; |
| 363 | private CharSequence mText; |
| 364 | private CharSequence mContentDescription; |
| 365 | |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 366 | private final SparseLongArray mChildNodeIds = new SparseLongArray(); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 367 | private int mActions; |
| 368 | |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 369 | private int mMovementGranularities; |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 370 | |
Svetoslav Ganov | d116d7c | 2011-11-21 18:41:59 -0800 | [diff] [blame] | 371 | private int mConnectionId = UNDEFINED; |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 372 | |
| 373 | /** |
| 374 | * Hide constructor from clients. |
| 375 | */ |
| 376 | private AccessibilityNodeInfo() { |
| 377 | /* do nothing */ |
| 378 | } |
| 379 | |
| 380 | /** |
| 381 | * Sets the source. |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 382 | * <p> |
| 383 | * <strong>Note:</strong> Cannot be called from an |
| 384 | * {@link android.accessibilityservice.AccessibilityService}. |
| 385 | * This class is made immutable before being delivered to an AccessibilityService. |
| 386 | * </p> |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 387 | * |
| 388 | * @param source The info source. |
| 389 | */ |
| 390 | public void setSource(View source) { |
Svetoslav Ganov | f3b4f31 | 2011-11-30 18:15:01 -0800 | [diff] [blame] | 391 | setSource(source, UNDEFINED); |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 392 | } |
| 393 | |
| 394 | /** |
| 395 | * Sets the source to be a virtual descendant of the given <code>root</code>. |
Svetoslav Ganov | 71b4e71 | 2011-10-25 11:31:31 -0700 | [diff] [blame] | 396 | * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 397 | * is set as the source. |
| 398 | * <p> |
| 399 | * A virtual descendant is an imaginary View that is reported as a part of the view |
| 400 | * hierarchy for accessibility purposes. This enables custom views that draw complex |
Svetoslav Ganov | 71b4e71 | 2011-10-25 11:31:31 -0700 | [diff] [blame] | 401 | * content to report themselves as a tree of virtual views, thus conveying their |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 402 | * logical structure. |
| 403 | * </p> |
| 404 | * <p> |
| 405 | * <strong>Note:</strong> Cannot be called from an |
| 406 | * {@link android.accessibilityservice.AccessibilityService}. |
| 407 | * This class is made immutable before being delivered to an AccessibilityService. |
| 408 | * </p> |
| 409 | * |
| 410 | * @param root The root of the virtual subtree. |
| 411 | * @param virtualDescendantId The id of the virtual descendant. |
| 412 | */ |
| 413 | public void setSource(View root, int virtualDescendantId) { |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 414 | enforceNotSealed(); |
Svetoslav Ganov | f3b4f31 | 2011-11-30 18:15:01 -0800 | [diff] [blame] | 415 | mWindowId = (root != null) ? root.getAccessibilityWindowId() : UNDEFINED; |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 416 | final int rootAccessibilityViewId = |
Svetoslav Ganov | f3b4f31 | 2011-11-30 18:15:01 -0800 | [diff] [blame] | 417 | (root != null) ? root.getAccessibilityViewId() : UNDEFINED; |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 418 | mSourceNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 419 | } |
Svetoslav Ganov | 005b83b | 2012-04-16 18:17:17 -0700 | [diff] [blame] | 420 | |
Svetoslav Ganov | 4213804 | 2012-03-20 11:51:39 -0700 | [diff] [blame] | 421 | /** |
Svetoslav Ganov | 005b83b | 2012-04-16 18:17:17 -0700 | [diff] [blame] | 422 | * Find the view that has the specified focus type. The search starts from |
Svetoslav Ganov | 4213804 | 2012-03-20 11:51:39 -0700 | [diff] [blame] | 423 | * the view represented by this node info. |
| 424 | * |
| 425 | * @param focus The focus to find. One of {@link #FOCUS_INPUT} or |
| 426 | * {@link #FOCUS_ACCESSIBILITY}. |
| 427 | * @return The node info of the focused view or null. |
| 428 | * |
| 429 | * @see #FOCUS_INPUT |
| 430 | * @see #FOCUS_ACCESSIBILITY |
| 431 | */ |
| 432 | public AccessibilityNodeInfo findFocus(int focus) { |
| 433 | enforceSealed(); |
| 434 | if (!canPerformRequestOverConnection(mSourceNodeId)) { |
| 435 | return null; |
| 436 | } |
| 437 | return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId, mWindowId, |
| 438 | mSourceNodeId, focus); |
| 439 | } |
| 440 | |
| 441 | /** |
| 442 | * Searches for the nearest view in the specified direction that can take |
| 443 | * the input focus. |
| 444 | * |
| 445 | * @param direction The direction. Can be one of: |
| 446 | * {@link View#FOCUS_DOWN}, |
| 447 | * {@link View#FOCUS_UP}, |
| 448 | * {@link View#FOCUS_LEFT}, |
| 449 | * {@link View#FOCUS_RIGHT}, |
| 450 | * {@link View#FOCUS_FORWARD}, |
| 451 | * {@link View#FOCUS_BACKWARD}, |
Svetoslav Ganov | 4213804 | 2012-03-20 11:51:39 -0700 | [diff] [blame] | 452 | * {@link View#ACCESSIBILITY_FOCUS_FORWARD}, |
| 453 | * {@link View#ACCESSIBILITY_FOCUS_BACKWARD}, |
| 454 | * {@link View#ACCESSIBILITY_FOCUS_UP}, |
| 455 | * {@link View#ACCESSIBILITY_FOCUS_RIGHT}, |
| 456 | * {@link View#ACCESSIBILITY_FOCUS_DOWN}, |
| 457 | * {@link View#ACCESSIBILITY_FOCUS_LEFT}. |
| 458 | * |
| 459 | * @return The node info for the view that can take accessibility focus. |
| 460 | */ |
| 461 | public AccessibilityNodeInfo focusSearch(int direction) { |
| 462 | enforceSealed(); |
| 463 | if (!canPerformRequestOverConnection(mSourceNodeId)) { |
| 464 | return null; |
| 465 | } |
| 466 | return AccessibilityInteractionClient.getInstance().focusSearch(mConnectionId, mWindowId, |
| 467 | mSourceNodeId, direction); |
| 468 | } |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 469 | |
| 470 | /** |
| 471 | * Gets the id of the window from which the info comes from. |
| 472 | * |
| 473 | * @return The window id. |
| 474 | */ |
Svetoslav Ganov | eeee4d2 | 2011-06-10 20:51:30 -0700 | [diff] [blame] | 475 | public int getWindowId() { |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 476 | return mWindowId; |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 477 | } |
| 478 | |
| 479 | /** |
Svetoslav Ganov | 57c7fd5 | 2012-02-23 18:31:39 -0800 | [diff] [blame] | 480 | * @return The ids of the children. |
| 481 | * |
| 482 | * @hide |
| 483 | */ |
| 484 | public SparseLongArray getChildNodeIds() { |
| 485 | return mChildNodeIds; |
| 486 | } |
| 487 | |
| 488 | /** |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 489 | * Gets the number of children. |
| 490 | * |
| 491 | * @return The child count. |
| 492 | */ |
| 493 | public int getChildCount() { |
Svetoslav Ganov | 57c7fd5 | 2012-02-23 18:31:39 -0800 | [diff] [blame] | 494 | return mChildNodeIds.size(); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 495 | } |
| 496 | |
| 497 | /** |
| 498 | * Get the child at given index. |
| 499 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 500 | * <strong>Note:</strong> It is a client responsibility to recycle the |
| 501 | * received info by calling {@link AccessibilityNodeInfo#recycle()} |
| 502 | * to avoid creating of multiple instances. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 503 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 504 | * |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 505 | * @param index The child index. |
| 506 | * @return The child node. |
| 507 | * |
| 508 | * @throws IllegalStateException If called outside of an AccessibilityService. |
| 509 | * |
| 510 | */ |
| 511 | public AccessibilityNodeInfo getChild(int index) { |
| 512 | enforceSealed(); |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 513 | if (!canPerformRequestOverConnection(mSourceNodeId)) { |
Svetoslav Ganov | eeee4d2 | 2011-06-10 20:51:30 -0700 | [diff] [blame] | 514 | return null; |
| 515 | } |
Svetoslav Ganov | 57c7fd5 | 2012-02-23 18:31:39 -0800 | [diff] [blame] | 516 | final long childId = mChildNodeIds.get(index); |
Svetoslav Ganov | 8bd6961 | 2011-08-23 13:40:30 -0700 | [diff] [blame] | 517 | AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); |
Svetoslav Ganov | 57c7fd5 | 2012-02-23 18:31:39 -0800 | [diff] [blame] | 518 | return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mWindowId, |
| 519 | childId, FLAG_PREFETCH_DESCENDANTS); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 520 | } |
| 521 | |
| 522 | /** |
| 523 | * Adds a child. |
| 524 | * <p> |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 525 | * <strong>Note:</strong> Cannot be called from an |
| 526 | * {@link android.accessibilityservice.AccessibilityService}. |
| 527 | * This class is made immutable before being delivered to an AccessibilityService. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 528 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 529 | * |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 530 | * @param child The child. |
| 531 | * |
| 532 | * @throws IllegalStateException If called from an AccessibilityService. |
| 533 | */ |
| 534 | public void addChild(View child) { |
Svetoslav Ganov | f3b4f31 | 2011-11-30 18:15:01 -0800 | [diff] [blame] | 535 | addChild(child, UNDEFINED); |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 536 | } |
| 537 | |
| 538 | /** |
| 539 | * Adds a virtual child which is a descendant of the given <code>root</code>. |
Svetoslav Ganov | 71b4e71 | 2011-10-25 11:31:31 -0700 | [diff] [blame] | 540 | * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 541 | * is added as a child. |
| 542 | * <p> |
| 543 | * A virtual descendant is an imaginary View that is reported as a part of the view |
| 544 | * hierarchy for accessibility purposes. This enables custom views that draw complex |
| 545 | * content to report them selves as a tree of virtual views, thus conveying their |
| 546 | * logical structure. |
| 547 | * </p> |
| 548 | * |
| 549 | * @param root The root of the virtual subtree. |
| 550 | * @param virtualDescendantId The id of the virtual child. |
| 551 | */ |
| 552 | public void addChild(View root, int virtualDescendantId) { |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 553 | enforceNotSealed(); |
Svetoslav Ganov | 57c7fd5 | 2012-02-23 18:31:39 -0800 | [diff] [blame] | 554 | final int index = mChildNodeIds.size(); |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 555 | final int rootAccessibilityViewId = |
Svetoslav Ganov | f3b4f31 | 2011-11-30 18:15:01 -0800 | [diff] [blame] | 556 | (root != null) ? root.getAccessibilityViewId() : UNDEFINED; |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 557 | final long childNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId); |
Svetoslav Ganov | 57c7fd5 | 2012-02-23 18:31:39 -0800 | [diff] [blame] | 558 | mChildNodeIds.put(index, childNodeId); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 559 | } |
| 560 | |
| 561 | /** |
| 562 | * Gets the actions that can be performed on the node. |
| 563 | * |
| 564 | * @return The bit mask of with actions. |
| 565 | * |
| 566 | * @see AccessibilityNodeInfo#ACTION_FOCUS |
| 567 | * @see AccessibilityNodeInfo#ACTION_CLEAR_FOCUS |
| 568 | * @see AccessibilityNodeInfo#ACTION_SELECT |
| 569 | * @see AccessibilityNodeInfo#ACTION_CLEAR_SELECTION |
| 570 | */ |
| 571 | public int getActions() { |
| 572 | return mActions; |
| 573 | } |
| 574 | |
| 575 | /** |
| 576 | * Adds an action that can be performed on the node. |
| 577 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 578 | * <strong>Note:</strong> Cannot be called from an |
| 579 | * {@link android.accessibilityservice.AccessibilityService}. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 580 | * This class is made immutable before being delivered to an AccessibilityService. |
| 581 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 582 | * |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 583 | * @param action The action. |
| 584 | * |
| 585 | * @throws IllegalStateException If called from an AccessibilityService. |
| 586 | */ |
| 587 | public void addAction(int action) { |
| 588 | enforceNotSealed(); |
| 589 | mActions |= action; |
| 590 | } |
| 591 | |
| 592 | /** |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 593 | * Sets the movement granularities for traversing the text of this node. |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 594 | * <p> |
| 595 | * <strong>Note:</strong> Cannot be called from an |
| 596 | * {@link android.accessibilityservice.AccessibilityService}. |
| 597 | * This class is made immutable before being delivered to an AccessibilityService. |
| 598 | * </p> |
| 599 | * |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 600 | * @param granularities The bit mask with granularities. |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 601 | * |
| 602 | * @throws IllegalStateException If called from an AccessibilityService. |
| 603 | */ |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 604 | public void setMovementGranularities(int granularities) { |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 605 | enforceNotSealed(); |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 606 | mMovementGranularities = granularities; |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 607 | } |
| 608 | |
| 609 | /** |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 610 | * Gets the movement granularities for traversing the text of this node. |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 611 | * |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 612 | * @return The bit mask with granularities. |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 613 | */ |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 614 | public int getMovementGranularities() { |
| 615 | return mMovementGranularities; |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 616 | } |
| 617 | |
| 618 | /** |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 619 | * Performs an action on the node. |
| 620 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 621 | * <strong>Note:</strong> An action can be performed only if the request is made |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 622 | * from an {@link android.accessibilityservice.AccessibilityService}. |
| 623 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 624 | * |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 625 | * @param action The action to perform. |
| 626 | * @return True if the action was performed. |
| 627 | * |
| 628 | * @throws IllegalStateException If called outside of an AccessibilityService. |
| 629 | */ |
| 630 | public boolean performAction(int action) { |
| 631 | enforceSealed(); |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 632 | if (!canPerformRequestOverConnection(mSourceNodeId)) { |
Svetoslav Ganov | eeee4d2 | 2011-06-10 20:51:30 -0700 | [diff] [blame] | 633 | return false; |
| 634 | } |
Svetoslav Ganov | 8bd6961 | 2011-08-23 13:40:30 -0700 | [diff] [blame] | 635 | AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 636 | return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId, |
| 637 | action, null); |
| 638 | } |
| 639 | |
| 640 | /** |
| 641 | * Performs an action on the node. |
| 642 | * <p> |
| 643 | * <strong>Note:</strong> An action can be performed only if the request is made |
| 644 | * from an {@link android.accessibilityservice.AccessibilityService}. |
| 645 | * </p> |
| 646 | * |
| 647 | * @param action The action to perform. |
| 648 | * @param arguments A bundle with additional arguments. |
| 649 | * @return True if the action was performed. |
| 650 | * |
| 651 | * @throws IllegalStateException If called outside of an AccessibilityService. |
| 652 | */ |
| 653 | public boolean performAction(int action, Bundle arguments) { |
| 654 | enforceSealed(); |
| 655 | if (!canPerformRequestOverConnection(mSourceNodeId)) { |
| 656 | return false; |
| 657 | } |
| 658 | AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); |
| 659 | return client.performAccessibilityAction(mConnectionId, mWindowId, mSourceNodeId, |
| 660 | action, arguments); |
Svetoslav Ganov | eeee4d2 | 2011-06-10 20:51:30 -0700 | [diff] [blame] | 661 | } |
| 662 | |
| 663 | /** |
| 664 | * Finds {@link AccessibilityNodeInfo}s by text. The match is case |
Svetoslav Ganov | 86398bd | 2011-06-21 17:38:43 -0700 | [diff] [blame] | 665 | * insensitive containment. The search is relative to this info i.e. |
| 666 | * this info is the root of the traversed tree. |
Svetoslav Ganov | ea515ae | 2011-09-14 18:15:32 -0700 | [diff] [blame] | 667 | * |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 668 | * <p> |
| 669 | * <strong>Note:</strong> It is a client responsibility to recycle the |
| 670 | * received info by calling {@link AccessibilityNodeInfo#recycle()} |
| 671 | * to avoid creating of multiple instances. |
| 672 | * </p> |
Svetoslav Ganov | eeee4d2 | 2011-06-10 20:51:30 -0700 | [diff] [blame] | 673 | * |
| 674 | * @param text The searched text. |
| 675 | * @return A list of node info. |
| 676 | */ |
| 677 | public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text) { |
| 678 | enforceSealed(); |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 679 | if (!canPerformRequestOverConnection(mSourceNodeId)) { |
Svetoslav Ganov | 86398bd | 2011-06-21 17:38:43 -0700 | [diff] [blame] | 680 | return Collections.emptyList(); |
Svetoslav Ganov | eeee4d2 | 2011-06-10 20:51:30 -0700 | [diff] [blame] | 681 | } |
Svetoslav Ganov | 8bd6961 | 2011-08-23 13:40:30 -0700 | [diff] [blame] | 682 | AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); |
Svetoslav Ganov | 79311c4 | 2012-01-17 20:24:26 -0800 | [diff] [blame] | 683 | return client.findAccessibilityNodeInfosByText(mConnectionId, mWindowId, mSourceNodeId, |
| 684 | text); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 685 | } |
| 686 | |
| 687 | /** |
Svetoslav Ganov | 00aabf7 | 2011-07-21 11:35:03 -0700 | [diff] [blame] | 688 | * Gets the parent. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 689 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 690 | * <strong>Note:</strong> It is a client responsibility to recycle the |
| 691 | * received info by calling {@link AccessibilityNodeInfo#recycle()} |
| 692 | * to avoid creating of multiple instances. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 693 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 694 | * |
Svetoslav Ganov | 00aabf7 | 2011-07-21 11:35:03 -0700 | [diff] [blame] | 695 | * @return The parent. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 696 | */ |
| 697 | public AccessibilityNodeInfo getParent() { |
| 698 | enforceSealed(); |
Svetoslav Ganov | af0d984 | 2011-10-26 15:29:26 -0700 | [diff] [blame] | 699 | if (!canPerformRequestOverConnection(mParentNodeId)) { |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 700 | return null; |
| 701 | } |
Svetoslav Ganov | 8bd6961 | 2011-08-23 13:40:30 -0700 | [diff] [blame] | 702 | AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance(); |
Svetoslav Ganov | d116d7c | 2011-11-21 18:41:59 -0800 | [diff] [blame] | 703 | return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, |
Svetoslav Ganov | 57c7fd5 | 2012-02-23 18:31:39 -0800 | [diff] [blame] | 704 | mWindowId, mParentNodeId, FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS); |
| 705 | } |
| 706 | |
| 707 | /** |
| 708 | * @return The parent node id. |
| 709 | * |
| 710 | * @hide |
| 711 | */ |
| 712 | public long getParentNodeId() { |
| 713 | return mParentNodeId; |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 714 | } |
| 715 | |
| 716 | /** |
| 717 | * Sets the parent. |
| 718 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 719 | * <strong>Note:</strong> Cannot be called from an |
| 720 | * {@link android.accessibilityservice.AccessibilityService}. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 721 | * This class is made immutable before being delivered to an AccessibilityService. |
| 722 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 723 | * |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 724 | * @param parent The parent. |
| 725 | * |
| 726 | * @throws IllegalStateException If called from an AccessibilityService. |
| 727 | */ |
| 728 | public void setParent(View parent) { |
Svetoslav Ganov | f3b4f31 | 2011-11-30 18:15:01 -0800 | [diff] [blame] | 729 | setParent(parent, UNDEFINED); |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 730 | } |
| 731 | |
| 732 | /** |
| 733 | * Sets the parent to be a virtual descendant of the given <code>root</code>. |
| 734 | * If <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root |
| 735 | * is set as the parent. |
| 736 | * <p> |
| 737 | * A virtual descendant is an imaginary View that is reported as a part of the view |
| 738 | * hierarchy for accessibility purposes. This enables custom views that draw complex |
| 739 | * content to report them selves as a tree of virtual views, thus conveying their |
| 740 | * logical structure. |
| 741 | * </p> |
| 742 | * <p> |
| 743 | * <strong>Note:</strong> Cannot be called from an |
| 744 | * {@link android.accessibilityservice.AccessibilityService}. |
| 745 | * This class is made immutable before being delivered to an AccessibilityService. |
| 746 | * </p> |
| 747 | * |
| 748 | * @param root The root of the virtual subtree. |
| 749 | * @param virtualDescendantId The id of the virtual descendant. |
| 750 | */ |
| 751 | public void setParent(View root, int virtualDescendantId) { |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 752 | enforceNotSealed(); |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 753 | final int rootAccessibilityViewId = |
Svetoslav Ganov | f3b4f31 | 2011-11-30 18:15:01 -0800 | [diff] [blame] | 754 | (root != null) ? root.getAccessibilityViewId() : UNDEFINED; |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 755 | mParentNodeId = makeNodeId(rootAccessibilityViewId, virtualDescendantId); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 756 | } |
| 757 | |
| 758 | /** |
| 759 | * Gets the node bounds in parent coordinates. |
| 760 | * |
| 761 | * @param outBounds The output node bounds. |
| 762 | */ |
Svetoslav Ganov | eeee4d2 | 2011-06-10 20:51:30 -0700 | [diff] [blame] | 763 | public void getBoundsInParent(Rect outBounds) { |
| 764 | outBounds.set(mBoundsInParent.left, mBoundsInParent.top, |
| 765 | mBoundsInParent.right, mBoundsInParent.bottom); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 766 | } |
| 767 | |
| 768 | /** |
| 769 | * Sets the node bounds in parent coordinates. |
| 770 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 771 | * <strong>Note:</strong> Cannot be called from an |
| 772 | * {@link android.accessibilityservice.AccessibilityService}. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 773 | * This class is made immutable before being delivered to an AccessibilityService. |
| 774 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 775 | * |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 776 | * @param bounds The node bounds. |
| 777 | * |
| 778 | * @throws IllegalStateException If called from an AccessibilityService. |
| 779 | */ |
Svetoslav Ganov | eeee4d2 | 2011-06-10 20:51:30 -0700 | [diff] [blame] | 780 | public void setBoundsInParent(Rect bounds) { |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 781 | enforceNotSealed(); |
Svetoslav Ganov | eeee4d2 | 2011-06-10 20:51:30 -0700 | [diff] [blame] | 782 | mBoundsInParent.set(bounds.left, bounds.top, bounds.right, bounds.bottom); |
| 783 | } |
| 784 | |
| 785 | /** |
| 786 | * Gets the node bounds in screen coordinates. |
| 787 | * |
| 788 | * @param outBounds The output node bounds. |
| 789 | */ |
| 790 | public void getBoundsInScreen(Rect outBounds) { |
| 791 | outBounds.set(mBoundsInScreen.left, mBoundsInScreen.top, |
| 792 | mBoundsInScreen.right, mBoundsInScreen.bottom); |
| 793 | } |
| 794 | |
| 795 | /** |
| 796 | * Sets the node bounds in screen coordinates. |
| 797 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 798 | * <strong>Note:</strong> Cannot be called from an |
| 799 | * {@link android.accessibilityservice.AccessibilityService}. |
Svetoslav Ganov | eeee4d2 | 2011-06-10 20:51:30 -0700 | [diff] [blame] | 800 | * This class is made immutable before being delivered to an AccessibilityService. |
| 801 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 802 | * |
Svetoslav Ganov | eeee4d2 | 2011-06-10 20:51:30 -0700 | [diff] [blame] | 803 | * @param bounds The node bounds. |
| 804 | * |
| 805 | * @throws IllegalStateException If called from an AccessibilityService. |
| 806 | */ |
| 807 | public void setBoundsInScreen(Rect bounds) { |
| 808 | enforceNotSealed(); |
| 809 | mBoundsInScreen.set(bounds.left, bounds.top, bounds.right, bounds.bottom); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 810 | } |
| 811 | |
| 812 | /** |
| 813 | * Gets whether this node is checkable. |
| 814 | * |
| 815 | * @return True if the node is checkable. |
| 816 | */ |
| 817 | public boolean isCheckable() { |
| 818 | return getBooleanProperty(PROPERTY_CHECKABLE); |
| 819 | } |
| 820 | |
| 821 | /** |
| 822 | * Sets whether this node is checkable. |
| 823 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 824 | * <strong>Note:</strong> Cannot be called from an |
| 825 | * {@link android.accessibilityservice.AccessibilityService}. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 826 | * This class is made immutable before being delivered to an AccessibilityService. |
| 827 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 828 | * |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 829 | * @param checkable True if the node is checkable. |
| 830 | * |
| 831 | * @throws IllegalStateException If called from an AccessibilityService. |
| 832 | */ |
| 833 | public void setCheckable(boolean checkable) { |
| 834 | setBooleanProperty(PROPERTY_CHECKABLE, checkable); |
| 835 | } |
| 836 | |
| 837 | /** |
| 838 | * Gets whether this node is checked. |
| 839 | * |
| 840 | * @return True if the node is checked. |
| 841 | */ |
| 842 | public boolean isChecked() { |
| 843 | return getBooleanProperty(PROPERTY_CHECKED); |
| 844 | } |
| 845 | |
| 846 | /** |
| 847 | * Sets whether this node is checked. |
| 848 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 849 | * <strong>Note:</strong> Cannot be called from an |
| 850 | * {@link android.accessibilityservice.AccessibilityService}. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 851 | * This class is made immutable before being delivered to an AccessibilityService. |
| 852 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 853 | * |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 854 | * @param checked True if the node is checked. |
| 855 | * |
| 856 | * @throws IllegalStateException If called from an AccessibilityService. |
| 857 | */ |
| 858 | public void setChecked(boolean checked) { |
| 859 | setBooleanProperty(PROPERTY_CHECKED, checked); |
| 860 | } |
| 861 | |
| 862 | /** |
| 863 | * Gets whether this node is focusable. |
| 864 | * |
| 865 | * @return True if the node is focusable. |
| 866 | */ |
| 867 | public boolean isFocusable() { |
| 868 | return getBooleanProperty(PROPERTY_FOCUSABLE); |
| 869 | } |
| 870 | |
| 871 | /** |
| 872 | * Sets whether this node is focusable. |
| 873 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 874 | * <strong>Note:</strong> Cannot be called from an |
| 875 | * {@link android.accessibilityservice.AccessibilityService}. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 876 | * This class is made immutable before being delivered to an AccessibilityService. |
| 877 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 878 | * |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 879 | * @param focusable True if the node is focusable. |
| 880 | * |
| 881 | * @throws IllegalStateException If called from an AccessibilityService. |
| 882 | */ |
| 883 | public void setFocusable(boolean focusable) { |
| 884 | setBooleanProperty(PROPERTY_FOCUSABLE, focusable); |
| 885 | } |
| 886 | |
| 887 | /** |
| 888 | * Gets whether this node is focused. |
| 889 | * |
| 890 | * @return True if the node is focused. |
| 891 | */ |
| 892 | public boolean isFocused() { |
| 893 | return getBooleanProperty(PROPERTY_FOCUSED); |
| 894 | } |
| 895 | |
| 896 | /** |
| 897 | * Sets whether this node is focused. |
| 898 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 899 | * <strong>Note:</strong> Cannot be called from an |
| 900 | * {@link android.accessibilityservice.AccessibilityService}. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 901 | * This class is made immutable before being delivered to an AccessibilityService. |
| 902 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 903 | * |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 904 | * @param focused True if the node is focused. |
| 905 | * |
| 906 | * @throws IllegalStateException If called from an AccessibilityService. |
| 907 | */ |
| 908 | public void setFocused(boolean focused) { |
| 909 | setBooleanProperty(PROPERTY_FOCUSED, focused); |
| 910 | } |
| 911 | |
| 912 | /** |
Svetoslav Ganov | 4213804 | 2012-03-20 11:51:39 -0700 | [diff] [blame] | 913 | * Gets whether this node is accessibility focused. |
| 914 | * |
| 915 | * @return True if the node is accessibility focused. |
| 916 | */ |
| 917 | public boolean isAccessibilityFocused() { |
| 918 | return getBooleanProperty(PROPERTY_ACCESSIBILITY_FOCUSED); |
| 919 | } |
| 920 | |
| 921 | /** |
| 922 | * Sets whether this node is accessibility focused. |
| 923 | * <p> |
| 924 | * <strong>Note:</strong> Cannot be called from an |
| 925 | * {@link android.accessibilityservice.AccessibilityService}. |
| 926 | * This class is made immutable before being delivered to an AccessibilityService. |
| 927 | * </p> |
| 928 | * |
| 929 | * @param focused True if the node is accessibility focused. |
| 930 | * |
| 931 | * @throws IllegalStateException If called from an AccessibilityService. |
| 932 | */ |
| 933 | public void setAccessibilityFocused(boolean focused) { |
| 934 | setBooleanProperty(PROPERTY_ACCESSIBILITY_FOCUSED, focused); |
| 935 | } |
| 936 | |
| 937 | /** |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 938 | * Gets whether this node is selected. |
| 939 | * |
| 940 | * @return True if the node is selected. |
| 941 | */ |
| 942 | public boolean isSelected() { |
| 943 | return getBooleanProperty(PROPERTY_SELECTED); |
| 944 | } |
| 945 | |
| 946 | /** |
| 947 | * Sets whether this node is selected. |
| 948 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 949 | * <strong>Note:</strong> Cannot be called from an |
| 950 | * {@link android.accessibilityservice.AccessibilityService}. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 951 | * This class is made immutable before being delivered to an AccessibilityService. |
| 952 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 953 | * |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 954 | * @param selected True if the node is selected. |
| 955 | * |
| 956 | * @throws IllegalStateException If called from an AccessibilityService. |
| 957 | */ |
| 958 | public void setSelected(boolean selected) { |
| 959 | setBooleanProperty(PROPERTY_SELECTED, selected); |
| 960 | } |
| 961 | |
| 962 | /** |
| 963 | * Gets whether this node is clickable. |
| 964 | * |
| 965 | * @return True if the node is clickable. |
| 966 | */ |
| 967 | public boolean isClickable() { |
| 968 | return getBooleanProperty(PROPERTY_CLICKABLE); |
| 969 | } |
| 970 | |
| 971 | /** |
| 972 | * Sets whether this node is clickable. |
| 973 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 974 | * <strong>Note:</strong> Cannot be called from an |
| 975 | * {@link android.accessibilityservice.AccessibilityService}. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 976 | * This class is made immutable before being delivered to an AccessibilityService. |
| 977 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 978 | * |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 979 | * @param clickable True if the node is clickable. |
| 980 | * |
| 981 | * @throws IllegalStateException If called from an AccessibilityService. |
| 982 | */ |
| 983 | public void setClickable(boolean clickable) { |
| 984 | setBooleanProperty(PROPERTY_CLICKABLE, clickable); |
| 985 | } |
| 986 | |
| 987 | /** |
| 988 | * Gets whether this node is long clickable. |
| 989 | * |
| 990 | * @return True if the node is long clickable. |
| 991 | */ |
| 992 | public boolean isLongClickable() { |
| 993 | return getBooleanProperty(PROPERTY_LONG_CLICKABLE); |
| 994 | } |
| 995 | |
| 996 | /** |
| 997 | * Sets whether this node is long clickable. |
| 998 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 999 | * <strong>Note:</strong> Cannot be called from an |
| 1000 | * {@link android.accessibilityservice.AccessibilityService}. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1001 | * This class is made immutable before being delivered to an AccessibilityService. |
| 1002 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 1003 | * |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1004 | * @param longClickable True if the node is long clickable. |
| 1005 | * |
| 1006 | * @throws IllegalStateException If called from an AccessibilityService. |
| 1007 | */ |
| 1008 | public void setLongClickable(boolean longClickable) { |
| 1009 | setBooleanProperty(PROPERTY_LONG_CLICKABLE, longClickable); |
| 1010 | } |
| 1011 | |
| 1012 | /** |
| 1013 | * Gets whether this node is enabled. |
| 1014 | * |
| 1015 | * @return True if the node is enabled. |
| 1016 | */ |
| 1017 | public boolean isEnabled() { |
| 1018 | return getBooleanProperty(PROPERTY_ENABLED); |
| 1019 | } |
| 1020 | |
| 1021 | /** |
| 1022 | * Sets whether this node is enabled. |
| 1023 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 1024 | * <strong>Note:</strong> Cannot be called from an |
| 1025 | * {@link android.accessibilityservice.AccessibilityService}. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1026 | * This class is made immutable before being delivered to an AccessibilityService. |
| 1027 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 1028 | * |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1029 | * @param enabled True if the node is enabled. |
| 1030 | * |
| 1031 | * @throws IllegalStateException If called from an AccessibilityService. |
| 1032 | */ |
| 1033 | public void setEnabled(boolean enabled) { |
| 1034 | setBooleanProperty(PROPERTY_ENABLED, enabled); |
| 1035 | } |
| 1036 | |
| 1037 | /** |
| 1038 | * Gets whether this node is a password. |
| 1039 | * |
| 1040 | * @return True if the node is a password. |
| 1041 | */ |
| 1042 | public boolean isPassword() { |
| 1043 | return getBooleanProperty(PROPERTY_PASSWORD); |
| 1044 | } |
| 1045 | |
| 1046 | /** |
| 1047 | * Sets whether this node is a password. |
| 1048 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 1049 | * <strong>Note:</strong> Cannot be called from an |
| 1050 | * {@link android.accessibilityservice.AccessibilityService}. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1051 | * This class is made immutable before being delivered to an AccessibilityService. |
| 1052 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 1053 | * |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1054 | * @param password True if the node is a password. |
| 1055 | * |
| 1056 | * @throws IllegalStateException If called from an AccessibilityService. |
| 1057 | */ |
| 1058 | public void setPassword(boolean password) { |
| 1059 | setBooleanProperty(PROPERTY_PASSWORD, password); |
| 1060 | } |
| 1061 | |
| 1062 | /** |
Svetoslav Ganov | a015617 | 2011-06-26 17:55:44 -0700 | [diff] [blame] | 1063 | * Gets if the node is scrollable. |
| 1064 | * |
| 1065 | * @return True if the node is scrollable, false otherwise. |
| 1066 | */ |
| 1067 | public boolean isScrollable() { |
| 1068 | return getBooleanProperty(PROPERTY_SCROLLABLE); |
| 1069 | } |
| 1070 | |
| 1071 | /** |
| 1072 | * Sets if the node is scrollable. |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 1073 | * <p> |
| 1074 | * <strong>Note:</strong> Cannot be called from an |
| 1075 | * {@link android.accessibilityservice.AccessibilityService}. |
| 1076 | * This class is made immutable before being delivered to an AccessibilityService. |
| 1077 | * </p> |
Svetoslav Ganov | a015617 | 2011-06-26 17:55:44 -0700 | [diff] [blame] | 1078 | * |
| 1079 | * @param scrollable True if the node is scrollable, false otherwise. |
| 1080 | * |
| 1081 | * @throws IllegalStateException If called from an AccessibilityService. |
| 1082 | */ |
| 1083 | public void setScrollable(boolean scrollable) { |
| 1084 | enforceNotSealed(); |
| 1085 | setBooleanProperty(PROPERTY_SCROLLABLE, scrollable); |
| 1086 | } |
| 1087 | |
| 1088 | /** |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1089 | * Gets the package this node comes from. |
| 1090 | * |
| 1091 | * @return The package name. |
| 1092 | */ |
| 1093 | public CharSequence getPackageName() { |
| 1094 | return mPackageName; |
| 1095 | } |
| 1096 | |
| 1097 | /** |
| 1098 | * Sets the package this node comes from. |
| 1099 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 1100 | * <strong>Note:</strong> Cannot be called from an |
| 1101 | * {@link android.accessibilityservice.AccessibilityService}. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1102 | * This class is made immutable before being delivered to an AccessibilityService. |
| 1103 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 1104 | * |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1105 | * @param packageName The package name. |
| 1106 | * |
| 1107 | * @throws IllegalStateException If called from an AccessibilityService. |
| 1108 | */ |
| 1109 | public void setPackageName(CharSequence packageName) { |
| 1110 | enforceNotSealed(); |
| 1111 | mPackageName = packageName; |
| 1112 | } |
| 1113 | |
| 1114 | /** |
| 1115 | * Gets the class this node comes from. |
| 1116 | * |
| 1117 | * @return The class name. |
| 1118 | */ |
| 1119 | public CharSequence getClassName() { |
| 1120 | return mClassName; |
| 1121 | } |
| 1122 | |
| 1123 | /** |
| 1124 | * Sets the class this node comes from. |
| 1125 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 1126 | * <strong>Note:</strong> Cannot be called from an |
| 1127 | * {@link android.accessibilityservice.AccessibilityService}. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1128 | * This class is made immutable before being delivered to an AccessibilityService. |
| 1129 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 1130 | * |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1131 | * @param className The class name. |
| 1132 | * |
| 1133 | * @throws IllegalStateException If called from an AccessibilityService. |
| 1134 | */ |
| 1135 | public void setClassName(CharSequence className) { |
| 1136 | enforceNotSealed(); |
| 1137 | mClassName = className; |
| 1138 | } |
| 1139 | |
| 1140 | /** |
| 1141 | * Gets the text of this node. |
| 1142 | * |
| 1143 | * @return The text. |
| 1144 | */ |
| 1145 | public CharSequence getText() { |
| 1146 | return mText; |
| 1147 | } |
| 1148 | |
| 1149 | /** |
| 1150 | * Sets the text of this node. |
| 1151 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 1152 | * <strong>Note:</strong> Cannot be called from an |
| 1153 | * {@link android.accessibilityservice.AccessibilityService}. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1154 | * This class is made immutable before being delivered to an AccessibilityService. |
| 1155 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 1156 | * |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1157 | * @param text The text. |
| 1158 | * |
| 1159 | * @throws IllegalStateException If called from an AccessibilityService. |
| 1160 | */ |
| 1161 | public void setText(CharSequence text) { |
| 1162 | enforceNotSealed(); |
| 1163 | mText = text; |
| 1164 | } |
| 1165 | |
| 1166 | /** |
| 1167 | * Gets the content description of this node. |
| 1168 | * |
| 1169 | * @return The content description. |
| 1170 | */ |
| 1171 | public CharSequence getContentDescription() { |
| 1172 | return mContentDescription; |
| 1173 | } |
| 1174 | |
| 1175 | /** |
| 1176 | * Sets the content description of this node. |
| 1177 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 1178 | * <strong>Note:</strong> Cannot be called from an |
| 1179 | * {@link android.accessibilityservice.AccessibilityService}. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1180 | * This class is made immutable before being delivered to an AccessibilityService. |
| 1181 | * </p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 1182 | * |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1183 | * @param contentDescription The content description. |
| 1184 | * |
| 1185 | * @throws IllegalStateException If called from an AccessibilityService. |
| 1186 | */ |
| 1187 | public void setContentDescription(CharSequence contentDescription) { |
| 1188 | enforceNotSealed(); |
| 1189 | mContentDescription = contentDescription; |
| 1190 | } |
| 1191 | |
| 1192 | /** |
| 1193 | * Gets the value of a boolean property. |
| 1194 | * |
| 1195 | * @param property The property. |
| 1196 | * @return The value. |
| 1197 | */ |
| 1198 | private boolean getBooleanProperty(int property) { |
| 1199 | return (mBooleanProperties & property) != 0; |
| 1200 | } |
| 1201 | |
| 1202 | /** |
| 1203 | * Sets a boolean property. |
| 1204 | * |
| 1205 | * @param property The property. |
| 1206 | * @param value The value. |
| 1207 | * |
| 1208 | * @throws IllegalStateException If called from an AccessibilityService. |
| 1209 | */ |
| 1210 | private void setBooleanProperty(int property, boolean value) { |
| 1211 | enforceNotSealed(); |
| 1212 | if (value) { |
| 1213 | mBooleanProperties |= property; |
| 1214 | } else { |
| 1215 | mBooleanProperties &= ~property; |
| 1216 | } |
| 1217 | } |
| 1218 | |
| 1219 | /** |
Svetoslav Ganov | d116d7c | 2011-11-21 18:41:59 -0800 | [diff] [blame] | 1220 | * Sets the unique id of the IAccessibilityServiceConnection over which |
| 1221 | * this instance can send requests to the system. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1222 | * |
Svetoslav Ganov | d116d7c | 2011-11-21 18:41:59 -0800 | [diff] [blame] | 1223 | * @param connectionId The connection id. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1224 | * |
| 1225 | * @hide |
| 1226 | */ |
Svetoslav Ganov | d116d7c | 2011-11-21 18:41:59 -0800 | [diff] [blame] | 1227 | public void setConnectionId(int connectionId) { |
Svetoslav Ganov | eeee4d2 | 2011-06-10 20:51:30 -0700 | [diff] [blame] | 1228 | enforceNotSealed(); |
Svetoslav Ganov | d116d7c | 2011-11-21 18:41:59 -0800 | [diff] [blame] | 1229 | mConnectionId = connectionId; |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1230 | } |
| 1231 | |
| 1232 | /** |
| 1233 | * {@inheritDoc} |
| 1234 | */ |
| 1235 | public int describeContents() { |
| 1236 | return 0; |
| 1237 | } |
| 1238 | |
| 1239 | /** |
Svetoslav Ganov | 79311c4 | 2012-01-17 20:24:26 -0800 | [diff] [blame] | 1240 | * Gets the id of the source node. |
| 1241 | * |
| 1242 | * @return The id. |
| 1243 | * |
| 1244 | * @hide |
| 1245 | */ |
| 1246 | public long getSourceNodeId() { |
| 1247 | return mSourceNodeId; |
| 1248 | } |
| 1249 | |
| 1250 | /** |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1251 | * Sets if this instance is sealed. |
| 1252 | * |
| 1253 | * @param sealed Whether is sealed. |
| 1254 | * |
| 1255 | * @hide |
| 1256 | */ |
| 1257 | public void setSealed(boolean sealed) { |
| 1258 | mSealed = sealed; |
| 1259 | } |
| 1260 | |
| 1261 | /** |
| 1262 | * Gets if this instance is sealed. |
| 1263 | * |
| 1264 | * @return Whether is sealed. |
| 1265 | * |
| 1266 | * @hide |
| 1267 | */ |
| 1268 | public boolean isSealed() { |
| 1269 | return mSealed; |
| 1270 | } |
| 1271 | |
| 1272 | /** |
| 1273 | * Enforces that this instance is sealed. |
| 1274 | * |
| 1275 | * @throws IllegalStateException If this instance is not sealed. |
| 1276 | * |
| 1277 | * @hide |
| 1278 | */ |
| 1279 | protected void enforceSealed() { |
| 1280 | if (!isSealed()) { |
| 1281 | throw new IllegalStateException("Cannot perform this " |
| 1282 | + "action on a not sealed instance."); |
| 1283 | } |
| 1284 | } |
| 1285 | |
| 1286 | /** |
| 1287 | * Enforces that this instance is not sealed. |
| 1288 | * |
| 1289 | * @throws IllegalStateException If this instance is sealed. |
| 1290 | * |
| 1291 | * @hide |
| 1292 | */ |
| 1293 | protected void enforceNotSealed() { |
| 1294 | if (isSealed()) { |
| 1295 | throw new IllegalStateException("Cannot perform this " |
Ken Wakasa | f76a50c | 2012-03-09 19:56:35 +0900 | [diff] [blame] | 1296 | + "action on a sealed instance."); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1297 | } |
| 1298 | } |
| 1299 | |
| 1300 | /** |
| 1301 | * Returns a cached instance if such is available otherwise a new one |
| 1302 | * and sets the source. |
| 1303 | * |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 1304 | * @param source The source view. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1305 | * @return An instance. |
| 1306 | * |
| 1307 | * @see #setSource(View) |
| 1308 | */ |
| 1309 | public static AccessibilityNodeInfo obtain(View source) { |
| 1310 | AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(); |
| 1311 | info.setSource(source); |
| 1312 | return info; |
| 1313 | } |
| 1314 | |
| 1315 | /** |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 1316 | * Returns a cached instance if such is available otherwise a new one |
| 1317 | * and sets the source. |
| 1318 | * |
| 1319 | * @param root The root of the virtual subtree. |
| 1320 | * @param virtualDescendantId The id of the virtual descendant. |
| 1321 | * @return An instance. |
| 1322 | * |
| 1323 | * @see #setSource(View, int) |
| 1324 | */ |
| 1325 | public static AccessibilityNodeInfo obtain(View root, int virtualDescendantId) { |
| 1326 | AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(); |
| 1327 | info.setSource(root, virtualDescendantId); |
| 1328 | return info; |
| 1329 | } |
| 1330 | |
| 1331 | /** |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1332 | * Returns a cached instance if such is available otherwise a new one. |
| 1333 | * |
| 1334 | * @return An instance. |
| 1335 | */ |
| 1336 | public static AccessibilityNodeInfo obtain() { |
| 1337 | synchronized (sPoolLock) { |
| 1338 | if (sPool != null) { |
| 1339 | AccessibilityNodeInfo info = sPool; |
| 1340 | sPool = sPool.mNext; |
| 1341 | sPoolSize--; |
| 1342 | info.mNext = null; |
| 1343 | info.mIsInPool = false; |
Svetoslav Ganov | 9210ccb | 2011-06-08 19:42:51 -0700 | [diff] [blame] | 1344 | return info; |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1345 | } |
| 1346 | return new AccessibilityNodeInfo(); |
| 1347 | } |
| 1348 | } |
| 1349 | |
| 1350 | /** |
Svetoslav Ganov | 35bfede | 2011-07-14 17:57:06 -0700 | [diff] [blame] | 1351 | * Returns a cached instance if such is available or a new one is |
| 1352 | * create. The returned instance is initialized from the given |
| 1353 | * <code>info</code>. |
| 1354 | * |
| 1355 | * @param info The other info. |
| 1356 | * @return An instance. |
| 1357 | */ |
| 1358 | public static AccessibilityNodeInfo obtain(AccessibilityNodeInfo info) { |
| 1359 | AccessibilityNodeInfo infoClone = AccessibilityNodeInfo.obtain(); |
| 1360 | infoClone.init(info); |
| 1361 | return infoClone; |
| 1362 | } |
| 1363 | |
| 1364 | /** |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1365 | * Return an instance back to be reused. |
| 1366 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 1367 | * <strong>Note:</strong> You must not touch the object after calling this function. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1368 | * |
| 1369 | * @throws IllegalStateException If the info is already recycled. |
| 1370 | */ |
| 1371 | public void recycle() { |
| 1372 | if (mIsInPool) { |
| 1373 | throw new IllegalStateException("Info already recycled!"); |
| 1374 | } |
| 1375 | clear(); |
| 1376 | synchronized (sPoolLock) { |
| 1377 | if (sPoolSize <= MAX_POOL_SIZE) { |
| 1378 | mNext = sPool; |
| 1379 | sPool = this; |
| 1380 | mIsInPool = true; |
| 1381 | sPoolSize++; |
| 1382 | } |
| 1383 | } |
| 1384 | } |
| 1385 | |
| 1386 | /** |
| 1387 | * {@inheritDoc} |
| 1388 | * <p> |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 1389 | * <strong>Note:</strong> After the instance is written to a parcel it |
| 1390 | * is recycled. You must not touch the object after calling this function. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1391 | * </p> |
| 1392 | */ |
| 1393 | public void writeToParcel(Parcel parcel, int flags) { |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1394 | parcel.writeInt(isSealed() ? 1 : 0); |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 1395 | parcel.writeLong(mSourceNodeId); |
| 1396 | parcel.writeInt(mWindowId); |
| 1397 | parcel.writeLong(mParentNodeId); |
Svetoslav Ganov | d116d7c | 2011-11-21 18:41:59 -0800 | [diff] [blame] | 1398 | parcel.writeInt(mConnectionId); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1399 | |
Svetoslav Ganov | 57c7fd5 | 2012-02-23 18:31:39 -0800 | [diff] [blame] | 1400 | SparseLongArray childIds = mChildNodeIds; |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1401 | final int childIdsSize = childIds.size(); |
| 1402 | parcel.writeInt(childIdsSize); |
| 1403 | for (int i = 0; i < childIdsSize; i++) { |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 1404 | parcel.writeLong(childIds.valueAt(i)); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1405 | } |
| 1406 | |
Svetoslav Ganov | eeee4d2 | 2011-06-10 20:51:30 -0700 | [diff] [blame] | 1407 | parcel.writeInt(mBoundsInParent.top); |
| 1408 | parcel.writeInt(mBoundsInParent.bottom); |
| 1409 | parcel.writeInt(mBoundsInParent.left); |
| 1410 | parcel.writeInt(mBoundsInParent.right); |
| 1411 | |
| 1412 | parcel.writeInt(mBoundsInScreen.top); |
| 1413 | parcel.writeInt(mBoundsInScreen.bottom); |
| 1414 | parcel.writeInt(mBoundsInScreen.left); |
| 1415 | parcel.writeInt(mBoundsInScreen.right); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1416 | |
| 1417 | parcel.writeInt(mActions); |
| 1418 | |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 1419 | parcel.writeInt(mMovementGranularities); |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 1420 | |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1421 | parcel.writeInt(mBooleanProperties); |
| 1422 | |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 1423 | parcel.writeCharSequence(mPackageName); |
| 1424 | parcel.writeCharSequence(mClassName); |
| 1425 | parcel.writeCharSequence(mText); |
| 1426 | parcel.writeCharSequence(mContentDescription); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1427 | |
| 1428 | // Since instances of this class are fetched via synchronous i.e. blocking |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 1429 | // calls in IPCs we always recycle as soon as the instance is marshaled. |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1430 | recycle(); |
| 1431 | } |
| 1432 | |
| 1433 | /** |
Svetoslav Ganov | 35bfede | 2011-07-14 17:57:06 -0700 | [diff] [blame] | 1434 | * Initializes this instance from another one. |
| 1435 | * |
| 1436 | * @param other The other instance. |
| 1437 | */ |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 1438 | @SuppressWarnings("unchecked") |
Svetoslav Ganov | 35bfede | 2011-07-14 17:57:06 -0700 | [diff] [blame] | 1439 | private void init(AccessibilityNodeInfo other) { |
| 1440 | mSealed = other.mSealed; |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 1441 | mSourceNodeId = other.mSourceNodeId; |
| 1442 | mParentNodeId = other.mParentNodeId; |
| 1443 | mWindowId = other.mWindowId; |
Svetoslav Ganov | d116d7c | 2011-11-21 18:41:59 -0800 | [diff] [blame] | 1444 | mConnectionId = other.mConnectionId; |
Svetoslav Ganov | 35bfede | 2011-07-14 17:57:06 -0700 | [diff] [blame] | 1445 | mBoundsInParent.set(other.mBoundsInParent); |
| 1446 | mBoundsInScreen.set(other.mBoundsInScreen); |
| 1447 | mPackageName = other.mPackageName; |
| 1448 | mClassName = other.mClassName; |
| 1449 | mText = other.mText; |
| 1450 | mContentDescription = other.mContentDescription; |
| 1451 | mActions= other.mActions; |
| 1452 | mBooleanProperties = other.mBooleanProperties; |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 1453 | mMovementGranularities = other.mMovementGranularities; |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 1454 | final int otherChildIdCount = other.mChildNodeIds.size(); |
| 1455 | for (int i = 0; i < otherChildIdCount; i++) { |
| 1456 | mChildNodeIds.put(i, other.mChildNodeIds.valueAt(i)); |
| 1457 | } |
Svetoslav Ganov | 35bfede | 2011-07-14 17:57:06 -0700 | [diff] [blame] | 1458 | } |
| 1459 | |
| 1460 | /** |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1461 | * Creates a new instance from a {@link Parcel}. |
| 1462 | * |
| 1463 | * @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}. |
| 1464 | */ |
| 1465 | private void initFromParcel(Parcel parcel) { |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1466 | mSealed = (parcel.readInt() == 1); |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 1467 | mSourceNodeId = parcel.readLong(); |
| 1468 | mWindowId = parcel.readInt(); |
| 1469 | mParentNodeId = parcel.readLong(); |
Svetoslav Ganov | d116d7c | 2011-11-21 18:41:59 -0800 | [diff] [blame] | 1470 | mConnectionId = parcel.readInt(); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1471 | |
Svetoslav Ganov | 57c7fd5 | 2012-02-23 18:31:39 -0800 | [diff] [blame] | 1472 | SparseLongArray childIds = mChildNodeIds; |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1473 | final int childrenSize = parcel.readInt(); |
| 1474 | for (int i = 0; i < childrenSize; i++) { |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 1475 | final long childId = parcel.readLong(); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1476 | childIds.put(i, childId); |
| 1477 | } |
| 1478 | |
Svetoslav Ganov | eeee4d2 | 2011-06-10 20:51:30 -0700 | [diff] [blame] | 1479 | mBoundsInParent.top = parcel.readInt(); |
| 1480 | mBoundsInParent.bottom = parcel.readInt(); |
| 1481 | mBoundsInParent.left = parcel.readInt(); |
| 1482 | mBoundsInParent.right = parcel.readInt(); |
| 1483 | |
| 1484 | mBoundsInScreen.top = parcel.readInt(); |
| 1485 | mBoundsInScreen.bottom = parcel.readInt(); |
| 1486 | mBoundsInScreen.left = parcel.readInt(); |
| 1487 | mBoundsInScreen.right = parcel.readInt(); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1488 | |
| 1489 | mActions = parcel.readInt(); |
| 1490 | |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 1491 | mMovementGranularities = parcel.readInt(); |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 1492 | |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1493 | mBooleanProperties = parcel.readInt(); |
| 1494 | |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 1495 | mPackageName = parcel.readCharSequence(); |
| 1496 | mClassName = parcel.readCharSequence(); |
| 1497 | mText = parcel.readCharSequence(); |
| 1498 | mContentDescription = parcel.readCharSequence(); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1499 | } |
| 1500 | |
| 1501 | /** |
| 1502 | * Clears the state of this instance. |
| 1503 | */ |
| 1504 | private void clear() { |
| 1505 | mSealed = false; |
Svetoslav Ganov | 0d04e24 | 2012-02-21 13:46:36 -0800 | [diff] [blame] | 1506 | mSourceNodeId = ROOT_NODE_ID; |
| 1507 | mParentNodeId = ROOT_NODE_ID; |
Svetoslav Ganov | f3b4f31 | 2011-11-30 18:15:01 -0800 | [diff] [blame] | 1508 | mWindowId = UNDEFINED; |
Svetoslav Ganov | d116d7c | 2011-11-21 18:41:59 -0800 | [diff] [blame] | 1509 | mConnectionId = UNDEFINED; |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 1510 | mMovementGranularities = 0; |
Svetoslav Ganov | 57c7fd5 | 2012-02-23 18:31:39 -0800 | [diff] [blame] | 1511 | mChildNodeIds.clear(); |
Svetoslav Ganov | eeee4d2 | 2011-06-10 20:51:30 -0700 | [diff] [blame] | 1512 | mBoundsInParent.set(0, 0, 0, 0); |
| 1513 | mBoundsInScreen.set(0, 0, 0, 0); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1514 | mBooleanProperties = 0; |
| 1515 | mPackageName = null; |
| 1516 | mClassName = null; |
| 1517 | mText = null; |
| 1518 | mContentDescription = null; |
| 1519 | mActions = 0; |
| 1520 | } |
| 1521 | |
| 1522 | /** |
| 1523 | * Gets the human readable action symbolic name. |
| 1524 | * |
| 1525 | * @param action The action. |
| 1526 | * @return The symbolic name. |
| 1527 | */ |
| 1528 | private static String getActionSymbolicName(int action) { |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 1529 | switch (action) { |
| 1530 | case ACTION_FOCUS: |
| 1531 | return "ACTION_FOCUS"; |
| 1532 | case ACTION_CLEAR_FOCUS: |
| 1533 | return "ACTION_CLEAR_FOCUS"; |
| 1534 | case ACTION_SELECT: |
| 1535 | return "ACTION_SELECT"; |
| 1536 | case ACTION_CLEAR_SELECTION: |
| 1537 | return "ACTION_CLEAR_SELECTION"; |
Svetoslav Ganov | e9bda15 | 2012-04-30 16:55:21 -0700 | [diff] [blame] | 1538 | case ACTION_CLICK: |
| 1539 | return "ACTION_CLICK"; |
| 1540 | case ACTION_LONG_CLICK: |
| 1541 | return "ACTION_LONG_CLICK"; |
| 1542 | case ACTION_ACCESSIBILITY_FOCUS: |
| 1543 | return "ACTION_ACCESSIBILITY_FOCUS"; |
| 1544 | case ACTION_CLEAR_ACCESSIBILITY_FOCUS: |
| 1545 | return "ACTION_CLEAR_ACCESSIBILITY_FOCUS"; |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 1546 | case ACTION_NEXT_AT_MOVEMENT_GRANULARITY: |
| 1547 | return "ACTION_NEXT_AT_MOVEMENT_GRANULARITY"; |
| 1548 | case ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: |
| 1549 | return "ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY"; |
Svetoslav Ganov | e9bda15 | 2012-04-30 16:55:21 -0700 | [diff] [blame] | 1550 | case ACTION_NEXT_HTML_ELEMENT: |
| 1551 | return "ACTION_NEXT_HTML_ELEMENT"; |
| 1552 | case ACTION_PREVIOUS_HTML_ELEMENT: |
| 1553 | return "ACTION_PREVIOUS_HTML_ELEMENT"; |
Svetoslav Ganov | 38e8b4e | 2011-06-29 20:00:53 -0700 | [diff] [blame] | 1554 | default: |
| 1555 | throw new IllegalArgumentException("Unknown action: " + action); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1556 | } |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1557 | } |
| 1558 | |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 1559 | /** |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 1560 | * Gets the human readable movement granularity symbolic name. |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 1561 | * |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 1562 | * @param granularity The granularity. |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 1563 | * @return The symbolic name. |
| 1564 | */ |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 1565 | private static String getMovementGranularitySymbolicName(int granularity) { |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 1566 | switch (granularity) { |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 1567 | case MOVEMENT_GRANULARITY_CHARACTER: |
| 1568 | return "MOVEMENT_GRANULARITY_CHARACTER"; |
| 1569 | case MOVEMENT_GRANULARITY_WORD: |
| 1570 | return "MOVEMENT_GRANULARITY_WORD"; |
| 1571 | case MOVEMENT_GRANULARITY_LINE: |
| 1572 | return "MOVEMENT_GRANULARITY_LINE"; |
| 1573 | case MOVEMENT_GRANULARITY_PARAGRAPH: |
| 1574 | return "MOVEMENT_GRANULARITY_PARAGRAPH"; |
| 1575 | case MOVEMENT_GRANULARITY_PAGE: |
| 1576 | return "MOVEMENT_GRANULARITY_PAGE"; |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 1577 | default: |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 1578 | throw new IllegalArgumentException("Unknown movement granularity: " + granularity); |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 1579 | } |
| 1580 | } |
| 1581 | |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 1582 | private boolean canPerformRequestOverConnection(long accessibilityNodeId) { |
Svetoslav Ganov | f3b4f31 | 2011-11-30 18:15:01 -0800 | [diff] [blame] | 1583 | return (mWindowId != UNDEFINED |
| 1584 | && getAccessibilityViewId(accessibilityNodeId) != UNDEFINED |
| 1585 | && mConnectionId != UNDEFINED); |
Svetoslav Ganov | eeee4d2 | 2011-06-10 20:51:30 -0700 | [diff] [blame] | 1586 | } |
| 1587 | |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1588 | @Override |
Svetoslav Ganov | 8dffad6 | 2011-06-10 12:38:36 -0700 | [diff] [blame] | 1589 | public boolean equals(Object object) { |
| 1590 | if (this == object) { |
| 1591 | return true; |
| 1592 | } |
| 1593 | if (object == null) { |
| 1594 | return false; |
| 1595 | } |
| 1596 | if (getClass() != object.getClass()) { |
| 1597 | return false; |
| 1598 | } |
| 1599 | AccessibilityNodeInfo other = (AccessibilityNodeInfo) object; |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 1600 | if (mSourceNodeId != other.mSourceNodeId) { |
Svetoslav Ganov | 8dffad6 | 2011-06-10 12:38:36 -0700 | [diff] [blame] | 1601 | return false; |
| 1602 | } |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 1603 | if (mWindowId != other.mWindowId) { |
Svetoslav Ganov | 8dffad6 | 2011-06-10 12:38:36 -0700 | [diff] [blame] | 1604 | return false; |
| 1605 | } |
| 1606 | return true; |
| 1607 | } |
| 1608 | |
| 1609 | @Override |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1610 | public int hashCode() { |
| 1611 | final int prime = 31; |
| 1612 | int result = 1; |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 1613 | result = prime * result + getAccessibilityViewId(mSourceNodeId); |
| 1614 | result = prime * result + getVirtualDescendantId(mSourceNodeId); |
| 1615 | result = prime * result + mWindowId; |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1616 | return result; |
| 1617 | } |
| 1618 | |
| 1619 | @Override |
| 1620 | public String toString() { |
| 1621 | StringBuilder builder = new StringBuilder(); |
| 1622 | builder.append(super.toString()); |
| 1623 | |
| 1624 | if (DEBUG) { |
Svetoslav Ganov | 0210785 | 2011-10-03 17:06:56 -0700 | [diff] [blame] | 1625 | builder.append("; accessibilityViewId: " + getAccessibilityViewId(mSourceNodeId)); |
| 1626 | builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId)); |
| 1627 | builder.append("; mParentNodeId: " + mParentNodeId); |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 1628 | |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 1629 | int granularities = mMovementGranularities; |
| 1630 | builder.append("; MovementGranularities: ["); |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 1631 | while (granularities != 0) { |
| 1632 | final int granularity = 1 << Integer.numberOfTrailingZeros(granularities); |
| 1633 | granularities &= ~granularity; |
Svetoslav Ganov | 2b435aa | 2012-05-04 17:16:37 -0700 | [diff] [blame^] | 1634 | builder.append(getMovementGranularitySymbolicName(granularity)); |
Svetoslav Ganov | b7ff325 | 2012-04-24 18:40:07 -0700 | [diff] [blame] | 1635 | if (granularities != 0) { |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 1636 | builder.append(", "); |
| 1637 | } |
| 1638 | } |
| 1639 | builder.append("]"); |
| 1640 | |
Svetoslav Ganov | 57c7fd5 | 2012-02-23 18:31:39 -0800 | [diff] [blame] | 1641 | SparseLongArray childIds = mChildNodeIds; |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1642 | builder.append("; childAccessibilityIds: ["); |
| 1643 | for (int i = 0, count = childIds.size(); i < count; i++) { |
| 1644 | builder.append(childIds.valueAt(i)); |
| 1645 | if (i < count - 1) { |
| 1646 | builder.append(", "); |
| 1647 | } |
Svetoslav Ganov | aa780c1 | 2012-04-19 23:01:39 -0700 | [diff] [blame] | 1648 | } |
| 1649 | builder.append("]"); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1650 | } |
| 1651 | |
Svetoslav Ganov | eeee4d2 | 2011-06-10 20:51:30 -0700 | [diff] [blame] | 1652 | builder.append("; boundsInParent: " + mBoundsInParent); |
| 1653 | builder.append("; boundsInScreen: " + mBoundsInScreen); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1654 | |
| 1655 | builder.append("; packageName: ").append(mPackageName); |
| 1656 | builder.append("; className: ").append(mClassName); |
| 1657 | builder.append("; text: ").append(mText); |
| 1658 | builder.append("; contentDescription: ").append(mContentDescription); |
| 1659 | |
| 1660 | builder.append("; checkable: ").append(isCheckable()); |
| 1661 | builder.append("; checked: ").append(isChecked()); |
| 1662 | builder.append("; focusable: ").append(isFocusable()); |
| 1663 | builder.append("; focused: ").append(isFocused()); |
| 1664 | builder.append("; selected: ").append(isSelected()); |
| 1665 | builder.append("; clickable: ").append(isClickable()); |
| 1666 | builder.append("; longClickable: ").append(isLongClickable()); |
| 1667 | builder.append("; enabled: ").append(isEnabled()); |
| 1668 | builder.append("; password: ").append(isPassword()); |
Svetoslav Ganov | a015617 | 2011-06-26 17:55:44 -0700 | [diff] [blame] | 1669 | builder.append("; scrollable: " + isScrollable()); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1670 | |
| 1671 | builder.append("; ["); |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1672 | for (int actionBits = mActions; actionBits != 0;) { |
| 1673 | final int action = 1 << Integer.numberOfTrailingZeros(actionBits); |
| 1674 | actionBits &= ~action; |
| 1675 | builder.append(getActionSymbolicName(action)); |
| 1676 | if (actionBits != 0) { |
| 1677 | builder.append(", "); |
| 1678 | } |
| 1679 | } |
Svetoslav Ganov | 8643aa0 | 2011-04-20 12:12:33 -0700 | [diff] [blame] | 1680 | builder.append("]"); |
| 1681 | |
| 1682 | return builder.toString(); |
| 1683 | } |
| 1684 | |
| 1685 | /** |
| 1686 | * @see Parcelable.Creator |
| 1687 | */ |
| 1688 | public static final Parcelable.Creator<AccessibilityNodeInfo> CREATOR = |
| 1689 | new Parcelable.Creator<AccessibilityNodeInfo>() { |
| 1690 | public AccessibilityNodeInfo createFromParcel(Parcel parcel) { |
| 1691 | AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(); |
| 1692 | info.initFromParcel(parcel); |
| 1693 | return info; |
| 1694 | } |
| 1695 | |
| 1696 | public AccessibilityNodeInfo[] newArray(int size) { |
| 1697 | return new AccessibilityNodeInfo[size]; |
| 1698 | } |
| 1699 | }; |
| 1700 | } |