blob: 7147c57c8b0d2885e0ea9aaf70c555b582a247f3 [file] [log] [blame]
Svetoslav Ganov736c2752011-04-22 18:30:36 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view.accessibility;
18
19import android.os.Parcelable;
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -070020import android.view.View;
Svetoslav Ganov736c2752011-04-22 18:30:36 -070021
22import java.util.ArrayList;
23import java.util.List;
24
25/**
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070026 * Represents a record in an {@link AccessibilityEvent} and contains information
27 * about state change of its source {@link android.view.View}. When a view fires
28 * an accessibility event it requests from its parent to dispatch the
29 * constructed event. The parent may optionally append a record for itself
30 * for providing more context to
31 * {@link android.accessibilityservice.AccessibilityService}s. Hence,
32 * accessibility services can facilitate additional accessibility records
33 * to enhance feedback.
34 * </p>
35 * <p>
36 * Once the accessibility event containing a record is dispatched the record is
37 * made immutable and calling a state mutation method generates an error.
38 * </p>
39 * <p>
40 * <strong>Note:</strong> Not all properties are applicable to all accessibility
41 * event types. For detailed information please refer to {@link AccessibilityEvent}.
42 * </p>
Svetoslav Ganov736c2752011-04-22 18:30:36 -070043 *
Joe Fernandeze1302ed2012-02-06 14:30:15 -080044 * <div class="special reference">
45 * <h3>Developer Guides</h3>
46 * <p>For more information about creating and processing AccessibilityRecords, read the
47 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
48 * developer guide.</p>
49 * </div>
50 *
Svetoslav Ganov736c2752011-04-22 18:30:36 -070051 * @see AccessibilityEvent
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070052 * @see AccessibilityManager
53 * @see android.accessibilityservice.AccessibilityService
54 * @see AccessibilityNodeInfo
Svetoslav Ganov736c2752011-04-22 18:30:36 -070055 */
56public class AccessibilityRecord {
57
Svetoslav Ganov47b779b2011-07-17 11:07:53 -070058 private static final int UNDEFINED = -1;
Svetoslav Ganov736c2752011-04-22 18:30:36 -070059
60 private static final int PROPERTY_CHECKED = 0x00000001;
61 private static final int PROPERTY_ENABLED = 0x00000002;
62 private static final int PROPERTY_PASSWORD = 0x00000004;
63 private static final int PROPERTY_FULL_SCREEN = 0x00000080;
Svetoslav Ganova0156172011-06-26 17:55:44 -070064 private static final int PROPERTY_SCROLLABLE = 0x00000100;
Svetoslav Ganov42138042012-03-20 11:51:39 -070065 private static final int PROPERTY_IMPORTANT_FOR_ACCESSIBILITY = 0x00000200;
Svetoslav Ganov736c2752011-04-22 18:30:36 -070066
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -080067 private static final int GET_SOURCE_PREFETCH_FLAGS =
68 AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS
69 | AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS
70 | AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS;
71
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070072 // Housekeeping
Svetoslav Ganov736c2752011-04-22 18:30:36 -070073 private static final int MAX_POOL_SIZE = 10;
Svetoslav Ganov887e1a12011-04-29 15:09:28 -070074 private static final Object sPoolLock = new Object();
Svetoslav Ganov736c2752011-04-22 18:30:36 -070075 private static AccessibilityRecord sPool;
76 private static int sPoolSize;
Svetoslav Ganov736c2752011-04-22 18:30:36 -070077 private AccessibilityRecord mNext;
78 private boolean mIsInPool;
79
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -070080 boolean mSealed;
Svetoslav Ganov42138042012-03-20 11:51:39 -070081 int mBooleanProperties = PROPERTY_IMPORTANT_FOR_ACCESSIBILITY;
Svetoslav Ganov47b779b2011-07-17 11:07:53 -070082 int mCurrentItemIndex = UNDEFINED;
83 int mItemCount = UNDEFINED;
84 int mFromIndex = UNDEFINED;
85 int mToIndex = UNDEFINED;
86 int mScrollX = UNDEFINED;
87 int mScrollY = UNDEFINED;
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -070088 int mMaxScrollX = UNDEFINED;
89 int mMaxScrollY = UNDEFINED;
Svetoslav Ganova0156172011-06-26 17:55:44 -070090
Svetoslav Ganov47b779b2011-07-17 11:07:53 -070091 int mAddedCount= UNDEFINED;
92 int mRemovedCount = UNDEFINED;
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -080093 long mSourceNodeId = AccessibilityNodeInfo.makeNodeId(UNDEFINED, UNDEFINED);
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -080094 int mSourceWindowId = UNDEFINED;
Svetoslav Ganov736c2752011-04-22 18:30:36 -070095
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -070096 CharSequence mClassName;
97 CharSequence mContentDescription;
98 CharSequence mBeforeText;
99 Parcelable mParcelableData;
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700100
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700101 final List<CharSequence> mText = new ArrayList<CharSequence>();
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -0800102
103 int mConnectionId = UNDEFINED;
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700104
105 /*
106 * Hide constructor.
107 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700108 AccessibilityRecord() {
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700109 }
110
111 /**
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700112 * Sets the event source.
113 *
114 * @param source The source.
115 *
116 * @throws IllegalStateException If called from an AccessibilityService.
117 */
118 public void setSource(View source) {
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800119 setSource(source, UNDEFINED);
Svetoslav Ganov02107852011-10-03 17:06:56 -0700120 }
121
122 /**
123 * Sets the source to be a virtual descendant of the given <code>root</code>.
124 * If <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root
125 * is set as the source.
126 * <p>
127 * A virtual descendant is an imaginary View that is reported as a part of the view
128 * hierarchy for accessibility purposes. This enables custom views that draw complex
129 * content to report them selves as a tree of virtual views, thus conveying their
130 * logical structure.
131 * </p>
132 *
133 * @param root The root of the virtual subtree.
134 * @param virtualDescendantId The id of the virtual descendant.
135 */
136 public void setSource(View root, int virtualDescendantId) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700137 enforceNotSealed();
Svetoslav Ganov52a62372012-05-02 14:19:37 -0700138 final boolean important;
139 if (virtualDescendantId == UNDEFINED) {
140 important = (root != null) ? root.isImportantForAccessibility() : true;
141 } else {
142 important = true;
143 }
Svetoslav Ganov42138042012-03-20 11:51:39 -0700144 setBooleanProperty(PROPERTY_IMPORTANT_FOR_ACCESSIBILITY, important);
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800145 mSourceWindowId = (root != null) ? root.getAccessibilityWindowId() : UNDEFINED;
146 final int rootViewId = (root != null) ? root.getAccessibilityViewId() : UNDEFINED;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700147 mSourceNodeId = AccessibilityNodeInfo.makeNodeId(rootViewId, virtualDescendantId);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700148 }
149
150 /**
151 * Gets the {@link AccessibilityNodeInfo} of the event source.
152 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700153 * <strong>Note:</strong> It is a client responsibility to recycle the received info
154 * by calling {@link AccessibilityNodeInfo#recycle() AccessibilityNodeInfo#recycle()}
155 * to avoid creating of multiple instances.
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700156 * </p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700157 * @return The info of the source.
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700158 */
159 public AccessibilityNodeInfo getSource() {
160 enforceSealed();
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -0800161 if (mConnectionId == UNDEFINED || mSourceWindowId == UNDEFINED
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800162 || AccessibilityNodeInfo.getAccessibilityViewId(mSourceNodeId) == UNDEFINED) {
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700163 return null;
164 }
Svetoslav Ganov8bd69612011-08-23 13:40:30 -0700165 AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -0800166 return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mSourceWindowId,
Svetoslav Ganov57c7fd52012-02-23 18:31:39 -0800167 mSourceNodeId, GET_SOURCE_PREFETCH_FLAGS);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700168 }
169
170 /**
Svetoslav Ganovfc9c4cd2012-11-02 11:49:22 -0700171 * Sets the window id.
172 *
173 * @param windowId The window id.
174 *
175 * @hide
176 */
177 public void setWindowId(int windowId) {
178 mSourceWindowId = windowId;
179 }
180
181 /**
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700182 * Gets the id of the window from which the event comes from.
183 *
184 * @return The window id.
185 */
186 public int getWindowId() {
187 return mSourceWindowId;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700188 }
189
190 /**
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700191 * Gets if the source is checked.
192 *
193 * @return True if the view is checked, false otherwise.
194 */
195 public boolean isChecked() {
196 return getBooleanProperty(PROPERTY_CHECKED);
197 }
198
199 /**
200 * Sets if the source is checked.
201 *
202 * @param isChecked True if the view is checked, false otherwise.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700203 *
204 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700205 */
206 public void setChecked(boolean isChecked) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700207 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700208 setBooleanProperty(PROPERTY_CHECKED, isChecked);
209 }
210
211 /**
212 * Gets if the source is enabled.
213 *
214 * @return True if the view is enabled, false otherwise.
215 */
216 public boolean isEnabled() {
217 return getBooleanProperty(PROPERTY_ENABLED);
218 }
219
220 /**
221 * Sets if the source is enabled.
222 *
223 * @param isEnabled True if the view is enabled, false otherwise.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700224 *
225 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700226 */
227 public void setEnabled(boolean isEnabled) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700228 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700229 setBooleanProperty(PROPERTY_ENABLED, isEnabled);
230 }
231
232 /**
233 * Gets if the source is a password field.
234 *
235 * @return True if the view is a password field, false otherwise.
236 */
237 public boolean isPassword() {
238 return getBooleanProperty(PROPERTY_PASSWORD);
239 }
240
241 /**
242 * Sets if the source is a password field.
243 *
244 * @param isPassword True if the view is a password field, false otherwise.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700245 *
246 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700247 */
248 public void setPassword(boolean isPassword) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700249 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700250 setBooleanProperty(PROPERTY_PASSWORD, isPassword);
251 }
252
253 /**
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700254 * Gets if the source is taking the entire screen.
255 *
256 * @return True if the source is full screen, false otherwise.
257 */
258 public boolean isFullScreen() {
259 return getBooleanProperty(PROPERTY_FULL_SCREEN);
260 }
261
262 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700263 * Sets if the source is taking the entire screen.
264 *
265 * @param isFullScreen True if the source is full screen, false otherwise.
266 *
267 * @throws IllegalStateException If called from an AccessibilityService.
268 */
269 public void setFullScreen(boolean isFullScreen) {
270 enforceNotSealed();
271 setBooleanProperty(PROPERTY_FULL_SCREEN, isFullScreen);
272 }
273
274 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -0700275 * Gets if the source is scrollable.
276 *
277 * @return True if the source is scrollable, false otherwise.
278 */
279 public boolean isScrollable() {
280 return getBooleanProperty(PROPERTY_SCROLLABLE);
281 }
282
283 /**
284 * Sets if the source is scrollable.
285 *
286 * @param scrollable True if the source is scrollable, false otherwise.
287 *
288 * @throws IllegalStateException If called from an AccessibilityService.
289 */
290 public void setScrollable(boolean scrollable) {
291 enforceNotSealed();
292 setBooleanProperty(PROPERTY_SCROLLABLE, scrollable);
293 }
294
295 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -0700296 * Gets if the source is important for accessibility.
297 *
298 * <strong>Note:</strong> Used only internally to determine whether
299 * to deliver the event to a given accessibility service since some
300 * services may want to regard all views for accessibility while others
301 * may want to regard only the important views for accessibility.
302 *
303 * @return True if the source is important for accessibility,
304 * false otherwise.
305 *
306 * @hide
307 */
308 public boolean isImportantForAccessibility() {
309 return getBooleanProperty(PROPERTY_IMPORTANT_FOR_ACCESSIBILITY);
310 }
311
312 /**
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700313 * Gets the number of items that can be visited.
314 *
315 * @return The number of items.
316 */
317 public int getItemCount() {
318 return mItemCount;
319 }
320
321 /**
322 * Sets the number of items that can be visited.
323 *
324 * @param itemCount The number of items.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700325 *
326 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700327 */
328 public void setItemCount(int itemCount) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700329 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700330 mItemCount = itemCount;
331 }
332
333 /**
334 * Gets the index of the source in the list of items the can be visited.
335 *
336 * @return The current item index.
337 */
338 public int getCurrentItemIndex() {
339 return mCurrentItemIndex;
340 }
341
342 /**
343 * Sets the index of the source in the list of items that can be visited.
344 *
345 * @param currentItemIndex The current item index.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700346 *
347 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700348 */
349 public void setCurrentItemIndex(int currentItemIndex) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700350 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700351 mCurrentItemIndex = currentItemIndex;
352 }
353
354 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -0700355 * Gets the index of the first character of the changed sequence,
356 * or the beginning of a text selection or the index of the first
357 * visible item when scrolling.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700358 *
Svetoslav Ganova0156172011-06-26 17:55:44 -0700359 * @return The index of the first character or selection
360 * start or the first visible item.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700361 */
362 public int getFromIndex() {
363 return mFromIndex;
364 }
365
366 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -0700367 * Sets the index of the first character of the changed sequence
368 * or the beginning of a text selection or the index of the first
369 * visible item when scrolling.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700370 *
Svetoslav Ganova0156172011-06-26 17:55:44 -0700371 * @param fromIndex The index of the first character or selection
372 * start or the first visible item.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700373 *
374 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700375 */
376 public void setFromIndex(int fromIndex) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700377 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700378 mFromIndex = fromIndex;
379 }
380
381 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -0700382 * Gets the index of text selection end or the index of the last
383 * visible item when scrolling.
384 *
385 * @return The index of selection end or last item index.
386 */
387 public int getToIndex() {
388 return mToIndex;
389 }
390
391 /**
392 * Sets the index of text selection end or the index of the last
393 * visible item when scrolling.
394 *
395 * @param toIndex The index of selection end or last item index.
396 */
397 public void setToIndex(int toIndex) {
398 enforceNotSealed();
399 mToIndex = toIndex;
400 }
401
402 /**
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700403 * Gets the scroll offset of the source left edge in pixels.
Svetoslav Ganova0156172011-06-26 17:55:44 -0700404 *
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700405 * @return The scroll.
Svetoslav Ganova0156172011-06-26 17:55:44 -0700406 */
407 public int getScrollX() {
408 return mScrollX;
409 }
410
411 /**
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700412 * Sets the scroll offset of the source left edge in pixels.
Svetoslav Ganova0156172011-06-26 17:55:44 -0700413 *
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700414 * @param scrollX The scroll.
Svetoslav Ganova0156172011-06-26 17:55:44 -0700415 */
416 public void setScrollX(int scrollX) {
417 enforceNotSealed();
418 mScrollX = scrollX;
419 }
420
421 /**
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700422 * Gets the scroll offset of the source top edge in pixels.
Svetoslav Ganova0156172011-06-26 17:55:44 -0700423 *
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700424 * @return The scroll.
Svetoslav Ganova0156172011-06-26 17:55:44 -0700425 */
426 public int getScrollY() {
427 return mScrollY;
428 }
429
430 /**
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700431 * Sets the scroll offset of the source top edge in pixels.
Svetoslav Ganova0156172011-06-26 17:55:44 -0700432 *
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700433 * @param scrollY The scroll.
Svetoslav Ganova0156172011-06-26 17:55:44 -0700434 */
435 public void setScrollY(int scrollY) {
436 enforceNotSealed();
437 mScrollY = scrollY;
438 }
439
440 /**
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700441 * Gets the max scroll offset of the source left edge in pixels.
442 *
443 * @return The max scroll.
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700444 */
445 public int getMaxScrollX() {
446 return mMaxScrollX;
447 }
Svetoslav Ganov02107852011-10-03 17:06:56 -0700448
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700449 /**
450 * Sets the max scroll offset of the source left edge in pixels.
451 *
452 * @param maxScrollX The max scroll.
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700453 */
454 public void setMaxScrollX(int maxScrollX) {
455 enforceNotSealed();
456 mMaxScrollX = maxScrollX;
457 }
458
459 /**
460 * Gets the max scroll offset of the source top edge in pixels.
461 *
462 * @return The max scroll.
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700463 */
464 public int getMaxScrollY() {
465 return mMaxScrollY;
466 }
467
468 /**
469 * Sets the max scroll offset of the source top edge in pixels.
470 *
471 * @param maxScrollY The max scroll.
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700472 */
473 public void setMaxScrollY(int maxScrollY) {
474 enforceNotSealed();
475 mMaxScrollY = maxScrollY;
476 }
477
478 /**
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700479 * Gets the number of added characters.
480 *
481 * @return The number of added characters.
482 */
483 public int getAddedCount() {
484 return mAddedCount;
485 }
486
487 /**
488 * Sets the number of added characters.
489 *
490 * @param addedCount The number of added characters.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700491 *
492 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700493 */
494 public void setAddedCount(int addedCount) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700495 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700496 mAddedCount = addedCount;
497 }
498
499 /**
500 * Gets the number of removed characters.
501 *
502 * @return The number of removed characters.
503 */
504 public int getRemovedCount() {
505 return mRemovedCount;
506 }
507
508 /**
509 * Sets the number of removed characters.
510 *
511 * @param removedCount The number of removed characters.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700512 *
513 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700514 */
515 public void setRemovedCount(int removedCount) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700516 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700517 mRemovedCount = removedCount;
518 }
519
520 /**
521 * Gets the class name of the source.
522 *
523 * @return The class name.
524 */
525 public CharSequence getClassName() {
526 return mClassName;
527 }
528
529 /**
530 * Sets the class name of the source.
531 *
532 * @param className The lass name.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700533 *
534 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700535 */
536 public void setClassName(CharSequence className) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700537 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700538 mClassName = className;
539 }
540
541 /**
542 * Gets the text of the event. The index in the list represents the priority
543 * of the text. Specifically, the lower the index the higher the priority.
544 *
545 * @return The text.
546 */
547 public List<CharSequence> getText() {
548 return mText;
549 }
550
551 /**
552 * Sets the text before a change.
553 *
554 * @return The text before the change.
555 */
556 public CharSequence getBeforeText() {
557 return mBeforeText;
558 }
559
560 /**
561 * Sets the text before a change.
562 *
563 * @param beforeText The text before the change.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700564 *
565 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700566 */
567 public void setBeforeText(CharSequence beforeText) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700568 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700569 mBeforeText = beforeText;
570 }
571
572 /**
573 * Gets the description of the source.
574 *
575 * @return The description.
576 */
577 public CharSequence getContentDescription() {
578 return mContentDescription;
579 }
580
581 /**
582 * Sets the description of the source.
583 *
584 * @param contentDescription The description.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700585 *
586 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700587 */
588 public void setContentDescription(CharSequence contentDescription) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700589 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700590 mContentDescription = contentDescription;
591 }
592
593 /**
594 * Gets the {@link Parcelable} data.
595 *
596 * @return The parcelable data.
597 */
598 public Parcelable getParcelableData() {
599 return mParcelableData;
600 }
601
602 /**
603 * Sets the {@link Parcelable} data of the event.
604 *
605 * @param parcelableData The parcelable data.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700606 *
607 * @throws IllegalStateException If called from an AccessibilityService.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700608 */
609 public void setParcelableData(Parcelable parcelableData) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700610 enforceNotSealed();
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700611 mParcelableData = parcelableData;
612 }
613
614 /**
Svetoslav Ganov79311c42012-01-17 20:24:26 -0800615 * Gets the id of the source node.
616 *
617 * @return The id.
618 *
619 * @hide
620 */
621 public long getSourceNodeId() {
622 return mSourceNodeId;
623 }
624
625 /**
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -0800626 * Sets the unique id of the IAccessibilityServiceConnection over which
627 * this instance can send requests to the system.
628 *
629 * @param connectionId The connection id.
630 *
631 * @hide
632 */
633 public void setConnectionId(int connectionId) {
634 enforceNotSealed();
635 mConnectionId = connectionId;
636 }
637
638 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700639 * Sets if this instance is sealed.
640 *
641 * @param sealed Whether is sealed.
642 *
643 * @hide
644 */
645 public void setSealed(boolean sealed) {
646 mSealed = sealed;
647 }
648
649 /**
650 * Gets if this instance is sealed.
651 *
652 * @return Whether is sealed.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700653 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700654 boolean isSealed() {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700655 return mSealed;
656 }
657
658 /**
659 * Enforces that this instance is sealed.
660 *
661 * @throws IllegalStateException If this instance is not sealed.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700662 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700663 void enforceSealed() {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700664 if (!isSealed()) {
665 throw new IllegalStateException("Cannot perform this "
666 + "action on a not sealed instance.");
667 }
668 }
669
670 /**
671 * Enforces that this instance is not sealed.
672 *
673 * @throws IllegalStateException If this instance is sealed.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700674 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700675 void enforceNotSealed() {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700676 if (isSealed()) {
677 throw new IllegalStateException("Cannot perform this "
Ken Wakasaf76a50c2012-03-09 19:56:35 +0900678 + "action on a sealed instance.");
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700679 }
680 }
681
682 /**
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700683 * Gets the value of a boolean property.
684 *
685 * @param property The property.
686 * @return The value.
687 */
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700688 private boolean getBooleanProperty(int property) {
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700689 return (mBooleanProperties & property) == property;
690 }
691
692 /**
693 * Sets a boolean property.
694 *
695 * @param property The property.
696 * @param value The value.
697 */
698 private void setBooleanProperty(int property, boolean value) {
699 if (value) {
700 mBooleanProperties |= property;
701 } else {
702 mBooleanProperties &= ~property;
703 }
704 }
705
706 /**
707 * Returns a cached instance if such is available or a new one is
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700708 * instantiated. The instance is initialized with data from the
709 * given record.
710 *
711 * @return An instance.
712 */
713 public static AccessibilityRecord obtain(AccessibilityRecord record) {
714 AccessibilityRecord clone = AccessibilityRecord.obtain();
715 clone.init(record);
716 return clone;
717 }
718
719 /**
720 * Returns a cached instance if such is available or a new one is
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700721 * instantiated.
722 *
723 * @return An instance.
724 */
Svetoslav Ganovd36a6992011-05-18 20:50:03 -0700725 public static AccessibilityRecord obtain() {
Svetoslav Ganov887e1a12011-04-29 15:09:28 -0700726 synchronized (sPoolLock) {
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700727 if (sPool != null) {
728 AccessibilityRecord record = sPool;
729 sPool = sPool.mNext;
730 sPoolSize--;
731 record.mNext = null;
732 record.mIsInPool = false;
733 return record;
734 }
735 return new AccessibilityRecord();
736 }
737 }
738
739 /**
740 * Return an instance back to be reused.
741 * <p>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700742 * <strong>Note:</strong> You must not touch the object after calling this function.
Svetoslav Ganov887e1a12011-04-29 15:09:28 -0700743 *
744 * @throws IllegalStateException If the record is already recycled.
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700745 */
746 public void recycle() {
747 if (mIsInPool) {
Svetoslav Ganov887e1a12011-04-29 15:09:28 -0700748 throw new IllegalStateException("Record already recycled!");
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700749 }
750 clear();
Svetoslav Ganov887e1a12011-04-29 15:09:28 -0700751 synchronized (sPoolLock) {
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700752 if (sPoolSize <= MAX_POOL_SIZE) {
753 mNext = sPool;
754 sPool = this;
755 mIsInPool = true;
756 sPoolSize++;
757 }
758 }
759 }
760
761 /**
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700762 * Initialize this record from another one.
763 *
764 * @param record The to initialize from.
765 */
766 void init(AccessibilityRecord record) {
767 mSealed = record.mSealed;
768 mBooleanProperties = record.mBooleanProperties;
769 mCurrentItemIndex = record.mCurrentItemIndex;
770 mItemCount = record.mItemCount;
771 mFromIndex = record.mFromIndex;
772 mToIndex = record.mToIndex;
773 mScrollX = record.mScrollX;
774 mScrollY = record.mScrollY;
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700775 mMaxScrollX = record.mMaxScrollX;
776 mMaxScrollY = record.mMaxScrollY;
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700777 mAddedCount = record.mAddedCount;
778 mRemovedCount = record.mRemovedCount;
779 mClassName = record.mClassName;
780 mContentDescription = record.mContentDescription;
781 mBeforeText = record.mBeforeText;
782 mParcelableData = record.mParcelableData;
783 mText.addAll(record.mText);
784 mSourceWindowId = record.mSourceWindowId;
Svetoslav Ganov02107852011-10-03 17:06:56 -0700785 mSourceNodeId = record.mSourceNodeId;
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -0800786 mConnectionId = record.mConnectionId;
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700787 }
788
789 /**
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700790 * Clears the state of this instance.
791 */
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -0700792 void clear() {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700793 mSealed = false;
Svetoslav Ganov42138042012-03-20 11:51:39 -0700794 mBooleanProperties = PROPERTY_IMPORTANT_FOR_ACCESSIBILITY;
Svetoslav Ganov47b779b2011-07-17 11:07:53 -0700795 mCurrentItemIndex = UNDEFINED;
796 mItemCount = UNDEFINED;
797 mFromIndex = UNDEFINED;
798 mToIndex = UNDEFINED;
799 mScrollX = UNDEFINED;
800 mScrollY = UNDEFINED;
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700801 mMaxScrollX = UNDEFINED;
802 mMaxScrollY = UNDEFINED;
Svetoslav Ganov47b779b2011-07-17 11:07:53 -0700803 mAddedCount = UNDEFINED;
804 mRemovedCount = UNDEFINED;
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700805 mClassName = null;
806 mContentDescription = null;
807 mBeforeText = null;
808 mParcelableData = null;
809 mText.clear();
Svetoslav Ganovf3b4f312011-11-30 18:15:01 -0800810 mSourceNodeId = AccessibilityNodeInfo.makeNodeId(UNDEFINED, UNDEFINED);
Svetoslav Ganovd116d7c2011-11-21 18:41:59 -0800811 mSourceWindowId = UNDEFINED;
812 mConnectionId = UNDEFINED;
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700813 }
814
815 @Override
816 public String toString() {
817 StringBuilder builder = new StringBuilder();
818 builder.append(" [ ClassName: " + mClassName);
819 builder.append("; Text: " + mText);
820 builder.append("; ContentDescription: " + mContentDescription);
821 builder.append("; ItemCount: " + mItemCount);
822 builder.append("; CurrentItemIndex: " + mCurrentItemIndex);
823 builder.append("; IsEnabled: " + getBooleanProperty(PROPERTY_ENABLED));
824 builder.append("; IsPassword: " + getBooleanProperty(PROPERTY_PASSWORD));
825 builder.append("; IsChecked: " + getBooleanProperty(PROPERTY_CHECKED));
826 builder.append("; IsFullScreen: " + getBooleanProperty(PROPERTY_FULL_SCREEN));
Svetoslav Ganova0156172011-06-26 17:55:44 -0700827 builder.append("; Scrollable: " + getBooleanProperty(PROPERTY_SCROLLABLE));
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700828 builder.append("; BeforeText: " + mBeforeText);
829 builder.append("; FromIndex: " + mFromIndex);
Svetoslav Ganova0156172011-06-26 17:55:44 -0700830 builder.append("; ToIndex: " + mToIndex);
831 builder.append("; ScrollX: " + mScrollX);
832 builder.append("; ScrollY: " + mScrollY);
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -0700833 builder.append("; MaxScrollX: " + mMaxScrollX);
834 builder.append("; MaxScrollY: " + mMaxScrollY);
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700835 builder.append("; AddedCount: " + mAddedCount);
836 builder.append("; RemovedCount: " + mRemovedCount);
837 builder.append("; ParcelableData: " + mParcelableData);
838 builder.append(" ]");
839 return builder.toString();
840 }
841}