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 androidx.core.accessibilityservice; 18 19 import android.accessibilityservice.AccessibilityService; 20 import android.accessibilityservice.AccessibilityServiceInfo; 21 import android.content.pm.PackageManager; 22 import android.os.Build; 23 import android.view.View; 24 25 import androidx.annotation.NonNull; 26 import androidx.annotation.Nullable; 27 28 /** 29 * Helper for accessing features in {@link AccessibilityServiceInfo}. 30 */ 31 public final class AccessibilityServiceInfoCompat { 32 /** 33 * Capability: This accessibility service can retrieve the active window content. 34 */ 35 public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 0x00000001; 36 37 /** 38 * Capability: This accessibility service can request touch exploration mode in which 39 * touched items are spoken aloud and the UI can be explored via gestures. 40 */ 41 public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 0x00000002; 42 43 /** 44 * Capability: This accessibility service can request enhanced web accessibility 45 * enhancements. For example, installing scripts to make app content more accessible. 46 */ 47 public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000004; 48 49 /** 50 * Capability: This accessibility service can filter the key event stream. 51 */ 52 public static final int CAPABILITY_CAN_FILTER_KEY_EVENTS = 0x00000008; 53 54 // Feedback types 55 56 /** 57 * Denotes braille feedback. 58 */ 59 public static final int FEEDBACK_BRAILLE = 0x0000020; 60 61 /** 62 * Mask for all feedback types. 63 * 64 * @see AccessibilityServiceInfo#FEEDBACK_SPOKEN 65 * @see AccessibilityServiceInfo#FEEDBACK_HAPTIC 66 * @see AccessibilityServiceInfo#FEEDBACK_AUDIBLE 67 * @see AccessibilityServiceInfo#FEEDBACK_VISUAL 68 * @see AccessibilityServiceInfo#FEEDBACK_GENERIC 69 * @see AccessibilityServiceInfo#FEEDBACK_BRAILLE 70 */ 71 public static final int FEEDBACK_ALL_MASK = 0xFFFFFFFF; 72 73 // Flags 74 75 /** 76 * If this flag is set the system will regard views that are not important 77 * for accessibility in addition to the ones that are important for accessibility. 78 * That is, views that are marked as not important for accessibility via 79 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO} or 80 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS} and views that are 81 * marked as potentially important for accessibility via 82 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_AUTO} for which the system has determined 83 * that are not important for accessibility, are both reported while querying the 84 * window content and also the accessibility service will receive accessibility events 85 * from them. 86 * <p> 87 * <strong>Note:</strong> For accessibility services targeting API version 88 * {@link Build.VERSION_CODES#JELLY_BEAN} or higher this flag has to be explicitly 89 * set for the system to regard views that are not important for accessibility. For 90 * accessibility services targeting API version lower than 91 * {@link Build.VERSION_CODES#JELLY_BEAN} this flag is ignored and all views are 92 * regarded for accessibility purposes. 93 * </p> 94 * <p> 95 * Usually views not important for accessibility are layout managers that do not 96 * react to user actions, do not draw any content, and do not have any special 97 * semantics in the context of the screen content. For example, a three by three 98 * grid can be implemented as three horizontal linear layouts and one vertical, 99 * or three vertical linear layouts and one horizontal, or one grid layout, etc. 100 * In this context the actual layout mangers used to achieve the grid configuration 101 * are not important, rather it is important that there are nine evenly distributed 102 * elements. 103 * </p> 104 */ 105 public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x0000002; 106 107 /** 108 * This flag requests that the system gets into touch exploration mode. 109 * In this mode a single finger moving on the screen behaves as a mouse 110 * pointer hovering over the user interface. The system will also detect 111 * certain gestures performed on the touch screen and notify this service. 112 * The system will enable touch exploration mode if there is at least one 113 * accessibility service that has this flag set. Hence, clearing this 114 * flag does not guarantee that the device will not be in touch exploration 115 * mode since there may be another enabled service that requested it. 116 * <p> 117 * For accessibility services targeting API version higher than 118 * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} that want to set 119 * this flag have to declare this capability in their meta-data by setting 120 * the attribute canRequestTouchExplorationMode to true, otherwise this flag 121 * will be ignored. For how to declare the meta-data of a service refer to 122 * {@value AccessibilityService#SERVICE_META_DATA}. 123 * </p> 124 * <p> 125 * Services targeting API version equal to or lower than 126 * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} will work normally, i.e. 127 * the first time they are run, if this flag is specified, a dialog is 128 * shown to the user to confirm enabling explore by touch. 129 * </p> 130 */ 131 public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 0x0000004; 132 133 /** 134 * This flag requests from the system to enable web accessibility enhancing 135 * extensions. Such extensions aim to provide improved accessibility support 136 * for content presented in a {@link android.webkit.WebView}. An example of such 137 * an extension is injecting JavaScript from a secure source. The system will enable 138 * enhanced web accessibility if there is at least one accessibility service 139 * that has this flag set. Hence, clearing this flag does not guarantee that the 140 * device will not have enhanced web accessibility enabled since there may be 141 * another enabled service that requested it. 142 * <p> 143 * Services that want to set this flag have to declare this capability 144 * in their meta-data by setting the attribute canRequestEnhancedWebAccessibility 145 * to true, otherwise this flag will be ignored. For how to declare the meta-data 146 * of a service refer to {@value AccessibilityService#SERVICE_META_DATA}. 147 * </p> 148 */ 149 public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000008; 150 151 /** 152 * This flag requests that the AccessibilityNodeInfos obtained 153 * by an {@link AccessibilityService} contain the id of the source view. 154 * The source view id will be a fully qualified resource name of the 155 * form "package:id/name", for example "foo.bar:id/my_list", and it is 156 * useful for UI test automation. This flag is not set by default. 157 */ 158 public static final int FLAG_REPORT_VIEW_IDS = 0x00000010; 159 160 /** 161 * This flag requests from the system to filter key events. If this flag 162 * is set the accessibility service will receive the key events before 163 * applications allowing it implement global shortcuts. Setting this flag 164 * does not guarantee that this service will filter key events since only 165 * one service can do so at any given time. This avoids user confusion due 166 * to behavior change in case different key filtering services are enabled. 167 * If there is already another key filtering service enabled, this one will 168 * not receive key events. 169 * <p> 170 * Services that want to set this flag have to declare this capability 171 * in their meta-data by setting the attribute canRequestFilterKeyEvents 172 * to true, otherwise this flag will be ignored. For how to declare the meta 173 * -data of a service refer to {@value AccessibilityService#SERVICE_META_DATA}. 174 * </p> 175 */ 176 public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 0x00000020; 177 178 /* 179 * Hide constructor 180 */ AccessibilityServiceInfoCompat()181 private AccessibilityServiceInfoCompat() {} 182 183 /** 184 * The localized description of the accessibility service. 185 * <p> 186 * <strong>Statically set from 187 * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong> 188 * </p> 189 * 190 * @param info The service info of interest 191 * @param packageManager The current package manager 192 * @return The localized description. 193 */ 194 @Nullable loadDescription( @onNull AccessibilityServiceInfo info, @NonNull PackageManager packageManager)195 public static String loadDescription( 196 @NonNull AccessibilityServiceInfo info, @NonNull PackageManager packageManager) { 197 if (Build.VERSION.SDK_INT >= 16) { 198 return info.loadDescription(packageManager); 199 } else { 200 //noinspection deprecation 201 return info.getDescription(); 202 } 203 } 204 205 /** 206 * Returns the string representation of a feedback type. For example, 207 * {@link AccessibilityServiceInfo#FEEDBACK_SPOKEN} is represented by the 208 * string FEEDBACK_SPOKEN. 209 * 210 * @param feedbackType The feedback type. 211 * @return The string representation. 212 */ 213 @NonNull feedbackTypeToString(int feedbackType)214 public static String feedbackTypeToString(int feedbackType) { 215 StringBuilder builder = new StringBuilder(); 216 builder.append("["); 217 while (feedbackType > 0) { 218 final int feedbackTypeFlag = 1 << Integer.numberOfTrailingZeros(feedbackType); 219 feedbackType &= ~feedbackTypeFlag; 220 if (builder.length() > 1) { 221 builder.append(", "); 222 } 223 switch (feedbackTypeFlag) { 224 case AccessibilityServiceInfo.FEEDBACK_AUDIBLE: 225 builder.append("FEEDBACK_AUDIBLE"); 226 break; 227 case AccessibilityServiceInfo.FEEDBACK_HAPTIC: 228 builder.append("FEEDBACK_HAPTIC"); 229 break; 230 case AccessibilityServiceInfo.FEEDBACK_GENERIC: 231 builder.append("FEEDBACK_GENERIC"); 232 break; 233 case AccessibilityServiceInfo.FEEDBACK_SPOKEN: 234 builder.append("FEEDBACK_SPOKEN"); 235 break; 236 case AccessibilityServiceInfo.FEEDBACK_VISUAL: 237 builder.append("FEEDBACK_VISUAL"); 238 break; 239 } 240 } 241 builder.append("]"); 242 return builder.toString(); 243 } 244 245 /** 246 * Returns the string representation of a flag. For example, 247 * {@link AccessibilityServiceInfo#DEFAULT} is represented by the 248 * string DEFAULT. 249 * 250 * @param flag The flag. 251 * @return The string representation. 252 */ 253 @Nullable flagToString(int flag)254 public static String flagToString(int flag) { 255 switch (flag) { 256 case AccessibilityServiceInfo.DEFAULT: 257 return "DEFAULT"; 258 case FLAG_INCLUDE_NOT_IMPORTANT_VIEWS: 259 return "FLAG_INCLUDE_NOT_IMPORTANT_VIEWS"; 260 case FLAG_REQUEST_TOUCH_EXPLORATION_MODE: 261 return "FLAG_REQUEST_TOUCH_EXPLORATION_MODE"; 262 case FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY: 263 return "FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY"; 264 case FLAG_REPORT_VIEW_IDS: 265 return "FLAG_REPORT_VIEW_IDS"; 266 case FLAG_REQUEST_FILTER_KEY_EVENTS: 267 return "FLAG_REQUEST_FILTER_KEY_EVENTS"; 268 default: 269 return null; 270 } 271 } 272 273 /** 274 * Returns the bit mask of capabilities this accessibility service has such as 275 * being able to retrieve the active window content, etc. 276 * 277 * @param info The service info whose capabilities to get. 278 * @return The capability bit mask. 279 * 280 * @see #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT 281 * @see #CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION 282 * @see #CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY 283 * @see #CAPABILITY_CAN_FILTER_KEY_EVENTS 284 */ getCapabilities(@onNull AccessibilityServiceInfo info)285 public static int getCapabilities(@NonNull AccessibilityServiceInfo info) { 286 if (Build.VERSION.SDK_INT >= 18) { 287 return info.getCapabilities(); 288 } else { 289 //noinspection deprecation 290 if (info.getCanRetrieveWindowContent()) { 291 return CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT; 292 } 293 return 0; 294 } 295 } 296 297 /** 298 * Returns the string representation of a capability. For example, 299 * {@link #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT} is represented 300 * by the string CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT. 301 * 302 * @param capability The capability. 303 * @return The string representation. 304 */ 305 @NonNull capabilityToString(int capability)306 public static String capabilityToString(int capability) { 307 switch (capability) { 308 case CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT: 309 return "CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT"; 310 case CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION: 311 return "CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION"; 312 case CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY: 313 return "CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY"; 314 case CAPABILITY_CAN_FILTER_KEY_EVENTS: 315 return "CAPABILITY_CAN_FILTER_KEY_EVENTS"; 316 default: 317 return "UNKNOWN"; 318 } 319 } 320 } 321