AccessibilityServiceInfoCompat.java revision 1ef22af9051a858183b028cc4f7c02c973653be4
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.accessibilityservice;
18
19import android.accessibilityservice.AccessibilityService;
20import android.accessibilityservice.AccessibilityServiceInfo;
21import android.content.pm.PackageManager;
22import android.content.pm.ResolveInfo;
23import android.os.Build;
24import android.view.View;
25
26/**
27 * Helper for accessing features in {@link android.accessibilityservice.AccessibilityService}
28 * introduced after API level 4 in a backwards compatible fashion.
29 */
30public final class AccessibilityServiceInfoCompat {
31
32    static interface AccessibilityServiceInfoVersionImpl {
33        public String getId(AccessibilityServiceInfo info);
34        public ResolveInfo getResolveInfo(AccessibilityServiceInfo info);
35        public boolean getCanRetrieveWindowContent(AccessibilityServiceInfo info);
36        public String getDescription(AccessibilityServiceInfo info);
37        public String getSettingsActivityName(AccessibilityServiceInfo info);
38        public int getCapabilities(AccessibilityServiceInfo info);
39        public String loadDescription(AccessibilityServiceInfo info, PackageManager pm);
40    }
41
42    static class AccessibilityServiceInfoStubImpl implements AccessibilityServiceInfoVersionImpl {
43
44        @Override
45        public boolean getCanRetrieveWindowContent(AccessibilityServiceInfo info) {
46            return false;
47        }
48
49        @Override
50        public String getDescription(AccessibilityServiceInfo info) {
51            return null;
52        }
53
54        @Override
55        public String getId(AccessibilityServiceInfo info) {
56            return null;
57        }
58
59        @Override
60        public ResolveInfo getResolveInfo(AccessibilityServiceInfo info) {
61            return null;
62        }
63
64        @Override
65        public String getSettingsActivityName(AccessibilityServiceInfo info) {
66            return null;
67        }
68
69        @Override
70        public int getCapabilities(AccessibilityServiceInfo info) {
71            return 0;
72        }
73
74        @Override
75        public String loadDescription(AccessibilityServiceInfo info, PackageManager pm) {
76            return null;
77        }
78    }
79
80    static class AccessibilityServiceInfoIcsImpl extends AccessibilityServiceInfoStubImpl {
81
82        @Override
83        public boolean getCanRetrieveWindowContent(AccessibilityServiceInfo info) {
84            return AccessibilityServiceInfoCompatIcs.getCanRetrieveWindowContent(info);
85        }
86
87        @Override
88        public String getDescription(AccessibilityServiceInfo info) {
89            return AccessibilityServiceInfoCompatIcs.getDescription(info);
90        }
91
92        @Override
93        public String getId(AccessibilityServiceInfo info) {
94            return AccessibilityServiceInfoCompatIcs.getId(info);
95        }
96
97        @Override
98        public ResolveInfo getResolveInfo(AccessibilityServiceInfo info) {
99            return AccessibilityServiceInfoCompatIcs.getResolveInfo(info);
100        }
101
102        @Override
103        public String getSettingsActivityName(AccessibilityServiceInfo info) {
104            return AccessibilityServiceInfoCompatIcs.getSettingsActivityName(info);
105        }
106
107        @Override
108        public int getCapabilities(AccessibilityServiceInfo info) {
109            if (getCanRetrieveWindowContent(info)) {
110                return CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT;
111            }
112            return 0;
113        }
114    }
115
116    static class AccessibilityServiceInfoJellyBeanImpl extends AccessibilityServiceInfoIcsImpl {
117        @Override
118        public String loadDescription(AccessibilityServiceInfo info, PackageManager pm) {
119            return AccessibilityServiceInfoCompatJellyBean.loadDescription(info, pm);
120        }
121    }
122
123    static class AccessibilityServiceInfoJellyBeanMr2Impl
124            extends AccessibilityServiceInfoJellyBeanImpl {
125        @Override
126        public int getCapabilities(AccessibilityServiceInfo info) {
127            return AccessibilityServiceInfoCompatJellyBeanMr2.getCapabilities(info);
128        }
129    }
130
131    static {
132        if (Build.VERSION.SDK_INT >= 18) { // JellyBean MR2
133            IMPL = new AccessibilityServiceInfoJellyBeanMr2Impl();
134        } else if (Build.VERSION.SDK_INT >= 16) { // JB
135            IMPL = new AccessibilityServiceInfoJellyBeanImpl();
136        } else if (Build.VERSION.SDK_INT >= 14) { // ICS
137            IMPL = new AccessibilityServiceInfoIcsImpl();
138        } else {
139            IMPL = new AccessibilityServiceInfoStubImpl();
140        }
141    }
142
143    // Capabilities
144
145    private static final AccessibilityServiceInfoVersionImpl IMPL;
146
147    /**
148     * Capability: This accessibility service can retrieve the active window content.
149     */
150    public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 0x00000001;
151
152    /**
153     * Capability: This accessibility service can request touch exploration mode in which
154     * touched items are spoken aloud and the UI can be explored via gestures.
155     */
156    public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 0x00000002;
157
158    /**
159     * Capability: This accessibility service can request enhanced web accessibility
160     * enhancements. For example, installing scripts to make app content more accessible.
161     */
162    public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000004;
163
164    /**
165     * Capability: This accessibility service can filter the key event stream.
166     */
167    public static final int CAPABILITY_CAN_FILTER_KEY_EVENTS = 0x00000008;
168
169    // Feedback types
170
171    /**
172     * Denotes braille feedback.
173     */
174    public static final int FEEDBACK_BRAILLE = 0x0000020;
175
176    /**
177     * Mask for all feedback types.
178     *
179     * @see AccessibilityServiceInfo#FEEDBACK_SPOKEN
180     * @see AccessibilityServiceInfo#FEEDBACK_HAPTIC
181     * @see AccessibilityServiceInfo#FEEDBACK_AUDIBLE
182     * @see AccessibilityServiceInfo#FEEDBACK_VISUAL
183     * @see AccessibilityServiceInfo#FEEDBACK_GENERIC
184     * @see FEEDBACK_BRAILLE
185     */
186    public static final int FEEDBACK_ALL_MASK = 0xFFFFFFFF;
187
188    // Flags
189
190    /**
191     * If an {@link AccessibilityService} is the default for a given type.
192     * Default service is invoked only if no package specific one exists. In case of
193     * more than one package specific service only the earlier registered is notified.
194     */
195    public static final int DEFAULT = 0x0000001;
196
197    /**
198     * If this flag is set the system will regard views that are not important
199     * for accessibility in addition to the ones that are important for accessibility.
200     * That is, views that are marked as not important for accessibility via
201     * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO} or
202     * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS} and views that are
203     * marked as potentially important for accessibility via
204     * {@link View#IMPORTANT_FOR_ACCESSIBILITY_AUTO} for which the system has determined
205     * that are not important for accessibility, are both reported while querying the
206     * window content and also the accessibility service will receive accessibility events
207     * from them.
208     * <p>
209     * <strong>Note:</strong> For accessibility services targeting API version
210     * {@link Build.VERSION_CODES#JELLY_BEAN} or higher this flag has to be explicitly
211     * set for the system to regard views that are not important for accessibility. For
212     * accessibility services targeting API version lower than
213     * {@link Build.VERSION_CODES#JELLY_BEAN} this flag is ignored and all views are
214     * regarded for accessibility purposes.
215     * </p>
216     * <p>
217     * Usually views not important for accessibility are layout managers that do not
218     * react to user actions, do not draw any content, and do not have any special
219     * semantics in the context of the screen content. For example, a three by three
220     * grid can be implemented as three horizontal linear layouts and one vertical,
221     * or three vertical linear layouts and one horizontal, or one grid layout, etc.
222     * In this context the actual layout mangers used to achieve the grid configuration
223     * are not important, rather it is important that there are nine evenly distributed
224     * elements.
225     * </p>
226     */
227    public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x0000002;
228
229    /**
230     * This flag requests that the system gets into touch exploration mode.
231     * In this mode a single finger moving on the screen behaves as a mouse
232     * pointer hovering over the user interface. The system will also detect
233     * certain gestures performed on the touch screen and notify this service.
234     * The system will enable touch exploration mode if there is at least one
235     * accessibility service that has this flag set. Hence, clearing this
236     * flag does not guarantee that the device will not be in touch exploration
237     * mode since there may be another enabled service that requested it.
238     * <p>
239     * For accessibility services targeting API version higher than
240     * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} that want to set
241     * this flag have to declare this capability in their meta-data by setting
242     * the attribute canRequestTouchExplorationMode to true, otherwise this flag
243     * will be ignored. For how to declare the meta-data of a service refer to
244     * {@value AccessibilityService#SERVICE_META_DATA}.
245     * </p>
246     * <p>
247     * Services targeting API version equal to or lower than
248     * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} will work normally, i.e.
249     * the first time they are run, if this flag is specified, a dialog is
250     * shown to the user to confirm enabling explore by touch.
251     * </p>
252     */
253    public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 0x0000004;
254
255    /**
256     * This flag requests from the system to enable web accessibility enhancing
257     * extensions. Such extensions aim to provide improved accessibility support
258     * for content presented in a {@link android.webkit.WebView}. An example of such
259     * an extension is injecting JavaScript from a secure source. The system will enable
260     * enhanced web accessibility if there is at least one accessibility service
261     * that has this flag set. Hence, clearing this flag does not guarantee that the
262     * device will not have enhanced web accessibility enabled since there may be
263     * another enabled service that requested it.
264     * <p>
265     * Services that want to set this flag have to declare this capability
266     * in their meta-data by setting the attribute canRequestEnhancedWebAccessibility
267     * to true, otherwise this flag will be ignored. For how to declare the meta-data
268     * of a service refer to {@value AccessibilityService#SERVICE_META_DATA}.
269     * </p>
270     */
271    public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000008;
272
273    /**
274     * This flag requests that the AccessibilityNodeInfos obtained
275     * by an {@link AccessibilityService} contain the id of the source view.
276     * The source view id will be a fully qualified resource name of the
277     * form "package:id/name", for example "foo.bar:id/my_list", and it is
278     * useful for UI test automation. This flag is not set by default.
279     */
280    public static final int FLAG_REPORT_VIEW_IDS = 0x00000010;
281
282    /**
283     * This flag requests from the system to filter key events. If this flag
284     * is set the accessibility service will receive the key events before
285     * applications allowing it implement global shortcuts. Setting this flag
286     * does not guarantee that this service will filter key events since only
287     * one service can do so at any given time. This avoids user confusion due
288     * to behavior change in case different key filtering services are enabled.
289     * If there is already another key filtering service enabled, this one will
290     * not receive key events.
291     * <p>
292     * Services that want to set this flag have to declare this capability
293     * in their meta-data by setting the attribute canRequestFilterKeyEvents
294     * to true, otherwise this flag will be ignored. For how to declare the meta
295     * -data of a service refer to {@value AccessibilityService#SERVICE_META_DATA}.
296     * </p>
297     */
298    public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 0x00000020;
299
300    /*
301     * Hide constructor
302     */
303    private AccessibilityServiceInfoCompat() {}
304
305    /**
306     * The accessibility service id.
307     * <p>
308     * <strong>Generated by the system.</strong>
309     * </p>
310     *
311     * @param info The service info of interest
312     * @return The id.
313     */
314    public static String getId(AccessibilityServiceInfo info) {
315        return IMPL.getId(info);
316    }
317
318    /**
319     * The service {@link ResolveInfo}.
320     * <p>
321     * <strong>Generated by the system.</strong>
322     * </p>
323     *
324     * @param info The service info of interest
325     * @return The info.
326     */
327    public static ResolveInfo getResolveInfo(AccessibilityServiceInfo info) {
328        return IMPL.getResolveInfo(info);
329    }
330
331    /**
332     * The settings activity name.
333     * <p>
334     * <strong>Statically set from {@link AccessibilityService#SERVICE_META_DATA
335     * meta-data}.</strong>
336     * </p>
337     *
338     * @param info The service info of interest
339     * @return The settings activity name.
340     */
341    public static String getSettingsActivityName(AccessibilityServiceInfo info) {
342        return IMPL.getSettingsActivityName(info);
343    }
344
345    /**
346     * Whether this service can retrieve the current window's content.
347     * <p>
348     * <strong>Statically set from {@link AccessibilityService#SERVICE_META_DATA
349     * meta-data}.</strong>
350     * </p>
351     *
352     * @param info The service info of interest
353     * @return True window content can be retrieved.
354     */
355    public static boolean getCanRetrieveWindowContent(AccessibilityServiceInfo info) {
356        return IMPL.getCanRetrieveWindowContent(info);
357    }
358
359    /**
360     * Non-localized description of the accessibility service.
361     * <p>
362     * <strong>Statically set from {@link AccessibilityService#SERVICE_META_DATA
363     * meta-data}.</strong>
364     * </p>
365     *
366     * @param info The service info of interest
367     * @return The description.
368     *
369     * @deprecated Use {@link #loadDescription(AccessibilityServiceInfo, PackageManager)}.
370     */
371    public static String getDescription(AccessibilityServiceInfo info) {
372        return IMPL.getDescription(info);
373    }
374
375    /**
376     * The localized description of the accessibility service.
377     * <p>
378     *    <strong>Statically set from
379     *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
380     * </p>
381     *
382     * @param info The service info of interest
383     * @param packageManager The current package manager
384     * @return The localized description.
385     */
386    public static String loadDescription(
387            AccessibilityServiceInfo info, PackageManager packageManager) {
388        return IMPL.loadDescription(info, packageManager);
389    }
390
391    /**
392     * Returns the string representation of a feedback type. For example,
393     * {@link AccessibilityServiceInfo#FEEDBACK_SPOKEN} is represented by the
394     * string FEEDBACK_SPOKEN.
395     *
396     * @param feedbackType The feedback type.
397     * @return The string representation.
398     */
399    public static String feedbackTypeToString(int feedbackType) {
400        StringBuilder builder = new StringBuilder();
401        builder.append("[");
402        while (feedbackType > 0) {
403            final int feedbackTypeFlag = 1 << Integer.numberOfTrailingZeros(feedbackType);
404            feedbackType &= ~feedbackTypeFlag;
405            if (builder.length() > 1) {
406                builder.append(", ");
407            }
408            switch (feedbackTypeFlag) {
409                case AccessibilityServiceInfo.FEEDBACK_AUDIBLE:
410                    builder.append("FEEDBACK_AUDIBLE");
411                    break;
412                case AccessibilityServiceInfo.FEEDBACK_HAPTIC:
413                    builder.append("FEEDBACK_HAPTIC");
414                    break;
415                case AccessibilityServiceInfo.FEEDBACK_GENERIC:
416                    builder.append("FEEDBACK_GENERIC");
417                    break;
418                case AccessibilityServiceInfo.FEEDBACK_SPOKEN:
419                    builder.append("FEEDBACK_SPOKEN");
420                    break;
421                case AccessibilityServiceInfo.FEEDBACK_VISUAL:
422                    builder.append("FEEDBACK_VISUAL");
423                    break;
424            }
425        }
426        builder.append("]");
427        return builder.toString();
428    }
429
430    /**
431     * Returns the string representation of a flag. For example,
432     * {@link AccessibilityServiceInfo#DEFAULT} is represented by the
433     * string DEFAULT.
434     *
435     * @param flag The flag.
436     * @return The string representation.
437     */
438    public static String flagToString(int flag) {
439        switch (flag) {
440            case DEFAULT:
441                return "DEFAULT";
442            case FLAG_INCLUDE_NOT_IMPORTANT_VIEWS:
443                return "FLAG_INCLUDE_NOT_IMPORTANT_VIEWS";
444            case FLAG_REQUEST_TOUCH_EXPLORATION_MODE:
445                return "FLAG_REQUEST_TOUCH_EXPLORATION_MODE";
446            case FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY:
447                return "FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY";
448            case FLAG_REPORT_VIEW_IDS:
449                return "FLAG_REPORT_VIEW_IDS";
450            case FLAG_REQUEST_FILTER_KEY_EVENTS:
451                return "FLAG_REQUEST_FILTER_KEY_EVENTS";
452            default:
453                return null;
454        }
455    }
456
457    /**
458     * Returns the bit mask of capabilities this accessibility service has such as
459     * being able to retrieve the active window content, etc.
460     *
461     * @param info The service info whose capabilities to get.
462     * @return The capability bit mask.
463     *
464     * @see #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT
465     * @see #CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION
466     * @see #CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY
467     * @see #CAPABILITY_CAN_FILTER_KEY_EVENTS
468     */
469    public static int getCapabilities(AccessibilityServiceInfo info) {
470        return IMPL.getCapabilities(info);
471    }
472
473    /**
474     * Returns the string representation of a capability. For example,
475     * {@link #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT} is represented
476     * by the string CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT.
477     *
478     * @param capability The capability.
479     * @return The string representation.
480     */
481    public static String capabilityToString(int capability) {
482        switch (capability) {
483            case CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT:
484                return "CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT";
485            case CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION:
486                return "CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION";
487            case CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY:
488                return "CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY";
489            case CAPABILITY_CAN_FILTER_KEY_EVENTS:
490                return "CAPABILITY_CAN_FILTER_KEY_EVENTS";
491            default:
492                return "UNKNOWN";
493        }
494    }
495}
496