AccessibilityNodeInfoCompat.java revision 9648c538bac4f04145c118cc41168d1d7a536312
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.view.View;
22
23import java.util.ArrayList;
24import java.util.List;
25
26/**
27 * Helper for accessing AccessibilityNodeInfo from newer platform versions.
28 */
29public class AccessibilityNodeInfoCompat {
30
31    static interface AccessibilityNodeInfoImpl {
32        public Object obtain();
33        public Object obtain(View source);
34        public Object obtain(Object info);
35        public void setSource(Object info, View source);
36        public int getWindowId(Object info);
37        public int getChildCount(Object info);
38        public Object getChild(Object info, int index);
39        public void addChild(Object info, View child);
40        public int getActions(Object info);
41        public void addAction(Object info, int action);
42        public boolean performAction(Object info, int action);
43        public List<Object> findAccessibilityNodeInfosByText(Object info, String text);
44        public Object getParent(Object info);
45        public void setParent(Object info, View parent);
46        public void getBoundsInParent(Object info, Rect outBounds);
47        public void setBoundsInParent(Object info, Rect bounds);
48        public void getBoundsInScreen(Object info, Rect outBounds);
49        public void setBoundsInScreen(Object info, Rect bounds);
50        public boolean isCheckable(Object info);
51        public void setCheckable(Object info, boolean checkable);
52        public boolean isChecked(Object info);
53        public void setChecked(Object info, boolean checked);
54        public boolean isFocusable(Object info);
55        public void setFocusable(Object info, boolean focusable);
56        public boolean isFocused(Object info);
57        public void setFocused(Object info, boolean focused);
58        public boolean isSelected(Object info);
59        public void setSelected(Object info, boolean selected);
60        public boolean isClickable(Object info);
61        public void setClickable(Object info, boolean clickable);
62        public boolean isLongClickable(Object info);
63        public void setLongClickable(Object info, boolean longClickable);
64        public boolean isEnabled(Object info);
65        public void setEnabled(Object info, boolean enabled);
66        public boolean isPassword(Object info);
67        public void setPassword(Object info, boolean password);
68        public boolean isScrollable(Object info);
69        public void setScrollable(Object info, boolean scrollable);
70        public CharSequence getPackageName(Object info);
71        public void setPackageName(Object info, CharSequence packageName);
72        public CharSequence getClassName(Object info);
73        public void setClassName(Object info, CharSequence className);
74        public CharSequence getText(Object info);
75        public void setText(Object info, CharSequence text);
76        public CharSequence getContentDescription(Object info);
77        public void setContentDescription(Object info, CharSequence contentDescription);
78        public void recycle(Object info);
79    }
80
81    static class AccessibilityNodeInfoStubImpl implements AccessibilityNodeInfoImpl {
82        public Object obtain() {
83            return null;
84        }
85
86        public Object obtain(View source) {
87            return null;
88        }
89
90        public Object obtain(Object info) {
91            return null;
92        }
93
94        public void addAction(Object info, int action) {
95
96        }
97
98        public void addChild(Object info, View child) {
99
100        }
101
102        public List<Object> findAccessibilityNodeInfosByText(Object info, String text) {
103            return null;
104        }
105
106        public int getActions(Object info) {
107            return 0;
108        }
109
110        public void getBoundsInParent(Object info, Rect outBounds) {
111
112        }
113
114        public void getBoundsInScreen(Object info, Rect outBounds) {
115
116        }
117
118        public Object getChild(Object info, int index) {
119            return null;
120        }
121
122        public int getChildCount(Object info) {
123            return 0;
124        }
125
126        public CharSequence getClassName(Object info) {
127            return null;
128        }
129
130        public CharSequence getContentDescription(Object info) {
131            return null;
132        }
133
134        public CharSequence getPackageName(Object info) {
135            return null;
136        }
137
138        public AccessibilityNodeInfoCompat getParent(Object info) {
139            return null;
140        }
141
142        public CharSequence getText(Object info) {
143            return null;
144        }
145
146        public int getWindowId(Object info) {
147            return 0;
148        }
149
150        public boolean isCheckable(Object info) {
151            return false;
152        }
153
154        public boolean isChecked(Object info) {
155            return false;
156        }
157
158        public boolean isClickable(Object info) {
159            return false;
160        }
161
162        public boolean isEnabled(Object info) {
163            return false;
164        }
165
166        public boolean isFocusable(Object info) {
167            return false;
168        }
169
170        public boolean isFocused(Object info) {
171            return false;
172        }
173
174        public boolean isLongClickable(Object info) {
175            return false;
176        }
177
178        public boolean isPassword(Object info) {
179            return false;
180        }
181
182        public boolean isScrollable(Object info) {
183            return false;
184        }
185
186        public boolean isSelected(Object info) {
187            return false;
188        }
189
190        public boolean performAction(Object info, int action) {
191            return false;
192        }
193
194        public void setBoundsInParent(Object info, Rect bounds) {
195
196        }
197
198        public void setBoundsInScreen(Object info, Rect bounds) {
199
200        }
201
202        public void setCheckable(Object info, boolean checkable) {
203
204        }
205
206        public void setChecked(Object info, boolean checked) {
207
208        }
209
210        public void setClassName(Object info, CharSequence className) {
211
212        }
213
214        public void setClickable(Object info, boolean clickable) {
215
216        }
217
218        public void setContentDescription(Object info, CharSequence contentDescription) {
219
220        }
221
222        public void setEnabled(Object info, boolean enabled) {
223
224        }
225
226        public void setFocusable(Object info, boolean focusable) {
227
228        }
229
230        public void setFocused(Object info, boolean focused) {
231
232        }
233
234        public void setLongClickable(Object info, boolean longClickable) {
235
236        }
237
238        public void setPackageName(Object info, CharSequence packageName) {
239
240        }
241
242        public void setParent(Object info, View parent) {
243
244        }
245
246        public void setPassword(Object info, boolean password) {
247
248        }
249
250        public void setScrollable(Object info, boolean scrollable) {
251
252        }
253
254        public void setSelected(Object info, boolean selected) {
255
256        }
257
258        public void setSource(Object info, View source) {
259
260        }
261
262        public void setText(Object info, CharSequence text) {
263
264        }
265
266        public void recycle(Object info) {
267
268        }
269    }
270
271    static class AccessibilityNodeInfoIcsImpl extends AccessibilityNodeInfoStubImpl {
272        @Override
273        public Object obtain() {
274            return AccessibilityNodeInfoCompatIcs.obtain();
275        }
276
277        @Override
278        public Object obtain(View source) {
279            return AccessibilityNodeInfoCompatIcs.obtain(source);
280        }
281
282        @Override
283        public Object obtain(Object info) {
284            return AccessibilityNodeInfoCompatIcs.obtain(info);
285        }
286
287        @Override
288        public void addAction(Object info, int action) {
289            AccessibilityNodeInfoCompatIcs.addAction(info, action);
290        }
291
292        @Override
293        public void addChild(Object info, View child) {
294            AccessibilityNodeInfoCompatIcs.addChild(info, child);
295        }
296
297        @Override
298        public List<Object> findAccessibilityNodeInfosByText(Object info, String text) {
299            return AccessibilityNodeInfoCompatIcs.findAccessibilityNodeInfosByText(info, text);
300        }
301
302        @Override
303        public int getActions(Object info) {
304            return AccessibilityNodeInfoCompatIcs.getActions(info);
305        }
306
307        @Override
308        public void getBoundsInParent(Object info, Rect outBounds) {
309            AccessibilityNodeInfoCompatIcs.getBoundsInParent(info, outBounds);
310        }
311
312        @Override
313        public void getBoundsInScreen(Object info, Rect outBounds) {
314            AccessibilityNodeInfoCompatIcs.getBoundsInScreen(info, outBounds);
315        }
316
317        @Override
318        public AccessibilityNodeInfoCompat getChild(Object info, int index) {
319            return new AccessibilityNodeInfoCompat(IMPL.getChild(info, index));
320        }
321
322        @Override
323        public int getChildCount(Object info) {
324            return AccessibilityNodeInfoCompatIcs.getChildCount(info);
325        }
326
327        @Override
328        public CharSequence getClassName(Object info) {
329            return AccessibilityNodeInfoCompatIcs.getClassName(info);
330        }
331
332        @Override
333        public CharSequence getContentDescription(Object info) {
334            return AccessibilityNodeInfoCompatIcs.getContentDescription(info);
335        }
336
337        @Override
338        public CharSequence getPackageName(Object info) {
339            return AccessibilityNodeInfoCompatIcs.getPackageName(info);
340        }
341
342        @Override
343        public AccessibilityNodeInfoCompat getParent(Object info) {
344            return new AccessibilityNodeInfoCompat(IMPL.getParent(info));
345        }
346
347        @Override
348        public CharSequence getText(Object info) {
349            return AccessibilityNodeInfoCompatIcs.getText(info);
350        }
351
352        @Override
353        public int getWindowId(Object info) {
354            return AccessibilityNodeInfoCompatIcs.getWindowId(info);
355        }
356
357        @Override
358        public boolean isCheckable(Object info) {
359            return AccessibilityNodeInfoCompatIcs.isCheckable(info);
360        }
361
362        @Override
363        public boolean isChecked(Object info) {
364            return AccessibilityNodeInfoCompatIcs.isChecked(info);
365        }
366
367        @Override
368        public boolean isClickable(Object info) {
369            return AccessibilityNodeInfoCompatIcs.isClickable(info);
370        }
371
372        @Override
373        public boolean isEnabled(Object info) {
374            return AccessibilityNodeInfoCompatIcs.isEnabled(info);
375        }
376
377        @Override
378        public boolean isFocusable(Object info) {
379            return AccessibilityNodeInfoCompatIcs.isFocusable(info);
380        }
381
382        @Override
383        public boolean isFocused(Object info) {
384            return AccessibilityNodeInfoCompatIcs.isFocused(info);
385        }
386
387        @Override
388        public boolean isLongClickable(Object info) {
389            return AccessibilityNodeInfoCompatIcs.isLongClickable(info);
390        }
391
392        @Override
393        public boolean isPassword(Object info) {
394            return AccessibilityNodeInfoCompatIcs.isPassword(info);
395        }
396
397        @Override
398        public boolean isScrollable(Object info) {
399            return AccessibilityNodeInfoCompatIcs.isScrollable(info);
400        }
401
402        @Override
403        public boolean isSelected(Object info) {
404            return AccessibilityNodeInfoCompatIcs.isSelected(info);
405        }
406
407        @Override
408        public boolean performAction(Object info, int action) {
409            return AccessibilityNodeInfoCompatIcs.performAction(info, action);
410        }
411
412        @Override
413        public void setBoundsInParent(Object info, Rect bounds) {
414            AccessibilityNodeInfoCompatIcs.setBoundsInParent(info, bounds);
415        }
416
417        @Override
418        public void setBoundsInScreen(Object info, Rect bounds) {
419            AccessibilityNodeInfoCompatIcs.setBoundsInScreen(info, bounds);
420        }
421
422        @Override
423        public void setCheckable(Object info, boolean checkable) {
424            AccessibilityNodeInfoCompatIcs.setCheckable(info, checkable);
425        }
426
427        @Override
428        public void setChecked(Object info, boolean checked) {
429            AccessibilityNodeInfoCompatIcs.setChecked(info, checked);
430        }
431
432        @Override
433        public void setClassName(Object info, CharSequence className) {
434            AccessibilityNodeInfoCompatIcs.setClassName(info, className);
435        }
436
437        @Override
438        public void setClickable(Object info, boolean clickable) {
439            AccessibilityNodeInfoCompatIcs.setClickable(info, clickable);
440        }
441
442        @Override
443        public void setContentDescription(Object info, CharSequence contentDescription) {
444            AccessibilityNodeInfoCompatIcs.setContentDescription(info, contentDescription);
445        }
446
447        @Override
448        public void setEnabled(Object info, boolean enabled) {
449            AccessibilityNodeInfoCompatIcs.setEnabled(info, enabled);
450        }
451
452        @Override
453        public void setFocusable(Object info, boolean focusable) {
454            AccessibilityNodeInfoCompatIcs.setFocusable(info, focusable);
455        }
456
457        @Override
458        public void setFocused(Object info, boolean focused) {
459            AccessibilityNodeInfoCompatIcs.setFocused(info, focused);
460        }
461
462        @Override
463        public void setLongClickable(Object info, boolean longClickable) {
464            AccessibilityNodeInfoCompatIcs.setLongClickable(info, longClickable);
465        }
466
467        @Override
468        public void setPackageName(Object info, CharSequence packageName) {
469            AccessibilityNodeInfoCompatIcs.setPackageName(info, packageName);
470        }
471
472        @Override
473        public void setParent(Object info, View parent) {
474            AccessibilityNodeInfoCompatIcs.setParent(info, parent);
475        }
476
477        @Override
478        public void setPassword(Object info, boolean password) {
479            AccessibilityNodeInfoCompatIcs.setPassword(info, password);
480        }
481
482        @Override
483        public void setScrollable(Object info, boolean scrollable) {
484            AccessibilityNodeInfoCompatIcs.setScrollable(info, scrollable);
485        }
486
487        @Override
488        public void setSelected(Object info, boolean selected) {
489            AccessibilityNodeInfoCompatIcs.setSelected(info, selected);
490        }
491
492        @Override
493        public void setSource(Object info, View source) {
494            AccessibilityNodeInfoCompatIcs.setSource(info, source);
495        }
496
497        @Override
498        public void setText(Object info, CharSequence text) {
499            AccessibilityNodeInfoCompatIcs.setText(info, text);
500        }
501
502        @Override
503        public void recycle(Object info) {
504            AccessibilityNodeInfoCompatIcs.recycle(info);
505        }
506    }
507
508    static {
509        if (Build.VERSION.SDK_INT >= 14) { // ICS
510            IMPL = new AccessibilityNodeInfoIcsImpl();
511        } else {
512            IMPL = new AccessibilityNodeInfoStubImpl();
513        }
514    }
515
516    private static final AccessibilityNodeInfoImpl IMPL;
517
518    private final Object mInfo;
519
520    // Actions.
521
522    /**
523     * Action that focuses the node.
524     */
525    public static final int ACTION_FOCUS = 0x00000001;
526
527    /**
528     * Action that unfocuses the node.
529     */
530    public static final int ACTION_CLEAR_FOCUS = 0x00000002;
531
532    /**
533     * Action that selects the node.
534     */
535    public static final int ACTION_SELECT = 0x00000004;
536
537    /**
538     * Action that unselects the node.
539     */
540    public static final int ACTION_CLEAR_SELECTION = 0x00000008;
541
542    /*
543     * Hide constructor from clients.
544     */
545    public AccessibilityNodeInfoCompat(Object info) {
546        mInfo = info;
547    }
548
549    /**
550     * @return The wrapped actual implementation.
551     *
552     * @hide
553     */
554    public Object getImpl() {
555        return mInfo;
556    }
557
558    /**
559     * Returns a cached instance if such is available otherwise a new one and
560     * sets the source.
561     *
562     * @return An instance.
563     * @see #setSource(View)
564     */
565    public static AccessibilityNodeInfoCompat obtain(View source) {
566        return new AccessibilityNodeInfoCompat(IMPL.obtain(source));
567    }
568
569    /**
570     * Returns a cached instance if such is available otherwise a new one.
571     *
572     * @return An instance.
573     */
574    public static AccessibilityNodeInfoCompat obtain() {
575        return new AccessibilityNodeInfoCompat(IMPL.obtain());
576    }
577
578    /**
579     * Returns a cached instance if such is available or a new one is create.
580     * The returned instance is initialized from the given <code>info</code>.
581     *
582     * @param info The other info.
583     * @return An instance.
584     */
585    public static AccessibilityNodeInfoCompat obtain(AccessibilityNodeInfoCompat info) {
586        return new AccessibilityNodeInfoCompat(IMPL.obtain(info.mInfo));
587    }
588
589    /**
590     * Sets the source.
591     *
592     * @param source The info source.
593     */
594    public void setSource(View source) {
595        IMPL.setSource(mInfo, source);
596    }
597
598    /**
599     * Gets the id of the window from which the info comes from.
600     *
601     * @return The window id.
602     */
603    public int getWindowId() {
604        return IMPL.getWindowId(mInfo);
605    }
606
607    /**
608     * Gets the number of children.
609     *
610     * @return The child count.
611     */
612    public int getChildCount() {
613        return IMPL.getChildCount(mInfo);
614    }
615
616    /**
617     * Get the child at given index.
618     * <p>
619     * <strong>Note:</strong> It is a client responsibility to recycle the
620     * received info by calling {@link AccessibilityNodeInfoCompat#recycle()} to
621     * avoid creating of multiple instances.
622     * </p>
623     *
624     * @param index The child index.
625     * @return The child node.
626     * @throws IllegalStateException If called outside of an
627     *             AccessibilityService.
628     */
629    public AccessibilityNodeInfoCompat getChild(int index) {
630        return new AccessibilityNodeInfoCompat(IMPL.getChild(mInfo, index));
631    }
632
633    /**
634     * Adds a child.
635     * <p>
636     * <strong>Note:</strong> Cannot be called from an
637     * {@link android.accessibilityservice.AccessibilityService}. This class is
638     * made immutable before being delivered to an AccessibilityService.
639     * </p>
640     *
641     * @param child The child.
642     * @throws IllegalStateException If called from an AccessibilityService.
643     */
644    public void addChild(View child) {
645        IMPL.addChild(mInfo, child);
646    }
647
648    /**
649     * Gets the actions that can be performed on the node.
650     *
651     * @return The bit mask of with actions.
652     * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_FOCUS
653     * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_CLEAR_FOCUS
654     * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_SELECT
655     * @see android.view.accessibility.AccessibilityNodeInfo#ACTION_CLEAR_SELECTION
656     */
657    public int getActions() {
658        return IMPL.getActions(mInfo);
659    }
660
661    /**
662     * Adds an action that can be performed on the node.
663     * <p>
664     * <strong>Note:</strong> Cannot be called from an
665     * {@link android.accessibilityservice.AccessibilityService}. This class is
666     * made immutable before being delivered to an AccessibilityService.
667     * </p>
668     *
669     * @param action The action.
670     * @throws IllegalStateException If called from an AccessibilityService.
671     */
672    public void addAction(int action) {
673        IMPL.addAction(mInfo, action);
674    }
675
676    /**
677     * Performs an action on the node.
678     * <p>
679     * <strong>Note:</strong> An action can be performed only if the request is
680     * made from an {@link android.accessibilityservice.AccessibilityService}.
681     * </p>
682     *
683     * @param action The action to perform.
684     * @return True if the action was performed.
685     * @throws IllegalStateException If called outside of an
686     *             AccessibilityService.
687     */
688    public boolean performAction(int action) {
689        return IMPL.performAction(mInfo, action);
690    }
691
692    /**
693     * Finds {@link android.view.accessibility.AccessibilityNodeInfo}s by text. The match
694     * is case insensitive containment. The search is relative to this info i.e. this
695     * info is the root of the traversed tree.
696     * <p>
697     * <strong>Note:</strong> It is a client responsibility to recycle the
698     * received info by calling {@link android.view.accessibility.AccessibilityNodeInfo#recycle()}
699     * to avoid creating of multiple instances.
700     * </p>
701     *
702     * @param text The searched text.
703     * @return A list of node info.
704     */
705    public List<AccessibilityNodeInfoCompat> findAccessibilityNodeInfosByText(String text) {
706        List<AccessibilityNodeInfoCompat> result = new ArrayList<AccessibilityNodeInfoCompat>();
707        List<Object> infos = IMPL.findAccessibilityNodeInfosByText(mInfo, text);
708        final int infoCount = infos.size();
709        for (int i = 0; i < infoCount; i++) {
710            Object info = infos.get(i);
711            result.add(new AccessibilityNodeInfoCompat(info));
712        }
713        return result;
714    }
715
716    /**
717     * Gets the parent.
718     * <p>
719     * <strong>Note:</strong> It is a client responsibility to recycle the
720     * received info by calling {@link android.view.accessibility.AccessibilityNodeInfo#recycle()}
721     * to avoid creating of multiple instances.
722     * </p>
723     *
724     * @return The parent.
725     */
726    public AccessibilityNodeInfoCompat getParent() {
727        return new AccessibilityNodeInfoCompat(IMPL.getParent(mInfo));
728    }
729
730    /**
731     * Sets the parent.
732     * <p>
733     * <strong>Note:</strong> Cannot be called from an
734     * {@link android.accessibilityservice.AccessibilityService}. This class is
735     * made immutable before being delivered to an AccessibilityService.
736     * </p>
737     *
738     * @param parent The parent.
739     * @throws IllegalStateException If called from an AccessibilityService.
740     */
741    public void setParent(View parent) {
742        IMPL.setParent(mInfo, parent);
743    }
744
745    /**
746     * Gets the node bounds in parent coordinates.
747     *
748     * @param outBounds The output node bounds.
749     */
750    public void getBoundsInParent(Rect outBounds) {
751        IMPL.getBoundsInParent(mInfo, outBounds);
752    }
753
754    /**
755     * Sets the node bounds in parent coordinates.
756     * <p>
757     * <strong>Note:</strong> Cannot be called from an
758     * {@link android.accessibilityservice.AccessibilityService}. This class is
759     * made immutable before being delivered to an AccessibilityService.
760     * </p>
761     *
762     * @param bounds The node bounds.
763     *@throws IllegalStateException If called from an AccessibilityService.
764     */
765    public void setBoundsInParent(Rect bounds) {
766        IMPL.setBoundsInParent(mInfo, bounds);
767    }
768
769    /**
770     * Gets the node bounds in screen coordinates.
771     *
772     * @param outBounds The output node bounds.
773     */
774    public void getBoundsInScreen(Rect outBounds) {
775        IMPL.getBoundsInScreen(mInfo, outBounds);
776    }
777
778    /**
779     * Sets the node bounds in screen coordinates.
780     * <p>
781     * <strong>Note:</strong> Cannot be called from an
782     * {@link android.accessibilityservice.AccessibilityService}. This class is
783     * made immutable before being delivered to an AccessibilityService.
784     * </p>
785     *
786     * @param bounds The node bounds.
787     * @throws IllegalStateException If called from an AccessibilityService.
788     */
789    public void setBoundsInScreen(Rect bounds) {
790        IMPL.setBoundsInParent(mInfo, bounds);
791    }
792
793    /**
794     * Gets whether this node is checkable.
795     *
796     * @return True if the node is checkable.
797     */
798    public boolean isCheckable() {
799        return IMPL.isCheckable(mInfo);
800    }
801
802    /**
803     * Sets whether this node is checkable.
804     * <p>
805     * <strong>Note:</strong> Cannot be called from an
806     * {@link android.accessibilityservice.AccessibilityService}. This class is
807     * made immutable before being delivered to an AccessibilityService.
808     * </p>
809     *
810     * @param checkable True if the node is checkable.
811     * @throws IllegalStateException If called from an AccessibilityService.
812     */
813    public void setCheckable(boolean checkable) {
814        IMPL.setCheckable(mInfo, checkable);
815    }
816
817    /**
818     * Gets whether this node is checked.
819     *
820     * @return True if the node is checked.
821     */
822    public boolean isChecked() {
823        return IMPL.isChecked(mInfo);
824    }
825
826    /**
827     * Sets whether this node is checked.
828     * <p>
829     * <strong>Note:</strong> Cannot be called from an
830     * {@link android.accessibilityservice.AccessibilityService}. This class is
831     * made immutable before being delivered to an AccessibilityService.
832     * </p>
833     *
834     * @param checked True if the node is checked.
835     * @throws IllegalStateException If called from an AccessibilityService.
836     */
837    public void setChecked(boolean checked) {
838        IMPL.setChecked(mInfo, checked);
839    }
840
841    /**
842     * Gets whether this node is focusable.
843     *
844     * @return True if the node is focusable.
845     */
846    public boolean isFocusable() {
847        return IMPL.isFocusable(mInfo);
848    }
849
850    /**
851     * Sets whether this node is focusable.
852     * <p>
853     * <strong>Note:</strong> Cannot be called from an
854     * {@link android.accessibilityservice.AccessibilityService}. This class is
855     * made immutable before being delivered to an AccessibilityService.
856     * </p>
857     *
858     * @param focusable True if the node is focusable.
859     * @throws IllegalStateException If called from an AccessibilityService.
860     */
861    public void setFocusable(boolean focusable) {
862        IMPL.setFocusable(mInfo, focusable);
863    }
864
865    /**
866     * Gets whether this node is focused.
867     *
868     * @return True if the node is focused.
869     */
870    public boolean isFocused() {
871        return IMPL.isFocused(mInfo);
872    }
873
874    /**
875     * Sets whether this node is focused.
876     * <p>
877     * <strong>Note:</strong> Cannot be called from an
878     * {@link android.accessibilityservice.AccessibilityService}. This class is
879     * made immutable before being delivered to an AccessibilityService.
880     * </p>
881     *
882     * @param focused True if the node is focused.
883     * @throws IllegalStateException If called from an AccessibilityService.
884     */
885    public void setFocused(boolean focused) {
886        IMPL.setFocused(mInfo, focused);
887    }
888
889    /**
890     * Gets whether this node is selected.
891     *
892     * @return True if the node is selected.
893     */
894    public boolean isSelected() {
895        return IMPL.isSelected(mInfo);
896    }
897
898    /**
899     * Sets whether this node is selected.
900     * <p>
901     * <strong>Note:</strong> Cannot be called from an
902     * {@link android.accessibilityservice.AccessibilityService}. This class is
903     * made immutable before being delivered to an AccessibilityService.
904     * </p>
905     *
906     * @param selected True if the node is selected.
907     * @throws IllegalStateException If called from an AccessibilityService.
908     */
909    public void setSelected(boolean selected) {
910        IMPL.setSelected(mInfo, selected);
911    }
912
913    /**
914     * Gets whether this node is clickable.
915     *
916     * @return True if the node is clickable.
917     */
918    public boolean isClickable() {
919        return IMPL.isClickable(mInfo);
920    }
921
922    /**
923     * Sets whether this node is clickable.
924     * <p>
925     * <strong>Note:</strong> Cannot be called from an
926     * {@link android.accessibilityservice.AccessibilityService}. This class is
927     * made immutable before being delivered to an AccessibilityService.
928     * </p>
929     *
930     * @param clickable True if the node is clickable.
931     * @throws IllegalStateException If called from an AccessibilityService.
932     */
933    public void setClickable(boolean clickable) {
934        IMPL.setClickable(mInfo, clickable);
935    }
936
937    /**
938     * Gets whether this node is long clickable.
939     *
940     * @return True if the node is long clickable.
941     */
942    public boolean isLongClickable() {
943        return IMPL.isLongClickable(mInfo);
944    }
945
946    /**
947     * Sets whether this node is long clickable.
948     * <p>
949     * <strong>Note:</strong> Cannot be called from an
950     * {@link android.accessibilityservice.AccessibilityService}. This class is
951     * made immutable before being delivered to an AccessibilityService.
952     * </p>
953     *
954     * @param longClickable True if the node is long clickable.
955     * @throws IllegalStateException If called from an AccessibilityService.
956     */
957    public void setLongClickable(boolean longClickable) {
958        IMPL.setLongClickable(mInfo, longClickable);
959    }
960
961    /**
962     * Gets whether this node is enabled.
963     *
964     * @return True if the node is enabled.
965     */
966    public boolean isEnabled() {
967        return IMPL.isEnabled(mInfo);
968    }
969
970    /**
971     * Sets whether this node is enabled.
972     * <p>
973     * <strong>Note:</strong> Cannot be called from an
974     * {@link android.accessibilityservice.AccessibilityService}. This class is
975     * made immutable before being delivered to an AccessibilityService.
976     * </p>
977     *
978     * @param enabled True if the node is enabled.
979     * @throws IllegalStateException If called from an AccessibilityService.
980     */
981    public void setEnabled(boolean enabled) {
982        IMPL.setEnabled(mInfo, enabled);
983    }
984
985    /**
986     * Gets whether this node is a password.
987     *
988     * @return True if the node is a password.
989     */
990    public boolean isPassword() {
991        return IMPL.isPassword(mInfo);
992    }
993
994    /**
995     * Sets whether this node is a password.
996     * <p>
997     * <strong>Note:</strong> Cannot be called from an
998     * {@link android.accessibilityservice.AccessibilityService}. This class is
999     * made immutable before being delivered to an AccessibilityService.
1000     * </p>
1001     *
1002     * @param password True if the node is a password.
1003     * @throws IllegalStateException If called from an AccessibilityService.
1004     */
1005    public void setPassword(boolean password) {
1006        IMPL.setPassword(mInfo, password);
1007    }
1008
1009    /**
1010     * Gets if the node is scrollable.
1011     *
1012     * @return True if the node is scrollable, false otherwise.
1013     */
1014    public boolean isScrollable() {
1015        return IMPL.isScrollable(mInfo);
1016    }
1017
1018    /**
1019     * Sets if the node is scrollable.
1020     * <p>
1021     * <strong>Note:</strong> Cannot be called from an
1022     * {@link android.accessibilityservice.AccessibilityService}. This class is
1023     * made immutable before being delivered to an AccessibilityService.
1024     * </p>
1025     *
1026     * @param scrollable True if the node is scrollable, false otherwise.
1027     * @throws IllegalStateException If called from an AccessibilityService.
1028     */
1029    public void setScrollable(boolean scrollable) {
1030        IMPL.setScrollable(mInfo, scrollable);
1031    }
1032
1033    /**
1034     * Gets the package this node comes from.
1035     *
1036     * @return The package name.
1037     */
1038    public CharSequence getPackageName() {
1039        return IMPL.getPackageName(mInfo);
1040    }
1041
1042    /**
1043     * Sets the package this node comes from.
1044     * <p>
1045     * <strong>Note:</strong> Cannot be called from an
1046     * {@link android.accessibilityservice.AccessibilityService}. This class is
1047     * made immutable before being delivered to an AccessibilityService.
1048     * </p>
1049     *
1050     * @param packageName The package name.
1051     * @throws IllegalStateException If called from an AccessibilityService.
1052     */
1053    public void setPackageName(CharSequence packageName) {
1054        IMPL.setPackageName(mInfo, packageName);
1055    }
1056
1057    /**
1058     * Gets the class this node comes from.
1059     *
1060     * @return The class name.
1061     */
1062    public CharSequence getClassName() {
1063        return IMPL.getClassName(mInfo);
1064    }
1065
1066    /**
1067     * Sets the class this node comes from.
1068     * <p>
1069     * <strong>Note:</strong> Cannot be called from an
1070     * {@link android.accessibilityservice.AccessibilityService}. This class is
1071     * made immutable before being delivered to an AccessibilityService.
1072     * </p>
1073     *
1074     * @param className The class name.
1075     * @throws IllegalStateException If called from an AccessibilityService.
1076     */
1077    public void setClassName(CharSequence className) {
1078        IMPL.setClassName(mInfo, className);
1079    }
1080
1081    /**
1082     * Gets the text of this node.
1083     *
1084     * @return The text.
1085     */
1086    public CharSequence getText() {
1087        return IMPL.getText(mInfo);
1088    }
1089
1090    /**
1091     * Sets the text of this node.
1092     * <p>
1093     * <strong>Note:</strong> Cannot be called from an
1094     * {@link android.accessibilityservice.AccessibilityService}. This class is
1095     * made immutable before being delivered to an AccessibilityService.
1096     * </p>
1097     *
1098     * @param text The text.
1099     * @throws IllegalStateException If called from an AccessibilityService.
1100     */
1101    public void setText(CharSequence text) {
1102        IMPL.setText(mInfo, text);
1103    }
1104
1105    /**
1106     * Gets the content description of this node.
1107     *
1108     * @return The content description.
1109     */
1110    public CharSequence getContentDescription() {
1111        return IMPL.getContentDescription(mInfo);
1112    }
1113
1114    /**
1115     * Sets the content description of this node.
1116     * <p>
1117     * <strong>Note:</strong> Cannot be called from an
1118     * {@link android.accessibilityservice.AccessibilityService}. This class is
1119     * made immutable before being delivered to an AccessibilityService.
1120     * </p>
1121     *
1122     * @param contentDescription The content description.
1123     * @throws IllegalStateException If called from an AccessibilityService.
1124     */
1125    public void setContentDescription(CharSequence contentDescription) {
1126        IMPL.setContentDescription(mInfo, contentDescription);
1127    }
1128
1129    /**
1130     * Return an instance back to be reused.
1131     * <p>
1132     * <strong>Note:</strong> You must not touch the object after calling this function.
1133     *
1134     * @throws IllegalStateException If the info is already recycled.
1135     */
1136    public void recycle() {
1137        IMPL.recycle(mInfo);
1138    }
1139
1140    @Override
1141    public int hashCode() {
1142        return (mInfo == null) ? 0 : mInfo.hashCode();
1143    }
1144
1145    @Override
1146    public boolean equals(Object obj) {
1147        if (this == obj) {
1148            return true;
1149        }
1150        if (obj == null) {
1151            return false;
1152        }
1153        if (getClass() != obj.getClass()) {
1154            return false;
1155        }
1156        AccessibilityNodeInfoCompat other = (AccessibilityNodeInfoCompat) obj;
1157        if (mInfo == null) {
1158            if (other.mInfo != null) {
1159                return false;
1160            }
1161        } else if (!mInfo.equals(other.mInfo)) {
1162            return false;
1163        }
1164        return true;
1165    }
1166}
1167