diff options
| author | Svetoslav Ganov <svetoslavganov@google.com> | 2011-04-20 12:12:33 -0700 |
|---|---|---|
| committer | Svetoslav Ganov <svetoslavganov@google.com> | 2011-06-06 18:46:03 -0700 |
| commit | 8643aa0179e598e78d938c59035389054535a229 (patch) | |
| tree | c1d0ab0f77329fb34231e45703687d21a601fc88 /core/java/android/accessibilityservice | |
| parent | 219451363d7c9e657cb856bebce34bc29d7876fa (diff) | |
| download | frameworks_base-8643aa0179e598e78d938c59035389054535a229.zip frameworks_base-8643aa0179e598e78d938c59035389054535a229.tar.gz frameworks_base-8643aa0179e598e78d938c59035389054535a229.tar.bz2 | |
Interrogation of the view hierarchy from an AccessibilityService.
1. Views are represented as AccessibilityNodeInfos to AccessibilityServices.
2. An accessibility service receives AccessibilityEvents and can ask
for its source and gets an AccessibilityNodeInfo which can be used
to get its parent and children infos and so on.
3. AccessibilityNodeInfo contains some attributes and actions that
can be performed on the source.
4. AccessibilityService can request the system to preform an action
on the source of an AccessibilityNodeInfo.
5. ViewAncestor provides an interaction connection to the
AccessibiltyManagerService and an accessibility service uses
its connection to the latter to interact with screen content.
6. AccessibilityService can interact ONLY with the focused window
and all calls are routed through the AccessibilityManagerService
which imposes security.
7. Hidden APIs on AccessibilityService can find AccessibilityNodeInfos
based on some criteria. These API go through the AccessibilityManagerServcie
for security check.
8. Some actions are hidden and are exposes only to eng builds for UI testing.
Change-Id: Ie34fa4219f350eb3f4f6f9f45b24f709bd98783c
Diffstat (limited to 'core/java/android/accessibilityservice')
| -rw-r--r-- | core/java/android/accessibilityservice/AccessibilityService.java | 68 | ||||
| -rw-r--r-- | core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl | 64 |
2 files changed, 117 insertions, 15 deletions
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java index 28fc21a..8bb305d 100644 --- a/core/java/android/accessibilityservice/AccessibilityService.java +++ b/core/java/android/accessibilityservice/AccessibilityService.java @@ -25,6 +25,7 @@ import android.os.Message; import android.os.RemoteException; import android.util.Log; import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; /** * An accessibility service runs in the background and receives callbacks by the system @@ -51,7 +52,11 @@ import android.view.accessibility.AccessibilityEvent; * enabling or disabling it in the device settings. After the system binds to a service it * calls {@link AccessibilityService#onServiceConnected()}. This method can be * overriden by clients that want to perform post binding setup. + * </p> * <p> + * An accessibility service can be configured to receive specific types of accessibility events, + * listen only to specific packages, get events from each type only once in a given time frame, + * retrieve window content, specify a settings activity, etc. * </p> * There are two approaches for configuring an accessibility service: * <ul> @@ -59,20 +64,23 @@ import android.view.accessibility.AccessibilityEvent; * Providing a {@link #SERVICE_META_DATA meta-data} entry in the manifest when declaring * the service. A service declaration with a meta-data tag is presented below: * <p> - * <code> - * <service android:name=".MyAccessibilityService"><br> - * <intent-filter><br> - * <action android:name="android.accessibilityservice.AccessibilityService" /><br> - * </intent-filter><br> - * <meta-data android:name="android.accessibilityservice.as" android:resource="@xml/accessibilityservice" /><br> - * </service><br> - * </code> + * <code> + * <service android:name=".MyAccessibilityService"><br> + * <intent-filter><br> + * <action android:name="android.accessibilityservice.AccessibilityService" /><br> + * </intent-filter><br> + * <meta-data android:name="android.accessibilityservice.as" android:resource="@xml/accessibilityservice" /><br> + * </service><br> + * </code> * </p> * <p> * <strong> * This approach enables setting all accessibility service properties. * </strong> * </p> + * <p> + * For more details refer to {@link #SERVICE_META_DATA}. + * </p> * </li> * <li> * Calling {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}. Note @@ -88,6 +96,9 @@ import android.view.accessibility.AccessibilityEvent; * {@link AccessibilityServiceInfo#packageNames} * </strong> * </p> + * <p> + * For more details refer to {@link AccessibilityServiceInfo}. + * </p> * </li> * </ul> * <p> @@ -151,16 +162,49 @@ public abstract class AccessibilityService extends Service { * <code> * <?xml version="1.0" encoding="utf-8"?><br> * <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"<br> - * android:eventTypes="typeViewClicked|typeViewFocused"<br> + * android:accessibilityEventTypes="typeViewClicked|typeViewFocused"<br> * android:packageNames="foo.bar, foo.baz"<br> - * android:feedbackType="feedbackSpoken"<br> + * android:accessibilityFeedbackType="feedbackSpoken"<br> * android:notificationTimeout="100"<br> - * android:flags="flagDefault"<br> + * android:accessibilityFlags="flagDefault"<br> * android:settingsActivity="foo.bar.TestBackActivity"<br> * . . .<br> * /> * </code> * </p> + * <p> + * <strong>Note:</strong> A service can retrieve only the content of the active window. + * An active window is the source of the most recent event of type + * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START}, + * {@link AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END}, + * {@link AccessibilityEvent#TYPE_VIEW_CLICKED}, + * {@link AccessibilityEvent#TYPE_VIEW_FOCUSED}, + * {@link AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}, + * {@link AccessibilityEvent#TYPE_VIEW_HOVER_EXIT}, + * {@link AccessibilityEvent#TYPE_VIEW_LONG_CLICKED}, + * {@link AccessibilityEvent#TYPE_VIEW_SELECTED}, + * {@link AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED}, + * {@link AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED}. + * Therefore the service should: + * <ul> + * <li> + * Register for all event types with no notification timeout and keep track + * for the active window by calling + * {@link AccessibilityEvent#getAccessibilityWindowId()} of the last received + * event and compare this with the + * {@link AccessibilityNodeInfo#getAccessibilityWindowId()} before calling + * retrieval methods on the latter. + * </li> + * <li> + * Prepare that a retrieval method on {@link AccessibilityNodeInfo} may fail + * since the active window has changed and the service did not get the + * accessibility event. Note that it is possible to have a retrieval method + * failing event adopting the strategy specified in the previous bullet + * because the accessibility event dispatch is asynchronous and crosses + * process boundaries. + * </li> + * <ul> + * </p> */ public static final String SERVICE_META_DATA = "android.accessibilityservice"; @@ -224,7 +268,7 @@ public abstract class AccessibilityService extends Service { /** * Implement to return the implementation of the internal accessibility - * service interface. Subclasses should not override. + * service interface. */ @Override public final IBinder onBind(Intent intent) { diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl index 7157def..19f0bf0 100644 --- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl +++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl @@ -17,14 +17,72 @@ package android.accessibilityservice; import android.accessibilityservice.AccessibilityServiceInfo; +import android.view.accessibility.AccessibilityNodeInfo; /** - * Interface AccessibilityManagerService#Service implements, and passes to an - * AccessibilityService so it can dynamically configure how the system handles it. + * Interface given to an AccessibilitySerivce to talk to the AccessibilityManagerService. * * @hide */ -oneway interface IAccessibilityServiceConnection { +interface IAccessibilityServiceConnection { void setServiceInfo(in AccessibilityServiceInfo info); + + /** + * Finds an {@link AccessibilityNodeInfo} by accessibility id. + * <p> + * <strong> + * It is a client responsibility to recycle the received info by + * calling {@link AccessibilityNodeInfo#recycle()} to avoid creating + * of multiple instances. + * </strong> + * </p> + * + * @param accessibilityWindowId A unique window id. + * @param accessibilityViewId A unique View accessibility id. + * @return The node info. + */ + AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId, + int accessibilityViewId); + + /** + * Finds {@link AccessibilityNodeInfo}s by View text. The match is case + * insensitive containment. + * <p> + * <strong> + * It is a client responsibility to recycle the received infos by + * calling {@link AccessibilityNodeInfo#recycle()} to avoid creating + * of multiple instances. + * </strong> + * </p> + * + * @param text The searched text. + * @return A list of node info. + */ + List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText(String text); + + /** + * Finds an {@link AccessibilityNodeInfo} by View id. + * <p> + * <strong> + * It is a client responsibility to recycle the received info by + * calling {@link AccessibilityNodeInfo#recycle()} to avoid creating + * of multiple instances. + * </strong> + * </p> + * + * @param id The id of the node. + * @return The node info. + */ + AccessibilityNodeInfo findAccessibilityNodeInfoByViewId(int viewId); + + /** + * Performs an accessibility action on an {@link AccessibilityNodeInfo}. + * + * @param accessibilityWindowId The id of the window. + * @param accessibilityViewId The of a view in the . + * @return Whether the action was performed. + */ + boolean performAccessibilityAction(int accessibilityWindowId, int accessibilityViewId, + int action); } |
