• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
19 import android.os.Parcelable;
20 import android.view.View;
21 
22 import java.util.ArrayList;
23 import java.util.List;
24 
25 /**
26  * 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>
43  *
44  * <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  *
51  * @see AccessibilityEvent
52  * @see AccessibilityManager
53  * @see android.accessibilityservice.AccessibilityService
54  * @see AccessibilityNodeInfo
55  */
56 public class AccessibilityRecord {
57 
58     private static final int UNDEFINED = -1;
59 
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;
64     private static final int PROPERTY_SCROLLABLE = 0x00000100;
65     private static final int PROPERTY_IMPORTANT_FOR_ACCESSIBILITY = 0x00000200;
66 
67     private static final int GET_SOURCE_PREFETCH_FLAGS =
68         AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS
69         | AccessibilityNodeInfo.FLAG_PREFETCH_SIBLINGS
70         | AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS;
71 
72     // Housekeeping
73     private static final int MAX_POOL_SIZE = 10;
74     private static final Object sPoolLock = new Object();
75     private static AccessibilityRecord sPool;
76     private static int sPoolSize;
77     private AccessibilityRecord mNext;
78     private boolean mIsInPool;
79 
80     boolean mSealed;
81     int mBooleanProperties = PROPERTY_IMPORTANT_FOR_ACCESSIBILITY;
82     int mCurrentItemIndex = UNDEFINED;
83     int mItemCount = UNDEFINED;
84     int mFromIndex = UNDEFINED;
85     int mToIndex = UNDEFINED;
86     int mScrollX = UNDEFINED;
87     int mScrollY = UNDEFINED;
88     int mMaxScrollX = UNDEFINED;
89     int mMaxScrollY = UNDEFINED;
90 
91     int mAddedCount= UNDEFINED;
92     int mRemovedCount = UNDEFINED;
93     long mSourceNodeId = AccessibilityNodeInfo.makeNodeId(UNDEFINED, UNDEFINED);
94     int mSourceWindowId = UNDEFINED;
95 
96     CharSequence mClassName;
97     CharSequence mContentDescription;
98     CharSequence mBeforeText;
99     Parcelable mParcelableData;
100 
101     final List<CharSequence> mText = new ArrayList<CharSequence>();
102 
103     int mConnectionId = UNDEFINED;
104 
105     /*
106      * Hide constructor.
107      */
AccessibilityRecord()108     AccessibilityRecord() {
109     }
110 
111     /**
112      * Sets the event source.
113      *
114      * @param source The source.
115      *
116      * @throws IllegalStateException If called from an AccessibilityService.
117      */
setSource(View source)118     public void setSource(View source) {
119         setSource(source, UNDEFINED);
120     }
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      */
setSource(View root, int virtualDescendantId)136     public void setSource(View root, int virtualDescendantId) {
137         enforceNotSealed();
138         final boolean important;
139         if (virtualDescendantId == UNDEFINED) {
140             important = (root != null) ? root.isImportantForAccessibility() : true;
141         } else {
142             important = true;
143         }
144         setBooleanProperty(PROPERTY_IMPORTANT_FOR_ACCESSIBILITY, important);
145         mSourceWindowId = (root != null) ? root.getAccessibilityWindowId() : UNDEFINED;
146         final int rootViewId = (root != null) ? root.getAccessibilityViewId() : UNDEFINED;
147         mSourceNodeId = AccessibilityNodeInfo.makeNodeId(rootViewId, virtualDescendantId);
148     }
149 
150     /**
151      * Gets the {@link AccessibilityNodeInfo} of the event source.
152      * <p>
153      *   <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.
156      * </p>
157      * @return The info of the source.
158      */
getSource()159     public AccessibilityNodeInfo getSource() {
160         enforceSealed();
161         if (mConnectionId == UNDEFINED || mSourceWindowId == UNDEFINED
162                 || AccessibilityNodeInfo.getAccessibilityViewId(mSourceNodeId) == UNDEFINED) {
163             return null;
164         }
165         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
166         return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId, mSourceWindowId,
167                 mSourceNodeId, GET_SOURCE_PREFETCH_FLAGS);
168     }
169 
170     /**
171      * Gets the id of the window from which the event comes from.
172      *
173      * @return The window id.
174      */
getWindowId()175     public int getWindowId() {
176         return mSourceWindowId;
177     }
178 
179     /**
180      * Gets if the source is checked.
181      *
182      * @return True if the view is checked, false otherwise.
183      */
isChecked()184     public boolean isChecked() {
185         return getBooleanProperty(PROPERTY_CHECKED);
186     }
187 
188     /**
189      * Sets if the source is checked.
190      *
191      * @param isChecked True if the view is checked, false otherwise.
192      *
193      * @throws IllegalStateException If called from an AccessibilityService.
194      */
setChecked(boolean isChecked)195     public void setChecked(boolean isChecked) {
196         enforceNotSealed();
197         setBooleanProperty(PROPERTY_CHECKED, isChecked);
198     }
199 
200     /**
201      * Gets if the source is enabled.
202      *
203      * @return True if the view is enabled, false otherwise.
204      */
isEnabled()205     public boolean isEnabled() {
206         return getBooleanProperty(PROPERTY_ENABLED);
207     }
208 
209     /**
210      * Sets if the source is enabled.
211      *
212      * @param isEnabled True if the view is enabled, false otherwise.
213      *
214      * @throws IllegalStateException If called from an AccessibilityService.
215      */
setEnabled(boolean isEnabled)216     public void setEnabled(boolean isEnabled) {
217         enforceNotSealed();
218         setBooleanProperty(PROPERTY_ENABLED, isEnabled);
219     }
220 
221     /**
222      * Gets if the source is a password field.
223      *
224      * @return True if the view is a password field, false otherwise.
225      */
isPassword()226     public boolean isPassword() {
227         return getBooleanProperty(PROPERTY_PASSWORD);
228     }
229 
230     /**
231      * Sets if the source is a password field.
232      *
233      * @param isPassword True if the view is a password field, false otherwise.
234      *
235      * @throws IllegalStateException If called from an AccessibilityService.
236      */
setPassword(boolean isPassword)237     public void setPassword(boolean isPassword) {
238         enforceNotSealed();
239         setBooleanProperty(PROPERTY_PASSWORD, isPassword);
240     }
241 
242     /**
243      * Gets if the source is taking the entire screen.
244      *
245      * @return True if the source is full screen, false otherwise.
246      */
isFullScreen()247     public boolean isFullScreen() {
248         return getBooleanProperty(PROPERTY_FULL_SCREEN);
249     }
250 
251     /**
252      * Sets if the source is taking the entire screen.
253      *
254      * @param isFullScreen True if the source is full screen, false otherwise.
255      *
256      * @throws IllegalStateException If called from an AccessibilityService.
257      */
setFullScreen(boolean isFullScreen)258     public void setFullScreen(boolean isFullScreen) {
259         enforceNotSealed();
260         setBooleanProperty(PROPERTY_FULL_SCREEN, isFullScreen);
261     }
262 
263     /**
264      * Gets if the source is scrollable.
265      *
266      * @return True if the source is scrollable, false otherwise.
267      */
isScrollable()268     public boolean isScrollable() {
269         return getBooleanProperty(PROPERTY_SCROLLABLE);
270     }
271 
272     /**
273      * Sets if the source is scrollable.
274      *
275      * @param scrollable True if the source is scrollable, false otherwise.
276      *
277      * @throws IllegalStateException If called from an AccessibilityService.
278      */
setScrollable(boolean scrollable)279     public void setScrollable(boolean scrollable) {
280         enforceNotSealed();
281         setBooleanProperty(PROPERTY_SCROLLABLE, scrollable);
282     }
283 
284     /**
285      * Gets if the source is important for accessibility.
286      *
287      * <strong>Note:</strong> Used only internally to determine whether
288      * to deliver the event to a given accessibility service since some
289      * services may want to regard all views for accessibility while others
290      * may want to regard only the important views for accessibility.
291      *
292      * @return True if the source is important for accessibility,
293      *        false otherwise.
294      *
295      * @hide
296      */
isImportantForAccessibility()297     public boolean isImportantForAccessibility() {
298         return getBooleanProperty(PROPERTY_IMPORTANT_FOR_ACCESSIBILITY);
299     }
300 
301     /**
302      * Gets the number of items that can be visited.
303      *
304      * @return The number of items.
305      */
getItemCount()306     public int getItemCount() {
307         return mItemCount;
308     }
309 
310     /**
311      * Sets the number of items that can be visited.
312      *
313      * @param itemCount The number of items.
314      *
315      * @throws IllegalStateException If called from an AccessibilityService.
316      */
setItemCount(int itemCount)317     public void setItemCount(int itemCount) {
318         enforceNotSealed();
319         mItemCount = itemCount;
320     }
321 
322     /**
323      * Gets the index of the source in the list of items the can be visited.
324      *
325      * @return The current item index.
326      */
getCurrentItemIndex()327     public int getCurrentItemIndex() {
328         return mCurrentItemIndex;
329     }
330 
331     /**
332      * Sets the index of the source in the list of items that can be visited.
333      *
334      * @param currentItemIndex The current item index.
335      *
336      * @throws IllegalStateException If called from an AccessibilityService.
337      */
setCurrentItemIndex(int currentItemIndex)338     public void setCurrentItemIndex(int currentItemIndex) {
339         enforceNotSealed();
340         mCurrentItemIndex = currentItemIndex;
341     }
342 
343     /**
344      * Gets the index of the first character of the changed sequence,
345      * or the beginning of a text selection or the index of the first
346      * visible item when scrolling.
347      *
348      * @return The index of the first character or selection
349      *        start or the first visible item.
350      */
getFromIndex()351     public int getFromIndex() {
352         return mFromIndex;
353     }
354 
355     /**
356      * Sets the index of the first character of the changed sequence
357      * or the beginning of a text selection or the index of the first
358      * visible item when scrolling.
359      *
360      * @param fromIndex The index of the first character or selection
361      *        start or the first visible item.
362      *
363      * @throws IllegalStateException If called from an AccessibilityService.
364      */
setFromIndex(int fromIndex)365     public void setFromIndex(int fromIndex) {
366         enforceNotSealed();
367         mFromIndex = fromIndex;
368     }
369 
370     /**
371      * Gets the index of text selection end or the index of the last
372      * visible item when scrolling.
373      *
374      * @return The index of selection end or last item index.
375      */
getToIndex()376     public int getToIndex() {
377         return mToIndex;
378     }
379 
380     /**
381      * Sets the index of text selection end or the index of the last
382      * visible item when scrolling.
383      *
384      * @param toIndex The index of selection end or last item index.
385      */
setToIndex(int toIndex)386     public void setToIndex(int toIndex) {
387         enforceNotSealed();
388         mToIndex = toIndex;
389     }
390 
391     /**
392      * Gets the scroll offset of the source left edge in pixels.
393      *
394      * @return The scroll.
395      */
getScrollX()396     public int getScrollX() {
397         return mScrollX;
398     }
399 
400     /**
401      * Sets the scroll offset of the source left edge in pixels.
402      *
403      * @param scrollX The scroll.
404      */
setScrollX(int scrollX)405     public void setScrollX(int scrollX) {
406         enforceNotSealed();
407         mScrollX = scrollX;
408     }
409 
410     /**
411      * Gets the scroll offset of the source top edge in pixels.
412      *
413      * @return The scroll.
414      */
getScrollY()415     public int getScrollY() {
416         return mScrollY;
417     }
418 
419     /**
420      * Sets the scroll offset of the source top edge in pixels.
421      *
422      * @param scrollY The scroll.
423      */
setScrollY(int scrollY)424     public void setScrollY(int scrollY) {
425         enforceNotSealed();
426         mScrollY = scrollY;
427     }
428 
429     /**
430      * Gets the max scroll offset of the source left edge in pixels.
431      *
432      * @return The max scroll.
433      */
getMaxScrollX()434     public int getMaxScrollX() {
435         return mMaxScrollX;
436     }
437 
438     /**
439      * Sets the max scroll offset of the source left edge in pixels.
440      *
441      * @param maxScrollX The max scroll.
442      */
setMaxScrollX(int maxScrollX)443     public void setMaxScrollX(int maxScrollX) {
444         enforceNotSealed();
445         mMaxScrollX = maxScrollX;
446     }
447 
448     /**
449      * Gets the max scroll offset of the source top edge in pixels.
450      *
451      * @return The max scroll.
452      */
getMaxScrollY()453     public int getMaxScrollY() {
454         return mMaxScrollY;
455     }
456 
457     /**
458      * Sets the max scroll offset of the source top edge in pixels.
459      *
460      * @param maxScrollY The max scroll.
461      */
setMaxScrollY(int maxScrollY)462     public void setMaxScrollY(int maxScrollY) {
463         enforceNotSealed();
464         mMaxScrollY = maxScrollY;
465     }
466 
467     /**
468      * Gets the number of added characters.
469      *
470      * @return The number of added characters.
471      */
getAddedCount()472     public int getAddedCount() {
473         return mAddedCount;
474     }
475 
476     /**
477      * Sets the number of added characters.
478      *
479      * @param addedCount The number of added characters.
480      *
481      * @throws IllegalStateException If called from an AccessibilityService.
482      */
setAddedCount(int addedCount)483     public void setAddedCount(int addedCount) {
484         enforceNotSealed();
485         mAddedCount = addedCount;
486     }
487 
488     /**
489      * Gets the number of removed characters.
490      *
491      * @return The number of removed characters.
492      */
getRemovedCount()493     public int getRemovedCount() {
494         return mRemovedCount;
495     }
496 
497     /**
498      * Sets the number of removed characters.
499      *
500      * @param removedCount The number of removed characters.
501      *
502      * @throws IllegalStateException If called from an AccessibilityService.
503      */
setRemovedCount(int removedCount)504     public void setRemovedCount(int removedCount) {
505         enforceNotSealed();
506         mRemovedCount = removedCount;
507     }
508 
509     /**
510      * Gets the class name of the source.
511      *
512      * @return The class name.
513      */
getClassName()514     public CharSequence getClassName() {
515         return mClassName;
516     }
517 
518     /**
519      * Sets the class name of the source.
520      *
521      * @param className The lass name.
522      *
523      * @throws IllegalStateException If called from an AccessibilityService.
524      */
setClassName(CharSequence className)525     public void setClassName(CharSequence className) {
526         enforceNotSealed();
527         mClassName = className;
528     }
529 
530     /**
531      * Gets the text of the event. The index in the list represents the priority
532      * of the text. Specifically, the lower the index the higher the priority.
533      *
534      * @return The text.
535      */
getText()536     public List<CharSequence> getText() {
537         return mText;
538     }
539 
540     /**
541      * Sets the text before a change.
542      *
543      * @return The text before the change.
544      */
getBeforeText()545     public CharSequence getBeforeText() {
546         return mBeforeText;
547     }
548 
549     /**
550      * Sets the text before a change.
551      *
552      * @param beforeText The text before the change.
553      *
554      * @throws IllegalStateException If called from an AccessibilityService.
555      */
setBeforeText(CharSequence beforeText)556     public void setBeforeText(CharSequence beforeText) {
557         enforceNotSealed();
558         mBeforeText = beforeText;
559     }
560 
561     /**
562      * Gets the description of the source.
563      *
564      * @return The description.
565      */
getContentDescription()566     public CharSequence getContentDescription() {
567         return mContentDescription;
568     }
569 
570     /**
571      * Sets the description of the source.
572      *
573      * @param contentDescription The description.
574      *
575      * @throws IllegalStateException If called from an AccessibilityService.
576      */
setContentDescription(CharSequence contentDescription)577     public void setContentDescription(CharSequence contentDescription) {
578         enforceNotSealed();
579         mContentDescription = contentDescription;
580     }
581 
582     /**
583      * Gets the {@link Parcelable} data.
584      *
585      * @return The parcelable data.
586      */
getParcelableData()587     public Parcelable getParcelableData() {
588         return mParcelableData;
589     }
590 
591     /**
592      * Sets the {@link Parcelable} data of the event.
593      *
594      * @param parcelableData The parcelable data.
595      *
596      * @throws IllegalStateException If called from an AccessibilityService.
597      */
setParcelableData(Parcelable parcelableData)598     public void setParcelableData(Parcelable parcelableData) {
599         enforceNotSealed();
600         mParcelableData = parcelableData;
601     }
602 
603     /**
604      * Gets the id of the source node.
605      *
606      * @return The id.
607      *
608      * @hide
609      */
getSourceNodeId()610     public long getSourceNodeId() {
611         return mSourceNodeId;
612     }
613 
614     /**
615      * Sets the unique id of the IAccessibilityServiceConnection over which
616      * this instance can send requests to the system.
617      *
618      * @param connectionId The connection id.
619      *
620      * @hide
621      */
setConnectionId(int connectionId)622     public void setConnectionId(int connectionId) {
623         enforceNotSealed();
624         mConnectionId = connectionId;
625     }
626 
627     /**
628      * Sets if this instance is sealed.
629      *
630      * @param sealed Whether is sealed.
631      *
632      * @hide
633      */
setSealed(boolean sealed)634     public void setSealed(boolean sealed) {
635         mSealed = sealed;
636     }
637 
638     /**
639      * Gets if this instance is sealed.
640      *
641      * @return Whether is sealed.
642      */
isSealed()643     boolean isSealed() {
644         return mSealed;
645     }
646 
647     /**
648      * Enforces that this instance is sealed.
649      *
650      * @throws IllegalStateException If this instance is not sealed.
651      */
enforceSealed()652     void enforceSealed() {
653         if (!isSealed()) {
654             throw new IllegalStateException("Cannot perform this "
655                     + "action on a not sealed instance.");
656         }
657     }
658 
659     /**
660      * Enforces that this instance is not sealed.
661      *
662      * @throws IllegalStateException If this instance is sealed.
663      */
enforceNotSealed()664     void enforceNotSealed() {
665         if (isSealed()) {
666             throw new IllegalStateException("Cannot perform this "
667                     + "action on a sealed instance.");
668         }
669     }
670 
671     /**
672      * Gets the value of a boolean property.
673      *
674      * @param property The property.
675      * @return The value.
676      */
getBooleanProperty(int property)677     private boolean getBooleanProperty(int property) {
678         return (mBooleanProperties & property) == property;
679     }
680 
681     /**
682      * Sets a boolean property.
683      *
684      * @param property The property.
685      * @param value The value.
686      */
setBooleanProperty(int property, boolean value)687     private void setBooleanProperty(int property, boolean value) {
688         if (value) {
689             mBooleanProperties |= property;
690         } else {
691             mBooleanProperties &= ~property;
692         }
693     }
694 
695     /**
696      * Returns a cached instance if such is available or a new one is
697      * instantiated. The instance is initialized with data from the
698      * given record.
699      *
700      * @return An instance.
701      */
obtain(AccessibilityRecord record)702     public static AccessibilityRecord obtain(AccessibilityRecord record) {
703        AccessibilityRecord clone = AccessibilityRecord.obtain();
704        clone.init(record);
705        return clone;
706     }
707 
708     /**
709      * Returns a cached instance if such is available or a new one is
710      * instantiated.
711      *
712      * @return An instance.
713      */
obtain()714     public static AccessibilityRecord obtain() {
715         synchronized (sPoolLock) {
716             if (sPool != null) {
717                 AccessibilityRecord record = sPool;
718                 sPool = sPool.mNext;
719                 sPoolSize--;
720                 record.mNext = null;
721                 record.mIsInPool = false;
722                 return record;
723             }
724             return new AccessibilityRecord();
725         }
726     }
727 
728     /**
729      * Return an instance back to be reused.
730      * <p>
731      * <strong>Note:</strong> You must not touch the object after calling this function.
732      *
733      * @throws IllegalStateException If the record is already recycled.
734      */
recycle()735     public void recycle() {
736         if (mIsInPool) {
737             throw new IllegalStateException("Record already recycled!");
738         }
739         clear();
740         synchronized (sPoolLock) {
741             if (sPoolSize <= MAX_POOL_SIZE) {
742                 mNext = sPool;
743                 sPool = this;
744                 mIsInPool = true;
745                 sPoolSize++;
746             }
747         }
748     }
749 
750     /**
751      * Initialize this record from another one.
752      *
753      * @param record The to initialize from.
754      */
init(AccessibilityRecord record)755     void init(AccessibilityRecord record) {
756         mSealed = record.mSealed;
757         mBooleanProperties = record.mBooleanProperties;
758         mCurrentItemIndex = record.mCurrentItemIndex;
759         mItemCount = record.mItemCount;
760         mFromIndex = record.mFromIndex;
761         mToIndex = record.mToIndex;
762         mScrollX = record.mScrollX;
763         mScrollY = record.mScrollY;
764         mMaxScrollX = record.mMaxScrollX;
765         mMaxScrollY = record.mMaxScrollY;
766         mAddedCount = record.mAddedCount;
767         mRemovedCount = record.mRemovedCount;
768         mClassName = record.mClassName;
769         mContentDescription = record.mContentDescription;
770         mBeforeText = record.mBeforeText;
771         mParcelableData = record.mParcelableData;
772         mText.addAll(record.mText);
773         mSourceWindowId = record.mSourceWindowId;
774         mSourceNodeId = record.mSourceNodeId;
775         mConnectionId = record.mConnectionId;
776     }
777 
778     /**
779      * Clears the state of this instance.
780      */
clear()781     void clear() {
782         mSealed = false;
783         mBooleanProperties = PROPERTY_IMPORTANT_FOR_ACCESSIBILITY;
784         mCurrentItemIndex = UNDEFINED;
785         mItemCount = UNDEFINED;
786         mFromIndex = UNDEFINED;
787         mToIndex = UNDEFINED;
788         mScrollX = UNDEFINED;
789         mScrollY = UNDEFINED;
790         mMaxScrollX = UNDEFINED;
791         mMaxScrollY = UNDEFINED;
792         mAddedCount = UNDEFINED;
793         mRemovedCount = UNDEFINED;
794         mClassName = null;
795         mContentDescription = null;
796         mBeforeText = null;
797         mParcelableData = null;
798         mText.clear();
799         mSourceNodeId = AccessibilityNodeInfo.makeNodeId(UNDEFINED, UNDEFINED);
800         mSourceWindowId = UNDEFINED;
801         mConnectionId = UNDEFINED;
802     }
803 
804     @Override
toString()805     public String toString() {
806         StringBuilder builder = new StringBuilder();
807         builder.append(" [ ClassName: " + mClassName);
808         builder.append("; Text: " + mText);
809         builder.append("; ContentDescription: " + mContentDescription);
810         builder.append("; ItemCount: " + mItemCount);
811         builder.append("; CurrentItemIndex: " + mCurrentItemIndex);
812         builder.append("; IsEnabled: " + getBooleanProperty(PROPERTY_ENABLED));
813         builder.append("; IsPassword: " + getBooleanProperty(PROPERTY_PASSWORD));
814         builder.append("; IsChecked: " + getBooleanProperty(PROPERTY_CHECKED));
815         builder.append("; IsFullScreen: " + getBooleanProperty(PROPERTY_FULL_SCREEN));
816         builder.append("; Scrollable: " + getBooleanProperty(PROPERTY_SCROLLABLE));
817         builder.append("; BeforeText: " + mBeforeText);
818         builder.append("; FromIndex: " + mFromIndex);
819         builder.append("; ToIndex: " + mToIndex);
820         builder.append("; ScrollX: " + mScrollX);
821         builder.append("; ScrollY: " + mScrollY);
822         builder.append("; MaxScrollX: " + mMaxScrollX);
823         builder.append("; MaxScrollY: " + mMaxScrollY);
824         builder.append("; AddedCount: " + mAddedCount);
825         builder.append("; RemovedCount: " + mRemovedCount);
826         builder.append("; ParcelableData: " + mParcelableData);
827         builder.append(" ]");
828         return builder.toString();
829     }
830 }
831