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.view.accessibility.AccessibilityEvent;
21
22/**
23 * Helper for accessing features in {@link AccessibilityEvent}
24 * introduced after API level 4 in a backwards compatible fashion.
25 */
26public final class AccessibilityEventCompat {
27
28    static interface AccessibilityEventVersionImpl {
29        int getRecordCount(AccessibilityEvent event);
30        void appendRecord(AccessibilityEvent event, Object record);
31        Object getRecord(AccessibilityEvent event, int index);
32        void setContentChangeTypes(AccessibilityEvent event, int types);
33        int getContentChangeTypes(AccessibilityEvent event);
34    }
35
36    static class AccessibilityEventStubImpl implements AccessibilityEventVersionImpl {
37
38        @Override
39        public void appendRecord(AccessibilityEvent event, Object record) {
40
41        }
42
43        @Override
44        public Object getRecord(AccessibilityEvent event, int index) {
45            return null;
46        }
47
48        @Override
49        public void setContentChangeTypes(AccessibilityEvent event, int types) {
50
51        }
52
53        @Override
54        public int getRecordCount(AccessibilityEvent event) {
55            return 0;
56        }
57
58        @Override
59        public int getContentChangeTypes(AccessibilityEvent event) {
60            return 0;
61        }
62    }
63
64    static class AccessibilityEventIcsImpl extends AccessibilityEventStubImpl {
65
66        @Override
67        public void appendRecord(AccessibilityEvent event, Object record) {
68            AccessibilityEventCompatIcs.appendRecord(event, record);
69        }
70
71        @Override
72        public Object getRecord(AccessibilityEvent event, int index) {
73            return AccessibilityEventCompatIcs.getRecord(event, index);
74        }
75
76        @Override
77        public int getRecordCount(AccessibilityEvent event) {
78            return AccessibilityEventCompatIcs.getRecordCount(event);
79        }
80    }
81
82    static class AccessibilityEventKitKatImpl extends AccessibilityEventIcsImpl {
83
84        @Override
85        public void setContentChangeTypes(AccessibilityEvent event, int types) {
86            AccessibilityEventCompatKitKat.setContentChangeTypes(event, types);
87        }
88
89        @Override
90        public int getContentChangeTypes(AccessibilityEvent event) {
91            return AccessibilityEventCompatKitKat.getContentChangeTypes(event);
92        }
93    }
94
95    private final static AccessibilityEventVersionImpl IMPL;
96
97    static {
98        if (Build.VERSION.SDK_INT >= 19) { // KitKat
99            IMPL = new AccessibilityEventKitKatImpl();
100        } else if (Build.VERSION.SDK_INT >= 14) { // ICS
101            IMPL = new AccessibilityEventIcsImpl();
102        } else {
103            IMPL = new AccessibilityEventStubImpl();
104        }
105    }
106
107    /**
108     * Represents the event of a hover enter over a {@link android.view.View}.
109     */
110    public static final int TYPE_VIEW_HOVER_ENTER = 0x00000080;
111
112    /**
113     * Represents the event of a hover exit over a {@link android.view.View}.
114     */
115    public static final int TYPE_VIEW_HOVER_EXIT = 0x00000100;
116
117    /**
118     * Represents the event of starting a touch exploration gesture.
119     */
120    public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 0x00000200;
121
122    /**
123     * Represents the event of ending a touch exploration gesture.
124     */
125    public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 0x00000400;
126
127    /**
128     * Represents the event of changing the content of a window.
129     */
130    public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800;
131
132    /**
133     * Represents the event of scrolling a view.
134     */
135    public static final int TYPE_VIEW_SCROLLED = 0x00001000;
136
137    /**
138     * Represents the event of changing the selection in an {@link android.widget.EditText}.
139     */
140    public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 0x00002000;
141
142    /**
143     * Represents the event of an application making an announcement.
144     */
145    public static final int TYPE_ANNOUNCEMENT = 0x00004000;
146
147    /**
148     * Represents the event of gaining accessibility focus.
149     */
150    public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED = 0x00008000;
151
152    /**
153     * Represents the event of clearing accessibility focus.
154     */
155    public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 0x00010000;
156
157    /**
158     * Represents the event of traversing the text of a view at a given movement granularity.
159     */
160    public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 0x00020000;
161
162    /**
163     * Represents the event of beginning gesture detection.
164     */
165    public static final int TYPE_GESTURE_DETECTION_START = 0x00040000;
166
167    /**
168     * Represents the event of ending gesture detection.
169     */
170    public static final int TYPE_GESTURE_DETECTION_END = 0x00080000;
171
172    /**
173     * Represents the event of the user starting to touch the screen.
174     */
175    public static final int TYPE_TOUCH_INTERACTION_START = 0x00100000;
176
177    /**
178     * Represents the event of the user ending to touch the screen.
179     */
180    public static final int TYPE_TOUCH_INTERACTION_END = 0x00200000;
181
182    /**
183     * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
184     * The type of change is not defined.
185     */
186    public static final int CONTENT_CHANGE_TYPE_UNDEFINED = 0x00000000;
187
188    /**
189     * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
190     * A node in the subtree rooted at the source node was added or removed.
191     */
192    public static final int CONTENT_CHANGE_TYPE_SUBTREE = 0x00000001;
193
194    /**
195     * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
196     * The node's text changed.
197     */
198    public static final int CONTENT_CHANGE_TYPE_TEXT = 0x00000002;
199
200    /**
201     * Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
202     * The node's content description changed.
203     */
204    public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 0x00000004;
205
206    /**
207     * Mask for {@link AccessibilityEvent} all types.
208     *
209     * @see AccessibilityEvent#TYPE_VIEW_CLICKED
210     * @see AccessibilityEvent#TYPE_VIEW_LONG_CLICKED
211     * @see AccessibilityEvent#TYPE_VIEW_SELECTED
212     * @see AccessibilityEvent#TYPE_VIEW_FOCUSED
213     * @see AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED
214     * @see AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED
215     * @see AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED
216     * @see #TYPE_VIEW_HOVER_ENTER
217     * @see #TYPE_VIEW_HOVER_EXIT
218     * @see #TYPE_TOUCH_EXPLORATION_GESTURE_START
219     * @see #TYPE_TOUCH_EXPLORATION_GESTURE_END
220     * @see #TYPE_WINDOW_CONTENT_CHANGED
221     * @see #TYPE_VIEW_SCROLLED
222     * @see #TYPE_VIEW_TEXT_SELECTION_CHANGED
223     * @see #TYPE_ANNOUNCEMENT
224     * @see #TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
225     * @see #TYPE_GESTURE_DETECTION_START
226     * @see #TYPE_GESTURE_DETECTION_END
227     * @see #TYPE_TOUCH_INTERACTION_START
228     * @see #TYPE_TOUCH_INTERACTION_END
229     */
230    public static final int TYPES_ALL_MASK = 0xFFFFFFFF;
231
232    /*
233     * Hide constructor from clients.
234     */
235    private AccessibilityEventCompat() {
236
237    }
238
239    /**
240     * Gets the number of records contained in the event.
241     *
242     * @return The number of records.
243     */
244    public static int getRecordCount(AccessibilityEvent event) {
245        return IMPL.getRecordCount(event);
246    }
247
248    /**
249     * Appends an {@link android.view.accessibility.AccessibilityRecord} to the end of
250     * event records.
251     *
252     * @param record The record to append.
253     *
254     * @throws IllegalStateException If called from an AccessibilityService.
255     */
256    public static void appendRecord(AccessibilityEvent event, AccessibilityRecordCompat record) {
257        IMPL.appendRecord(event, record.getImpl());
258    }
259
260    /**
261     * Gets the record at a given index.
262     *
263     * @param index The index.
264     * @return The record at the specified index.
265     */
266    public static AccessibilityRecordCompat getRecord(AccessibilityEvent event, int index) {
267        return new AccessibilityRecordCompat(IMPL.getRecord(event, index));
268    }
269
270    /**
271     * Creates an {@link AccessibilityRecordCompat} from an {@link AccessibilityEvent}
272     * that can be used to manipulate the event properties defined in
273     * {@link android.view.accessibility.AccessibilityRecord}.
274     * <p>
275     * <strong>Note:</strong> Do not call {@link AccessibilityRecordCompat#recycle()} on the
276     * returned {@link AccessibilityRecordCompat}. Call {@link AccessibilityEvent#recycle()}
277     * in case you want to recycle the event.
278     * </p>
279     *
280     * @param event The from which to create a record.
281     * @return An {@link AccessibilityRecordCompat}.
282     */
283    public static AccessibilityRecordCompat asRecord(AccessibilityEvent event) {
284        return new AccessibilityRecordCompat(event);
285    }
286
287    /**
288     * Sets the bit mask of node tree changes signaled by an
289     * {@link #TYPE_WINDOW_CONTENT_CHANGED} event.
290     *
291     * @param changeTypes The bit mask of change types.
292     * @throws IllegalStateException If called from an AccessibilityService.
293     * @see #getContentChangeTypes(AccessibilityEvent)
294     */
295    public static void setContentChangeTypes(AccessibilityEvent event, int changeTypes) {
296        IMPL.setContentChangeTypes(event, changeTypes);
297    }
298
299    /**
300     * Gets the bit mask of change types signaled by an
301     * {@link #TYPE_WINDOW_CONTENT_CHANGED} event. A single event may represent
302     * multiple change types.
303     *
304     * @return The bit mask of change types. One or more of:
305     *         <ul>
306     *         <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION}
307     *         <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_SUBTREE}
308     *         <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_TEXT}
309     *         <li>{@link AccessibilityEvent#CONTENT_CHANGE_TYPE_UNDEFINED}
310     *         </ul>
311     */
312    public static int getContentChangeTypes(AccessibilityEvent event) {
313        return IMPL.getContentChangeTypes(event);
314    }
315
316}
317