Home | History | Annotate | Download | only in accessibilityservice
      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.KeyEvent;
     28 import android.view.accessibility.AccessibilityEvent;
     29 import android.view.accessibility.AccessibilityInteractionClient;
     30 import android.view.accessibility.AccessibilityNodeInfo;
     31 import android.view.accessibility.AccessibilityWindowInfo;
     32 
     33 import com.android.internal.os.HandlerCaller;
     34 
     35 import java.util.List;
     36 
     37 /**
     38  * An accessibility service runs in the background and receives callbacks by the system
     39  * when {@link AccessibilityEvent}s are fired. Such events denote some state transition
     40  * in the user interface, for example, the focus has changed, a button has been clicked,
     41  * etc. Such a service can optionally request the capability for querying the content
     42  * of the active window. Development of an accessibility service requires extending this
     43  * class and implementing its abstract methods.
     44  *
     45  * <div class="special reference">
     46  * <h3>Developer Guides</h3>
     47  * <p>For more information about creating AccessibilityServices, read the
     48  * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
     49  * developer guide.</p>
     50  * </div>
     51  *
     52  * <h3>Lifecycle</h3>
     53  * <p>
     54  * The lifecycle of an accessibility service is managed exclusively by the system and
     55  * follows the established service life cycle. Additionally, starting or stopping an
     56  * accessibility service is triggered exclusively by an explicit user action through
     57  * enabling or disabling it in the device settings. After the system binds to a service it
     58  * calls {@link AccessibilityService#onServiceConnected()}. This method can be
     59  * overriden by clients that want to perform post binding setup.
     60  * </p>
     61  * <h3>Declaration</h3>
     62  * <p>
     63  * An accessibility is declared as any other service in an AndroidManifest.xml but it
     64  * must also specify that it handles the "android.accessibilityservice.AccessibilityService"
     65  * {@link android.content.Intent}. Failure to declare this intent will cause the system to
     66  * ignore the accessibility service. Additionally an accessibility service must request the
     67  * {@link android.Manifest.permission#BIND_ACCESSIBILITY_SERVICE} permission to ensure
     68  * that only the system
     69  * can bind to it. Failure to declare this intent will cause the system to ignore the
     70  * accessibility service. Following is an example declaration:
     71  * </p>
     72  * <pre> &lt;service android:name=".MyAccessibilityService"
     73  *         android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"&gt;
     74  *     &lt;intent-filter&gt;
     75  *         &lt;action android:name="android.accessibilityservice.AccessibilityService" /&gt;
     76  *     &lt;/intent-filter&gt;
     77  *     . . .
     78  * &lt;/service&gt;</pre>
     79  * <h3>Configuration</h3>
     80  * <p>
     81  * An accessibility service can be configured to receive specific types of accessibility events,
     82  * listen only to specific packages, get events from each type only once in a given time frame,
     83  * retrieve window content, specify a settings activity, etc.
     84  * </p>
     85  * <p>
     86  * There are two approaches for configuring an accessibility service:
     87  * </p>
     88  * <ul>
     89  * <li>
     90  * Providing a {@link #SERVICE_META_DATA meta-data} entry in the manifest when declaring
     91  * the service. A service declaration with a meta-data tag is presented below:
     92  * <pre> &lt;service android:name=".MyAccessibilityService"&gt;
     93  *     &lt;intent-filter&gt;
     94  *         &lt;action android:name="android.accessibilityservice.AccessibilityService" /&gt;
     95  *     &lt;/intent-filter&gt;
     96  *     &lt;meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibilityservice" /&gt;
     97  * &lt;/service&gt;</pre>
     98  * <p class="note">
     99  * <strong>Note:</strong> This approach enables setting all properties.
    100  * </p>
    101  * <p>
    102  * For more details refer to {@link #SERVICE_META_DATA} and
    103  * <code>&lt;{@link android.R.styleable#AccessibilityService accessibility-service}&gt;</code>.
    104  * </p>
    105  * </li>
    106  * <li>
    107  * Calling {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}. Note
    108  * that this method can be called any time to dynamically change the service configuration.
    109  * <p class="note">
    110  * <strong>Note:</strong> This approach enables setting only dynamically configurable properties:
    111  * {@link AccessibilityServiceInfo#eventTypes},
    112  * {@link AccessibilityServiceInfo#feedbackType},
    113  * {@link AccessibilityServiceInfo#flags},
    114  * {@link AccessibilityServiceInfo#notificationTimeout},
    115  * {@link AccessibilityServiceInfo#packageNames}
    116  * </p>
    117  * <p>
    118  * For more details refer to {@link AccessibilityServiceInfo}.
    119  * </p>
    120  * </li>
    121  * </ul>
    122  * <h3>Retrieving window content</h3>
    123  * <p>
    124  * A service can specify in its declaration that it can retrieve the active window
    125  * content which is represented as a tree of {@link AccessibilityNodeInfo}. Note that
    126  * declaring this capability requires that the service declares its configuration via
    127  * an XML resource referenced by {@link #SERVICE_META_DATA}.
    128  * </p>
    129  * <p>
    130  * For security purposes an accessibility service can retrieve only the content of the
    131  * currently active window. The currently active window is defined as the window from
    132  * which was fired the last event of the following types:
    133  * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED},
    134  * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER},
    135  * {@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT},
    136  * In other words, the last window that was shown or the last window that the user has touched
    137  * during touch exploration.
    138  * </p>
    139  * <p>
    140  * The entry point for retrieving window content is through calling
    141  * {@link AccessibilityEvent#getSource() AccessibilityEvent.getSource()} of the last received
    142  * event of the above types or a previous event from the same window
    143  * (see {@link AccessibilityEvent#getWindowId() AccessibilityEvent.getWindowId()}). Invoking
    144  * this method will return an {@link AccessibilityNodeInfo} that can be used to traverse the
    145  * window content which represented as a tree of such objects.
    146  * </p>
    147  * <p class="note">
    148  * <strong>Note</strong> An accessibility service may have requested to be notified for
    149  * a subset of the event types, thus be unaware that the active window has changed. Therefore
    150  * accessibility service that would like to retrieve window content should:
    151  * <ul>
    152  * <li>
    153  * Register for all event types with no notification timeout and keep track for the active
    154  * window by calling {@link AccessibilityEvent#getWindowId()} of the last received event and
    155  * compare this with the {@link AccessibilityNodeInfo#getWindowId()} before calling retrieval
    156  * methods on the latter.
    157  * </li>
    158  * <li>
    159  * Prepare that a retrieval method on {@link AccessibilityNodeInfo} may fail since the
    160  * active window has changed and the service did not get the accessibility event yet. Note
    161  * that it is possible to have a retrieval method failing even adopting the strategy
    162  * specified in the previous bullet because the accessibility event dispatch is asynchronous
    163  * and crosses process boundaries.
    164  * </li>
    165  * </ul>
    166  * </p>
    167  * <h3>Notification strategy</h3>
    168  * <p>
    169  * For each feedback type only one accessibility service is notified. Services are notified
    170  * in the order of registration. Hence, if two services are registered for the same
    171  * feedback type in the same package the first one wins. It is possible however, to
    172  * register a service as the default one for a given feedback type. In such a case this
    173  * service is invoked if no other service was interested in the event. In other words, default
    174  * services do not compete with other services and are notified last regardless of the
    175  * registration order. This enables "generic" accessibility services that work reasonably
    176  * well with most applications to coexist with "polished" ones that are targeted for
    177  * specific applications.
    178  * </p>
    179  * <p class="note">
    180  * <strong>Note:</strong> The event notification timeout is useful to avoid propagating
    181  * events to the client too frequently since this is accomplished via an expensive
    182  * interprocess call. One can think of the timeout as a criteria to determine when
    183  * event generation has settled down.</p>
    184  * <h3>Event types</h3>
    185  * <ul>
    186  * <li>{@link AccessibilityEvent#TYPE_VIEW_CLICKED}</li>
    187  * <li>{@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED}</li>
    188  * <li>{@link AccessibilityEvent#TYPE_VIEW_FOCUSED}</li>
    189  * <li>{@link AccessibilityEvent#TYPE_VIEW_SELECTED}</li>
    190  * <li>{@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED}</li>
    191  * <li>{@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}</li>
    192  * <li>{@link AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED}</li>
    193  * <li>{@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START}</li>
    194  * <li>{@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END}</li>
    195  * <li>{@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}</li>
    196  * <li>{@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT}</li>
    197  * <li>{@link AccessibilityEvent#TYPE_VIEW_SCROLLED}</li>
    198  * <li>{@link AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED}</li>
    199  * <li>{@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED}</li>
    200  * <li>{@link AccessibilityEvent#TYPE_ANNOUNCEMENT}</li>
    201  * <li>{@link AccessibilityEvent#TYPE_GESTURE_DETECTION_START}</li>
    202  * <li>{@link AccessibilityEvent#TYPE_GESTURE_DETECTION_END}</li>
    203  * <li>{@link AccessibilityEvent#TYPE_TOUCH_INTERACTION_START}</li>
    204  * <li>{@link AccessibilityEvent#TYPE_TOUCH_INTERACTION_END}</li>
    205  * <li>{@link AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUSED}</li>
    206  * <li>{@link AccessibilityEvent#TYPE_WINDOWS_CHANGED}</li>
    207  * <li>{@link AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED}</li>
    208  * </ul>
    209  * <h3>Feedback types</h3>
    210  * <ul>
    211  * <li>{@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}</li>
    212  * <li>{@link AccessibilityServiceInfo#FEEDBACK_HAPTIC}</li>
    213  * <li>{@link AccessibilityServiceInfo#FEEDBACK_AUDIBLE}</li>
    214  * <li>{@link AccessibilityServiceInfo#FEEDBACK_VISUAL}</li>
    215  * <li>{@link AccessibilityServiceInfo#FEEDBACK_GENERIC}</li>
    216  * <li>{@link AccessibilityServiceInfo#FEEDBACK_BRAILLE}</li>
    217  * </ul>
    218  * @see AccessibilityEvent
    219  * @see AccessibilityServiceInfo
    220  * @see android.view.accessibility.AccessibilityManager
    221  */
    222 public abstract class AccessibilityService extends Service {
    223 
    224     /**
    225      * The user has performed a swipe up gesture on the touch screen.
    226      */
    227     public static final int GESTURE_SWIPE_UP = 1;
    228 
    229     /**
    230      * The user has performed a swipe down gesture on the touch screen.
    231      */
    232     public static final int GESTURE_SWIPE_DOWN = 2;
    233 
    234     /**
    235      * The user has performed a swipe left gesture on the touch screen.
    236      */
    237     public static final int GESTURE_SWIPE_LEFT = 3;
    238 
    239     /**
    240      * The user has performed a swipe right gesture on the touch screen.
    241      */
    242     public static final int GESTURE_SWIPE_RIGHT = 4;
    243 
    244     /**
    245      * The user has performed a swipe left and right gesture on the touch screen.
    246      */
    247     public static final int GESTURE_SWIPE_LEFT_AND_RIGHT = 5;
    248 
    249     /**
    250      * The user has performed a swipe right and left gesture on the touch screen.
    251      */
    252     public static final int GESTURE_SWIPE_RIGHT_AND_LEFT = 6;
    253 
    254     /**
    255      * The user has performed a swipe up and down gesture on the touch screen.
    256      */
    257     public static final int GESTURE_SWIPE_UP_AND_DOWN = 7;
    258 
    259     /**
    260      * The user has performed a swipe down and up gesture on the touch screen.
    261      */
    262     public static final int GESTURE_SWIPE_DOWN_AND_UP = 8;
    263 
    264     /**
    265      * The user has performed a left and up gesture on the touch screen.
    266      */
    267     public static final int GESTURE_SWIPE_LEFT_AND_UP = 9;
    268 
    269     /**
    270      * The user has performed a left and down gesture on the touch screen.
    271      */
    272     public static final int GESTURE_SWIPE_LEFT_AND_DOWN = 10;
    273 
    274     /**
    275      * The user has performed a right and up gesture on the touch screen.
    276      */
    277     public static final int GESTURE_SWIPE_RIGHT_AND_UP = 11;
    278 
    279     /**
    280      * The user has performed a right and down gesture on the touch screen.
    281      */
    282     public static final int GESTURE_SWIPE_RIGHT_AND_DOWN = 12;
    283 
    284     /**
    285      * The user has performed an up and left gesture on the touch screen.
    286      */
    287     public static final int GESTURE_SWIPE_UP_AND_LEFT = 13;
    288 
    289     /**
    290      * The user has performed an up and right gesture on the touch screen.
    291      */
    292     public static final int GESTURE_SWIPE_UP_AND_RIGHT = 14;
    293 
    294     /**
    295      * The user has performed an down and left gesture on the touch screen.
    296      */
    297     public static final int GESTURE_SWIPE_DOWN_AND_LEFT = 15;
    298 
    299     /**
    300      * The user has performed an down and right gesture on the touch screen.
    301      */
    302     public static final int GESTURE_SWIPE_DOWN_AND_RIGHT = 16;
    303 
    304     /**
    305      * The {@link Intent} that must be declared as handled by the service.
    306      */
    307     public static final String SERVICE_INTERFACE =
    308         "android.accessibilityservice.AccessibilityService";
    309 
    310     /**
    311      * Name under which an AccessibilityService component publishes information
    312      * about itself. This meta-data must reference an XML resource containing an
    313      * <code>&lt;{@link android.R.styleable#AccessibilityService accessibility-service}&gt;</code>
    314      * tag. This is a a sample XML file configuring an accessibility service:
    315      * <pre> &lt;accessibility-service
    316      *     android:accessibilityEventTypes="typeViewClicked|typeViewFocused"
    317      *     android:packageNames="foo.bar, foo.baz"
    318      *     android:accessibilityFeedbackType="feedbackSpoken"
    319      *     android:notificationTimeout="100"
    320      *     android:accessibilityFlags="flagDefault"
    321      *     android:settingsActivity="foo.bar.TestBackActivity"
    322      *     android:canRetrieveWindowContent="true"
    323      *     android:canRequestTouchExplorationMode="true"
    324      *     android:canRequestEnhancedWebAccessibility="true"
    325      *     . . .
    326      * /&gt;</pre>
    327      */
    328     public static final String SERVICE_META_DATA = "android.accessibilityservice";
    329 
    330     /**
    331      * Action to go back.
    332      */
    333     public static final int GLOBAL_ACTION_BACK = 1;
    334 
    335     /**
    336      * Action to go home.
    337      */
    338     public static final int GLOBAL_ACTION_HOME = 2;
    339 
    340     /**
    341      * Action to open the recent apps.
    342      */
    343     public static final int GLOBAL_ACTION_RECENTS = 3;
    344 
    345     /**
    346      * Action to open the notifications.
    347      */
    348     public static final int GLOBAL_ACTION_NOTIFICATIONS = 4;
    349 
    350     /**
    351      * Action to open the quick settings.
    352      */
    353     public static final int GLOBAL_ACTION_QUICK_SETTINGS = 5;
    354 
    355     /**
    356      * Action to open the power long-press dialog.
    357      */
    358     public static final int GLOBAL_ACTION_POWER_DIALOG = 6;
    359 
    360     private static final String LOG_TAG = "AccessibilityService";
    361 
    362     /**
    363      * @hide
    364      */
    365     public interface Callbacks {
    366         public void onAccessibilityEvent(AccessibilityEvent event);
    367         public void onInterrupt();
    368         public void onServiceConnected();
    369         public void onSetConnectionId(int connectionId);
    370         public boolean onGesture(int gestureId);
    371         public boolean onKeyEvent(KeyEvent event);
    372     }
    373 
    374     private int mConnectionId;
    375 
    376     private AccessibilityServiceInfo mInfo;
    377 
    378     /**
    379      * Callback for {@link android.view.accessibility.AccessibilityEvent}s.
    380      *
    381      * @param event An event.
    382      */
    383     public abstract void onAccessibilityEvent(AccessibilityEvent event);
    384 
    385     /**
    386      * Callback for interrupting the accessibility feedback.
    387      */
    388     public abstract void onInterrupt();
    389 
    390     /**
    391      * This method is a part of the {@link AccessibilityService} lifecycle and is
    392      * called after the system has successfully bound to the service. If is
    393      * convenient to use this method for setting the {@link AccessibilityServiceInfo}.
    394      *
    395      * @see AccessibilityServiceInfo
    396      * @see #setServiceInfo(AccessibilityServiceInfo)
    397      */
    398     protected void onServiceConnected() {
    399 
    400     }
    401 
    402     /**
    403      * Called by the system when the user performs a specific gesture on the
    404      * touch screen.
    405      *
    406      * <strong>Note:</strong> To receive gestures an accessibility service must
    407      * request that the device is in touch exploration mode by setting the
    408      * {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE}
    409      * flag.
    410      *
    411      * @param gestureId The unique id of the performed gesture.
    412      *
    413      * @return Whether the gesture was handled.
    414      *
    415      * @see #GESTURE_SWIPE_UP
    416      * @see #GESTURE_SWIPE_UP_AND_LEFT
    417      * @see #GESTURE_SWIPE_UP_AND_DOWN
    418      * @see #GESTURE_SWIPE_UP_AND_RIGHT
    419      * @see #GESTURE_SWIPE_DOWN
    420      * @see #GESTURE_SWIPE_DOWN_AND_LEFT
    421      * @see #GESTURE_SWIPE_DOWN_AND_UP
    422      * @see #GESTURE_SWIPE_DOWN_AND_RIGHT
    423      * @see #GESTURE_SWIPE_LEFT
    424      * @see #GESTURE_SWIPE_LEFT_AND_UP
    425      * @see #GESTURE_SWIPE_LEFT_AND_RIGHT
    426      * @see #GESTURE_SWIPE_LEFT_AND_DOWN
    427      * @see #GESTURE_SWIPE_RIGHT
    428      * @see #GESTURE_SWIPE_RIGHT_AND_UP
    429      * @see #GESTURE_SWIPE_RIGHT_AND_LEFT
    430      * @see #GESTURE_SWIPE_RIGHT_AND_DOWN
    431      */
    432     protected boolean onGesture(int gestureId) {
    433         return false;
    434     }
    435 
    436     /**
    437      * Callback that allows an accessibility service to observe the key events
    438      * before they are passed to the rest of the system. This means that the events
    439      * are first delivered here before they are passed to the device policy, the
    440      * input method, or applications.
    441      * <p>
    442      * <strong>Note:</strong> It is important that key events are handled in such
    443      * a way that the event stream that would be passed to the rest of the system
    444      * is well-formed. For example, handling the down event but not the up event
    445      * and vice versa would generate an inconsistent event stream.
    446      * </p>
    447      * <p>
    448      * <strong>Note:</strong> The key events delivered in this method are copies
    449      * and modifying them will have no effect on the events that will be passed
    450      * to the system. This method is intended to perform purely filtering
    451      * functionality.
    452      * <p>
    453      *
    454      * @param event The event to be processed.
    455      * @return If true then the event will be consumed and not delivered to
    456      *         applications, otherwise it will be delivered as usual.
    457      */
    458     protected boolean onKeyEvent(KeyEvent event) {
    459         return false;
    460     }
    461 
    462     /**
    463      * Gets the windows on the screen. This method returns only the windows
    464      * that a sighted user can interact with, as opposed to all windows.
    465      * For example, if there is a modal dialog shown and the user cannot touch
    466      * anything behind it, then only the modal window will be reported
    467      * (assuming it is the top one). For convenience the returned windows
    468      * are ordered in a descending layer order, which is the windows that
    469      * are higher in the Z-order are reported first. Since the user can always
    470      * interact with the window that has input focus by typing, the focused
    471      * window is always returned (even if covered by a modal window).
    472      * <p>
    473      * <strong>Note:</strong> In order to access the windows your service has
    474      * to declare the capability to retrieve window content by setting the
    475      * {@link android.R.styleable#AccessibilityService_canRetrieveWindowContent}
    476      * property in its meta-data. For details refer to {@link #SERVICE_META_DATA}.
    477      * Also the service has to opt-in to retrieve the interactive windows by
    478      * setting the {@link AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS}
    479      * flag.
    480      * </p>
    481      *
    482      * @return The windows if there are windows and the service is can retrieve
    483      *         them, otherwise an empty list.
    484      */
    485     public List<AccessibilityWindowInfo> getWindows() {
    486         return AccessibilityInteractionClient.getInstance().getWindows(mConnectionId);
    487     }
    488 
    489     /**
    490      * Gets the root node in the currently active window if this service
    491      * can retrieve window content. The active window is the one that the user
    492      * is currently touching or the window with input focus, if the user is not
    493      * touching any window.
    494      * <p>
    495      * <strong>Note:</strong> In order to access the root node your service has
    496      * to declare the capability to retrieve window content by setting the
    497      * {@link android.R.styleable#AccessibilityService_canRetrieveWindowContent}
    498      * property in its meta-data. For details refer to {@link #SERVICE_META_DATA}.
    499      * </p>
    500      *
    501      * @return The root node if this service can retrieve window content.
    502      */
    503     public AccessibilityNodeInfo getRootInActiveWindow() {
    504         return AccessibilityInteractionClient.getInstance().getRootInActiveWindow(mConnectionId);
    505     }
    506 
    507     /**
    508      * Performs a global action. Such an action can be performed
    509      * at any moment regardless of the current application or user
    510      * location in that application. For example going back, going
    511      * home, opening recents, etc.
    512      *
    513      * @param action The action to perform.
    514      * @return Whether the action was successfully performed.
    515      *
    516      * @see #GLOBAL_ACTION_BACK
    517      * @see #GLOBAL_ACTION_HOME
    518      * @see #GLOBAL_ACTION_NOTIFICATIONS
    519      * @see #GLOBAL_ACTION_RECENTS
    520      */
    521     public final boolean performGlobalAction(int action) {
    522         IAccessibilityServiceConnection connection =
    523             AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
    524         if (connection != null) {
    525             try {
    526                 return connection.performGlobalAction(action);
    527             } catch (RemoteException re) {
    528                 Log.w(LOG_TAG, "Error while calling performGlobalAction", re);
    529             }
    530         }
    531         return false;
    532     }
    533 
    534     /**
    535      * Find the view that has the specified focus type. The search is performed
    536      * across all windows.
    537      * <p>
    538      * <strong>Note:</strong> In order to access the windows your service has
    539      * to declare the capability to retrieve window content by setting the
    540      * {@link android.R.styleable#AccessibilityService_canRetrieveWindowContent}
    541      * property in its meta-data. For details refer to {@link #SERVICE_META_DATA}.
    542      * Also the service has to opt-in to retrieve the interactive windows by
    543      * setting the {@link AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS}
    544      * flag.Otherwise, the search will be performed only in the active window.
    545      * </p>
    546      *
    547      * @param focus The focus to find. One of {@link AccessibilityNodeInfo#FOCUS_INPUT} or
    548      *         {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}.
    549      * @return The node info of the focused view or null.
    550      *
    551      * @see AccessibilityNodeInfo#FOCUS_INPUT
    552      * @see AccessibilityNodeInfo#FOCUS_ACCESSIBILITY
    553      */
    554     public AccessibilityNodeInfo findFocus(int focus) {
    555         return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId,
    556                 AccessibilityNodeInfo.ANY_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID, focus);
    557     }
    558 
    559     /**
    560      * Gets the an {@link AccessibilityServiceInfo} describing this
    561      * {@link AccessibilityService}. This method is useful if one wants
    562      * to change some of the dynamically configurable properties at
    563      * runtime.
    564      *
    565      * @return The accessibility service info.
    566      *
    567      * @see AccessibilityServiceInfo
    568      */
    569     public final AccessibilityServiceInfo getServiceInfo() {
    570         IAccessibilityServiceConnection connection =
    571             AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
    572         if (connection != null) {
    573             try {
    574                 return connection.getServiceInfo();
    575             } catch (RemoteException re) {
    576                 Log.w(LOG_TAG, "Error while getting AccessibilityServiceInfo", re);
    577             }
    578         }
    579         return null;
    580     }
    581 
    582     /**
    583      * Sets the {@link AccessibilityServiceInfo} that describes this service.
    584      * <p>
    585      * Note: You can call this method any time but the info will be picked up after
    586      *       the system has bound to this service and when this method is called thereafter.
    587      *
    588      * @param info The info.
    589      */
    590     public final void setServiceInfo(AccessibilityServiceInfo info) {
    591         mInfo = info;
    592         sendServiceInfo();
    593     }
    594 
    595     /**
    596      * Sets the {@link AccessibilityServiceInfo} for this service if the latter is
    597      * properly set and there is an {@link IAccessibilityServiceConnection} to the
    598      * AccessibilityManagerService.
    599      */
    600     private void sendServiceInfo() {
    601         IAccessibilityServiceConnection connection =
    602             AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
    603         if (mInfo != null && connection != null) {
    604             try {
    605                 connection.setServiceInfo(mInfo);
    606                 mInfo = null;
    607                 AccessibilityInteractionClient.getInstance().clearCache();
    608             } catch (RemoteException re) {
    609                 Log.w(LOG_TAG, "Error while setting AccessibilityServiceInfo", re);
    610             }
    611         }
    612     }
    613 
    614     /**
    615      * Implement to return the implementation of the internal accessibility
    616      * service interface.
    617      */
    618     @Override
    619     public final IBinder onBind(Intent intent) {
    620         return new IAccessibilityServiceClientWrapper(this, getMainLooper(), new Callbacks() {
    621             @Override
    622             public void onServiceConnected() {
    623                 AccessibilityService.this.onServiceConnected();
    624             }
    625 
    626             @Override
    627             public void onInterrupt() {
    628                 AccessibilityService.this.onInterrupt();
    629             }
    630 
    631             @Override
    632             public void onAccessibilityEvent(AccessibilityEvent event) {
    633                 AccessibilityService.this.onAccessibilityEvent(event);
    634             }
    635 
    636             @Override
    637             public void onSetConnectionId( int connectionId) {
    638                 mConnectionId = connectionId;
    639             }
    640 
    641             @Override
    642             public boolean onGesture(int gestureId) {
    643                 return AccessibilityService.this.onGesture(gestureId);
    644             }
    645 
    646             @Override
    647             public boolean onKeyEvent(KeyEvent event) {
    648                 return AccessibilityService.this.onKeyEvent(event);
    649             }
    650         });
    651     }
    652 
    653     /**
    654      * Implements the internal {@link IAccessibilityServiceClient} interface to convert
    655      * incoming calls to it back to calls on an {@link AccessibilityService}.
    656      *
    657      * @hide
    658      */
    659     public static class IAccessibilityServiceClientWrapper extends IAccessibilityServiceClient.Stub
    660             implements HandlerCaller.Callback {
    661         private static final int DO_SET_SET_CONNECTION = 1;
    662         private static final int DO_ON_INTERRUPT = 2;
    663         private static final int DO_ON_ACCESSIBILITY_EVENT = 3;
    664         private static final int DO_ON_GESTURE = 4;
    665         private static final int DO_CLEAR_ACCESSIBILITY_CACHE = 5;
    666         private static final int DO_ON_KEY_EVENT = 6;
    667 
    668         private final HandlerCaller mCaller;
    669 
    670         private final Callbacks mCallback;
    671 
    672         private int mConnectionId;
    673 
    674         public IAccessibilityServiceClientWrapper(Context context, Looper looper,
    675                 Callbacks callback) {
    676             mCallback = callback;
    677             mCaller = new HandlerCaller(context, looper, this, true /*asyncHandler*/);
    678         }
    679 
    680         public void setConnection(IAccessibilityServiceConnection connection, int connectionId) {
    681             Message message = mCaller.obtainMessageIO(DO_SET_SET_CONNECTION, connectionId,
    682                     connection);
    683             mCaller.sendMessage(message);
    684         }
    685 
    686         public void onInterrupt() {
    687             Message message = mCaller.obtainMessage(DO_ON_INTERRUPT);
    688             mCaller.sendMessage(message);
    689         }
    690 
    691         public void onAccessibilityEvent(AccessibilityEvent event) {
    692             Message message = mCaller.obtainMessageO(DO_ON_ACCESSIBILITY_EVENT, event);
    693             mCaller.sendMessage(message);
    694         }
    695 
    696         public void onGesture(int gestureId) {
    697             Message message = mCaller.obtainMessageI(DO_ON_GESTURE, gestureId);
    698             mCaller.sendMessage(message);
    699         }
    700 
    701         public void clearAccessibilityCache() {
    702             Message message = mCaller.obtainMessage(DO_CLEAR_ACCESSIBILITY_CACHE);
    703             mCaller.sendMessage(message);
    704         }
    705 
    706         @Override
    707         public void onKeyEvent(KeyEvent event, int sequence) {
    708             Message message = mCaller.obtainMessageIO(DO_ON_KEY_EVENT, sequence, event);
    709             mCaller.sendMessage(message);
    710         }
    711 
    712         @Override
    713         public void executeMessage(Message message) {
    714             switch (message.what) {
    715                 case DO_ON_ACCESSIBILITY_EVENT: {
    716                     AccessibilityEvent event = (AccessibilityEvent) message.obj;
    717                     if (event != null) {
    718                         AccessibilityInteractionClient.getInstance().onAccessibilityEvent(event);
    719                         mCallback.onAccessibilityEvent(event);
    720                         // Make sure the event is recycled.
    721                         try {
    722                             event.recycle();
    723                         } catch (IllegalStateException ise) {
    724                             /* ignore - best effort */
    725                         }
    726                     }
    727                 } return;
    728 
    729                 case DO_ON_INTERRUPT: {
    730                     mCallback.onInterrupt();
    731                 } return;
    732 
    733                 case DO_SET_SET_CONNECTION: {
    734                     mConnectionId = message.arg1;
    735                     IAccessibilityServiceConnection connection =
    736                         (IAccessibilityServiceConnection) message.obj;
    737                     if (connection != null) {
    738                         AccessibilityInteractionClient.getInstance().addConnection(mConnectionId,
    739                                 connection);
    740                         mCallback.onSetConnectionId(mConnectionId);
    741                         mCallback.onServiceConnected();
    742                     } else {
    743                         AccessibilityInteractionClient.getInstance().removeConnection(
    744                                 mConnectionId);
    745                         AccessibilityInteractionClient.getInstance().clearCache();
    746                         mCallback.onSetConnectionId(AccessibilityInteractionClient.NO_ID);
    747                     }
    748                 } return;
    749 
    750                 case DO_ON_GESTURE: {
    751                     final int gestureId = message.arg1;
    752                     mCallback.onGesture(gestureId);
    753                 } return;
    754 
    755                 case DO_CLEAR_ACCESSIBILITY_CACHE: {
    756                     AccessibilityInteractionClient.getInstance().clearCache();
    757                 } return;
    758 
    759                 case DO_ON_KEY_EVENT: {
    760                     KeyEvent event = (KeyEvent) message.obj;
    761                     try {
    762                         IAccessibilityServiceConnection connection = AccessibilityInteractionClient
    763                                 .getInstance().getConnection(mConnectionId);
    764                         if (connection != null) {
    765                             final boolean result = mCallback.onKeyEvent(event);
    766                             final int sequence = message.arg1;
    767                             try {
    768                                 connection.setOnKeyEventResult(result, sequence);
    769                             } catch (RemoteException re) {
    770                                 /* ignore */
    771                             }
    772                         }
    773                     } finally {
    774                         // Make sure the event is recycled.
    775                         try {
    776                             event.recycle();
    777                         } catch (IllegalStateException ise) {
    778                             /* ignore - best effort */
    779                         }
    780                     }
    781                 } return;
    782 
    783                 default :
    784                     Log.w(LOG_TAG, "Unknown message type " + message.what);
    785             }
    786         }
    787     }
    788 }
    789