1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.support.v4.view.accessibility;
18 
19 import android.os.Build;
20 import 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  */
26 public class AccessibilityEventCompat {
27 
28     static interface AccessibilityEventVersionImpl {
getRecordCount(AccessibilityEvent event)29         int getRecordCount(AccessibilityEvent event);
appendRecord(AccessibilityEvent event, Object record)30         void appendRecord(AccessibilityEvent event, Object record);
getRecord(AccessibilityEvent event, int index)31         Object getRecord(AccessibilityEvent event, int index);
setContentChangeTypes(AccessibilityEvent event, int types)32         void setContentChangeTypes(AccessibilityEvent event, int types);
getContentChangeTypes(AccessibilityEvent event)33         int getContentChangeTypes(AccessibilityEvent event);
34     }
35 
36     static class AccessibilityEventStubImpl implements AccessibilityEventVersionImpl {
37 
38         @Override
appendRecord(AccessibilityEvent event, Object record)39         public void appendRecord(AccessibilityEvent event, Object record) {
40 
41         }
42 
43         @Override
getRecord(AccessibilityEvent event, int index)44         public Object getRecord(AccessibilityEvent event, int index) {
45             return null;
46         }
47 
48         @Override
setContentChangeTypes(AccessibilityEvent event, int types)49         public void setContentChangeTypes(AccessibilityEvent event, int types) {
50 
51         }
52 
53         @Override
getRecordCount(AccessibilityEvent event)54         public int getRecordCount(AccessibilityEvent event) {
55             return 0;
56         }
57 
58         @Override
getContentChangeTypes(AccessibilityEvent event)59         public int getContentChangeTypes(AccessibilityEvent event) {
60             return 0;
61         }
62     }
63 
64     static class AccessibilityEventIcsImpl extends AccessibilityEventStubImpl {
65 
66         @Override
appendRecord(AccessibilityEvent event, Object record)67         public void appendRecord(AccessibilityEvent event, Object record) {
68             AccessibilityEventCompatIcs.appendRecord(event, record);
69         }
70 
71         @Override
getRecord(AccessibilityEvent event, int index)72         public Object getRecord(AccessibilityEvent event, int index) {
73             return AccessibilityEventCompatIcs.getRecord(event, index);
74         }
75 
76         @Override
getRecordCount(AccessibilityEvent event)77         public int getRecordCount(AccessibilityEvent event) {
78             return AccessibilityEventCompatIcs.getRecordCount(event);
79         }
80     }
81 
82     static class AccessibilityEventKitKatImpl extends AccessibilityEventIcsImpl {
83 
84         @Override
setContentChangeTypes(AccessibilityEvent event, int types)85         public void setContentChangeTypes(AccessibilityEvent event, int types) {
86             AccessibilityEventCompatKitKat.setContentChangeTypes(event, types);
87         }
88 
89         @Override
getContentChangeTypes(AccessibilityEvent event)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      */
AccessibilityEventCompat()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      */
getRecordCount(AccessibilityEvent event)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      */
appendRecord(AccessibilityEvent event, AccessibilityRecordCompat record)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      */
getRecord(AccessibilityEvent event, int index)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      */
asRecord(AccessibilityEvent event)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      */
setContentChangeTypes(AccessibilityEvent event, int changeTypes)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      */
getContentChangeTypes(AccessibilityEvent event)312     public static int getContentChangeTypes(AccessibilityEvent event) {
313         return IMPL.getContentChangeTypes(event);
314     }
315 
316 }
317