1 /* 2 * Copyright (C) 2009 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.accessibilityservice; 18 19 import static android.content.pm.PackageManager.FEATURE_FINGERPRINT; 20 21 import android.annotation.IntDef; 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.pm.PackageManager; 25 import android.content.pm.PackageManager.NameNotFoundException; 26 import android.content.pm.ResolveInfo; 27 import android.content.pm.ServiceInfo; 28 import android.content.res.Resources; 29 import android.content.res.TypedArray; 30 import android.content.res.XmlResourceParser; 31 import android.hardware.fingerprint.FingerprintManager; 32 import android.os.Build; 33 import android.os.Parcel; 34 import android.os.Parcelable; 35 import android.util.AttributeSet; 36 import android.util.SparseArray; 37 import android.util.TypedValue; 38 import android.util.Xml; 39 import android.view.View; 40 import android.view.accessibility.AccessibilityEvent; 41 import android.view.accessibility.AccessibilityNodeInfo; 42 43 import com.android.internal.R; 44 45 import org.xmlpull.v1.XmlPullParser; 46 import org.xmlpull.v1.XmlPullParserException; 47 48 import java.io.IOException; 49 import java.lang.annotation.Retention; 50 import java.lang.annotation.RetentionPolicy; 51 import java.util.ArrayList; 52 import java.util.Collections; 53 import java.util.List; 54 55 /** 56 * This class describes an {@link AccessibilityService}. The system notifies an 57 * {@link AccessibilityService} for {@link android.view.accessibility.AccessibilityEvent}s 58 * according to the information encapsulated in this class. 59 * 60 * <div class="special reference"> 61 * <h3>Developer Guides</h3> 62 * <p>For more information about creating AccessibilityServices, read the 63 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a> 64 * developer guide.</p> 65 * </div> 66 * 67 * @attr ref android.R.styleable#AccessibilityService_accessibilityEventTypes 68 * @attr ref android.R.styleable#AccessibilityService_accessibilityFeedbackType 69 * @attr ref android.R.styleable#AccessibilityService_accessibilityFlags 70 * @attr ref android.R.styleable#AccessibilityService_canRequestEnhancedWebAccessibility 71 * @attr ref android.R.styleable#AccessibilityService_canRequestFilterKeyEvents 72 * @attr ref android.R.styleable#AccessibilityService_canRequestTouchExplorationMode 73 * @attr ref android.R.styleable#AccessibilityService_canRetrieveWindowContent 74 * @attr ref android.R.styleable#AccessibilityService_description 75 * @attr ref android.R.styleable#AccessibilityService_summary 76 * @attr ref android.R.styleable#AccessibilityService_notificationTimeout 77 * @attr ref android.R.styleable#AccessibilityService_packageNames 78 * @attr ref android.R.styleable#AccessibilityService_settingsActivity 79 * @see AccessibilityService 80 * @see android.view.accessibility.AccessibilityEvent 81 * @see android.view.accessibility.AccessibilityManager 82 */ 83 public class AccessibilityServiceInfo implements Parcelable { 84 85 private static final String TAG_ACCESSIBILITY_SERVICE = "accessibility-service"; 86 87 /** 88 * Capability: This accessibility service can retrieve the active window content. 89 * @see android.R.styleable#AccessibilityService_canRetrieveWindowContent 90 */ 91 public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 0x00000001; 92 93 /** 94 * Capability: This accessibility service can request touch exploration mode in which 95 * touched items are spoken aloud and the UI can be explored via gestures. 96 * @see android.R.styleable#AccessibilityService_canRequestTouchExplorationMode 97 */ 98 public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 0x00000002; 99 100 /** 101 * @deprecated No longer used 102 */ 103 public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000004; 104 105 /** 106 * Capability: This accessibility service can request to filter the key event stream. 107 * @see android.R.styleable#AccessibilityService_canRequestFilterKeyEvents 108 */ 109 public static final int CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS = 0x00000008; 110 111 /** 112 * Capability: This accessibility service can control display magnification. 113 * @see android.R.styleable#AccessibilityService_canControlMagnification 114 */ 115 public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 0x00000010; 116 117 /** 118 * Capability: This accessibility service can perform gestures. 119 * @see android.R.styleable#AccessibilityService_canPerformGestures 120 */ 121 public static final int CAPABILITY_CAN_PERFORM_GESTURES = 0x00000020; 122 123 /** 124 * Capability: This accessibility service can capture gestures from the fingerprint sensor 125 * @see android.R.styleable#AccessibilityService_canRequestFingerprintGestures 126 */ 127 public static final int CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES = 0x00000040; 128 129 private static SparseArray<CapabilityInfo> sAvailableCapabilityInfos; 130 131 /** 132 * Denotes spoken feedback. 133 */ 134 public static final int FEEDBACK_SPOKEN = 0x0000001; 135 136 /** 137 * Denotes haptic feedback. 138 */ 139 public static final int FEEDBACK_HAPTIC = 0x0000002; 140 141 /** 142 * Denotes audible (not spoken) feedback. 143 */ 144 public static final int FEEDBACK_AUDIBLE = 0x0000004; 145 146 /** 147 * Denotes visual feedback. 148 */ 149 public static final int FEEDBACK_VISUAL = 0x0000008; 150 151 /** 152 * Denotes generic feedback. 153 */ 154 public static final int FEEDBACK_GENERIC = 0x0000010; 155 156 /** 157 * Denotes braille feedback. 158 */ 159 public static final int FEEDBACK_BRAILLE = 0x0000020; 160 161 /** 162 * Mask for all feedback types. 163 * 164 * @see #FEEDBACK_SPOKEN 165 * @see #FEEDBACK_HAPTIC 166 * @see #FEEDBACK_AUDIBLE 167 * @see #FEEDBACK_VISUAL 168 * @see #FEEDBACK_GENERIC 169 * @see #FEEDBACK_BRAILLE 170 */ 171 public static final int FEEDBACK_ALL_MASK = 0xFFFFFFFF; 172 173 /** 174 * If an {@link AccessibilityService} is the default for a given type. 175 * Default service is invoked only if no package specific one exists. In case of 176 * more than one package specific service only the earlier registered is notified. 177 */ 178 public static final int DEFAULT = 0x0000001; 179 180 /** 181 * If this flag is set the system will regard views that are not important 182 * for accessibility in addition to the ones that are important for accessibility. 183 * That is, views that are marked as not important for accessibility via 184 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO} or 185 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS} and views that are 186 * marked as potentially important for accessibility via 187 * {@link View#IMPORTANT_FOR_ACCESSIBILITY_AUTO} for which the system has determined 188 * that are not important for accessibility, are reported while querying the window 189 * content and also the accessibility service will receive accessibility events from 190 * them. 191 * <p> 192 * <strong>Note:</strong> For accessibility services targeting API version 193 * {@link Build.VERSION_CODES#JELLY_BEAN} or higher this flag has to be explicitly 194 * set for the system to regard views that are not important for accessibility. For 195 * accessibility services targeting API version lower than 196 * {@link Build.VERSION_CODES#JELLY_BEAN} this flag is ignored and all views are 197 * regarded for accessibility purposes. 198 * </p> 199 * <p> 200 * Usually views not important for accessibility are layout managers that do not 201 * react to user actions, do not draw any content, and do not have any special 202 * semantics in the context of the screen content. For example, a three by three 203 * grid can be implemented as three horizontal linear layouts and one vertical, 204 * or three vertical linear layouts and one horizontal, or one grid layout, etc. 205 * In this context the actual layout mangers used to achieve the grid configuration 206 * are not important, rather it is important that there are nine evenly distributed 207 * elements. 208 * </p> 209 */ 210 public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x0000002; 211 212 /** 213 * This flag requests that the system gets into touch exploration mode. 214 * In this mode a single finger moving on the screen behaves as a mouse 215 * pointer hovering over the user interface. The system will also detect 216 * certain gestures performed on the touch screen and notify this service. 217 * The system will enable touch exploration mode if there is at least one 218 * accessibility service that has this flag set. Hence, clearing this 219 * flag does not guarantee that the device will not be in touch exploration 220 * mode since there may be another enabled service that requested it. 221 * <p> 222 * For accessibility services targeting API version higher than 223 * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} that want to set 224 * this flag have to declare this capability in their meta-data by setting 225 * the attribute {@link android.R.attr#canRequestTouchExplorationMode 226 * canRequestTouchExplorationMode} to true, otherwise this flag will 227 * be ignored. For how to declare the meta-data of a service refer to 228 * {@value AccessibilityService#SERVICE_META_DATA}. 229 * </p> 230 * <p> 231 * Services targeting API version equal to or lower than 232 * {@link Build.VERSION_CODES#JELLY_BEAN_MR1} will work normally, i.e. 233 * the first time they are run, if this flag is specified, a dialog is 234 * shown to the user to confirm enabling explore by touch. 235 * </p> 236 * @see android.R.styleable#AccessibilityService_canRequestTouchExplorationMode 237 */ 238 public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE = 0x0000004; 239 240 /** 241 * @deprecated No longer used 242 */ 243 public static final int FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 0x00000008; 244 245 /** 246 * This flag requests that the {@link AccessibilityNodeInfo}s obtained 247 * by an {@link AccessibilityService} contain the id of the source view. 248 * The source view id will be a fully qualified resource name of the 249 * form "package:id/name", for example "foo.bar:id/my_list", and it is 250 * useful for UI test automation. This flag is not set by default. 251 */ 252 public static final int FLAG_REPORT_VIEW_IDS = 0x00000010; 253 254 /** 255 * This flag requests from the system to filter key events. If this flag 256 * is set the accessibility service will receive the key events before 257 * applications allowing it implement global shortcuts. 258 * <p> 259 * Services that want to set this flag have to declare this capability 260 * in their meta-data by setting the attribute {@link android.R.attr 261 * #canRequestFilterKeyEvents canRequestFilterKeyEvents} to true, 262 * otherwise this flag will be ignored. For how to declare the meta-data 263 * of a service refer to {@value AccessibilityService#SERVICE_META_DATA}. 264 * </p> 265 * @see android.R.styleable#AccessibilityService_canRequestFilterKeyEvents 266 */ 267 public static final int FLAG_REQUEST_FILTER_KEY_EVENTS = 0x00000020; 268 269 /** 270 * This flag indicates to the system that the accessibility service wants 271 * to access content of all interactive windows. An interactive window is a 272 * window that has input focus or can be touched by a sighted user when explore 273 * by touch is not enabled. If this flag is not set your service will not receive 274 * {@link android.view.accessibility.AccessibilityEvent#TYPE_WINDOWS_CHANGED} 275 * events, calling AccessibilityService{@link AccessibilityService#getWindows() 276 * AccessibilityService.getWindows()} will return an empty list, and {@link 277 * AccessibilityNodeInfo#getWindow() AccessibilityNodeInfo.getWindow()} will 278 * return null. 279 * <p> 280 * Services that want to set this flag have to declare the capability 281 * to retrieve window content in their meta-data by setting the attribute 282 * {@link android.R.attr#canRetrieveWindowContent canRetrieveWindowContent} to 283 * true, otherwise this flag will be ignored. For how to declare the meta-data 284 * of a service refer to {@value AccessibilityService#SERVICE_META_DATA}. 285 * </p> 286 * @see android.R.styleable#AccessibilityService_canRetrieveWindowContent 287 */ 288 public static final int FLAG_RETRIEVE_INTERACTIVE_WINDOWS = 0x00000040; 289 290 /** 291 * This flag requests that all audio tracks system-wide with 292 * {@link android.media.AudioAttributes#USAGE_ASSISTANCE_ACCESSIBILITY} be controlled by the 293 * {@link android.media.AudioManager#STREAM_ACCESSIBILITY} volume. 294 */ 295 public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 0x00000080; 296 297 /** 298 * This flag indicates to the system that the accessibility service requests that an 299 * accessibility button be shown within the system's navigation area, if available. 300 */ 301 public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 0x00000100; 302 303 /** 304 * This flag requests that all fingerprint gestures be sent to the accessibility service. 305 * <p> 306 * Services that want to set this flag have to declare the capability 307 * to retrieve window content in their meta-data by setting the attribute 308 * {@link android.R.attr#canRequestFingerprintGestures} to 309 * true, otherwise this flag will be ignored. For how to declare the meta-data 310 * of a service refer to {@value AccessibilityService#SERVICE_META_DATA}. 311 * </p> 312 * 313 * @see android.R.styleable#AccessibilityService_canRequestFingerprintGestures 314 * @see AccessibilityService#getFingerprintGestureController() 315 */ 316 public static final int FLAG_REQUEST_FINGERPRINT_GESTURES = 0x00000200; 317 318 /** {@hide} */ 319 public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 0x00010000; 320 321 /** 322 * The event types an {@link AccessibilityService} is interested in. 323 * <p> 324 * <strong>Can be dynamically set at runtime.</strong> 325 * </p> 326 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED 327 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_LONG_CLICKED 328 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_FOCUSED 329 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SELECTED 330 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED 331 * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED 332 * @see android.view.accessibility.AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED 333 * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START 334 * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END 335 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER 336 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_EXIT 337 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SCROLLED 338 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED 339 * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED 340 * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_INTERACTION_START 341 * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_INTERACTION_END 342 * @see android.view.accessibility.AccessibilityEvent#TYPE_ANNOUNCEMENT 343 * @see android.view.accessibility.AccessibilityEvent#TYPE_GESTURE_DETECTION_START 344 * @see android.view.accessibility.AccessibilityEvent#TYPE_GESTURE_DETECTION_END 345 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUSED 346 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED 347 * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY 348 * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOWS_CHANGED 349 */ 350 public int eventTypes; 351 352 /** 353 * The package names an {@link AccessibilityService} is interested in. Setting 354 * to <code>null</code> is equivalent to all packages. 355 * <p> 356 * <strong>Can be dynamically set at runtime.</strong> 357 * </p> 358 */ 359 public String[] packageNames; 360 361 362 /** @hide */ 363 @IntDef(flag = true, prefix = { "FEEDBACK_" }, value = { 364 FEEDBACK_AUDIBLE, 365 FEEDBACK_GENERIC, 366 FEEDBACK_HAPTIC, 367 FEEDBACK_SPOKEN, 368 FEEDBACK_VISUAL, 369 FEEDBACK_BRAILLE 370 }) 371 @Retention(RetentionPolicy.SOURCE) 372 public @interface FeedbackType {} 373 374 /** 375 * The feedback type an {@link AccessibilityService} provides. 376 * <p> 377 * <strong>Can be dynamically set at runtime.</strong> 378 * </p> 379 * @see #FEEDBACK_AUDIBLE 380 * @see #FEEDBACK_GENERIC 381 * @see #FEEDBACK_HAPTIC 382 * @see #FEEDBACK_SPOKEN 383 * @see #FEEDBACK_VISUAL 384 * @see #FEEDBACK_BRAILLE 385 */ 386 @FeedbackType 387 public int feedbackType; 388 389 /** 390 * The timeout after the most recent event of a given type before an 391 * {@link AccessibilityService} is notified. 392 * <p> 393 * <strong>Can be dynamically set at runtime.</strong>. 394 * </p> 395 * <p> 396 * <strong>Note:</strong> The event notification timeout is useful to avoid propagating 397 * events to the client too frequently since this is accomplished via an expensive 398 * interprocess call. One can think of the timeout as a criteria to determine when 399 * event generation has settled down. 400 */ 401 public long notificationTimeout; 402 403 /** 404 * This field represents a set of flags used for configuring an 405 * {@link AccessibilityService}. 406 * <p> 407 * <strong>Can be dynamically set at runtime.</strong> 408 * </p> 409 * @see #DEFAULT 410 * @see #FLAG_INCLUDE_NOT_IMPORTANT_VIEWS 411 * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE 412 * @see #FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY 413 * @see #FLAG_REQUEST_FILTER_KEY_EVENTS 414 * @see #FLAG_REPORT_VIEW_IDS 415 * @see #FLAG_RETRIEVE_INTERACTIVE_WINDOWS 416 * @see #FLAG_ENABLE_ACCESSIBILITY_VOLUME 417 * @see #FLAG_REQUEST_ACCESSIBILITY_BUTTON 418 */ 419 public int flags; 420 421 /** 422 * Whether or not the service has crashed and is awaiting restart. Only valid from {@link 423 * android.view.accessibility.AccessibilityManager#getEnabledAccessibilityServiceList(int)}, 424 * because that is populated from the internal list of running services. 425 * 426 * @hide 427 */ 428 public boolean crashed; 429 430 /** 431 * The component name the accessibility service. 432 */ 433 private ComponentName mComponentName; 434 435 /** 436 * The Service that implements this accessibility service component. 437 */ 438 private ResolveInfo mResolveInfo; 439 440 /** 441 * The accessibility service setting activity's name, used by the system 442 * settings to launch the setting activity of this accessibility service. 443 */ 444 private String mSettingsActivityName; 445 446 /** 447 * Bit mask with capabilities of this service. 448 */ 449 private int mCapabilities; 450 451 /** 452 * Resource id of the summary of the accessibility service. 453 */ 454 private int mSummaryResId; 455 456 /** 457 * Non-localized summary of the accessibility service. 458 */ 459 private String mNonLocalizedSummary; 460 461 /** 462 * Resource id of the description of the accessibility service. 463 */ 464 private int mDescriptionResId; 465 466 /** 467 * Non localized description of the accessibility service. 468 */ 469 private String mNonLocalizedDescription; 470 471 /** 472 * Creates a new instance. 473 */ AccessibilityServiceInfo()474 public AccessibilityServiceInfo() { 475 /* do nothing */ 476 } 477 478 /** 479 * Creates a new instance. 480 * 481 * @param resolveInfo The service resolve info. 482 * @param context Context for accessing resources. 483 * @throws XmlPullParserException If a XML parsing error occurs. 484 * @throws IOException If a XML parsing error occurs. 485 * 486 * @hide 487 */ AccessibilityServiceInfo(ResolveInfo resolveInfo, Context context)488 public AccessibilityServiceInfo(ResolveInfo resolveInfo, Context context) 489 throws XmlPullParserException, IOException { 490 ServiceInfo serviceInfo = resolveInfo.serviceInfo; 491 mComponentName = new ComponentName(serviceInfo.packageName, serviceInfo.name); 492 mResolveInfo = resolveInfo; 493 494 XmlResourceParser parser = null; 495 496 try { 497 PackageManager packageManager = context.getPackageManager(); 498 parser = serviceInfo.loadXmlMetaData(packageManager, 499 AccessibilityService.SERVICE_META_DATA); 500 if (parser == null) { 501 return; 502 } 503 504 int type = 0; 505 while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) { 506 type = parser.next(); 507 } 508 509 String nodeName = parser.getName(); 510 if (!TAG_ACCESSIBILITY_SERVICE.equals(nodeName)) { 511 throw new XmlPullParserException( "Meta-data does not start with" 512 + TAG_ACCESSIBILITY_SERVICE + " tag"); 513 } 514 515 AttributeSet allAttributes = Xml.asAttributeSet(parser); 516 Resources resources = packageManager.getResourcesForApplication( 517 serviceInfo.applicationInfo); 518 TypedArray asAttributes = resources.obtainAttributes(allAttributes, 519 com.android.internal.R.styleable.AccessibilityService); 520 eventTypes = asAttributes.getInt( 521 com.android.internal.R.styleable.AccessibilityService_accessibilityEventTypes, 522 0); 523 String packageNamez = asAttributes.getString( 524 com.android.internal.R.styleable.AccessibilityService_packageNames); 525 if (packageNamez != null) { 526 packageNames = packageNamez.split("(\\s)*,(\\s)*"); 527 } 528 feedbackType = asAttributes.getInt( 529 com.android.internal.R.styleable.AccessibilityService_accessibilityFeedbackType, 530 0); 531 notificationTimeout = asAttributes.getInt( 532 com.android.internal.R.styleable.AccessibilityService_notificationTimeout, 533 0); 534 flags = asAttributes.getInt( 535 com.android.internal.R.styleable.AccessibilityService_accessibilityFlags, 0); 536 mSettingsActivityName = asAttributes.getString( 537 com.android.internal.R.styleable.AccessibilityService_settingsActivity); 538 if (asAttributes.getBoolean(com.android.internal.R.styleable 539 .AccessibilityService_canRetrieveWindowContent, false)) { 540 mCapabilities |= CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT; 541 } 542 if (asAttributes.getBoolean(com.android.internal.R.styleable 543 .AccessibilityService_canRequestTouchExplorationMode, false)) { 544 mCapabilities |= CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION; 545 } 546 if (asAttributes.getBoolean(com.android.internal.R.styleable 547 .AccessibilityService_canRequestFilterKeyEvents, false)) { 548 mCapabilities |= CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS; 549 } 550 if (asAttributes.getBoolean(com.android.internal.R.styleable 551 .AccessibilityService_canControlMagnification, false)) { 552 mCapabilities |= CAPABILITY_CAN_CONTROL_MAGNIFICATION; 553 } 554 if (asAttributes.getBoolean(com.android.internal.R.styleable 555 .AccessibilityService_canPerformGestures, false)) { 556 mCapabilities |= CAPABILITY_CAN_PERFORM_GESTURES; 557 } 558 if (asAttributes.getBoolean(com.android.internal.R.styleable 559 .AccessibilityService_canRequestFingerprintGestures, false)) { 560 mCapabilities |= CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES; 561 } 562 TypedValue peekedValue = asAttributes.peekValue( 563 com.android.internal.R.styleable.AccessibilityService_description); 564 if (peekedValue != null) { 565 mDescriptionResId = peekedValue.resourceId; 566 CharSequence nonLocalizedDescription = peekedValue.coerceToString(); 567 if (nonLocalizedDescription != null) { 568 mNonLocalizedDescription = nonLocalizedDescription.toString().trim(); 569 } 570 } 571 peekedValue = asAttributes.peekValue( 572 com.android.internal.R.styleable.AccessibilityService_summary); 573 if (peekedValue != null) { 574 mSummaryResId = peekedValue.resourceId; 575 CharSequence nonLocalizedSummary = peekedValue.coerceToString(); 576 if (nonLocalizedSummary != null) { 577 mNonLocalizedSummary = nonLocalizedSummary.toString().trim(); 578 } 579 } 580 asAttributes.recycle(); 581 } catch (NameNotFoundException e) { 582 throw new XmlPullParserException( "Unable to create context for: " 583 + serviceInfo.packageName); 584 } finally { 585 if (parser != null) { 586 parser.close(); 587 } 588 } 589 } 590 591 /** 592 * Updates the properties that an AccessibilitySerivice can change dynamically. 593 * 594 * @param other The info from which to update the properties. 595 * 596 * @hide 597 */ updateDynamicallyConfigurableProperties(AccessibilityServiceInfo other)598 public void updateDynamicallyConfigurableProperties(AccessibilityServiceInfo other) { 599 eventTypes = other.eventTypes; 600 packageNames = other.packageNames; 601 feedbackType = other.feedbackType; 602 notificationTimeout = other.notificationTimeout; 603 flags = other.flags; 604 } 605 606 /** 607 * @hide 608 */ setComponentName(ComponentName component)609 public void setComponentName(ComponentName component) { 610 mComponentName = component; 611 } 612 613 /** 614 * @hide 615 */ getComponentName()616 public ComponentName getComponentName() { 617 return mComponentName; 618 } 619 620 /** 621 * The accessibility service id. 622 * <p> 623 * <strong>Generated by the system.</strong> 624 * </p> 625 * @return The id. 626 */ getId()627 public String getId() { 628 return mComponentName.flattenToShortString(); 629 } 630 631 /** 632 * The service {@link ResolveInfo}. 633 * <p> 634 * <strong>Generated by the system.</strong> 635 * </p> 636 * @return The info. 637 */ getResolveInfo()638 public ResolveInfo getResolveInfo() { 639 return mResolveInfo; 640 } 641 642 /** 643 * The settings activity name. 644 * <p> 645 * <strong>Statically set from 646 * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong> 647 * </p> 648 * @return The settings activity name. 649 */ getSettingsActivityName()650 public String getSettingsActivityName() { 651 return mSettingsActivityName; 652 } 653 654 /** 655 * Whether this service can retrieve the current window's content. 656 * <p> 657 * <strong>Statically set from 658 * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong> 659 * </p> 660 * @return True if window content can be retrieved. 661 * 662 * @deprecated Use {@link #getCapabilities()}. 663 */ getCanRetrieveWindowContent()664 public boolean getCanRetrieveWindowContent() { 665 return (mCapabilities & CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0; 666 } 667 668 /** 669 * Returns the bit mask of capabilities this accessibility service has such as 670 * being able to retrieve the active window content, etc. 671 * 672 * @return The capability bit mask. 673 * 674 * @see #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT 675 * @see #CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION 676 * @see #CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS 677 * @see #CAPABILITY_CAN_CONTROL_MAGNIFICATION 678 * @see #CAPABILITY_CAN_PERFORM_GESTURES 679 */ getCapabilities()680 public int getCapabilities() { 681 return mCapabilities; 682 } 683 684 /** 685 * Sets the bit mask of capabilities this accessibility service has such as 686 * being able to retrieve the active window content, etc. 687 * 688 * @param capabilities The capability bit mask. 689 * 690 * @see #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT 691 * @see #CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION 692 * @see #CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS 693 * @see #CAPABILITY_CAN_CONTROL_MAGNIFICATION 694 * @see #CAPABILITY_CAN_PERFORM_GESTURES 695 * 696 * @hide 697 */ setCapabilities(int capabilities)698 public void setCapabilities(int capabilities) { 699 mCapabilities = capabilities; 700 } 701 702 /** 703 * The localized summary of the accessibility service. 704 * <p> 705 * <strong>Statically set from 706 * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong> 707 * </p> 708 * @return The localized summary if available, and {@code null} if a summary 709 * has not been provided. 710 */ loadSummary(PackageManager packageManager)711 public CharSequence loadSummary(PackageManager packageManager) { 712 if (mSummaryResId == 0) { 713 return mNonLocalizedSummary; 714 } 715 ServiceInfo serviceInfo = mResolveInfo.serviceInfo; 716 CharSequence summary = packageManager.getText(serviceInfo.packageName, 717 mSummaryResId, serviceInfo.applicationInfo); 718 if (summary != null) { 719 return summary.toString().trim(); 720 } 721 return null; 722 } 723 724 /** 725 * Gets the non-localized description of the accessibility service. 726 * <p> 727 * <strong>Statically set from 728 * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong> 729 * </p> 730 * @return The description. 731 * 732 * @deprecated Use {@link #loadDescription(PackageManager)}. 733 */ getDescription()734 public String getDescription() { 735 return mNonLocalizedDescription; 736 } 737 738 /** 739 * The localized description of the accessibility service. 740 * <p> 741 * <strong>Statically set from 742 * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong> 743 * </p> 744 * @return The localized description. 745 */ loadDescription(PackageManager packageManager)746 public String loadDescription(PackageManager packageManager) { 747 if (mDescriptionResId == 0) { 748 return mNonLocalizedDescription; 749 } 750 ServiceInfo serviceInfo = mResolveInfo.serviceInfo; 751 CharSequence description = packageManager.getText(serviceInfo.packageName, 752 mDescriptionResId, serviceInfo.applicationInfo); 753 if (description != null) { 754 return description.toString().trim(); 755 } 756 return null; 757 } 758 759 /** {@hide} */ isDirectBootAware()760 public boolean isDirectBootAware() { 761 return ((flags & FLAG_FORCE_DIRECT_BOOT_AWARE) != 0) 762 || mResolveInfo.serviceInfo.directBootAware; 763 } 764 765 /** 766 * {@inheritDoc} 767 */ describeContents()768 public int describeContents() { 769 return 0; 770 } 771 writeToParcel(Parcel parcel, int flagz)772 public void writeToParcel(Parcel parcel, int flagz) { 773 parcel.writeInt(eventTypes); 774 parcel.writeStringArray(packageNames); 775 parcel.writeInt(feedbackType); 776 parcel.writeLong(notificationTimeout); 777 parcel.writeInt(flags); 778 parcel.writeInt(crashed ? 1 : 0); 779 parcel.writeParcelable(mComponentName, flagz); 780 parcel.writeParcelable(mResolveInfo, 0); 781 parcel.writeString(mSettingsActivityName); 782 parcel.writeInt(mCapabilities); 783 parcel.writeInt(mSummaryResId); 784 parcel.writeString(mNonLocalizedSummary); 785 parcel.writeInt(mDescriptionResId); 786 parcel.writeString(mNonLocalizedDescription); 787 } 788 initFromParcel(Parcel parcel)789 private void initFromParcel(Parcel parcel) { 790 eventTypes = parcel.readInt(); 791 packageNames = parcel.readStringArray(); 792 feedbackType = parcel.readInt(); 793 notificationTimeout = parcel.readLong(); 794 flags = parcel.readInt(); 795 crashed = parcel.readInt() != 0; 796 mComponentName = parcel.readParcelable(this.getClass().getClassLoader()); 797 mResolveInfo = parcel.readParcelable(null); 798 mSettingsActivityName = parcel.readString(); 799 mCapabilities = parcel.readInt(); 800 mSummaryResId = parcel.readInt(); 801 mNonLocalizedSummary = parcel.readString(); 802 mDescriptionResId = parcel.readInt(); 803 mNonLocalizedDescription = parcel.readString(); 804 } 805 806 @Override hashCode()807 public int hashCode() { 808 return 31 * 1 + ((mComponentName == null) ? 0 : mComponentName.hashCode()); 809 } 810 811 @Override equals(Object obj)812 public boolean equals(Object obj) { 813 if (this == obj) { 814 return true; 815 } 816 if (obj == null) { 817 return false; 818 } 819 if (getClass() != obj.getClass()) { 820 return false; 821 } 822 AccessibilityServiceInfo other = (AccessibilityServiceInfo) obj; 823 if (mComponentName == null) { 824 if (other.mComponentName != null) { 825 return false; 826 } 827 } else if (!mComponentName.equals(other.mComponentName)) { 828 return false; 829 } 830 return true; 831 } 832 833 @Override toString()834 public String toString() { 835 StringBuilder stringBuilder = new StringBuilder(); 836 appendEventTypes(stringBuilder, eventTypes); 837 stringBuilder.append(", "); 838 appendPackageNames(stringBuilder, packageNames); 839 stringBuilder.append(", "); 840 appendFeedbackTypes(stringBuilder, feedbackType); 841 stringBuilder.append(", "); 842 stringBuilder.append("notificationTimeout: ").append(notificationTimeout); 843 stringBuilder.append(", "); 844 appendFlags(stringBuilder, flags); 845 stringBuilder.append(", "); 846 stringBuilder.append("id: ").append(getId()); 847 stringBuilder.append(", "); 848 stringBuilder.append("resolveInfo: ").append(mResolveInfo); 849 stringBuilder.append(", "); 850 stringBuilder.append("settingsActivityName: ").append(mSettingsActivityName); 851 stringBuilder.append(", "); 852 stringBuilder.append("summary: ").append(mNonLocalizedSummary); 853 stringBuilder.append(", "); 854 appendCapabilities(stringBuilder, mCapabilities); 855 return stringBuilder.toString(); 856 } 857 appendFeedbackTypes(StringBuilder stringBuilder, @FeedbackType int feedbackTypes)858 private static void appendFeedbackTypes(StringBuilder stringBuilder, 859 @FeedbackType int feedbackTypes) { 860 stringBuilder.append("feedbackTypes:"); 861 stringBuilder.append("["); 862 while (feedbackTypes != 0) { 863 final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackTypes)); 864 stringBuilder.append(feedbackTypeToString(feedbackTypeBit)); 865 feedbackTypes &= ~feedbackTypeBit; 866 if (feedbackTypes != 0) { 867 stringBuilder.append(", "); 868 } 869 } 870 stringBuilder.append("]"); 871 } 872 appendPackageNames(StringBuilder stringBuilder, String[] packageNames)873 private static void appendPackageNames(StringBuilder stringBuilder, String[] packageNames) { 874 stringBuilder.append("packageNames:"); 875 stringBuilder.append("["); 876 if (packageNames != null) { 877 final int packageNameCount = packageNames.length; 878 for (int i = 0; i < packageNameCount; i++) { 879 stringBuilder.append(packageNames[i]); 880 if (i < packageNameCount - 1) { 881 stringBuilder.append(", "); 882 } 883 } 884 } 885 stringBuilder.append("]"); 886 } 887 appendEventTypes(StringBuilder stringBuilder, int eventTypes)888 private static void appendEventTypes(StringBuilder stringBuilder, int eventTypes) { 889 stringBuilder.append("eventTypes:"); 890 stringBuilder.append("["); 891 while (eventTypes != 0) { 892 final int eventTypeBit = (1 << Integer.numberOfTrailingZeros(eventTypes)); 893 stringBuilder.append(AccessibilityEvent.eventTypeToString(eventTypeBit)); 894 eventTypes &= ~eventTypeBit; 895 if (eventTypes != 0) { 896 stringBuilder.append(", "); 897 } 898 } 899 stringBuilder.append("]"); 900 } 901 appendFlags(StringBuilder stringBuilder, int flags)902 private static void appendFlags(StringBuilder stringBuilder, int flags) { 903 stringBuilder.append("flags:"); 904 stringBuilder.append("["); 905 while (flags != 0) { 906 final int flagBit = (1 << Integer.numberOfTrailingZeros(flags)); 907 stringBuilder.append(flagToString(flagBit)); 908 flags &= ~flagBit; 909 if (flags != 0) { 910 stringBuilder.append(", "); 911 } 912 } 913 stringBuilder.append("]"); 914 } 915 appendCapabilities(StringBuilder stringBuilder, int capabilities)916 private static void appendCapabilities(StringBuilder stringBuilder, int capabilities) { 917 stringBuilder.append("capabilities:"); 918 stringBuilder.append("["); 919 while (capabilities != 0) { 920 final int capabilityBit = (1 << Integer.numberOfTrailingZeros(capabilities)); 921 stringBuilder.append(capabilityToString(capabilityBit)); 922 capabilities &= ~capabilityBit; 923 if (capabilities != 0) { 924 stringBuilder.append(", "); 925 } 926 } 927 stringBuilder.append("]"); 928 } 929 930 /** 931 * Returns the string representation of a feedback type. For example, 932 * {@link #FEEDBACK_SPOKEN} is represented by the string FEEDBACK_SPOKEN. 933 * 934 * @param feedbackType The feedback type. 935 * @return The string representation. 936 */ feedbackTypeToString(int feedbackType)937 public static String feedbackTypeToString(int feedbackType) { 938 StringBuilder builder = new StringBuilder(); 939 builder.append("["); 940 while (feedbackType != 0) { 941 final int feedbackTypeFlag = 1 << Integer.numberOfTrailingZeros(feedbackType); 942 feedbackType &= ~feedbackTypeFlag; 943 switch (feedbackTypeFlag) { 944 case FEEDBACK_AUDIBLE: 945 if (builder.length() > 1) { 946 builder.append(", "); 947 } 948 builder.append("FEEDBACK_AUDIBLE"); 949 break; 950 case FEEDBACK_HAPTIC: 951 if (builder.length() > 1) { 952 builder.append(", "); 953 } 954 builder.append("FEEDBACK_HAPTIC"); 955 break; 956 case FEEDBACK_GENERIC: 957 if (builder.length() > 1) { 958 builder.append(", "); 959 } 960 builder.append("FEEDBACK_GENERIC"); 961 break; 962 case FEEDBACK_SPOKEN: 963 if (builder.length() > 1) { 964 builder.append(", "); 965 } 966 builder.append("FEEDBACK_SPOKEN"); 967 break; 968 case FEEDBACK_VISUAL: 969 if (builder.length() > 1) { 970 builder.append(", "); 971 } 972 builder.append("FEEDBACK_VISUAL"); 973 break; 974 case FEEDBACK_BRAILLE: 975 if (builder.length() > 1) { 976 builder.append(", "); 977 } 978 builder.append("FEEDBACK_BRAILLE"); 979 break; 980 } 981 } 982 builder.append("]"); 983 return builder.toString(); 984 } 985 986 /** 987 * Returns the string representation of a flag. For example, 988 * {@link #DEFAULT} is represented by the string DEFAULT. 989 * 990 * @param flag The flag. 991 * @return The string representation. 992 */ flagToString(int flag)993 public static String flagToString(int flag) { 994 switch (flag) { 995 case DEFAULT: 996 return "DEFAULT"; 997 case FLAG_INCLUDE_NOT_IMPORTANT_VIEWS: 998 return "FLAG_INCLUDE_NOT_IMPORTANT_VIEWS"; 999 case FLAG_REQUEST_TOUCH_EXPLORATION_MODE: 1000 return "FLAG_REQUEST_TOUCH_EXPLORATION_MODE"; 1001 case FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY: 1002 return "FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY"; 1003 case FLAG_REPORT_VIEW_IDS: 1004 return "FLAG_REPORT_VIEW_IDS"; 1005 case FLAG_REQUEST_FILTER_KEY_EVENTS: 1006 return "FLAG_REQUEST_FILTER_KEY_EVENTS"; 1007 case FLAG_RETRIEVE_INTERACTIVE_WINDOWS: 1008 return "FLAG_RETRIEVE_INTERACTIVE_WINDOWS"; 1009 case FLAG_ENABLE_ACCESSIBILITY_VOLUME: 1010 return "FLAG_ENABLE_ACCESSIBILITY_VOLUME"; 1011 case FLAG_REQUEST_ACCESSIBILITY_BUTTON: 1012 return "FLAG_REQUEST_ACCESSIBILITY_BUTTON"; 1013 case FLAG_REQUEST_FINGERPRINT_GESTURES: 1014 return "FLAG_REQUEST_FINGERPRINT_GESTURES"; 1015 default: 1016 return null; 1017 } 1018 } 1019 1020 /** 1021 * Returns the string representation of a capability. For example, 1022 * {@link #CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT} is represented 1023 * by the string CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT. 1024 * 1025 * @param capability The capability. 1026 * @return The string representation. 1027 */ capabilityToString(int capability)1028 public static String capabilityToString(int capability) { 1029 switch (capability) { 1030 case CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT: 1031 return "CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT"; 1032 case CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION: 1033 return "CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION"; 1034 case CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY: 1035 return "CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY"; 1036 case CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS: 1037 return "CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS"; 1038 case CAPABILITY_CAN_CONTROL_MAGNIFICATION: 1039 return "CAPABILITY_CAN_CONTROL_MAGNIFICATION"; 1040 case CAPABILITY_CAN_PERFORM_GESTURES: 1041 return "CAPABILITY_CAN_PERFORM_GESTURES"; 1042 case CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES: 1043 return "CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES"; 1044 default: 1045 return "UNKNOWN"; 1046 } 1047 } 1048 1049 /** 1050 * @hide 1051 * @return The list of {@link CapabilityInfo} objects. 1052 * @deprecated The version that takes a context works better. 1053 */ getCapabilityInfos()1054 public List<CapabilityInfo> getCapabilityInfos() { 1055 return getCapabilityInfos(null); 1056 } 1057 1058 /** 1059 * @hide 1060 * @param context A valid context 1061 * @return The list of {@link CapabilityInfo} objects. 1062 */ getCapabilityInfos(Context context)1063 public List<CapabilityInfo> getCapabilityInfos(Context context) { 1064 if (mCapabilities == 0) { 1065 return Collections.emptyList(); 1066 } 1067 int capabilities = mCapabilities; 1068 List<CapabilityInfo> capabilityInfos = new ArrayList<CapabilityInfo>(); 1069 SparseArray<CapabilityInfo> capabilityInfoSparseArray = 1070 getCapabilityInfoSparseArray(context); 1071 while (capabilities != 0) { 1072 final int capabilityBit = 1 << Integer.numberOfTrailingZeros(capabilities); 1073 capabilities &= ~capabilityBit; 1074 CapabilityInfo capabilityInfo = capabilityInfoSparseArray.get(capabilityBit); 1075 if (capabilityInfo != null) { 1076 capabilityInfos.add(capabilityInfo); 1077 } 1078 } 1079 return capabilityInfos; 1080 } 1081 getCapabilityInfoSparseArray(Context context)1082 private static SparseArray<CapabilityInfo> getCapabilityInfoSparseArray(Context context) { 1083 if (sAvailableCapabilityInfos == null) { 1084 sAvailableCapabilityInfos = new SparseArray<CapabilityInfo>(); 1085 sAvailableCapabilityInfos.put(CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT, 1086 new CapabilityInfo(CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT, 1087 R.string.capability_title_canRetrieveWindowContent, 1088 R.string.capability_desc_canRetrieveWindowContent)); 1089 sAvailableCapabilityInfos.put(CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION, 1090 new CapabilityInfo(CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION, 1091 R.string.capability_title_canRequestTouchExploration, 1092 R.string.capability_desc_canRequestTouchExploration)); 1093 sAvailableCapabilityInfos.put(CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS, 1094 new CapabilityInfo(CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS, 1095 R.string.capability_title_canRequestFilterKeyEvents, 1096 R.string.capability_desc_canRequestFilterKeyEvents)); 1097 sAvailableCapabilityInfos.put(CAPABILITY_CAN_CONTROL_MAGNIFICATION, 1098 new CapabilityInfo(CAPABILITY_CAN_CONTROL_MAGNIFICATION, 1099 R.string.capability_title_canControlMagnification, 1100 R.string.capability_desc_canControlMagnification)); 1101 sAvailableCapabilityInfos.put(CAPABILITY_CAN_PERFORM_GESTURES, 1102 new CapabilityInfo(CAPABILITY_CAN_PERFORM_GESTURES, 1103 R.string.capability_title_canPerformGestures, 1104 R.string.capability_desc_canPerformGestures)); 1105 if ((context == null) || fingerprintAvailable(context)) { 1106 sAvailableCapabilityInfos.put(CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES, 1107 new CapabilityInfo(CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES, 1108 R.string.capability_title_canCaptureFingerprintGestures, 1109 R.string.capability_desc_canCaptureFingerprintGestures)); 1110 } 1111 } 1112 return sAvailableCapabilityInfos; 1113 } 1114 fingerprintAvailable(Context context)1115 private static boolean fingerprintAvailable(Context context) { 1116 return context.getPackageManager().hasSystemFeature(FEATURE_FINGERPRINT) 1117 && context.getSystemService(FingerprintManager.class).isHardwareDetected(); 1118 } 1119 /** 1120 * @hide 1121 */ 1122 public static final class CapabilityInfo { 1123 public final int capability; 1124 public final int titleResId; 1125 public final int descResId; 1126 CapabilityInfo(int capability, int titleResId, int descResId)1127 public CapabilityInfo(int capability, int titleResId, int descResId) { 1128 this.capability = capability; 1129 this.titleResId = titleResId; 1130 this.descResId = descResId; 1131 } 1132 } 1133 1134 /** 1135 * @see Parcelable.Creator 1136 */ 1137 public static final Parcelable.Creator<AccessibilityServiceInfo> CREATOR = 1138 new Parcelable.Creator<AccessibilityServiceInfo>() { 1139 public AccessibilityServiceInfo createFromParcel(Parcel parcel) { 1140 AccessibilityServiceInfo info = new AccessibilityServiceInfo(); 1141 info.initFromParcel(parcel); 1142 return info; 1143 } 1144 1145 public AccessibilityServiceInfo[] newArray(int size) { 1146 return new AccessibilityServiceInfo[size]; 1147 } 1148 }; 1149 } 1150