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.os.Build;
20import android.os.Parcelable;
21import android.view.View;
22import android.view.accessibility.AccessibilityEvent;
23
24import java.util.Collections;
25import java.util.List;
26
27/**
28 * Helper for accessing {@link android.view.accessibility.AccessibilityRecord}
29 * introduced after API level 4 in a backwards compatible fashion.
30 */
31public class AccessibilityRecordCompat {
32
33    static interface AccessibilityRecordImpl {
34        public Object obtain();
35        public Object obtain(Object record);
36        public void setSource(Object record, View source);
37        public void setSource(Object record, View root, int virtualDescendantId);
38        public AccessibilityNodeInfoCompat getSource(Object record);
39        public int getWindowId(Object record);
40        public boolean isChecked(Object record);
41        public void setChecked(Object record, boolean isChecked);
42        public boolean isEnabled(Object record);
43        public void setEnabled(Object record, boolean isEnabled);
44        public boolean isPassword(Object record);
45        public void setPassword(Object record, boolean isPassword);
46        public boolean isFullScreen(Object record);
47        public void setFullScreen(Object record, boolean isFullScreen);
48        public boolean isScrollable(Object record);
49        public void setScrollable(Object record, boolean scrollable);
50        public int getItemCount(Object record);
51        public void setItemCount(Object record, int itemCount);
52        public int getCurrentItemIndex(Object record);
53        public void setCurrentItemIndex(Object record, int currentItemIndex);
54        public int getFromIndex(Object record);
55        public void setFromIndex(Object record, int fromIndex);
56        public int getToIndex(Object record);
57        public void setToIndex(Object record, int toIndex);
58        public int getScrollX(Object record);
59        public void setScrollX(Object record, int scrollX);
60        public int getScrollY(Object record);
61        public void setScrollY(Object record, int scrollY);
62        public int getMaxScrollX(Object record);
63        public void setMaxScrollX(Object record, int maxScrollX);
64        public int getMaxScrollY(Object record);
65        public void setMaxScrollY(Object record, int maxScrollY);
66        public int getAddedCount(Object record);
67        public void setAddedCount(Object record, int addedCount);
68        public int getRemovedCount(Object record);
69        public void setRemovedCount(Object record, int removedCount);
70        public CharSequence getClassName(Object record);
71        public void setClassName(Object record, CharSequence className);
72        public List<CharSequence> getText(Object record);
73        public CharSequence getBeforeText(Object record);
74        public void setBeforeText(Object record, CharSequence beforeText);
75        public CharSequence getContentDescription(Object record);
76        public void setContentDescription(Object record, CharSequence contentDescription);
77        public Parcelable getParcelableData(Object record);
78        public void setParcelableData(Object record, Parcelable parcelableData);
79        public void recycle(Object record);
80    }
81
82    static class AccessibilityRecordStubImpl implements AccessibilityRecordImpl {
83        public Object obtain() {
84            return null;
85        }
86
87        public Object obtain(Object record) {
88            return null;
89        }
90
91        public int getAddedCount(Object record) {
92            return 0;
93        }
94
95        public CharSequence getBeforeText(Object record) {
96            return null;
97        }
98
99        public CharSequence getClassName(Object record) {
100            return null;
101        }
102
103        public CharSequence getContentDescription(Object record) {
104            return null;
105        }
106
107        public int getCurrentItemIndex(Object record) {
108            return 0;
109        }
110
111        public int getFromIndex(Object record) {
112            return 0;
113        }
114
115        public int getItemCount(Object record) {
116            return 0;
117        }
118
119        public int getMaxScrollX(Object record) {
120            return 0;
121        }
122
123        public int getMaxScrollY(Object record) {
124            return 0;
125        }
126
127        public Parcelable getParcelableData(Object record) {
128            return null;
129        }
130
131        public int getRemovedCount(Object record) {
132            return 0;
133        }
134
135        public int getScrollX(Object record) {
136            return 0;
137        }
138
139        public int getScrollY(Object record) {
140            return 0;
141        }
142
143        public AccessibilityNodeInfoCompat getSource(Object record) {
144            return null;
145        }
146
147        public List<CharSequence> getText(Object record) {
148            return Collections.emptyList();
149        }
150
151        public int getToIndex(Object record) {
152            return 0;
153        }
154
155        public int getWindowId(Object record) {
156            return 0;
157        }
158
159        public boolean isChecked(Object record) {
160            return false;
161        }
162
163        public boolean isEnabled(Object record) {
164            return false;
165        }
166
167        public boolean isFullScreen(Object record) {
168            return false;
169        }
170
171        public boolean isPassword(Object record) {
172            return false;
173        }
174
175        public boolean isScrollable(Object record) {
176            return false;
177        }
178
179        public void recycle(Object record) {
180
181        }
182
183        public void setAddedCount(Object record, int addedCount) {
184
185        }
186
187        public void setBeforeText(Object record, CharSequence beforeText) {
188
189        }
190
191        public void setChecked(Object record, boolean isChecked) {
192
193        }
194
195        public void setClassName(Object record, CharSequence className) {
196
197        }
198
199        public void setContentDescription(Object record, CharSequence contentDescription) {
200
201        }
202
203        public void setCurrentItemIndex(Object record, int currentItemIndex) {
204
205        }
206
207        public void setEnabled(Object record, boolean isEnabled) {
208
209        }
210
211        public void setFromIndex(Object record, int fromIndex) {
212
213        }
214
215        public void setFullScreen(Object record, boolean isFullScreen) {
216
217        }
218
219        public void setItemCount(Object record, int itemCount) {
220
221        }
222
223        public void setMaxScrollX(Object record, int maxScrollX) {
224
225        }
226
227        public void setMaxScrollY(Object record, int maxScrollY) {
228
229        }
230
231        public void setParcelableData(Object record, Parcelable parcelableData) {
232
233        }
234
235        public void setPassword(Object record, boolean isPassword) {
236
237        }
238
239        public void setRemovedCount(Object record, int removedCount) {
240
241        }
242
243        public void setScrollX(Object record, int scrollX) {
244
245        }
246
247        public void setScrollY(Object record, int scrollY) {
248
249        }
250
251        public void setScrollable(Object record, boolean scrollable) {
252
253        }
254
255        public void setSource(Object record, View source) {
256
257        }
258
259        public void setSource(Object record, View root, int virtualDescendantId) {
260
261        }
262
263        public void setToIndex(Object record, int toIndex) {
264
265        }
266    }
267
268    static class AccessibilityRecordIcsImpl extends AccessibilityRecordStubImpl {
269        @Override
270        public Object obtain() {
271            return AccessibilityRecordCompatIcs.obtain();
272        }
273
274        @Override
275        public Object obtain(Object record) {
276            return AccessibilityRecordCompatIcs.obtain(record);
277        }
278
279        @Override
280        public int getAddedCount(Object record) {
281            return AccessibilityRecordCompatIcs.getAddedCount(record);
282        }
283
284        @Override
285        public CharSequence getBeforeText(Object record) {
286            return AccessibilityRecordCompatIcs.getBeforeText(record);
287        }
288
289        @Override
290        public CharSequence getClassName(Object record) {
291            return AccessibilityRecordCompatIcs.getClassName(record);
292        }
293
294        @Override
295        public CharSequence getContentDescription(Object record) {
296            return AccessibilityRecordCompatIcs.getContentDescription(record);
297        }
298
299        @Override
300        public int getCurrentItemIndex(Object record) {
301            return AccessibilityRecordCompatIcs.getCurrentItemIndex(record);
302        }
303
304        @Override
305        public int getFromIndex(Object record) {
306            return AccessibilityRecordCompatIcs.getFromIndex(record);
307        }
308
309        @Override
310        public int getItemCount(Object record) {
311            return AccessibilityRecordCompatIcs.getItemCount(record);
312        }
313
314        @Override
315        public Parcelable getParcelableData(Object record) {
316            return AccessibilityRecordCompatIcs.getParcelableData(record);
317        }
318
319        @Override
320        public int getRemovedCount(Object record) {
321            return AccessibilityRecordCompatIcs.getRemovedCount(record);
322        }
323
324        @Override
325        public int getScrollX(Object record) {
326            return AccessibilityRecordCompatIcs.getScrollX(record);
327        }
328
329        @Override
330        public int getScrollY(Object record) {
331            return AccessibilityRecordCompatIcs.getScrollY(record);
332        }
333
334        @Override
335        public AccessibilityNodeInfoCompat getSource(Object record) {
336            return AccessibilityNodeInfoCompat.wrapNonNullInstance(
337                    AccessibilityRecordCompatIcs.getSource(record));
338        }
339
340        @Override
341        public List<CharSequence> getText(Object record) {
342            return AccessibilityRecordCompatIcs.getText(record);
343        }
344
345        @Override
346        public int getToIndex(Object record) {
347            return AccessibilityRecordCompatIcs.getToIndex(record);
348        }
349
350        @Override
351        public int getWindowId(Object record) {
352            return AccessibilityRecordCompatIcs.getWindowId(record);
353        }
354
355        @Override
356        public boolean isChecked(Object record) {
357            return AccessibilityRecordCompatIcs.isChecked(record);
358        }
359
360        @Override
361        public boolean isEnabled(Object record) {
362            return AccessibilityRecordCompatIcs.isEnabled(record);
363        }
364
365        @Override
366        public boolean isFullScreen(Object record) {
367            return AccessibilityRecordCompatIcs.isFullScreen(record);
368        }
369
370        @Override
371        public boolean isPassword(Object record) {
372            return AccessibilityRecordCompatIcs.isPassword(record);
373        }
374
375        @Override
376        public boolean isScrollable(Object record) {
377            return AccessibilityRecordCompatIcs.isScrollable(record);
378        }
379
380        @Override
381        public void recycle(Object record) {
382            AccessibilityRecordCompatIcs.recycle(record);
383        }
384
385        @Override
386        public void setAddedCount(Object record, int addedCount) {
387            AccessibilityRecordCompatIcs.setAddedCount(record, addedCount);
388        }
389
390        @Override
391        public void setBeforeText(Object record, CharSequence beforeText) {
392            AccessibilityRecordCompatIcs.setBeforeText(record, beforeText);
393        }
394
395        @Override
396        public void setChecked(Object record, boolean isChecked) {
397            AccessibilityRecordCompatIcs.setChecked(record, isChecked);
398        }
399
400        @Override
401        public void setClassName(Object record, CharSequence className) {
402            AccessibilityRecordCompatIcs.setClassName(record, className);
403        }
404
405        @Override
406        public void setContentDescription(Object record, CharSequence contentDescription) {
407            AccessibilityRecordCompatIcs.setContentDescription(record, contentDescription);
408        }
409
410        @Override
411        public void setCurrentItemIndex(Object record, int currentItemIndex) {
412            AccessibilityRecordCompatIcs.setCurrentItemIndex(record, currentItemIndex);
413        }
414
415        @Override
416        public void setEnabled(Object record, boolean isEnabled) {
417            AccessibilityRecordCompatIcs.setEnabled(record, isEnabled);
418        }
419
420        @Override
421        public void setFromIndex(Object record, int fromIndex) {
422            AccessibilityRecordCompatIcs.setFromIndex(record, fromIndex);
423        }
424
425        @Override
426        public void setFullScreen(Object record, boolean isFullScreen) {
427            AccessibilityRecordCompatIcs.setFullScreen(record, isFullScreen);
428        }
429
430        @Override
431        public void setItemCount(Object record, int itemCount) {
432            AccessibilityRecordCompatIcs.setItemCount(record, itemCount);
433        }
434
435        @Override
436        public void setParcelableData(Object record, Parcelable parcelableData) {
437            AccessibilityRecordCompatIcs.setParcelableData(record, parcelableData);
438        }
439
440        @Override
441        public void setPassword(Object record, boolean isPassword) {
442            AccessibilityRecordCompatIcs.setPassword(record, isPassword);
443        }
444
445        @Override
446        public void setRemovedCount(Object record, int removedCount) {
447            AccessibilityRecordCompatIcs.setRemovedCount(record, removedCount);
448        }
449
450        @Override
451        public void setScrollX(Object record, int scrollX) {
452            AccessibilityRecordCompatIcs.setScrollX(record, scrollX);
453        }
454
455        @Override
456        public void setScrollY(Object record, int scrollY) {
457            AccessibilityRecordCompatIcs.setScrollY(record, scrollY);
458        }
459
460        @Override
461        public void setScrollable(Object record, boolean scrollable) {
462            AccessibilityRecordCompatIcs.setScrollable(record, scrollable);
463        }
464
465        @Override
466        public void setSource(Object record, View source) {
467            AccessibilityRecordCompatIcs.setSource(record, source);
468        }
469
470        @Override
471        public void setToIndex(Object record, int toIndex) {
472            AccessibilityRecordCompatIcs.setToIndex(record, toIndex);
473        }
474    }
475
476    static class AccessibilityRecordIcsMr1Impl extends AccessibilityRecordIcsImpl {
477        @Override
478        public int getMaxScrollX(Object record) {
479            return AccessibilityRecordCompatIcsMr1.getMaxScrollX(record);
480        }
481
482        @Override
483        public int getMaxScrollY(Object record) {
484            return AccessibilityRecordCompatIcsMr1.getMaxScrollY(record);
485        }
486
487        @Override
488        public void setMaxScrollX(Object record, int maxScrollX) {
489            AccessibilityRecordCompatIcsMr1.setMaxScrollX(record, maxScrollX);
490        }
491
492        @Override
493        public void setMaxScrollY(Object record, int maxScrollY) {
494            AccessibilityRecordCompatIcsMr1.setMaxScrollY(record, maxScrollY);
495        }
496    }
497
498    static class AccessibilityRecordJellyBeanImpl extends AccessibilityRecordIcsMr1Impl {
499        @Override
500        public void setSource(Object record, View root, int virtualDescendantId) {
501            AccessibilityRecordCompatJellyBean.setSource(record, root, virtualDescendantId);
502        }
503    }
504
505    static {
506        if (Build.VERSION.SDK_INT >= 16) { // JellyBean
507            IMPL = new AccessibilityRecordJellyBeanImpl();
508        } else if (Build.VERSION.SDK_INT >= 15) {  // ICS MR1
509            IMPL = new AccessibilityRecordIcsMr1Impl();
510        } else if (Build.VERSION.SDK_INT >= 14) { // ICS
511            IMPL = new AccessibilityRecordIcsImpl();
512        } else {
513            IMPL = new AccessibilityRecordStubImpl();
514        }
515    }
516
517    private static final AccessibilityRecordImpl IMPL;
518
519    private final Object mRecord;
520
521    /**
522     * @deprecated This is not type safe. If you want to modify an
523     * {@link AccessibilityEvent}'s properties defined in
524     * {@link android.view.accessibility.AccessibilityRecord} use
525     * {@link AccessibilityEventCompat#asRecord(AccessibilityEvent)}. This method will be removed
526     * in a subsequent release of the support library.
527     */
528    public AccessibilityRecordCompat(Object record) {
529        mRecord = record;
530    }
531
532    /**
533     * @return The wrapped implementation.
534     *
535     * @deprecated This method will be removed in a subsequent release of
536     * the support library.
537     */
538    public Object getImpl() {
539        return mRecord;
540    }
541
542    /**
543     * Returns a cached instance if such is available or a new one is
544     * instantiated. The instance is initialized with data from the
545     * given record.
546     *
547     * @return An instance.
548     */
549    public static AccessibilityRecordCompat obtain(AccessibilityRecordCompat record) {
550       return new AccessibilityRecordCompat(IMPL.obtain(record.mRecord));
551    }
552
553    /**
554     * Returns a cached instance if such is available or a new one is
555     * instantiated.
556     *
557     * @return An instance.
558     */
559    public static AccessibilityRecordCompat obtain() {
560        return new AccessibilityRecordCompat(IMPL.obtain());
561    }
562
563    /**
564     * Sets the event source.
565     *
566     * @param source The source.
567     *
568     * @throws IllegalStateException If called from an AccessibilityService.
569     */
570    public void setSource(View source) {
571        IMPL.setSource(mRecord, source);
572    }
573
574    /**
575     * Sets the source to be a virtual descendant of the given <code>root</code>.
576     * If <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root
577     * is set as the source.
578     * <p>
579     * A virtual descendant is an imaginary View that is reported as a part of the view
580     * hierarchy for accessibility purposes. This enables custom views that draw complex
581     * content to report them selves as a tree of virtual views, thus conveying their
582     * logical structure.
583     * </p>
584     *
585     * @param root The root of the virtual subtree.
586     * @param virtualDescendantId The id of the virtual descendant.
587     */
588    public void setSource(View root, int virtualDescendantId) {
589        IMPL.setSource(mRecord, root, virtualDescendantId);
590    }
591
592    /**
593     * Gets the {@link android.view.accessibility.AccessibilityNodeInfo} of
594     * the event source.
595     * <p>
596     * <strong>Note:</strong> It is a client responsibility to recycle the
597     * received info by calling
598     * {@link android.view.accessibility.AccessibilityNodeInfo#recycle()
599     * AccessibilityNodeInfo#recycle()} to avoid creating of multiple instances.
600     *</p>
601     *
602     * @return The info of the source.
603     */
604    public AccessibilityNodeInfoCompat getSource() {
605        return IMPL.getSource(mRecord);
606    }
607
608    /**
609     * Gets the id of the window from which the event comes from.
610     *
611     * @return The window id.
612     */
613    public int getWindowId() {
614        return IMPL.getWindowId(mRecord);
615    }
616
617    /**
618     * Gets if the source is checked.
619     *
620     * @return True if the view is checked, false otherwise.
621     */
622    public boolean isChecked() {
623        return IMPL.isChecked(mRecord);
624    }
625
626    /**
627     * Sets if the source is checked.
628     *
629     * @param isChecked True if the view is checked, false otherwise.
630     *
631     * @throws IllegalStateException If called from an AccessibilityService.
632     */
633    public void setChecked(boolean isChecked) {
634        IMPL.setChecked(mRecord, isChecked);
635    }
636
637    /**
638     * Gets if the source is enabled.
639     *
640     * @return True if the view is enabled, false otherwise.
641     */
642    public boolean isEnabled() {
643        return IMPL.isEnabled(mRecord);
644    }
645
646    /**
647     * Sets if the source is enabled.
648     *
649     * @param isEnabled True if the view is enabled, false otherwise.
650     *
651     * @throws IllegalStateException If called from an AccessibilityService.
652     */
653    public void setEnabled(boolean isEnabled) {
654        IMPL.setEnabled(mRecord, isEnabled);
655    }
656
657    /**
658     * Gets if the source is a password field.
659     *
660     * @return True if the view is a password field, false otherwise.
661     */
662    public boolean isPassword() {
663        return IMPL.isPassword(mRecord);
664    }
665
666    /**
667     * Sets if the source is a password field.
668     *
669     * @param isPassword True if the view is a password field, false otherwise.
670     *
671     * @throws IllegalStateException If called from an AccessibilityService.
672     */
673    public void setPassword(boolean isPassword) {
674        IMPL.setPassword(mRecord, isPassword);
675    }
676
677    /**
678     * Gets if the source is taking the entire screen.
679     *
680     * @return True if the source is full screen, false otherwise.
681     */
682    public boolean isFullScreen() {
683        return IMPL.isFullScreen(mRecord);
684    }
685
686    /**
687     * Sets if the source is taking the entire screen.
688     *
689     * @param isFullScreen True if the source is full screen, false otherwise.
690     *
691     * @throws IllegalStateException If called from an AccessibilityService.
692     */
693    public void setFullScreen(boolean isFullScreen) {
694        IMPL.setFullScreen(mRecord, isFullScreen);
695    }
696
697    /**
698     * Gets if the source is scrollable.
699     *
700     * @return True if the source is scrollable, false otherwise.
701     */
702    public boolean isScrollable() {
703        return IMPL.isScrollable(mRecord);
704    }
705
706    /**
707     * Sets if the source is scrollable.
708     *
709     * @param scrollable True if the source is scrollable, false otherwise.
710     *
711     * @throws IllegalStateException If called from an AccessibilityService.
712     */
713    public void setScrollable(boolean scrollable) {
714        IMPL.setScrollable(mRecord, scrollable);
715    }
716
717    /**
718     * Gets the number of items that can be visited.
719     *
720     * @return The number of items.
721     */
722    public int getItemCount() {
723        return IMPL.getItemCount(mRecord);
724    }
725
726    /**
727     * Sets the number of items that can be visited.
728     *
729     * @param itemCount The number of items.
730     *
731     * @throws IllegalStateException If called from an AccessibilityService.
732     */
733    public void setItemCount(int itemCount) {
734        IMPL.setItemCount(mRecord, itemCount);
735    }
736
737    /**
738     * Gets the index of the source in the list of items the can be visited.
739     *
740     * @return The current item index.
741     */
742    public int getCurrentItemIndex() {
743        return IMPL.getCurrentItemIndex(mRecord);
744    }
745
746    /**
747     * Sets the index of the source in the list of items that can be visited.
748     *
749     * @param currentItemIndex The current item index.
750     *
751     * @throws IllegalStateException If called from an AccessibilityService.
752     */
753    public void setCurrentItemIndex(int currentItemIndex) {
754        IMPL.setCurrentItemIndex(mRecord, currentItemIndex);
755    }
756
757    /**
758     * Gets the index of the first character of the changed sequence,
759     * or the beginning of a text selection or the index of the first
760     * visible item when scrolling.
761     *
762     * @return The index of the first character or selection
763     *        start or the first visible item.
764     */
765    public int getFromIndex() {
766        return IMPL.getFromIndex(mRecord);
767    }
768
769    /**
770     * Sets the index of the first character of the changed sequence
771     * or the beginning of a text selection or the index of the first
772     * visible item when scrolling.
773     *
774     * @param fromIndex The index of the first character or selection
775     *        start or the first visible item.
776     *
777     * @throws IllegalStateException If called from an AccessibilityService.
778     */
779    public void setFromIndex(int fromIndex) {
780        IMPL.setFromIndex(mRecord, fromIndex);
781    }
782
783    /**
784     * Gets the index of text selection end or the index of the last
785     * visible item when scrolling.
786     *
787     * @return The index of selection end or last item index.
788     */
789    public int getToIndex() {
790        return IMPL.getToIndex(mRecord);
791    }
792
793    /**
794     * Sets the index of text selection end or the index of the last
795     * visible item when scrolling.
796     *
797     * @param toIndex The index of selection end or last item index.
798     */
799    public void setToIndex(int toIndex) {
800        IMPL.setToIndex(mRecord, toIndex);
801    }
802
803    /**
804     * Gets the scroll offset of the source left edge in pixels.
805     *
806     * @return The scroll.
807     */
808    public int getScrollX() {
809        return IMPL.getScrollX(mRecord);
810    }
811
812    /**
813     * Sets the scroll offset of the source left edge in pixels.
814     *
815     * @param scrollX The scroll.
816     */
817    public void setScrollX(int scrollX) {
818        IMPL.setScrollX(mRecord, scrollX);
819    }
820
821    /**
822     * Gets the scroll offset of the source top edge in pixels.
823     *
824     * @return The scroll.
825     */
826    public int getScrollY() {
827        return IMPL.getScrollY(mRecord);
828    }
829
830    /**
831     * Sets the scroll offset of the source top edge in pixels.
832     *
833     * @param scrollY The scroll.
834     */
835    public void setScrollY(int scrollY) {
836        IMPL.setScrollY(mRecord, scrollY);
837    }
838
839    /**
840     * Gets the max scroll offset of the source left edge in pixels.
841     *
842     * @return The max scroll.
843     */
844    public int getMaxScrollX() {
845        return IMPL.getMaxScrollX(mRecord);
846    }
847    /**
848     * Sets the max scroll offset of the source left edge in pixels.
849     *
850     * @param maxScrollX The max scroll.
851     */
852    public void setMaxScrollX(int maxScrollX) {
853        IMPL.setMaxScrollX(mRecord, maxScrollX);
854    }
855
856    /**
857     * Gets the max scroll offset of the source top edge in pixels.
858     *
859     * @return The max scroll.
860     */
861    public int getMaxScrollY() {
862        return IMPL.getMaxScrollY(mRecord);
863    }
864
865    /**
866     * Sets the max scroll offset of the source top edge in pixels.
867     *
868     * @param maxScrollY The max scroll.
869     */
870    public void setMaxScrollY(int maxScrollY) {
871        IMPL.setMaxScrollY(mRecord, maxScrollY);
872    }
873
874    /**
875     * Gets the number of added characters.
876     *
877     * @return The number of added characters.
878     */
879    public int getAddedCount() {
880        return IMPL.getAddedCount(mRecord);
881    }
882
883    /**
884     * Sets the number of added characters.
885     *
886     * @param addedCount The number of added characters.
887     *
888     * @throws IllegalStateException If called from an AccessibilityService.
889     */
890    public void setAddedCount(int addedCount) {
891        IMPL.setAddedCount(mRecord, addedCount);
892    }
893
894    /**
895     * Gets the number of removed characters.
896     *
897     * @return The number of removed characters.
898     */
899    public int getRemovedCount() {
900        return IMPL.getRemovedCount(mRecord);
901    }
902
903    /**
904     * Sets the number of removed characters.
905     *
906     * @param removedCount The number of removed characters.
907     *
908     * @throws IllegalStateException If called from an AccessibilityService.
909     */
910    public void setRemovedCount(int removedCount) {
911        IMPL.setRemovedCount(mRecord, removedCount);
912    }
913
914    /**
915     * Gets the class name of the source.
916     *
917     * @return The class name.
918     */
919    public CharSequence getClassName() {
920        return IMPL.getClassName(mRecord);
921    }
922
923    /**
924     * Sets the class name of the source.
925     *
926     * @param className The lass name.
927     *
928     * @throws IllegalStateException If called from an AccessibilityService.
929     */
930    public void setClassName(CharSequence className) {
931        IMPL.setClassName(mRecord, className);
932    }
933
934    /**
935     * Gets the text of the event. The index in the list represents the priority
936     * of the text. Specifically, the lower the index the higher the priority.
937     *
938     * @return The text.
939     */
940    public List<CharSequence> getText() {
941        return IMPL.getText(mRecord);
942    }
943
944    /**
945     * Sets the text before a change.
946     *
947     * @return The text before the change.
948     */
949    public CharSequence getBeforeText() {
950        return IMPL.getBeforeText(mRecord);
951    }
952
953    /**
954     * Sets the text before a change.
955     *
956     * @param beforeText The text before the change.
957     *
958     * @throws IllegalStateException If called from an AccessibilityService.
959     */
960    public void setBeforeText(CharSequence beforeText) {
961        IMPL.setBeforeText(mRecord, beforeText);
962    }
963
964    /**
965     * Gets the description of the source.
966     *
967     * @return The description.
968     */
969    public CharSequence getContentDescription() {
970        return IMPL.getContentDescription(mRecord);
971    }
972
973    /**
974     * Sets the description of the source.
975     *
976     * @param contentDescription The description.
977     *
978     * @throws IllegalStateException If called from an AccessibilityService.
979     */
980    public void setContentDescription(CharSequence contentDescription) {
981        IMPL.setContentDescription(mRecord, contentDescription);
982    }
983
984    /**
985     * Gets the {@link Parcelable} data.
986     *
987     * @return The parcelable data.
988     */
989    public Parcelable getParcelableData() {
990        return IMPL.getParcelableData(mRecord);
991    }
992
993    /**
994     * Sets the {@link Parcelable} data of the event.
995     *
996     * @param parcelableData The parcelable data.
997     *
998     * @throws IllegalStateException If called from an AccessibilityService.
999     */
1000    public void setParcelableData(Parcelable parcelableData) {
1001        IMPL.setParcelableData(mRecord, parcelableData);
1002    }
1003
1004    /**
1005     * Return an instance back to be reused.
1006     * <p>
1007     * <strong>Note:</strong> You must not touch the object after calling this
1008     * function.
1009     * </p>
1010     *
1011     * @throws IllegalStateException If the record is already recycled.
1012     */
1013    public void recycle() {
1014        IMPL.recycle(mRecord);
1015    }
1016
1017    @Override
1018    public int hashCode() {
1019        return (mRecord == null) ? 0 : mRecord.hashCode();
1020    }
1021
1022
1023    @Override
1024    public boolean equals(Object obj) {
1025        if (this == obj) {
1026            return true;
1027        }
1028        if (obj == null) {
1029            return false;
1030        }
1031        if (getClass() != obj.getClass()) {
1032            return false;
1033        }
1034        AccessibilityRecordCompat other = (AccessibilityRecordCompat) obj;
1035        if (mRecord == null) {
1036            if (other.mRecord != null) {
1037                return false;
1038            }
1039        } else if (!mRecord.equals(other.mRecord)) {
1040            return false;
1041        }
1042        return true;
1043    }
1044}
1045