• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.app.Service;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.os.IBinder;
23 import android.os.Looper;
24 import android.os.Message;
25 import android.os.RemoteException;
26 import android.util.Log;
27 import android.view.accessibility.AccessibilityEvent;
28 import android.view.accessibility.AccessibilityInteractionClient;
29 import android.view.accessibility.AccessibilityNodeInfo;
30 
31 import com.android.internal.os.HandlerCaller;
32 
33 /**
34  * An accessibility service runs in the background and receives callbacks by the system
35  * when {@link AccessibilityEvent}s are fired. Such events denote some state transition
36  * in the user interface, for example, the focus has changed, a button has been clicked,
37  * etc. Such a service can optionally request the capability for querying the content
38  * of the active window. Development of an accessibility service requires extending this
39  * class and implementing its abstract methods.
40  *
41  * <div class="special reference">
42  * <h3>Developer Guides</h3>
43  * <p>For more information about creating AccessibilityServices, read the
44  * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
45  * developer guide.</p>
46  * </div>
47  *
48  * <h3>Lifecycle</h3>
49  * <p>
50  * The lifecycle of an accessibility service is managed exclusively by the system and
51  * follows the established service life cycle. Additionally, starting or stopping an
52  * accessibility service is triggered exclusively by an explicit user action through
53  * enabling or disabling it in the device settings. After the system binds to a service it
54  * calls {@link AccessibilityService#onServiceConnected()}. This method can be
55  * overriden by clients that want to perform post binding setup.
56  * </p>
57  * <h3>Declaration</h3>
58  * <p>
59  * An accessibility is declared as any other service in an AndroidManifest.xml but it
60  * must also specify that it handles the "android.accessibilityservice.AccessibilityService"
61  * {@link android.content.Intent}. Failure to declare this intent will cause the system to
62  * ignore the accessibility service. Additionally an accessibility service must request the
63  * {@link android.Manifest.permission#BIND_ACCESSIBILITY_SERVICE} permission to ensure
64  * that only the system
65  * can bind to it. Failure to declare this intent will cause the system to ignore the
66  * accessibility service. Following is an example declaration:
67  * </p>
68  * <pre> &lt;service android:name=".MyAccessibilityService"
69  *         android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"&gt;
70  *     &lt;intent-filter&gt;
71  *         &lt;action android:name="android.accessibilityservice.AccessibilityService" /&gt;
72  *     &lt;/intent-filter&gt;
73  *     . . .
74  * &lt;/service&gt;</pre>
75  * <h3>Configuration</h3>
76  * <p>
77  * An accessibility service can be configured to receive specific types of accessibility events,
78  * listen only to specific packages, get events from each type only once in a given time frame,
79  * retrieve window content, specify a settings activity, etc.
80  * </p>
81  * <p>
82  * There are two approaches for configuring an accessibility service:
83  * </p>
84  * <ul>
85  * <li>
86  * Providing a {@link #SERVICE_META_DATA meta-data} entry in the manifest when declaring
87  * the service. A service declaration with a meta-data tag is presented below:
88  * <pre> &lt;service android:name=".MyAccessibilityService"&gt;
89  *     &lt;intent-filter&gt;
90  *         &lt;action android:name="android.accessibilityservice.AccessibilityService" /&gt;
91  *     &lt;/intent-filter&gt;
92  *     &lt;meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibilityservice" /&gt;
93  * &lt;/service&gt;</pre>
94  * <p class="note">
95  * <strong>Note:</strong> This approach enables setting all properties.
96  * </p>
97  * <p>
98  * For more details refer to {@link #SERVICE_META_DATA} and
99  * <code>&lt;{@link android.R.styleable#AccessibilityService accessibility-service}&gt;</code>.
100  * </p>
101  * </li>
102  * <li>
103  * Calling {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}. Note
104  * that this method can be called any time to dynamically change the service configuration.
105  * <p class="note">
106  * <strong>Note:</strong> This approach enables setting only dynamically configurable properties:
107  * {@link AccessibilityServiceInfo#eventTypes},
108  * {@link AccessibilityServiceInfo#feedbackType},
109  * {@link AccessibilityServiceInfo#flags},
110  * {@link AccessibilityServiceInfo#notificationTimeout},
111  * {@link AccessibilityServiceInfo#packageNames}
112  * </p>
113  * <p>
114  * For more details refer to {@link AccessibilityServiceInfo}.
115  * </p>
116  * </li>
117  * </ul>
118  * <h3>Retrieving window content</h3>
119  * <p>
120  * A service can specify in its declaration that it can retrieve the active window
121  * content which is represented as a tree of {@link AccessibilityNodeInfo}. Note that
122  * declaring this capability requires that the service declares its configuration via
123  * an XML resource referenced by {@link #SERVICE_META_DATA}.
124  * </p>
125  * <p>
126  * For security purposes an accessibility service can retrieve only the content of the
127  * currently active window. The currently active window is defined as the window from
128  * which was fired the last event of the following types:
129  * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED},
130  * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER},
131  * {@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT},
132  * In other words, the last window that was shown or the last window that the user has touched
133  * during touch exploration.
134  * </p>
135  * <p>
136  * The entry point for retrieving window content is through calling
137  * {@link AccessibilityEvent#getSource() AccessibilityEvent.getSource()} of the last received
138  * event of the above types or a previous event from the same window
139  * (see {@link AccessibilityEvent#getWindowId() AccessibilityEvent.getWindowId()}). Invoking
140  * this method will return an {@link AccessibilityNodeInfo} that can be used to traverse the
141  * window content which represented as a tree of such objects.
142  * </p>
143  * <p class="note">
144  * <strong>Note</strong> An accessibility service may have requested to be notified for
145  * a subset of the event types, thus be unaware that the active window has changed. Therefore
146  * accessibility service that would like to retrieve window content should:
147  * <ul>
148  * <li>
149  * Register for all event types with no notification timeout and keep track for the active
150  * window by calling {@link AccessibilityEvent#getWindowId()} of the last received event and
151  * compare this with the {@link AccessibilityNodeInfo#getWindowId()} before calling retrieval
152  * methods on the latter.
153  * </li>
154  * <li>
155  * Prepare that a retrieval method on {@link AccessibilityNodeInfo} may fail since the
156  * active window has changed and the service did not get the accessibility event yet. Note
157  * that it is possible to have a retrieval method failing even adopting the strategy
158  * specified in the previous bullet because the accessibility event dispatch is asynchronous
159  * and crosses process boundaries.
160  * </li>
161  * </ul>
162  * </p>
163  * <h3>Notification strategy</h3>
164  * <p>
165  * For each feedback type only one accessibility service is notified. Services are notified
166  * in the order of registration. Hence, if two services are registered for the same
167  * feedback type in the same package the first one wins. It is possible however, to
168  * register a service as the default one for a given feedback type. In such a case this
169  * service is invoked if no other service was interested in the event. In other words, default
170  * services do not compete with other services and are notified last regardless of the
171  * registration order. This enables "generic" accessibility services that work reasonably
172  * well with most applications to coexist with "polished" ones that are targeted for
173  * specific applications.
174  * </p>
175  * <p class="note">
176  * <strong>Note:</strong> The event notification timeout is useful to avoid propagating
177  * events to the client too frequently since this is accomplished via an expensive
178  * interprocess call. One can think of the timeout as a criteria to determine when
179  * event generation has settled down.</p>
180  * <h3>Event types</h3>
181  * <ul>
182  * <li>{@link AccessibilityEvent#TYPE_VIEW_CLICKED}
183  * <li>{@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED}
184  * <li>{@link AccessibilityEvent#TYPE_VIEW_FOCUSED}
185  * <li>{@link AccessibilityEvent#TYPE_VIEW_SELECTED}
186  * <li>{@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED}
187  * <li>{@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}
188  * <li>{@link AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED}
189  * <li>{@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START}
190  * <li>{@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END}
191  * <li>{@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}
192  * <li>{@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT}
193  * <li>{@link AccessibilityEvent#TYPE_VIEW_SCROLLED}
194  * <li>{@link AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED}
195  * <li>{@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}
196  * </ul>
197  * <h3>Feedback types</h3>
198  * <ul>
199  * <li>{@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}
200  * <li>{@link AccessibilityServiceInfo#FEEDBACK_HAPTIC}
201  * <li>{@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}
202  * <li>{@link AccessibilityServiceInfo#FEEDBACK_VISUAL}
203  * <li>{@link AccessibilityServiceInfo#FEEDBACK_GENERIC}
204  * </ul>
205  * @see AccessibilityEvent
206  * @see AccessibilityServiceInfo
207  * @see android.view.accessibility.AccessibilityManager
208  */
209 public abstract class AccessibilityService extends Service {
210 
211     /**
212      * The user has performed a swipe up gesture on the touch screen.
213      */
214     public static final int GESTURE_SWIPE_UP = 1;
215 
216     /**
217      * The user has performed a swipe down gesture on the touch screen.
218      */
219     public static final int GESTURE_SWIPE_DOWN = 2;
220 
221     /**
222      * The user has performed a swipe left gesture on the touch screen.
223      */
224     public static final int GESTURE_SWIPE_LEFT = 3;
225 
226     /**
227      * The user has performed a swipe right gesture on the touch screen.
228      */
229     public static final int GESTURE_SWIPE_RIGHT = 4;
230 
231     /**
232      * The user has performed a swipe left and right gesture on the touch screen.
233      */
234     public static final int GESTURE_SWIPE_LEFT_AND_RIGHT = 5;
235 
236     /**
237      * The user has performed a swipe right and left gesture on the touch screen.
238      */
239     public static final int GESTURE_SWIPE_RIGHT_AND_LEFT = 6;
240 
241     /**
242      * The user has performed a swipe up and down gesture on the touch screen.
243      */
244     public static final int GESTURE_SWIPE_UP_AND_DOWN = 7;
245 
246     /**
247      * The user has performed a swipe down and up gesture on the touch screen.
248      */
249     public static final int GESTURE_SWIPE_DOWN_AND_UP = 8;
250 
251     /**
252      * The user has performed a left and up gesture on the touch screen.
253      */
254     public static final int GESTURE_SWIPE_LEFT_AND_UP = 9;
255 
256     /**
257      * The user has performed a left and down gesture on the touch screen.
258      */
259     public static final int GESTURE_SWIPE_LEFT_AND_DOWN = 10;
260 
261     /**
262      * The user has performed a right and up gesture on the touch screen.
263      */
264     public static final int GESTURE_SWIPE_RIGHT_AND_UP = 11;
265 
266     /**
267      * The user has performed a right and down gesture on the touch screen.
268      */
269     public static final int GESTURE_SWIPE_RIGHT_AND_DOWN = 12;
270 
271     /**
272      * The user has performed an up and left gesture on the touch screen.
273      */
274     public static final int GESTURE_SWIPE_UP_AND_LEFT = 13;
275 
276     /**
277      * The user has performed an up and right gesture on the touch screen.
278      */
279     public static final int GESTURE_SWIPE_UP_AND_RIGHT = 14;
280 
281     /**
282      * The user has performed an down and left gesture on the touch screen.
283      */
284     public static final int GESTURE_SWIPE_DOWN_AND_LEFT = 15;
285 
286     /**
287      * The user has performed an down and right gesture on the touch screen.
288      */
289     public static final int GESTURE_SWIPE_DOWN_AND_RIGHT = 16;
290 
291     /**
292      * The {@link Intent} that must be declared as handled by the service.
293      */
294     public static final String SERVICE_INTERFACE =
295         "android.accessibilityservice.AccessibilityService";
296 
297     /**
298      * Name under which an AccessibilityService component publishes information
299      * about itself. This meta-data must reference an XML resource containing an
300      * <code>&lt;{@link android.R.styleable#AccessibilityService accessibility-service}&gt;</code>
301      * tag. This is a a sample XML file configuring an accessibility service:
302      * <pre> &lt;accessibility-service
303      *     android:accessibilityEventTypes="typeViewClicked|typeViewFocused"
304      *     android:packageNames="foo.bar, foo.baz"
305      *     android:accessibilityFeedbackType="feedbackSpoken"
306      *     android:notificationTimeout="100"
307      *     android:accessibilityFlags="flagDefault"
308      *     android:settingsActivity="foo.bar.TestBackActivity"
309      *     android:canRetrieveWindowContent="true"
310      *     . . .
311      * /&gt;</pre>
312      */
313     public static final String SERVICE_META_DATA = "android.accessibilityservice";
314 
315     /**
316      * Action to go back.
317      */
318     public static final int GLOBAL_ACTION_BACK = 1;
319 
320     /**
321      * Action to go home.
322      */
323     public static final int GLOBAL_ACTION_HOME = 2;
324 
325     /**
326      * Action to open the recent apps.
327      */
328     public static final int GLOBAL_ACTION_RECENTS = 3;
329 
330     /**
331      * Action to open the notifications.
332      */
333     public static final int GLOBAL_ACTION_NOTIFICATIONS = 4;
334 
335     /**
336      * Action to open the quick settings.
337      */
338     public static final int GLOBAL_ACTION_QUICK_SETTINGS = 5;
339 
340     private static final String LOG_TAG = "AccessibilityService";
341 
342     interface Callbacks {
onAccessibilityEvent(AccessibilityEvent event)343         public void onAccessibilityEvent(AccessibilityEvent event);
onInterrupt()344         public void onInterrupt();
onServiceConnected()345         public void onServiceConnected();
onSetConnectionId(int connectionId)346         public void onSetConnectionId(int connectionId);
onGesture(int gestureId)347         public boolean onGesture(int gestureId);
348     }
349 
350     private int mConnectionId;
351 
352     private AccessibilityServiceInfo mInfo;
353 
354     /**
355      * Callback for {@link android.view.accessibility.AccessibilityEvent}s.
356      *
357      * @param event An event.
358      */
onAccessibilityEvent(AccessibilityEvent event)359     public abstract void onAccessibilityEvent(AccessibilityEvent event);
360 
361     /**
362      * Callback for interrupting the accessibility feedback.
363      */
onInterrupt()364     public abstract void onInterrupt();
365 
366     /**
367      * This method is a part of the {@link AccessibilityService} lifecycle and is
368      * called after the system has successfully bound to the service. If is
369      * convenient to use this method for setting the {@link AccessibilityServiceInfo}.
370      *
371      * @see AccessibilityServiceInfo
372      * @see #setServiceInfo(AccessibilityServiceInfo)
373      */
onServiceConnected()374     protected void onServiceConnected() {
375 
376     }
377 
378     /**
379      * Called by the system when the user performs a specific gesture on the
380      * touch screen.
381      *
382      * <strong>Note:</strong> To receive gestures an accessibility service must
383      * request that the device is in touch exploration mode by setting the
384      * {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE}
385      * flag.
386      *
387      * @param gestureId The unique id of the performed gesture.
388      *
389      * @return Whether the gesture was handled.
390      *
391      * @see #GESTURE_SWIPE_UP
392      * @see #GESTURE_SWIPE_UP_AND_LEFT
393      * @see #GESTURE_SWIPE_UP_AND_DOWN
394      * @see #GESTURE_SWIPE_UP_AND_RIGHT
395      * @see #GESTURE_SWIPE_DOWN
396      * @see #GESTURE_SWIPE_DOWN_AND_LEFT
397      * @see #GESTURE_SWIPE_DOWN_AND_UP
398      * @see #GESTURE_SWIPE_DOWN_AND_RIGHT
399      * @see #GESTURE_SWIPE_LEFT
400      * @see #GESTURE_SWIPE_LEFT_AND_UP
401      * @see #GESTURE_SWIPE_LEFT_AND_RIGHT
402      * @see #GESTURE_SWIPE_LEFT_AND_DOWN
403      * @see #GESTURE_SWIPE_RIGHT
404      * @see #GESTURE_SWIPE_RIGHT_AND_UP
405      * @see #GESTURE_SWIPE_RIGHT_AND_LEFT
406      * @see #GESTURE_SWIPE_RIGHT_AND_DOWN
407      */
onGesture(int gestureId)408     protected boolean onGesture(int gestureId) {
409         return false;
410     }
411 
412     /**
413      * Gets the root node in the currently active window if this service
414      * can retrieve window content.
415      *
416      * @return The root node if this service can retrieve window content.
417      */
getRootInActiveWindow()418     public AccessibilityNodeInfo getRootInActiveWindow() {
419         return AccessibilityInteractionClient.getInstance().getRootInActiveWindow(mConnectionId);
420     }
421 
422     /**
423      * Performs a global action. Such an action can be performed
424      * at any moment regardless of the current application or user
425      * location in that application. For example going back, going
426      * home, opening recents, etc.
427      *
428      * @param action The action to perform.
429      * @return Whether the action was successfully performed.
430      *
431      * @see #GLOBAL_ACTION_BACK
432      * @see #GLOBAL_ACTION_HOME
433      * @see #GLOBAL_ACTION_NOTIFICATIONS
434      * @see #GLOBAL_ACTION_RECENTS
435      */
performGlobalAction(int action)436     public final boolean performGlobalAction(int action) {
437         IAccessibilityServiceConnection connection =
438             AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
439         if (connection != null) {
440             try {
441                 return connection.performGlobalAction(action);
442             } catch (RemoteException re) {
443                 Log.w(LOG_TAG, "Error while calling performGlobalAction", re);
444             }
445         }
446         return false;
447     }
448 
449     /**
450      * Gets the an {@link AccessibilityServiceInfo} describing this
451      * {@link AccessibilityService}. This method is useful if one wants
452      * to change some of the dynamically configurable properties at
453      * runtime.
454      *
455      * @return The accessibility service info.
456      *
457      * @see AccessibilityNodeInfo
458      */
getServiceInfo()459     public final AccessibilityServiceInfo getServiceInfo() {
460         IAccessibilityServiceConnection connection =
461             AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
462         if (connection != null) {
463             try {
464                 return connection.getServiceInfo();
465             } catch (RemoteException re) {
466                 Log.w(LOG_TAG, "Error while getting AccessibilityServiceInfo", re);
467             }
468         }
469         return null;
470     }
471 
472     /**
473      * Sets the {@link AccessibilityServiceInfo} that describes this service.
474      * <p>
475      * Note: You can call this method any time but the info will be picked up after
476      *       the system has bound to this service and when this method is called thereafter.
477      *
478      * @param info The info.
479      */
setServiceInfo(AccessibilityServiceInfo info)480     public final void setServiceInfo(AccessibilityServiceInfo info) {
481         mInfo = info;
482         sendServiceInfo();
483     }
484 
485     /**
486      * Sets the {@link AccessibilityServiceInfo} for this service if the latter is
487      * properly set and there is an {@link IAccessibilityServiceConnection} to the
488      * AccessibilityManagerService.
489      */
sendServiceInfo()490     private void sendServiceInfo() {
491         IAccessibilityServiceConnection connection =
492             AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
493         if (mInfo != null && connection != null) {
494             try {
495                 connection.setServiceInfo(mInfo);
496                 mInfo = null;
497                 AccessibilityInteractionClient.getInstance().clearCache();
498             } catch (RemoteException re) {
499                 Log.w(LOG_TAG, "Error while setting AccessibilityServiceInfo", re);
500             }
501         }
502     }
503 
504     /**
505      * Implement to return the implementation of the internal accessibility
506      * service interface.
507      */
508     @Override
onBind(Intent intent)509     public final IBinder onBind(Intent intent) {
510         return new IAccessibilityServiceClientWrapper(this, getMainLooper(), new Callbacks() {
511             @Override
512             public void onServiceConnected() {
513                 AccessibilityService.this.onServiceConnected();
514             }
515 
516             @Override
517             public void onInterrupt() {
518                 AccessibilityService.this.onInterrupt();
519             }
520 
521             @Override
522             public void onAccessibilityEvent(AccessibilityEvent event) {
523                 AccessibilityService.this.onAccessibilityEvent(event);
524             }
525 
526             @Override
527             public void onSetConnectionId( int connectionId) {
528                 mConnectionId = connectionId;
529             }
530 
531             @Override
532             public boolean onGesture(int gestureId) {
533                 return AccessibilityService.this.onGesture(gestureId);
534             }
535         });
536     }
537 
538     /**
539      * Implements the internal {@link IAccessibilityServiceClient} interface to convert
540      * incoming calls to it back to calls on an {@link AccessibilityService}.
541      */
542     static class IAccessibilityServiceClientWrapper extends IAccessibilityServiceClient.Stub
543             implements HandlerCaller.Callback {
544 
545         static final int NO_ID = -1;
546 
547         private static final int DO_SET_SET_CONNECTION = 10;
548         private static final int DO_ON_INTERRUPT = 20;
549         private static final int DO_ON_ACCESSIBILITY_EVENT = 30;
550         private static final int DO_ON_GESTURE = 40;
551 
552         private final HandlerCaller mCaller;
553 
554         private final Callbacks mCallback;
555 
556         public IAccessibilityServiceClientWrapper(Context context, Looper looper,
557                 Callbacks callback) {
558             mCallback = callback;
559             mCaller = new HandlerCaller(context, looper, this);
560         }
561 
562         public void setConnection(IAccessibilityServiceConnection connection, int connectionId) {
563             Message message = mCaller.obtainMessageIO(DO_SET_SET_CONNECTION, connectionId,
564                     connection);
565             mCaller.sendMessage(message);
566         }
567 
568         public void onInterrupt() {
569             Message message = mCaller.obtainMessage(DO_ON_INTERRUPT);
570             mCaller.sendMessage(message);
571         }
572 
573         public void onAccessibilityEvent(AccessibilityEvent event) {
574             Message message = mCaller.obtainMessageO(DO_ON_ACCESSIBILITY_EVENT, event);
575             mCaller.sendMessage(message);
576         }
577 
578         public void onGesture(int gestureId) {
579             Message message = mCaller.obtainMessageI(DO_ON_GESTURE, gestureId);
580             mCaller.sendMessage(message);
581         }
582 
583         public void executeMessage(Message message) {
584             switch (message.what) {
585                 case DO_ON_ACCESSIBILITY_EVENT :
586                     AccessibilityEvent event = (AccessibilityEvent) message.obj;
587                     if (event != null) {
588                         AccessibilityInteractionClient.getInstance().onAccessibilityEvent(event);
589                         mCallback.onAccessibilityEvent(event);
590                         event.recycle();
591                     }
592                     return;
593                 case DO_ON_INTERRUPT :
594                     mCallback.onInterrupt();
595                     return;
596                 case DO_SET_SET_CONNECTION :
597                     final int connectionId = message.arg1;
598                     IAccessibilityServiceConnection connection =
599                         (IAccessibilityServiceConnection) message.obj;
600                     if (connection != null) {
601                         AccessibilityInteractionClient.getInstance().addConnection(connectionId,
602                                 connection);
603                         mCallback.onSetConnectionId(connectionId);
604                         mCallback.onServiceConnected();
605                     } else {
606                         AccessibilityInteractionClient.getInstance().removeConnection(connectionId);
607                         mCallback.onSetConnectionId(AccessibilityInteractionClient.NO_ID);
608                     }
609                     return;
610                 case DO_ON_GESTURE :
611                     final int gestureId = message.arg1;
612                     mCallback.onGesture(gestureId);
613                     return;
614                 default :
615                     Log.w(LOG_TAG, "Unknown message type " + message.what);
616             }
617         }
618     }
619 }
620