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
17package android.support.v4.view.accessibility;
18
19import android.graphics.Rect;
20import android.os.Build;
21import android.os.Bundle;
22import android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat;
23import android.support.v4.view.ViewCompat;
24import android.view.View;
25
26import java.util.ArrayList;
27import java.util.Collections;
28import java.util.List;
29
30/**
31 * Helper for accessing {@link android.view.accessibility.AccessibilityNodeInfo}
32 * introduced after API level 4 in a backwards compatible fashion.
33 */
34public class AccessibilityNodeInfoCompat {
35
36    public static class AccessibilityActionCompat {
37        private final Object mAction;
38
39        private AccessibilityActionCompat(Object action) {
40            mAction = action;
41        }
42
43        /**
44         * Gets the id for this action.
45         *
46         * @return The action id.
47         */
48        public int getId() {
49            return AccessibilityNodeInfoCompatApi21.AccessibilityAction.getId(mAction);
50        }
51
52        /**
53         * Gets the label for this action. Its purpose is to describe the
54         * action to user.
55         *
56         * @return The label.
57         */
58        public CharSequence getLabel() {
59            return AccessibilityNodeInfoCompatApi21.AccessibilityAction.getLabel(mAction);
60        }
61    }
62
63    public static class CollectionInfoCompat {
64        /** Selection mode where items are not selectable. */
65        public static final int SELECTION_MODE_NONE = 0;
66
67        /** Selection mode where a single item may be selected. */
68        public static final int SELECTION_MODE_SINGLE = 1;
69
70        /** Selection mode where multiple items may be selected. */
71        public static final int SELECTION_MODE_MULTIPLE = 2;
72
73        final Object mInfo;
74
75        /**
76         * Returns a cached instance if such is available otherwise a new one.
77         *
78         * @return An instance.
79         */
80        public static CollectionInfoCompat obtain(int rowCount, int columnCount,
81                boolean hierarchical, int selectionMode) {
82            return new CollectionInfoCompat(IMPL.obtainCollectionInfo(rowCount, columnCount,
83                    hierarchical, selectionMode));
84        }
85
86        private CollectionInfoCompat(Object info) {
87            mInfo = info;
88        }
89
90        public int getColumnCount() {
91            return IMPL.getCollectionInfoColumnCount(mInfo);
92        }
93
94        public int getRowCount() {
95            return IMPL.getCollectionInfoRowCount(mInfo);
96        }
97
98        public boolean isHierarchical() {
99            return IMPL.isCollectionInfoHierarchical(mInfo);
100        }
101    }
102
103    public static class CollectionItemInfoCompat {
104
105        private final Object mInfo;
106
107        /**
108         * Returns a cached instance if such is available otherwise a new one.
109         *
110         * @return An instance.
111         */
112        public static CollectionItemInfoCompat obtain(int rowIndex, int rowSpan,
113                int columnIndex, int columnSpan, boolean heading, boolean selected) {
114            return new CollectionItemInfoCompat(IMPL.obtainCollectionItemInfo(rowIndex, rowSpan,
115                    columnIndex, columnSpan, heading, selected));
116        }
117
118        private CollectionItemInfoCompat(Object info) {
119            mInfo = info;
120        }
121
122        public int getColumnIndex() {
123            return IMPL.getCollectionItemColumnIndex(mInfo);
124        }
125
126        public int getColumnSpan() {
127            return IMPL.getCollectionItemColumnSpan(mInfo);
128        }
129
130        public int getRowIndex() {
131            return IMPL.getCollectionItemRowIndex(mInfo);
132        }
133
134        public int getRowSpan() {
135            return IMPL.getCollectionItemRowSpan(mInfo);
136        }
137
138        public boolean isHeading() {
139            return IMPL.isCollectionItemHeading(mInfo);
140        }
141
142        public boolean isSelected() {
143            return IMPL.isCollectionItemSelected(mInfo);
144        }
145    }
146
147    public static class RangeInfoCompat {
148        /** Range type: integer. */
149        public static final int RANGE_TYPE_INT = 0;
150        /** Range type: float. */
151        public static final int RANGE_TYPE_FLOAT = 1;
152        /** Range type: percent with values from zero to one.*/
153        public static final int RANGE_TYPE_PERCENT = 2;
154
155        private final Object mInfo;
156
157        private RangeInfoCompat(Object info) {
158            mInfo = info;
159        }
160
161        public float getCurrent() {
162            return AccessibilityNodeInfoCompatKitKat.RangeInfo.getCurrent(mInfo);
163        }
164
165        public float getMax() {
166            return AccessibilityNodeInfoCompatKitKat.RangeInfo.getMax(mInfo);
167        }
168
169        public float getMin() {
170            return AccessibilityNodeInfoCompatKitKat.RangeInfo.getMin(mInfo);
171        }
172
173        public int getType() {
174            return AccessibilityNodeInfoCompatKitKat.RangeInfo.getType(mInfo);
175        }
176    }
177
178    static interface AccessibilityNodeInfoImpl {
179        public Object obtain();
180        public Object obtain(View source);
181        public Object obtain(Object info);
182        public Object obtain(View root, int virtualDescendantId);
183        public void setSource(Object info, View source);
184        public void setSource(Object info, View root, int virtualDescendantId);
185        public Object findFocus(Object info, int focus);
186        public Object focusSearch(Object info, int direction);
187        public int getWindowId(Object info);
188        public int getChildCount(Object info);
189        public Object getChild(Object info, int index);
190        public void addChild(Object info, View child);
191        public void addChild(Object info, View child, int virtualDescendantId);
192        public int getActions(Object info);
193        public void addAction(Object info, int action);
194        public boolean performAction(Object info, int action);
195        public boolean performAction(Object info, int action, Bundle arguments);
196        public void setMovementGranularities(Object info, int granularities);
197        public int getMovementGranularities(Object info);
198        public List<Object> findAccessibilityNodeInfosByText(Object info, String text);
199        public Object getParent(Object info);
200        public void setParent(Object info, View root, int virtualDescendantId);
201        public void setParent(Object info, View parent);
202        public void getBoundsInParent(Object info, Rect outBounds);
203        public void setBoundsInParent(Object info, Rect bounds);
204        public void getBoundsInScreen(Object info, Rect outBounds);
205        public void setBoundsInScreen(Object info, Rect bounds);
206        public boolean isCheckable(Object info);
207        public void setCheckable(Object info, boolean checkable);
208        public boolean isChecked(Object info);
209        public void setChecked(Object info, boolean checked);
210        public boolean isFocusable(Object info);
211        public void setFocusable(Object info, boolean focusable);
212        public boolean isFocused(Object info);
213        public void setFocused(Object info, boolean focused);
214        public boolean isVisibleToUser(Object info);
215        public void setVisibleToUser(Object info, boolean visibleToUser);
216        public boolean isAccessibilityFocused(Object info);
217        public void setAccessibilityFocused(Object info, boolean focused);
218        public boolean isSelected(Object info);
219        public void setSelected(Object info, boolean selected);
220        public boolean isClickable(Object info);
221        public void setClickable(Object info, boolean clickable);
222        public boolean isLongClickable(Object info);
223        public void setLongClickable(Object info, boolean longClickable);
224        public boolean isEnabled(Object info);
225        public void setEnabled(Object info, boolean enabled);
226        public boolean isPassword(Object info);
227        public void setPassword(Object info, boolean password);
228        public boolean isScrollable(Object info);
229        public void setScrollable(Object info, boolean scrollable);
230        public CharSequence getPackageName(Object info);
231        public void setPackageName(Object info, CharSequence packageName);
232        public CharSequence getClassName(Object info);
233        public void setClassName(Object info, CharSequence className);
234        public CharSequence getText(Object info);
235        public void setText(Object info, CharSequence text);
236        public CharSequence getContentDescription(Object info);
237        public void setContentDescription(Object info, CharSequence contentDescription);
238        public void recycle(Object info);
239        public String getViewIdResourceName(Object info);
240        public void setViewIdResourceName(Object info, String viewId);
241        public int getLiveRegion(Object info);
242        public void setLiveRegion(Object info, int mode);
243        public Object getCollectionInfo(Object info);
244        public void setCollectionInfo(Object info, Object collectionInfo);
245        public Object getCollectionItemInfo(Object info);
246        public void setCollectionItemInfo(Object info, Object collectionItemInfo);
247        public Object getRangeInfo(Object info);
248        public List<Object> getActionList(Object info);
249        public void addAction(Object info, int id, CharSequence label);
250        public Object obtainCollectionInfo(int rowCount, int columnCount, boolean hierarchical,
251                int selectionMode);
252        public int getCollectionInfoColumnCount(Object info);
253        public int getCollectionInfoRowCount(Object info);
254        public boolean isCollectionInfoHierarchical(Object info);
255        public Object obtainCollectionItemInfo(int rowIndex, int rowSpan, int columnIndex,
256                int columnSpan, boolean heading, boolean selected);
257        public int getCollectionItemColumnIndex(Object info);
258        public int getCollectionItemColumnSpan(Object info);
259        public int getCollectionItemRowIndex(Object info);
260        public int getCollectionItemRowSpan(Object info);
261        public boolean isCollectionItemHeading(Object info);
262        public boolean isCollectionItemSelected(Object info);
263    }
264
265    static class AccessibilityNodeInfoStubImpl implements AccessibilityNodeInfoImpl {
266        @Override
267        public Object obtain() {
268            return null;
269        }
270
271        @Override
272        public Object obtain(View source) {
273            return null;
274        }
275
276        @Override
277        public Object obtain(View root, int virtualDescendantId) {
278            return null;
279        }
280
281        @Override
282        public Object obtain(Object info) {
283            return null;
284        }
285
286        @Override
287        public void addAction(Object info, int action) {
288
289        }
290
291        @Override
292        public void addChild(Object info, View child) {
293
294        }
295
296        @Override
297        public void addChild(Object info, View child, int virtualDescendantId) {
298
299        }
300
301        @Override
302        public List<Object> findAccessibilityNodeInfosByText(Object info, String text) {
303            return Collections.emptyList();
304        }
305
306        @Override
307        public int getActions(Object info) {
308            return 0;
309        }
310
311        @Override
312        public void getBoundsInParent(Object info, Rect outBounds) {
313
314        }
315
316        @Override
317        public void getBoundsInScreen(Object info, Rect outBounds) {
318
319        }
320
321        @Override
322        public Object getChild(Object info, int index) {
323            return null;
324        }
325
326        @Override
327        public int getChildCount(Object info) {
328            return 0;
329        }
330
331        @Override
332        public CharSequence getClassName(Object info) {
333            return null;
334        }
335
336        @Override
337        public CharSequence getContentDescription(Object info) {
338            return null;
339        }
340
341        @Override
342        public CharSequence getPackageName(Object info) {
343            return null;
344        }
345
346        @Override
347        public Object getParent(Object info) {
348            return null;
349        }
350
351        @Override
352        public CharSequence getText(Object info) {
353            return null;
354        }
355
356        @Override
357        public int getWindowId(Object info) {
358            return 0;
359        }
360
361        @Override
362        public boolean isCheckable(Object info) {
363            return false;
364        }
365
366        @Override
367        public boolean isChecked(Object info) {
368            return false;
369        }
370
371        @Override
372        public boolean isClickable(Object info) {
373            return false;
374        }
375
376        @Override
377        public boolean isEnabled(Object info) {
378            return false;
379        }
380
381        @Override
382        public boolean isFocusable(Object info) {
383            return false;
384        }
385
386        @Override
387        public boolean isFocused(Object info) {
388            return false;
389        }
390
391        @Override
392        public boolean isVisibleToUser(Object info) {
393            return false;
394        }
395
396        @Override
397        public boolean isAccessibilityFocused(Object info) {
398            return false;
399        }
400
401        @Override
402        public boolean isLongClickable(Object info) {
403            return false;
404        }
405
406        @Override
407        public boolean isPassword(Object info) {
408            return false;
409        }
410
411        @Override
412        public boolean isScrollable(Object info) {
413            return false;
414        }
415
416        @Override
417        public boolean isSelected(Object info) {
418            return false;
419        }
420
421        @Override
422        public boolean performAction(Object info, int action) {
423            return false;
424        }
425
426        @Override
427        public boolean performAction(Object info, int action, Bundle arguments) {
428            return false;
429        }
430
431        @Override
432        public void setMovementGranularities(Object info, int granularities) {
433
434        }
435
436        @Override
437        public int getMovementGranularities(Object info) {
438            return 0;
439        }
440
441        @Override
442        public void setBoundsInParent(Object info, Rect bounds) {
443
444        }
445
446        @Override
447        public void setBoundsInScreen(Object info, Rect bounds) {
448
449        }
450
451        @Override
452        public void setCheckable(Object info, boolean checkable) {
453
454        }
455
456        @Override
457        public void setChecked(Object info, boolean checked) {
458
459        }
460
461        @Override
462        public void setClassName(Object info, CharSequence className) {
463
464        }
465
466        @Override
467        public void setClickable(Object info, boolean clickable) {
468
469        }
470
471        @Override
472        public void setContentDescription(Object info, CharSequence contentDescription) {
473
474        }
475
476        @Override
477        public void setEnabled(Object info, boolean enabled) {
478
479        }
480
481        @Override
482        public void setFocusable(Object info, boolean focusable) {
483
484        }
485
486        @Override
487        public void setFocused(Object info, boolean focused) {
488
489        }
490
491        @Override
492        public void setVisibleToUser(Object info, boolean visibleToUser) {
493
494        }
495
496        @Override
497        public void setAccessibilityFocused(Object info, boolean focused) {
498
499        }
500
501        @Override
502        public void setLongClickable(Object info, boolean longClickable) {
503
504        }
505
506        @Override
507        public void setPackageName(Object info, CharSequence packageName) {
508
509        }
510
511        @Override
512        public void setParent(Object info, View parent) {
513
514        }
515
516        @Override
517        public void setPassword(Object info, boolean password) {
518
519        }
520
521        @Override
522        public void setScrollable(Object info, boolean scrollable) {
523
524        }
525
526        @Override
527        public void setSelected(Object info, boolean selected) {
528
529        }
530
531        @Override
532        public void setSource(Object info, View source) {
533
534        }
535
536        @Override
537        public void setSource(Object info, View root, int virtualDescendantId) {
538
539        }
540
541        @Override
542        public Object findFocus(Object info, int focus) {
543            return null;
544        }
545
546        @Override
547        public Object focusSearch(Object info, int direction) {
548            return null;
549        }
550
551        @Override
552        public void setText(Object info, CharSequence text) {
553
554        }
555
556        @Override
557        public void recycle(Object info) {
558
559        }
560
561        @Override
562        public void setParent(Object info, View root, int virtualDescendantId) {
563
564        }
565
566        @Override
567        public String getViewIdResourceName(Object info) {
568            return null;
569        }
570
571        @Override
572        public void setViewIdResourceName(Object info, String viewId) {
573
574        }
575
576        @Override
577        public int getLiveRegion(Object info) {
578            return ViewCompat.ACCESSIBILITY_LIVE_REGION_NONE;
579        }
580
581        @Override
582        public void setLiveRegion(Object info, int mode) {
583            // No-op
584        }
585
586        @Override
587        public Object getCollectionInfo(Object info) {
588            return null;
589        }
590
591        @Override
592        public void setCollectionInfo(Object info, Object collectionInfo) {
593        }
594
595        @Override
596        public Object getCollectionItemInfo(Object info) {
597            return null;
598        }
599
600        @Override
601        public void setCollectionItemInfo(Object info, Object collectionItemInfo) {
602        }
603
604        @Override
605        public Object getRangeInfo(Object info) {
606            return null;
607        }
608
609        @Override
610        public List<Object> getActionList(Object info) {
611            return null;
612        }
613
614        @Override
615        public void addAction(Object info, int id, CharSequence label) {
616        }
617
618        @Override
619        public Object obtainCollectionInfo(int rowCount, int columnCount, boolean hierarchical,
620                int selectionMode) {
621            return null;
622        }
623
624        @Override
625        public int getCollectionInfoColumnCount(Object info) {
626            return 0;
627        }
628
629        @Override
630        public int getCollectionInfoRowCount(Object info) {
631            return 0;
632        }
633
634        @Override
635        public boolean isCollectionInfoHierarchical(Object info) {
636            return false;
637        }
638
639        @Override
640        public Object obtainCollectionItemInfo(int rowIndex, int rowSpan, int columnIndex,
641                int columnSpan, boolean heading, boolean selected) {
642            return null;
643        }
644
645        @Override
646        public int getCollectionItemColumnIndex(Object info) {
647            return 0;
648        }
649
650        @Override
651        public int getCollectionItemColumnSpan(Object info) {
652            return 0;
653        }
654
655        @Override
656        public int getCollectionItemRowIndex(Object info) {
657            return 0;
658        }
659
660        @Override
661        public int getCollectionItemRowSpan(Object info) {
662            return 0;
663        }
664
665        @Override
666        public boolean isCollectionItemHeading(Object info) {
667            return false;
668        }
669
670        @Override
671        public boolean isCollectionItemSelected(Object info) {
672            return false;
673        }
674    }
675
676    static class AccessibilityNodeInfoIcsImpl extends AccessibilityNodeInfoStubImpl {
677        @Override
678        public Object obtain() {
679            return AccessibilityNodeInfoCompatIcs.obtain();
680        }
681
682        @Override
683        public Object obtain(View source) {
684            return AccessibilityNodeInfoCompatIcs.obtain(source);
685        }
686
687        @Override
688        public Object obtain(Object info) {
689            return AccessibilityNodeInfoCompatIcs.obtain(info);
690        }
691
692        @Override
693        public void addAction(Object info, int action) {
694            AccessibilityNodeInfoCompatIcs.addAction(info, action);
695        }
696
697        @Override
698        public void addChild(Object info, View child) {
699            AccessibilityNodeInfoCompatIcs.addChild(info, child);
700        }
701
702        @Override
703        public List<Object> findAccessibilityNodeInfosByText(Object info, String text) {
704            return AccessibilityNodeInfoCompatIcs.findAccessibilityNodeInfosByText(info, text);
705        }
706
707        @Override
708        public int getActions(Object info) {
709            return AccessibilityNodeInfoCompatIcs.getActions(info);
710        }
711
712        @Override
713        public void getBoundsInParent(Object info, Rect outBounds) {
714            AccessibilityNodeInfoCompatIcs.getBoundsInParent(info, outBounds);
715        }
716
717        @Override
718        public void getBoundsInScreen(Object info, Rect outBounds) {
719            AccessibilityNodeInfoCompatIcs.getBoundsInScreen(info, outBounds);
720        }
721
722        @Override
723        public Object getChild(Object info, int index) {
724            return AccessibilityNodeInfoCompatIcs.getChild(info, index);
725        }
726
727        @Override
728        public int getChildCount(Object info) {
729            return AccessibilityNodeInfoCompatIcs.getChildCount(info);
730        }
731
732        @Override
733        public CharSequence getClassName(Object info) {
734            return AccessibilityNodeInfoCompatIcs.getClassName(info);
735        }
736
737        @Override
738        public CharSequence getContentDescription(Object info) {
739            return AccessibilityNodeInfoCompatIcs.getContentDescription(info);
740        }
741
742        @Override
743        public CharSequence getPackageName(Object info) {
744            return AccessibilityNodeInfoCompatIcs.getPackageName(info);
745        }
746
747        @Override
748        public Object getParent(Object info) {
749            return AccessibilityNodeInfoCompatIcs.getParent(info);
750        }
751
752        @Override
753        public CharSequence getText(Object info) {
754            return AccessibilityNodeInfoCompatIcs.getText(info);
755        }
756
757        @Override
758        public int getWindowId(Object info) {
759            return AccessibilityNodeInfoCompatIcs.getWindowId(info);
760        }
761
762        @Override
763        public boolean isCheckable(Object info) {
764            return AccessibilityNodeInfoCompatIcs.isCheckable(info);
765        }
766
767        @Override
768        public boolean isChecked(Object info) {
769            return AccessibilityNodeInfoCompatIcs.isChecked(info);
770        }
771
772        @Override
773        public boolean isClickable(Object info) {
774            return AccessibilityNodeInfoCompatIcs.isClickable(info);
775        }
776
777        @Override
778        public boolean isEnabled(Object info) {
779            return AccessibilityNodeInfoCompatIcs.isEnabled(info);
780        }
781
782        @Override
783        public boolean isFocusable(Object info) {
784            return AccessibilityNodeInfoCompatIcs.isFocusable(info);
785        }
786
787        @Override
788        public boolean isFocused(Object info) {
789            return AccessibilityNodeInfoCompatIcs.isFocused(info);
790        }
791
792        @Override
793        public boolean isLongClickable(Object info) {
794            return AccessibilityNodeInfoCompatIcs.isLongClickable(info);
795        }
796
797        @Override
798        public boolean isPassword(Object info) {
799            return AccessibilityNodeInfoCompatIcs.isPassword(info);
800        }
801
802        @Override
803        public boolean isScrollable(Object info) {
804            return AccessibilityNodeInfoCompatIcs.isScrollable(info);
805        }
806
807        @Override
808        public boolean isSelected(Object info) {
809            return AccessibilityNodeInfoCompatIcs.isSelected(info);
810        }
811
812        @Override
813        public boolean performAction(Object info, int action) {
814            return AccessibilityNodeInfoCompatIcs.performAction(info, action);
815        }
816
817        @Override
818        public void setBoundsInParent(Object info, Rect bounds) {
819            AccessibilityNodeInfoCompatIcs.setBoundsInParent(info, bounds);
820        }
821
822        @Override
823        public void setBoundsInScreen(Object info, Rect bounds) {
824            AccessibilityNodeInfoCompatIcs.setBoundsInScreen(info, bounds);
825        }
826
827        @Override
828        public void setCheckable(Object info, boolean checkable) {
829            AccessibilityNodeInfoCompatIcs.setCheckable(info, checkable);
830        }
831
832        @Override
833        public void setChecked(Object info, boolean checked) {
834            AccessibilityNodeInfoCompatIcs.setChecked(info, checked);
835        }
836
837        @Override
838        public void setClassName(Object info, CharSequence className) {
839            AccessibilityNodeInfoCompatIcs.setClassName(info, className);
840        }
841
842        @Override
843        public void setClickable(Object info, boolean clickable) {
844            AccessibilityNodeInfoCompatIcs.setClickable(info, clickable);
845        }
846
847        @Override
848        public void setContentDescription(Object info, CharSequence contentDescription) {
849            AccessibilityNodeInfoCompatIcs.setContentDescription(info, contentDescription);
850        }
851
852        @Override
853        public void setEnabled(Object info, boolean enabled) {
854            AccessibilityNodeInfoCompatIcs.setEnabled(info, enabled);
855        }
856
857        @Override
858        public void setFocusable(Object info, boolean focusable) {
859            AccessibilityNodeInfoCompatIcs.setFocusable(info, focusable);
860        }
861
862        @Override
863        public void setFocused(Object info, boolean focused) {
864            AccessibilityNodeInfoCompatIcs.setFocused(info, focused);
865        }
866
867        @Override
868        public void setLongClickable(Object info, boolean longClickable) {
869            AccessibilityNodeInfoCompatIcs.setLongClickable(info, longClickable);
870        }
871
872        @Override
873        public void setPackageName(Object info, CharSequence packageName) {
874            AccessibilityNodeInfoCompatIcs.setPackageName(info, packageName);
875        }
876
877        @Override
878        public void setParent(Object info, View parent) {
879            AccessibilityNodeInfoCompatIcs.setParent(info, parent);
880        }
881
882        @Override
883        public void setPassword(Object info, boolean password) {
884            AccessibilityNodeInfoCompatIcs.setPassword(info, password);
885        }
886
887        @Override
888        public void setScrollable(Object info, boolean scrollable) {
889            AccessibilityNodeInfoCompatIcs.setScrollable(info, scrollable);
890        }
891
892        @Override
893        public void setSelected(Object info, boolean selected) {
894            AccessibilityNodeInfoCompatIcs.setSelected(info, selected);
895        }
896
897        @Override
898        public void setSource(Object info, View source) {
899            AccessibilityNodeInfoCompatIcs.setSource(info, source);
900        }
901
902        @Override
903        public void setText(Object info, CharSequence text) {
904            AccessibilityNodeInfoCompatIcs.setText(info, text);
905        }
906
907        @Override
908        public void recycle(Object info) {
909            AccessibilityNodeInfoCompatIcs.recycle(info);
910        }
911
912        @Override
913        public void addAction(Object info, int id, CharSequence label) {
914            if (Integer.bitCount(id) == 1) {
915                addAction(info, id);
916            }
917        }
918    }
919
920    static class AccessibilityNodeInfoJellybeanImpl extends AccessibilityNodeInfoIcsImpl {
921        @Override
922        public Object obtain(View root, int virtualDescendantId) {
923            return AccessibilityNodeInfoCompatJellyBean.obtain(root, virtualDescendantId);
924        }
925
926        @Override
927        public Object findFocus(Object info, int focus) {
928            return AccessibilityNodeInfoCompatJellyBean.findFocus(info, focus);
929        }
930
931        @Override
932        public Object focusSearch(Object info, int direction) {
933            return AccessibilityNodeInfoCompatJellyBean.focusSearch(info, direction);
934        }
935
936        @Override
937        public void addChild(Object info, View child, int virtualDescendantId) {
938            AccessibilityNodeInfoCompatJellyBean.addChild(info, child, virtualDescendantId);
939        }
940
941        @Override
942        public void setSource(Object info, View root, int virtualDescendantId) {
943            AccessibilityNodeInfoCompatJellyBean.setSource(info, root, virtualDescendantId);
944        }
945
946        @Override
947        public boolean isVisibleToUser(Object info) {
948            return AccessibilityNodeInfoCompatJellyBean.isVisibleToUser(info);
949        }
950
951        @Override
952        public void setVisibleToUser(Object info, boolean visibleToUser) {
953            AccessibilityNodeInfoCompatJellyBean.setVisibleToUser(info, visibleToUser);
954        }
955
956        @Override
957        public boolean isAccessibilityFocused(Object info) {
958            return AccessibilityNodeInfoCompatJellyBean.isAccessibilityFocused(info);
959        }
960
961        @Override
962        public void setAccessibilityFocused(Object info, boolean focused) {
963            AccessibilityNodeInfoCompatJellyBean.setAccesibilityFocused(info, focused);
964        }
965
966        @Override
967        public boolean performAction(Object info, int action, Bundle arguments) {
968            return AccessibilityNodeInfoCompatJellyBean.performAction(info, action, arguments);
969        }
970
971        @Override
972        public void setMovementGranularities(Object info, int granularities) {
973            AccessibilityNodeInfoCompatJellyBean.setMovementGranularities(info, granularities);
974        }
975
976        @Override
977        public int getMovementGranularities(Object info) {
978            return AccessibilityNodeInfoCompatJellyBean.getMovementGranularities(info);
979        }
980
981        @Override
982        public void setParent(Object info, View root, int virtualDescendantId) {
983            AccessibilityNodeInfoCompatJellyBean.setParent(info, root, virtualDescendantId);
984        }
985    }
986
987    static class AccessibilityNodeInfoJellybeanMr2Impl extends AccessibilityNodeInfoJellybeanImpl {
988
989        @Override
990        public String getViewIdResourceName(Object info) {
991            return AccessibilityNodeInfoCompatJellybeanMr2.getViewIdResourceName(info);
992        }
993
994        @Override
995        public void setViewIdResourceName(Object info, String viewId) {
996            AccessibilityNodeInfoCompatJellybeanMr2.setViewIdResourceName(info, viewId);
997        }
998    }
999
1000    static class AccessibilityNodeInfoKitKatImpl extends AccessibilityNodeInfoJellybeanMr2Impl {
1001        @Override
1002        public int getLiveRegion(Object info) {
1003            return AccessibilityNodeInfoCompatKitKat.getLiveRegion(info);
1004        }
1005
1006        @Override
1007        public void setLiveRegion(Object info, int mode) {
1008            AccessibilityNodeInfoCompatKitKat.setLiveRegion(info, mode);
1009        }
1010
1011        @Override
1012        public Object getCollectionInfo(Object info) {
1013            return AccessibilityNodeInfoCompatKitKat.getCollectionInfo(info);
1014        }
1015
1016        @Override
1017        public void setCollectionInfo(Object info, Object collectionInfo) {
1018            AccessibilityNodeInfoCompatKitKat.setCollectionInfo(info, collectionInfo);
1019        }
1020
1021        @Override
1022        public Object obtainCollectionInfo(int rowCount, int columnCount,
1023                boolean hierarchical, int selectionMode) {
1024            return AccessibilityNodeInfoCompatKitKat.obtainCollectionInfo(rowCount, columnCount,
1025                    hierarchical, selectionMode);
1026        }
1027
1028        @Override
1029        public Object obtainCollectionItemInfo(int rowIndex, int rowSpan, int columnIndex,
1030                int columnSpan, boolean heading, boolean selected) {
1031            return AccessibilityNodeInfoCompatKitKat
1032                    .obtainCollectionItemInfo(rowIndex, rowSpan, columnIndex, columnSpan, heading);
1033        }
1034
1035        @Override
1036        public int getCollectionInfoColumnCount(Object info) {
1037            return AccessibilityNodeInfoCompatKitKat.CollectionInfo.getColumnCount(info);
1038        }
1039
1040        @Override
1041        public int getCollectionInfoRowCount(Object info) {
1042            return AccessibilityNodeInfoCompatKitKat.CollectionInfo.getRowCount(info);
1043        }
1044
1045        @Override
1046        public boolean isCollectionInfoHierarchical(Object info) {
1047            return AccessibilityNodeInfoCompatKitKat.CollectionInfo.isHierarchical(info);
1048        }
1049
1050        @Override
1051        public Object getCollectionItemInfo(Object info) {
1052            return AccessibilityNodeInfoCompatKitKat.getCollectionItemInfo(info);
1053        }
1054
1055        @Override
1056        public Object getRangeInfo(Object info) {
1057            return AccessibilityNodeInfoCompatKitKat.getRangeInfo(info);
1058        }
1059
1060        @Override
1061        public int getCollectionItemColumnIndex(Object info) {
1062            return AccessibilityNodeInfoCompatKitKat.CollectionItemInfo.getColumnIndex(info);
1063        }
1064
1065        @Override
1066        public int getCollectionItemColumnSpan(Object info) {
1067            return AccessibilityNodeInfoCompatKitKat.CollectionItemInfo.getColumnSpan(info);
1068        }
1069
1070        @Override
1071        public int getCollectionItemRowIndex(Object info) {
1072            return AccessibilityNodeInfoCompatKitKat.CollectionItemInfo.getRowIndex(info);
1073        }
1074
1075        @Override
1076        public int getCollectionItemRowSpan(Object info) {
1077            return AccessibilityNodeInfoCompatKitKat.CollectionItemInfo.getRowSpan(info);
1078        }
1079
1080        @Override
1081        public boolean isCollectionItemHeading(Object info) {
1082            return AccessibilityNodeInfoCompatKitKat.CollectionItemInfo.isHeading(info);
1083        }
1084
1085        @Override
1086        public void setCollectionItemInfo(Object info, Object collectionItemInfo) {
1087            AccessibilityNodeInfoCompatKitKat.setCollectionItemInfo(info, collectionItemInfo);
1088        }
1089    }
1090
1091    static class AccessibilityNodeInfoApi21Impl extends AccessibilityNodeInfoKitKatImpl {
1092        @Override
1093        public List<Object> getActionList(Object info) {
1094            return AccessibilityNodeInfoCompatApi21.getActionList(info);
1095        }
1096
1097        @Override
1098        public Object obtainCollectionInfo(int rowCount, int columnCount, boolean hierarchical,
1099                int selectionMode) {
1100            return AccessibilityNodeInfoCompatApi21.obtainCollectionInfo(rowCount, columnCount,
1101                    hierarchical, selectionMode);
1102        }
1103
1104        @Override
1105        public void addAction(Object info, int id, CharSequence label) {
1106            AccessibilityNodeInfoCompatApi21.addAction(info, id, label);
1107        }
1108
1109        @Override
1110        public Object obtainCollectionItemInfo(int rowIndex, int rowSpan, int columnIndex,
1111                int columnSpan, boolean heading, boolean selected) {
1112            return AccessibilityNodeInfoCompatApi21.obtainCollectionItemInfo(rowIndex, rowSpan,
1113                    columnIndex, columnSpan, heading, selected);
1114        }
1115
1116        @Override
1117        public boolean isCollectionItemSelected(Object info) {
1118            return AccessibilityNodeInfoCompatApi21.CollectionItemInfo.isSelected(info);
1119        }
1120    }
1121
1122    static {
1123        if (Build.VERSION.SDK_INT >= 21) {
1124            IMPL = new AccessibilityNodeInfoApi21Impl();
1125        } else if (Build.VERSION.SDK_INT >= 19) { // KitKat
1126            IMPL = new AccessibilityNodeInfoKitKatImpl();
1127        } else if (Build.VERSION.SDK_INT >= 18) { // JellyBean MR2
1128            IMPL = new AccessibilityNodeInfoJellybeanMr2Impl();
1129        } else if (Build.VERSION.SDK_INT >= 16) { // JellyBean
1130            IMPL = new AccessibilityNodeInfoJellybeanImpl();
1131        } else if (Build.VERSION.SDK_INT >= 14) { // ICS
1132            IMPL = new AccessibilityNodeInfoIcsImpl();
1133        } else {
1134            IMPL = new AccessibilityNodeInfoStubImpl();
1135        }
1136    }
1137
1138    private static final AccessibilityNodeInfoImpl IMPL;
1139
1140    private final Object mInfo;
1141
1142    // Actions introduced in IceCreamSandwich
1143
1144    /**
1145     * Action that focuses the node.
1146     */
1147    public static final int ACTION_FOCUS = 0x00000001;
1148
1149    /**
1150     * Action that unfocuses the node.
1151     */
1152    public static final int ACTION_CLEAR_FOCUS = 0x00000002;
1153
1154    /**
1155     * Action that selects the node.
1156     */
1157    public static final int ACTION_SELECT = 0x00000004;
1158
1159    /**
1160     * Action that unselects the node.
1161     */
1162    public static final int ACTION_CLEAR_SELECTION = 0x00000008;
1163
1164    /**
1165     * Action that clicks on the node info.
1166     */
1167    public static final int ACTION_CLICK = 0x00000010;
1168
1169    /**
1170     * Action that long clicks on the node.
1171     */
1172    public static final int ACTION_LONG_CLICK = 0x00000020;
1173
1174    // Actions introduced in JellyBean
1175
1176    /**
1177     * Action that gives accessibility focus to the node.
1178     */
1179    public static final int ACTION_ACCESSIBILITY_FOCUS = 0x00000040;
1180
1181    /**
1182     * Action that clears accessibility focus of the node.
1183     */
1184    public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 0x00000080;
1185
1186    /**
1187     * Action that requests to go to the next entity in this node's text
1188     * at a given movement granularity. For example, move to the next character,
1189     * word, etc.
1190     * <p>
1191     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
1192     * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
1193     * <strong>Example:</strong> Move to the previous character and do not extend selection.
1194     * <code><pre><p>
1195     *   Bundle arguments = new Bundle();
1196     *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
1197     *           AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
1198     *   arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
1199     *           false);
1200     *   info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
1201     * </code></pre></p>
1202     * </p>
1203     *
1204     * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
1205     * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
1206     *
1207     * @see #setMovementGranularities(int)
1208     * @see #getMovementGranularities()
1209     *
1210     * @see #MOVEMENT_GRANULARITY_CHARACTER
1211     * @see #MOVEMENT_GRANULARITY_WORD
1212     * @see #MOVEMENT_GRANULARITY_LINE
1213     * @see #MOVEMENT_GRANULARITY_PARAGRAPH
1214     * @see #MOVEMENT_GRANULARITY_PAGE
1215     */
1216    public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 0x00000100;
1217
1218    /**
1219     * Action that requests to go to the previous entity in this node's text
1220     * at a given movement granularity. For example, move to the next character,
1221     * word, etc.
1222     * <p>
1223     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<,
1224     * {@link #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}<br>
1225     * <strong>Example:</strong> Move to the next character and do not extend selection.
1226     * <code><pre><p>
1227     *   Bundle arguments = new Bundle();
1228     *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
1229     *           AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
1230     *   arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
1231     *           false);
1232     *   info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
1233     *           arguments);
1234     * </code></pre></p>
1235     * </p>
1236     *
1237     * @see #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
1238     * @see #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
1239     *
1240     * @see #setMovementGranularities(int)
1241     * @see #getMovementGranularities()
1242     *
1243     * @see #MOVEMENT_GRANULARITY_CHARACTER
1244     * @see #MOVEMENT_GRANULARITY_WORD
1245     * @see #MOVEMENT_GRANULARITY_LINE
1246     * @see #MOVEMENT_GRANULARITY_PARAGRAPH
1247     * @see #MOVEMENT_GRANULARITY_PAGE
1248     */
1249    public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 0x00000200;
1250
1251    /**
1252     * Action to move to the next HTML element of a given type. For example, move
1253     * to the BUTTON, INPUT, TABLE, etc.
1254     * <p>
1255     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
1256     * <strong>Example:</strong>
1257     * <code><pre><p>
1258     *   Bundle arguments = new Bundle();
1259     *   arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
1260     *   info.performAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, arguments);
1261     * </code></pre></p>
1262     * </p>
1263     */
1264    public static final int ACTION_NEXT_HTML_ELEMENT = 0x00000400;
1265
1266    /**
1267     * Action to move to the previous HTML element of a given type. For example, move
1268     * to the BUTTON, INPUT, TABLE, etc.
1269     * <p>
1270     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_HTML_ELEMENT_STRING}<br>
1271     * <strong>Example:</strong>
1272     * <code><pre><p>
1273     *   Bundle arguments = new Bundle();
1274     *   arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
1275     *   info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT, arguments);
1276     * </code></pre></p>
1277     * </p>
1278     */
1279    public static final int ACTION_PREVIOUS_HTML_ELEMENT = 0x00000800;
1280
1281    /**
1282     * Action to scroll the node content forward.
1283     */
1284    public static final int ACTION_SCROLL_FORWARD = 0x00001000;
1285
1286    /**
1287     * Action to scroll the node content backward.
1288     */
1289    public static final int ACTION_SCROLL_BACKWARD = 0x00002000;
1290
1291    // Actions introduced in JellyBeanMr2
1292
1293    /**
1294     * Action to copy the current selection to the clipboard.
1295     */
1296    public static final int ACTION_COPY = 0x00004000;
1297
1298    /**
1299     * Action to paste the current clipboard content.
1300     */
1301    public static final int ACTION_PASTE = 0x00008000;
1302
1303    /**
1304     * Action to cut the current selection and place it to the clipboard.
1305     */
1306    public static final int ACTION_CUT = 0x00010000;
1307
1308    /**
1309     * Action to set the selection. Performing this action with no arguments
1310     * clears the selection.
1311     * <p>
1312     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_SELECTION_START_INT},
1313     * {@link #ACTION_ARGUMENT_SELECTION_END_INT}<br>
1314     * <strong>Example:</strong>
1315     * <code><pre><p>
1316     *   Bundle arguments = new Bundle();
1317     *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 1);
1318     *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 2);
1319     *   info.performAction(AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments);
1320     * </code></pre></p>
1321     * </p>
1322     *
1323     * @see #ACTION_ARGUMENT_SELECTION_START_INT
1324     * @see #ACTION_ARGUMENT_SELECTION_END_INT
1325     */
1326    public static final int ACTION_SET_SELECTION = 0x00020000;
1327
1328    /**
1329     * Action that sets the text of the node. Performing the action without argument, using <code>
1330     * null</code> or empty {@link CharSequence} will clear the text. This action will also put the
1331     * cursor at the end of text.
1332     * <p>
1333     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br>
1334     * <strong>Example:</strong>
1335     * <code><pre><p>
1336     *   Bundle arguments = new Bundle();
1337     *   arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
1338     *       "android");
1339     *   info.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
1340     * </code></pre></p>
1341     */
1342    public static final int ACTION_SET_TEXT = 0x00200000;
1343
1344    // Action arguments
1345
1346    /**
1347     * Argument for which movement granularity to be used when traversing the node text.
1348     * <p>
1349     * <strong>Type:</strong> int<br>
1350     * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_MOVEMENT_GRANULARITY},
1351     * {@link #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}
1352     * </p>
1353     */
1354    public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT =
1355        "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
1356
1357    /**
1358     * Argument for which HTML element to get moving to the next/previous HTML element.
1359     * <p>
1360     * <strong>Type:</strong> String<br>
1361     * <strong>Actions:</strong> {@link #ACTION_NEXT_HTML_ELEMENT},
1362     *         {@link #ACTION_PREVIOUS_HTML_ELEMENT}
1363     * </p>
1364     */
1365    public static final String ACTION_ARGUMENT_HTML_ELEMENT_STRING =
1366        "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
1367
1368    /**
1369     * Argument for whether when moving at granularity to extend the selection
1370     * or to move it otherwise.
1371     * <p>
1372     * <strong>Type:</strong> boolean<br>
1373     * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_MOVEMENT_GRANULARITY},
1374     * {@link #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}
1375     * </p>
1376     *
1377     * @see #ACTION_NEXT_AT_MOVEMENT_GRANULARITY
1378     * @see #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
1379     */
1380    public static final String ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN =
1381            "ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN";
1382
1383    /**
1384     * Argument for specifying the selection start.
1385     * <p>
1386     * <strong>Type:</strong> int<br>
1387     * <strong>Actions:</strong> {@link #ACTION_SET_SELECTION}
1388     * </p>
1389     *
1390     * @see #ACTION_SET_SELECTION
1391     */
1392    public static final String ACTION_ARGUMENT_SELECTION_START_INT =
1393            "ACTION_ARGUMENT_SELECTION_START_INT";
1394
1395    /**
1396     * Argument for specifying the selection end.
1397     * <p>
1398     * <strong>Type:</strong> int<br>
1399     * <strong>Actions:</strong> {@link #ACTION_SET_SELECTION}
1400     * </p>
1401     *
1402     * @see #ACTION_SET_SELECTION
1403     */
1404    public static final String ACTION_ARGUMENT_SELECTION_END_INT =
1405            "ACTION_ARGUMENT_SELECTION_END_INT";
1406
1407    /**
1408     * Argument for specifying the text content to set
1409     * <p>
1410     * <strong>Type:</strong> CharSequence<br>
1411     * <strong>Actions:</strong> {@link #ACTION_SET_TEXT}
1412     * </p>
1413     *
1414     * @see #ACTION_SET_TEXT
1415     */
1416    public static final String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE =
1417            "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE";
1418
1419    // Focus types
1420
1421    /**
1422     * The input focus.
1423     */
1424    public static final int FOCUS_INPUT = 1;
1425
1426    /**
1427     * The accessibility focus.
1428     */
1429    public static final int FOCUS_ACCESSIBILITY = 2;
1430
1431    // Movement granularities
1432
1433    /**
1434     * Movement granularity bit for traversing the text of a node by character.
1435     */
1436    public static final int MOVEMENT_GRANULARITY_CHARACTER = 0x00000001;
1437
1438    /**
1439     * Movement granularity bit for traversing the text of a node by word.
1440     */
1441    public static final int MOVEMENT_GRANULARITY_WORD = 0x00000002;
1442
1443    /**
1444     * Movement granularity bit for traversing the text of a node by line.
1445     */
1446    public static final int MOVEMENT_GRANULARITY_LINE = 0x00000004;
1447
1448    /**
1449     * Movement granularity bit for traversing the text of a node by paragraph.
1450     */
1451    public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 0x00000008;
1452
1453    /**
1454     * Movement granularity bit for traversing the text of a node by page.
1455     */
1456    public static final int MOVEMENT_GRANULARITY_PAGE = 0x00000010;
1457
1458    /**
1459     * Creates a wrapper for info implementation.
1460     *
1461     * @param object The info to wrap.
1462     * @return A wrapper for if the object is not null, null otherwise.
1463     */
1464    static AccessibilityNodeInfoCompat wrapNonNullInstance(Object object) {
1465        if (object != null) {
1466            return new AccessibilityNodeInfoCompat(object);
1467        }
1468        return null;
1469    }
1470
1471    /**
1472     * Creates a new instance wrapping an
1473     * {@link android.view.accessibility.AccessibilityNodeInfo}.
1474     *
1475     * @param info The info.
1476     */
1477    public AccessibilityNodeInfoCompat(Object info) {
1478        mInfo = info;
1479    }
1480
1481    /**
1482     * @return The wrapped {@link android.view.accessibility.AccessibilityNodeInfo}.
1483     */
1484    public Object getInfo() {
1485        return mInfo;
1486    }
1487
1488    /**
1489     * Returns a cached instance if such is available otherwise a new one and
1490     * sets the source.
1491     *
1492     * @return An instance.
1493     * @see #setSource(View)
1494     */
1495    public static AccessibilityNodeInfoCompat obtain(View source) {
1496        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.obtain(source));
1497    }
1498
1499    /**
1500     * Returns a cached instance if such is available otherwise a new one
1501     * and sets the source.
1502     *
1503     * @param root The root of the virtual subtree.
1504     * @param virtualDescendantId The id of the virtual descendant.
1505     * @return An instance.
1506     *
1507     * @see #setSource(View, int)
1508     */
1509    public static AccessibilityNodeInfoCompat obtain(View root, int virtualDescendantId) {
1510        return AccessibilityNodeInfoCompat.wrapNonNullInstance(
1511                IMPL.obtain(root, virtualDescendantId));
1512    }
1513
1514    /**
1515     * Returns a cached instance if such is available otherwise a new one.
1516     *
1517     * @return An instance.
1518     */
1519    public static AccessibilityNodeInfoCompat obtain() {
1520        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.obtain());
1521    }
1522
1523    /**
1524     * Returns a cached instance if such is available or a new one is create.
1525     * The returned instance is initialized from the given <code>info</code>.
1526     *
1527     * @param info The other info.
1528     * @return An instance.
1529     */
1530    public static AccessibilityNodeInfoCompat obtain(AccessibilityNodeInfoCompat info) {
1531        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.obtain(info.mInfo));
1532    }
1533
1534    /**
1535     * Sets the source.
1536     *
1537     * @param source The info source.
1538     */
1539    public void setSource(View source) {
1540        IMPL.setSource(mInfo, source);
1541    }
1542
1543    /**
1544     * Sets the source to be a virtual descendant of the given <code>root</code>.
1545     * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
1546     * is set as the source.
1547     * <p>
1548     * A virtual descendant is an imaginary View that is reported as a part of the view
1549     * hierarchy for accessibility purposes. This enables custom views that draw complex
1550     * content to report themselves as a tree of virtual views, thus conveying their
1551     * logical structure.
1552     * </p>
1553     * <p>
1554     *   <strong>Note:</strong> Cannot be called from an
1555     *   {@link android.accessibilityservice.AccessibilityService}.
1556     *   This class is made immutable before being delivered to an AccessibilityService.
1557     * </p>
1558     *
1559     * @param root The root of the virtual subtree.
1560     * @param virtualDescendantId The id of the virtual descendant.
1561     */
1562    public void setSource(View root, int virtualDescendantId) {
1563        IMPL.setSource(mInfo, root, virtualDescendantId);
1564    }
1565
1566    /**
1567     * Find the view that has the specified focus type. The search starts from
1568     * the view represented by this node info.
1569     *
1570     * @param focus The focus to find. One of {@link #FOCUS_INPUT} or
1571     *         {@link #FOCUS_ACCESSIBILITY}.
1572     * @return The node info of the focused view or null.
1573     *
1574     * @see #FOCUS_INPUT
1575     * @see #FOCUS_ACCESSIBILITY
1576     */
1577    public AccessibilityNodeInfoCompat findFocus(int focus) {
1578        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.findFocus(mInfo, focus));
1579    }
1580
1581    /**
1582     * Searches for the nearest view in the specified direction that can take
1583     * input focus.
1584     *
1585     * @param direction The direction. Can be one of:
1586     *     {@link View#FOCUS_DOWN},
1587     *     {@link View#FOCUS_UP},
1588     *     {@link View#FOCUS_LEFT},
1589     *     {@link View#FOCUS_RIGHT},
1590     *     {@link View#FOCUS_FORWARD},
1591     *     {@link View#FOCUS_BACKWARD}.
1592     *
1593     * @return The node info for the view that can take accessibility focus.
1594     */
1595    public AccessibilityNodeInfoCompat focusSearch(int direction) {
1596        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.focusSearch(mInfo, direction));
1597    }
1598
1599    /**
1600     * Gets the id of the window from which the info comes from.
1601     *
1602     * @return The window id.
1603     */
1604    public int getWindowId() {
1605        return IMPL.getWindowId(mInfo);
1606    }
1607
1608    /**
1609     * Gets the number of children.
1610     *
1611     * @return The child count.
1612     */
1613    public int getChildCount() {
1614        return IMPL.getChildCount(mInfo);
1615    }
1616
1617    /**
1618     * Get the child at given index.
1619     * <p>
1620     * <strong>Note:</strong> It is a client responsibility to recycle the
1621     * received info by calling {@link AccessibilityNodeInfoCompat#recycle()} to
1622     * avoid creating of multiple instances.
1623     * </p>
1624     *
1625     * @param index The child index.
1626     * @return The child node.
1627     * @throws IllegalStateException If called outside of an
1628     *             AccessibilityService.
1629     */
1630    public AccessibilityNodeInfoCompat getChild(int index) {
1631        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.getChild(mInfo, index));
1632    }
1633
1634    /**
1635     * Adds a child.
1636     * <p>
1637     * <strong>Note:</strong> Cannot be called from an
1638     * {@link android.accessibilityservice.AccessibilityService}. This class is
1639     * made immutable before being delivered to an AccessibilityService.
1640     * </p>
1641     *
1642     * @param child The child.
1643     * @throws IllegalStateException If called from an AccessibilityService.
1644     */
1645    public void addChild(View child) {
1646        IMPL.addChild(mInfo, child);
1647    }
1648
1649    /**
1650     * Adds a virtual child which is a descendant of the given <code>root</code>.
1651     * If <code>virtualDescendantId</code> is {@link View#NO_ID} the root
1652     * is added as a child.
1653     * <p>
1654     * A virtual descendant is an imaginary View that is reported as a part of the view
1655     * hierarchy for accessibility purposes. This enables custom views that draw complex
1656     * content to report them selves as a tree of virtual views, thus conveying their
1657     * logical structure.
1658     * </p>
1659     *
1660     * @param root The root of the virtual subtree.
1661     * @param virtualDescendantId The id of the virtual child.
1662     */
1663    public void addChild(View root, int virtualDescendantId) {
1664        IMPL.addChild(mInfo, root, virtualDescendantId);
1665    }
1666
1667    /**
1668     * Gets the actions that can be performed on the node.
1669     *
1670     * @return The bit mask of with actions.
1671     * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_FOCUS
1672     * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_CLEAR_FOCUS
1673     * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_SELECT
1674     * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_CLEAR_SELECTION
1675     */
1676    public int getActions() {
1677        return IMPL.getActions(mInfo);
1678    }
1679
1680    /**
1681     * Adds an action that can be performed on the node.
1682     * <p>
1683     * <strong>Note:</strong> Cannot be called from an
1684     * {@link android.accessibilityservice.AccessibilityService}. This class is
1685     * made immutable before being delivered to an AccessibilityService.
1686     * </p>
1687     *
1688     * @param action The action.
1689     * @throws IllegalStateException If called from an AccessibilityService.
1690     */
1691    public void addAction(int action) {
1692        IMPL.addAction(mInfo, action);
1693    }
1694
1695    /**
1696     * Performs an action on the node.
1697     * <p>
1698     * <strong>Note:</strong> An action can be performed only if the request is
1699     * made from an {@link android.accessibilityservice.AccessibilityService}.
1700     * </p>
1701     *
1702     * @param action The action to perform.
1703     * @return True if the action was performed.
1704     * @throws IllegalStateException If called outside of an
1705     *             AccessibilityService.
1706     */
1707    public boolean performAction(int action) {
1708        return IMPL.performAction(mInfo, action);
1709    }
1710
1711    /**
1712     * Performs an action on the node.
1713     * <p>
1714     *   <strong>Note:</strong> An action can be performed only if the request is made
1715     *   from an {@link android.accessibilityservice.AccessibilityService}.
1716     * </p>
1717     *
1718     * @param action The action to perform.
1719     * @param arguments A bundle with additional arguments.
1720     * @return True if the action was performed.
1721     *
1722     * @throws IllegalStateException If called outside of an AccessibilityService.
1723     */
1724    public boolean performAction(int action, Bundle arguments) {
1725        return IMPL.performAction(mInfo, action, arguments);
1726    }
1727
1728    /**
1729     * Sets the movement granularities for traversing the text of this node.
1730     * <p>
1731     *   <strong>Note:</strong> Cannot be called from an
1732     *   {@link android.accessibilityservice.AccessibilityService}.
1733     *   This class is made immutable before being delivered to an AccessibilityService.
1734     * </p>
1735     *
1736     * @param granularities The bit mask with granularities.
1737     *
1738     * @throws IllegalStateException If called from an AccessibilityService.
1739     */
1740    public void setMovementGranularities(int granularities) {
1741        IMPL.setMovementGranularities(mInfo, granularities);
1742    }
1743
1744    /**
1745     * Gets the movement granularities for traversing the text of this node.
1746     *
1747     * @return The bit mask with granularities.
1748     */
1749    public int getMovementGranularities() {
1750        return IMPL.getMovementGranularities(mInfo);
1751    }
1752
1753    /**
1754     * Finds {@link android.view.accessibility.AccessibilityNodeInfo}s by text. The match
1755     * is case insensitive containment. The search is relative to this info i.e. this
1756     * info is the root of the traversed tree.
1757     * <p>
1758     * <strong>Note:</strong> It is a client responsibility to recycle the
1759     * received info by calling {@link android.view.accessibility.AccessibilityNodeInfo#recycle()}
1760     * to avoid creating of multiple instances.
1761     * </p>
1762     *
1763     * @param text The searched text.
1764     * @return A list of node info.
1765     */
1766    public List<AccessibilityNodeInfoCompat> findAccessibilityNodeInfosByText(String text) {
1767        List<AccessibilityNodeInfoCompat> result = new ArrayList<AccessibilityNodeInfoCompat>();
1768        List<Object> infos = IMPL.findAccessibilityNodeInfosByText(mInfo, text);
1769        final int infoCount = infos.size();
1770        for (int i = 0; i < infoCount; i++) {
1771            Object info = infos.get(i);
1772            result.add(new AccessibilityNodeInfoCompat(info));
1773        }
1774        return result;
1775    }
1776
1777    /**
1778     * Gets the parent.
1779     * <p>
1780     * <strong>Note:</strong> It is a client responsibility to recycle the
1781     * received info by calling {@link android.view.accessibility.AccessibilityNodeInfo#recycle()}
1782     * to avoid creating of multiple instances.
1783     * </p>
1784     *
1785     * @return The parent.
1786     */
1787    public AccessibilityNodeInfoCompat getParent() {
1788        return AccessibilityNodeInfoCompat.wrapNonNullInstance(IMPL.getParent(mInfo));
1789    }
1790
1791    /**
1792     * Sets the parent.
1793     * <p>
1794     * <strong>Note:</strong> Cannot be called from an
1795     * {@link android.accessibilityservice.AccessibilityService}. This class is
1796     * made immutable before being delivered to an AccessibilityService.
1797     * </p>
1798     *
1799     * @param parent The parent.
1800     * @throws IllegalStateException If called from an AccessibilityService.
1801     */
1802    public void setParent(View parent) {
1803        IMPL.setParent(mInfo, parent);
1804    }
1805
1806    /**
1807     * Sets the parent to be a virtual descendant of the given <code>root</code>.
1808     * If <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root
1809     * is set as the parent.
1810     * <p>
1811     * A virtual descendant is an imaginary View that is reported as a part of the view
1812     * hierarchy for accessibility purposes. This enables custom views that draw complex
1813     * content to report them selves as a tree of virtual views, thus conveying their
1814     * logical structure.
1815     * </p>
1816     * <p>
1817     *   <strong>Note:</strong> Cannot be called from an
1818     *   {@link android.accessibilityservice.AccessibilityService}.
1819     *   This class is made immutable before being delivered to an AccessibilityService.
1820     * </p>
1821     *
1822     * @param root The root of the virtual subtree.
1823     * @param virtualDescendantId The id of the virtual descendant.
1824     */
1825    public void setParent(View root, int virtualDescendantId) {
1826        IMPL.setParent(mInfo, root, virtualDescendantId);
1827    }
1828
1829    /**
1830     * Gets the node bounds in parent coordinates.
1831     *
1832     * @param outBounds The output node bounds.
1833     */
1834    public void getBoundsInParent(Rect outBounds) {
1835        IMPL.getBoundsInParent(mInfo, outBounds);
1836    }
1837
1838    /**
1839     * Sets the node bounds in parent coordinates.
1840     * <p>
1841     * <strong>Note:</strong> Cannot be called from an
1842     * {@link android.accessibilityservice.AccessibilityService}. This class is
1843     * made immutable before being delivered to an AccessibilityService.
1844     * </p>
1845     *
1846     * @param bounds The node bounds.
1847     *@throws IllegalStateException If called from an AccessibilityService.
1848     */
1849    public void setBoundsInParent(Rect bounds) {
1850        IMPL.setBoundsInParent(mInfo, bounds);
1851    }
1852
1853    /**
1854     * Gets the node bounds in screen coordinates.
1855     *
1856     * @param outBounds The output node bounds.
1857     */
1858    public void getBoundsInScreen(Rect outBounds) {
1859        IMPL.getBoundsInScreen(mInfo, outBounds);
1860    }
1861
1862    /**
1863     * Sets the node bounds in screen coordinates.
1864     * <p>
1865     * <strong>Note:</strong> Cannot be called from an
1866     * {@link android.accessibilityservice.AccessibilityService}. This class is
1867     * made immutable before being delivered to an AccessibilityService.
1868     * </p>
1869     *
1870     * @param bounds The node bounds.
1871     * @throws IllegalStateException If called from an AccessibilityService.
1872     */
1873    public void setBoundsInScreen(Rect bounds) {
1874        IMPL.setBoundsInScreen(mInfo, bounds);
1875    }
1876
1877    /**
1878     * Gets whether this node is checkable.
1879     *
1880     * @return True if the node is checkable.
1881     */
1882    public boolean isCheckable() {
1883        return IMPL.isCheckable(mInfo);
1884    }
1885
1886    /**
1887     * Sets whether this node is checkable.
1888     * <p>
1889     * <strong>Note:</strong> Cannot be called from an
1890     * {@link android.accessibilityservice.AccessibilityService}. This class is
1891     * made immutable before being delivered to an AccessibilityService.
1892     * </p>
1893     *
1894     * @param checkable True if the node is checkable.
1895     * @throws IllegalStateException If called from an AccessibilityService.
1896     */
1897    public void setCheckable(boolean checkable) {
1898        IMPL.setCheckable(mInfo, checkable);
1899    }
1900
1901    /**
1902     * Gets whether this node is checked.
1903     *
1904     * @return True if the node is checked.
1905     */
1906    public boolean isChecked() {
1907        return IMPL.isChecked(mInfo);
1908    }
1909
1910    /**
1911     * Sets whether this node is checked.
1912     * <p>
1913     * <strong>Note:</strong> Cannot be called from an
1914     * {@link android.accessibilityservice.AccessibilityService}. This class is
1915     * made immutable before being delivered to an AccessibilityService.
1916     * </p>
1917     *
1918     * @param checked True if the node is checked.
1919     * @throws IllegalStateException If called from an AccessibilityService.
1920     */
1921    public void setChecked(boolean checked) {
1922        IMPL.setChecked(mInfo, checked);
1923    }
1924
1925    /**
1926     * Gets whether this node is focusable.
1927     *
1928     * @return True if the node is focusable.
1929     */
1930    public boolean isFocusable() {
1931        return IMPL.isFocusable(mInfo);
1932    }
1933
1934    /**
1935     * Sets whether this node is focusable.
1936     * <p>
1937     * <strong>Note:</strong> Cannot be called from an
1938     * {@link android.accessibilityservice.AccessibilityService}. This class is
1939     * made immutable before being delivered to an AccessibilityService.
1940     * </p>
1941     *
1942     * @param focusable True if the node is focusable.
1943     * @throws IllegalStateException If called from an AccessibilityService.
1944     */
1945    public void setFocusable(boolean focusable) {
1946        IMPL.setFocusable(mInfo, focusable);
1947    }
1948
1949    /**
1950     * Gets whether this node is focused.
1951     *
1952     * @return True if the node is focused.
1953     */
1954    public boolean isFocused() {
1955        return IMPL.isFocused(mInfo);
1956    }
1957
1958    /**
1959     * Sets whether this node is focused.
1960     * <p>
1961     * <strong>Note:</strong> Cannot be called from an
1962     * {@link android.accessibilityservice.AccessibilityService}. This class is
1963     * made immutable before being delivered to an AccessibilityService.
1964     * </p>
1965     *
1966     * @param focused True if the node is focused.
1967     * @throws IllegalStateException If called from an AccessibilityService.
1968     */
1969    public void setFocused(boolean focused) {
1970        IMPL.setFocused(mInfo, focused);
1971    }
1972
1973    /**
1974     * Sets whether this node is visible to the user.
1975     *
1976     * @return Whether the node is visible to the user.
1977     */
1978    public boolean isVisibleToUser() {
1979        return IMPL.isVisibleToUser(mInfo);
1980    }
1981
1982    /**
1983     * Sets whether this node is visible to the user.
1984     * <p>
1985     *   <strong>Note:</strong> Cannot be called from an
1986     *   {@link android.accessibilityservice.AccessibilityService}.
1987     *   This class is made immutable before being delivered to an AccessibilityService.
1988     * </p>
1989     *
1990     * @param visibleToUser Whether the node is visible to the user.
1991     *
1992     * @throws IllegalStateException If called from an AccessibilityService.
1993     */
1994    public void setVisibleToUser(boolean visibleToUser) {
1995        IMPL.setVisibleToUser(mInfo, visibleToUser);
1996    }
1997
1998    /**
1999     * Gets whether this node is accessibility focused.
2000     *
2001     * @return True if the node is accessibility focused.
2002     */
2003    public boolean isAccessibilityFocused() {
2004        return IMPL.isAccessibilityFocused(mInfo);
2005    }
2006
2007    /**
2008     * Sets whether this node is accessibility focused.
2009     * <p>
2010     *   <strong>Note:</strong> Cannot be called from an
2011     *   {@link android.accessibilityservice.AccessibilityService}.
2012     *   This class is made immutable before being delivered to an AccessibilityService.
2013     * </p>
2014     *
2015     * @param focused True if the node is accessibility focused.
2016     *
2017     * @throws IllegalStateException If called from an AccessibilityService.
2018     */
2019    public void setAccessibilityFocused(boolean focused) {
2020        IMPL.setAccessibilityFocused(mInfo, focused);
2021    }
2022
2023    /**
2024     * Gets whether this node is selected.
2025     *
2026     * @return True if the node is selected.
2027     */
2028    public boolean isSelected() {
2029        return IMPL.isSelected(mInfo);
2030    }
2031
2032    /**
2033     * Sets whether this node is selected.
2034     * <p>
2035     * <strong>Note:</strong> Cannot be called from an
2036     * {@link android.accessibilityservice.AccessibilityService}. This class is
2037     * made immutable before being delivered to an AccessibilityService.
2038     * </p>
2039     *
2040     * @param selected True if the node is selected.
2041     * @throws IllegalStateException If called from an AccessibilityService.
2042     */
2043    public void setSelected(boolean selected) {
2044        IMPL.setSelected(mInfo, selected);
2045    }
2046
2047    /**
2048     * Gets whether this node is clickable.
2049     *
2050     * @return True if the node is clickable.
2051     */
2052    public boolean isClickable() {
2053        return IMPL.isClickable(mInfo);
2054    }
2055
2056    /**
2057     * Sets whether this node is clickable.
2058     * <p>
2059     * <strong>Note:</strong> Cannot be called from an
2060     * {@link android.accessibilityservice.AccessibilityService}. This class is
2061     * made immutable before being delivered to an AccessibilityService.
2062     * </p>
2063     *
2064     * @param clickable True if the node is clickable.
2065     * @throws IllegalStateException If called from an AccessibilityService.
2066     */
2067    public void setClickable(boolean clickable) {
2068        IMPL.setClickable(mInfo, clickable);
2069    }
2070
2071    /**
2072     * Gets whether this node is long clickable.
2073     *
2074     * @return True if the node is long clickable.
2075     */
2076    public boolean isLongClickable() {
2077        return IMPL.isLongClickable(mInfo);
2078    }
2079
2080    /**
2081     * Sets whether this node is long clickable.
2082     * <p>
2083     * <strong>Note:</strong> Cannot be called from an
2084     * {@link android.accessibilityservice.AccessibilityService}. This class is
2085     * made immutable before being delivered to an AccessibilityService.
2086     * </p>
2087     *
2088     * @param longClickable True if the node is long clickable.
2089     * @throws IllegalStateException If called from an AccessibilityService.
2090     */
2091    public void setLongClickable(boolean longClickable) {
2092        IMPL.setLongClickable(mInfo, longClickable);
2093    }
2094
2095    /**
2096     * Gets whether this node is enabled.
2097     *
2098     * @return True if the node is enabled.
2099     */
2100    public boolean isEnabled() {
2101        return IMPL.isEnabled(mInfo);
2102    }
2103
2104    /**
2105     * Sets whether this node is enabled.
2106     * <p>
2107     * <strong>Note:</strong> Cannot be called from an
2108     * {@link android.accessibilityservice.AccessibilityService}. This class is
2109     * made immutable before being delivered to an AccessibilityService.
2110     * </p>
2111     *
2112     * @param enabled True if the node is enabled.
2113     * @throws IllegalStateException If called from an AccessibilityService.
2114     */
2115    public void setEnabled(boolean enabled) {
2116        IMPL.setEnabled(mInfo, enabled);
2117    }
2118
2119    /**
2120     * Gets whether this node is a password.
2121     *
2122     * @return True if the node is a password.
2123     */
2124    public boolean isPassword() {
2125        return IMPL.isPassword(mInfo);
2126    }
2127
2128    /**
2129     * Sets whether this node is a password.
2130     * <p>
2131     * <strong>Note:</strong> Cannot be called from an
2132     * {@link android.accessibilityservice.AccessibilityService}. This class is
2133     * made immutable before being delivered to an AccessibilityService.
2134     * </p>
2135     *
2136     * @param password True if the node is a password.
2137     * @throws IllegalStateException If called from an AccessibilityService.
2138     */
2139    public void setPassword(boolean password) {
2140        IMPL.setPassword(mInfo, password);
2141    }
2142
2143    /**
2144     * Gets if the node is scrollable.
2145     *
2146     * @return True if the node is scrollable, false otherwise.
2147     */
2148    public boolean isScrollable() {
2149        return IMPL.isScrollable(mInfo);
2150    }
2151
2152    /**
2153     * Sets if the node is scrollable.
2154     * <p>
2155     * <strong>Note:</strong> Cannot be called from an
2156     * {@link android.accessibilityservice.AccessibilityService}. This class is
2157     * made immutable before being delivered to an AccessibilityService.
2158     * </p>
2159     *
2160     * @param scrollable True if the node is scrollable, false otherwise.
2161     * @throws IllegalStateException If called from an AccessibilityService.
2162     */
2163    public void setScrollable(boolean scrollable) {
2164        IMPL.setScrollable(mInfo, scrollable);
2165    }
2166
2167    /**
2168     * Gets the package this node comes from.
2169     *
2170     * @return The package name.
2171     */
2172    public CharSequence getPackageName() {
2173        return IMPL.getPackageName(mInfo);
2174    }
2175
2176    /**
2177     * Sets the package this node comes from.
2178     * <p>
2179     * <strong>Note:</strong> Cannot be called from an
2180     * {@link android.accessibilityservice.AccessibilityService}. This class is
2181     * made immutable before being delivered to an AccessibilityService.
2182     * </p>
2183     *
2184     * @param packageName The package name.
2185     * @throws IllegalStateException If called from an AccessibilityService.
2186     */
2187    public void setPackageName(CharSequence packageName) {
2188        IMPL.setPackageName(mInfo, packageName);
2189    }
2190
2191    /**
2192     * Gets the class this node comes from.
2193     *
2194     * @return The class name.
2195     */
2196    public CharSequence getClassName() {
2197        return IMPL.getClassName(mInfo);
2198    }
2199
2200    /**
2201     * Sets the class this node comes from.
2202     * <p>
2203     * <strong>Note:</strong> Cannot be called from an
2204     * {@link android.accessibilityservice.AccessibilityService}. This class is
2205     * made immutable before being delivered to an AccessibilityService.
2206     * </p>
2207     *
2208     * @param className The class name.
2209     * @throws IllegalStateException If called from an AccessibilityService.
2210     */
2211    public void setClassName(CharSequence className) {
2212        IMPL.setClassName(mInfo, className);
2213    }
2214
2215    /**
2216     * Gets the text of this node.
2217     *
2218     * @return The text.
2219     */
2220    public CharSequence getText() {
2221        return IMPL.getText(mInfo);
2222    }
2223
2224    /**
2225     * Sets the text of this node.
2226     * <p>
2227     * <strong>Note:</strong> Cannot be called from an
2228     * {@link android.accessibilityservice.AccessibilityService}. This class is
2229     * made immutable before being delivered to an AccessibilityService.
2230     * </p>
2231     *
2232     * @param text The text.
2233     * @throws IllegalStateException If called from an AccessibilityService.
2234     */
2235    public void setText(CharSequence text) {
2236        IMPL.setText(mInfo, text);
2237    }
2238
2239    /**
2240     * Gets the content description of this node.
2241     *
2242     * @return The content description.
2243     */
2244    public CharSequence getContentDescription() {
2245        return IMPL.getContentDescription(mInfo);
2246    }
2247
2248    /**
2249     * Sets the content description of this node.
2250     * <p>
2251     * <strong>Note:</strong> Cannot be called from an
2252     * {@link android.accessibilityservice.AccessibilityService}. This class is
2253     * made immutable before being delivered to an AccessibilityService.
2254     * </p>
2255     *
2256     * @param contentDescription The content description.
2257     * @throws IllegalStateException If called from an AccessibilityService.
2258     */
2259    public void setContentDescription(CharSequence contentDescription) {
2260        IMPL.setContentDescription(mInfo, contentDescription);
2261    }
2262
2263    /**
2264     * Return an instance back to be reused.
2265     * <p>
2266     * <strong>Note:</strong> You must not touch the object after calling this function.
2267     *
2268     * @throws IllegalStateException If the info is already recycled.
2269     */
2270    public void recycle() {
2271        IMPL.recycle(mInfo);
2272    }
2273
2274    /**
2275     * Sets the fully qualified resource name of the source view's id.
2276     *
2277     * <p>
2278     *   <strong>Note:</strong> Cannot be called from an
2279     *   {@link android.accessibilityservice.AccessibilityService}.
2280     *   This class is made immutable before being delivered to an AccessibilityService.
2281     * </p>
2282     *
2283     * @param viewId The id resource name.
2284     */
2285    public void setViewIdResourceName(String viewId) {
2286        IMPL.setViewIdResourceName(mInfo, viewId);
2287    }
2288
2289    /**
2290     * Gets the fully qualified resource name of the source view's id.
2291     *
2292     * <p>
2293     *   <strong>Note:</strong> The primary usage of this API is for UI test automation
2294     *   and in order to report the source view id of an {@link AccessibilityNodeInfoCompat}
2295     *   the client has to set the {@link AccessibilityServiceInfoCompat#FLAG_REPORT_VIEW_IDS}
2296     *   flag when configuring his {@link android.accessibilityservice.AccessibilityService}.
2297     * </p>
2298     *
2299     * @return The id resource name.
2300     */
2301    public String getViewIdResourceName() {
2302        return IMPL.getViewIdResourceName(mInfo);
2303    }
2304
2305    /**
2306     * Gets the node's live region mode.
2307     * <p>
2308     * A live region is a node that contains information that is important for
2309     * the user and when it changes the user should be notified. For example,
2310     * in a login screen with a TextView that displays an "incorrect password"
2311     * notification, that view should be marked as a live region with mode
2312     * {@link ViewCompat#ACCESSIBILITY_LIVE_REGION_POLITE}.
2313     * <p>
2314     * It is the responsibility of the accessibility service to monitor
2315     * {@link AccessibilityEventCompat#TYPE_WINDOW_CONTENT_CHANGED} events
2316     * indicating changes to live region nodes and their children.
2317     *
2318     * @return The live region mode, or
2319     *         {@link ViewCompat#ACCESSIBILITY_LIVE_REGION_NONE} if the view is
2320     *         not a live region.
2321     * @see ViewCompat#getAccessibilityLiveRegion(View)
2322     */
2323    public int getLiveRegion() {
2324        return IMPL.getLiveRegion(mInfo);
2325    }
2326
2327    /**
2328     * Sets the node's live region mode.
2329     * <p>
2330     * <strong>Note:</strong> Cannot be called from an
2331     * {@link android.accessibilityservice.AccessibilityService}. This class is
2332     * made immutable before being delivered to an AccessibilityService.
2333     *
2334     * @param mode The live region mode, or
2335     *        {@link ViewCompat#ACCESSIBILITY_LIVE_REGION_NONE} if the view is
2336     *        not a live region.
2337     * @see ViewCompat#setAccessibilityLiveRegion(View, int)
2338     */
2339    public void setLiveRegion(int mode) {
2340        IMPL.setLiveRegion(mInfo, mode);
2341    }
2342
2343    /**
2344     * Gets the collection info if the node is a collection. A collection
2345     * child is always a collection item.
2346     *
2347     * @return The collection info.
2348     */
2349    public CollectionInfoCompat getCollectionInfo() {
2350        Object info = IMPL.getCollectionInfo(mInfo);
2351        if (info == null) return null;
2352        return new CollectionInfoCompat(info);
2353    }
2354
2355    public void setCollectionInfo(Object collectionInfo) {
2356        IMPL.setCollectionInfo(mInfo, ((CollectionInfoCompat) collectionInfo).mInfo);
2357    }
2358
2359    public void setCollectionItemInfo(Object collectionItemInfo) {
2360        IMPL.setCollectionItemInfo(mInfo, ((CollectionItemInfoCompat) collectionItemInfo).mInfo);
2361    }
2362
2363    /**
2364     * Gets the collection item info if the node is a collection item. A collection
2365     * item is always a child of a collection.
2366     *
2367     * @return The collection item info.
2368     */
2369    public CollectionItemInfoCompat getCollectionItemInfo() {
2370        Object info = IMPL.getCollectionItemInfo(mInfo);
2371        if (info == null) return null;
2372        return new CollectionItemInfoCompat(info);
2373    }
2374
2375    /**
2376     * Gets the range info if this node is a range.
2377     *
2378     * @return The range.
2379     */
2380    public RangeInfoCompat getRangeInfo() {
2381        Object info = IMPL.getRangeInfo(mInfo);
2382        if (info == null) return null;
2383        return new RangeInfoCompat(info);
2384    }
2385
2386    /**
2387     * Gets the actions that can be performed on the node.
2388     *
2389     * @return A list of AccessibilityActions.
2390     */
2391    public List<AccessibilityActionCompat> getActionList() {
2392        List<AccessibilityActionCompat> result = new ArrayList<AccessibilityActionCompat>();
2393        List<Object> actions = IMPL.getActionList(mInfo);
2394        final int actionCount = actions.size();
2395        for (int i = 0; i < actionCount; i++) {
2396            Object action = actions.get(i);
2397            result.add(new AccessibilityActionCompat(action));
2398        }
2399        return result;
2400    }
2401
2402
2403    @Override
2404    public int hashCode() {
2405        return (mInfo == null) ? 0 : mInfo.hashCode();
2406    }
2407
2408    @Override
2409    public boolean equals(Object obj) {
2410        if (this == obj) {
2411            return true;
2412        }
2413        if (obj == null) {
2414            return false;
2415        }
2416        if (getClass() != obj.getClass()) {
2417            return false;
2418        }
2419        AccessibilityNodeInfoCompat other = (AccessibilityNodeInfoCompat) obj;
2420        if (mInfo == null) {
2421            if (other.mInfo != null) {
2422                return false;
2423            }
2424        } else if (!mInfo.equals(other.mInfo)) {
2425            return false;
2426        }
2427        return true;
2428    }
2429
2430    @Override
2431    public String toString() {
2432        StringBuilder builder = new StringBuilder();
2433        builder.append(super.toString());
2434
2435        Rect bounds = new Rect();
2436
2437        getBoundsInParent(bounds);
2438        builder.append("; boundsInParent: " + bounds);
2439
2440        getBoundsInScreen(bounds);
2441        builder.append("; boundsInScreen: " + bounds);
2442
2443        builder.append("; packageName: ").append(getPackageName());
2444        builder.append("; className: ").append(getClassName());
2445        builder.append("; text: ").append(getText());
2446        builder.append("; contentDescription: ").append(getContentDescription());
2447        builder.append("; viewId: ").append(getViewIdResourceName());
2448
2449        builder.append("; checkable: ").append(isCheckable());
2450        builder.append("; checked: ").append(isChecked());
2451        builder.append("; focusable: ").append(isFocusable());
2452        builder.append("; focused: ").append(isFocused());
2453        builder.append("; selected: ").append(isSelected());
2454        builder.append("; clickable: ").append(isClickable());
2455        builder.append("; longClickable: ").append(isLongClickable());
2456        builder.append("; enabled: ").append(isEnabled());
2457        builder.append("; password: ").append(isPassword());
2458        builder.append("; scrollable: " + isScrollable());
2459
2460        builder.append("; [");
2461        for (int actionBits = getActions(); actionBits != 0;) {
2462            final int action = 1 << Integer.numberOfTrailingZeros(actionBits);
2463            actionBits &= ~action;
2464            builder.append(getActionSymbolicName(action));
2465            if (actionBits != 0) {
2466                builder.append(", ");
2467            }
2468        }
2469        builder.append("]");
2470
2471        return builder.toString();
2472    }
2473
2474    private static String getActionSymbolicName(int action) {
2475        switch (action) {
2476            case ACTION_FOCUS:
2477                return "ACTION_FOCUS";
2478            case ACTION_CLEAR_FOCUS:
2479                return "ACTION_CLEAR_FOCUS";
2480            case ACTION_SELECT:
2481                return "ACTION_SELECT";
2482            case ACTION_CLEAR_SELECTION:
2483                return "ACTION_CLEAR_SELECTION";
2484            case ACTION_CLICK:
2485                return "ACTION_CLICK";
2486            case ACTION_LONG_CLICK:
2487                return "ACTION_LONG_CLICK";
2488            case ACTION_ACCESSIBILITY_FOCUS:
2489                return "ACTION_ACCESSIBILITY_FOCUS";
2490            case ACTION_CLEAR_ACCESSIBILITY_FOCUS:
2491                return "ACTION_CLEAR_ACCESSIBILITY_FOCUS";
2492            case ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
2493                return "ACTION_NEXT_AT_MOVEMENT_GRANULARITY";
2494            case ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY:
2495                return "ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY";
2496            case ACTION_NEXT_HTML_ELEMENT:
2497                return "ACTION_NEXT_HTML_ELEMENT";
2498            case ACTION_PREVIOUS_HTML_ELEMENT:
2499                return "ACTION_PREVIOUS_HTML_ELEMENT";
2500            case ACTION_SCROLL_FORWARD:
2501                return "ACTION_SCROLL_FORWARD";
2502            case ACTION_SCROLL_BACKWARD:
2503                return "ACTION_SCROLL_BACKWARD";
2504            case ACTION_CUT:
2505                return "ACTION_CUT";
2506            case ACTION_COPY:
2507                return "ACTION_COPY";
2508            case ACTION_PASTE:
2509                return "ACTION_PASTE";
2510            case ACTION_SET_SELECTION:
2511                return "ACTION_SET_SELECTION";
2512            default:
2513                return"ACTION_UNKNOWN";
2514        }
2515    }
2516}
2517