Accessibility serviceconfiguration via meta-data
Note: This is a part of two CL change and contains the
system changes without updates to the settings.
1. Added a mechanism for configuring an accessibility service via
XML file specified in a meta-data tag (similar to IMEs).
2. Added property for specifying a settings activity for an
accessibility service.
3. Refactored the APIs in AccessibilityManager to return
lists of AccessiblityServiceInfo instead ServiceInfo
since the former describes an AccessibilityService in
particular (similar to IMEs).
Change-Id: Ie8781bb7e0cdb329e583b6702a612a507367ad7b
diff --git a/api/current.txt b/api/current.txt
index 1e90e47..3f41ca8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -269,6 +269,7 @@
field public static final int cacheColorHint = 16843009; // 0x1010101
field public static final int calendarViewShown = 16843596; // 0x101034c
field public static final int calendarViewStyle = 16843613; // 0x101035d
+ field public static final int canRetrieveWindowContent = 16843646; // 0x101037e
field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
field public static final deprecated int capitalize = 16843113; // 0x1010169
field public static final int centerBright = 16842956; // 0x10100cc
@@ -309,6 +310,7 @@
field public static final int completionHintView = 16843123; // 0x1010173
field public static final int completionThreshold = 16843124; // 0x1010174
field public static final int configChanges = 16842783; // 0x101001f
+ field public static final int configurationFlags = 16843645; // 0x101037d
field public static final int configure = 16843357; // 0x101025d
field public static final int constantSize = 16843158; // 0x1010196
field public static final int content = 16843355; // 0x101025b
@@ -387,6 +389,7 @@
field public static final int enterFadeDuration = 16843532; // 0x101030c
field public static final int entries = 16842930; // 0x10100b2
field public static final int entryValues = 16843256; // 0x10101f8
+ field public static final int eventNotificationTimeout = 16843644; // 0x101037c
field public static final int eventsInterceptionEnabled = 16843389; // 0x101027d
field public static final int excludeFromRecents = 16842775; // 0x1010017
field public static final int exitFadeDuration = 16843533; // 0x101030d
@@ -469,6 +472,8 @@
field public static final int hand_minute = 16843012; // 0x1010104
field public static final int handle = 16843354; // 0x101025a
field public static final int handleProfiling = 16842786; // 0x1010022
+ field public static final int handledEventTypes = 16843641; // 0x1010379
+ field public static final int handledPackageNames = 16843642; // 0x101037a
field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e
field public static final int hardwareAccelerated = 16843475; // 0x10102d3
field public static final int hasCode = 16842764; // 0x101000c
@@ -724,6 +729,7 @@
field public static final int prompt = 16843131; // 0x101017b
field public static final int propertyName = 16843489; // 0x10102e1
field public static final int protectionLevel = 16842761; // 0x1010009
+ field public static final int providedFeedbackType = 16843643; // 0x101037b
field public static final int queryActionMsg = 16843227; // 0x10101db
field public static final int queryAfterZeroResults = 16843394; // 0x1010282
field public static final int queryHint = 16843608; // 0x1010358
@@ -1693,11 +1699,18 @@
method protected void onServiceConnected();
method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService";
+ field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
}
public class AccessibilityServiceInfo implements android.os.Parcelable {
ctor public AccessibilityServiceInfo();
method public int describeContents();
+ method public static java.lang.String feedbackTypeToString(int);
+ method public static java.lang.String flagToString(int);
+ method public boolean getCanRetrieveWindowContent();
+ method public java.lang.String getId();
+ method public android.content.pm.ResolveInfo getResolveInfo();
+ method public java.lang.String getSettingsActivityName();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int DEFAULT = 1; // 0x1
@@ -22250,6 +22263,7 @@
public final class AccessibilityEvent extends android.view.accessibility.AccessibilityRecord implements android.os.Parcelable {
method public void appendRecord(android.view.accessibility.AccessibilityRecord);
method public int describeContents();
+ method public static java.lang.String eventTypeToString(int);
method public long getEventTime();
method public int getEventType();
method public java.lang.CharSequence getPackageName();
@@ -22285,8 +22299,9 @@
}
public final class AccessibilityManager {
- method public java.util.List<android.content.pm.ServiceInfo> getAccessibilityServiceList();
- method public java.util.List<android.content.pm.ServiceInfo> getEnabledAccessibilityServiceList(int);
+ method public deprecated java.util.List<android.content.pm.ServiceInfo> getAccessibilityServiceList();
+ method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int);
+ method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList();
method public void interrupt();
method public boolean isEnabled();
method public void sendAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 03346fe..28fc21a 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -39,21 +39,57 @@
* <p>
* <code>
* <service android:name=".MyAccessibilityService"><br>
- * <intent-filter><br>
- * <action android:name="android.accessibilityservice.AccessibilityService" /><br>
- * </intent-filter><br>
+ * <intent-filter><br>
+ * <action android:name="android.accessibilityservice.AccessibilityService" /><br>
+ * </intent-filter><br>
* </service><br>
* </code>
+ * </p>
* <p>
* The lifecycle of an accessibility service is managed exclusively by the system. Starting
* or stopping an accessibility service is triggered by an explicit user action through
* 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. An accessibility service
- * is configured though setting an {@link AccessibilityServiceInfo} by calling
- * {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}. You can call this
- * method any time to change the service configuration but it is good practice to do that
- * in the overriden {@link AccessibilityService#onServiceConnected()}.
+ * overriden by clients that want to perform post binding setup.
+ * <p>
+ * </p>
+ * There are two approaches for configuring an accessibility service:
+ * <ul>
+ * <li>
+ * 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>
+ * </p>
+ * <p>
+ * <strong>
+ * This approach enables setting all accessibility service properties.
+ * </strong>
+ * </p>
+ * </li>
+ * <li>
+ * Calling {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}. Note
+ * that this method can be called any time to change the service configuration.<br>
+ * <p>
+ * <strong>
+ * This approach enables setting only dynamically configurable accessibility
+ * service properties:
+ * {@link AccessibilityServiceInfo#eventTypes},
+ * {@link AccessibilityServiceInfo#feedbackType},
+ * {@link AccessibilityServiceInfo#flags},
+ * {@link AccessibilityServiceInfo#notificationTimeout},
+ * {@link AccessibilityServiceInfo#packageNames}
+ * </strong>
+ * </p>
+ * </li>
+ * </ul>
* <p>
* An accessibility service can be registered for events in specific packages to provide a
* specific type of feedback and is notified with a certain timeout after the last event
@@ -105,6 +141,29 @@
public static final String SERVICE_INTERFACE =
"android.accessibilityservice.AccessibilityService";
+ /**
+ * Name under which an AccessibilityService component publishes information
+ * about itself. This meta-data must reference an XML resource containing
+ * an
+ * <code><{@link android.R.styleable#AccessibilityService accessibility-service}></code>
+ * tag. This is a a sample XML file configuring an accessibility service:
+ * <p>
+ * <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:packageNames="foo.bar, foo.baz"<br>
+ * android:feedbackType="feedbackSpoken"<br>
+ * android:notificationTimeout="100"<br>
+ * android:flags="flagDefault"<br>
+ * android:settingsActivity="foo.bar.TestBackActivity"<br>
+ * . . .<br>
+ * />
+ * </code>
+ * </p>
+ */
+ public static final String SERVICE_META_DATA = "android.accessibilityservice";
+
private static final String LOG_TAG = "AccessibilityService";
private AccessibilityServiceInfo mInfo;
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index bf9e07d..b9878cd 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -16,8 +16,25 @@
package android.accessibilityservice;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.Xml;
+import android.view.accessibility.AccessibilityEvent;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
/**
* This class describes an {@link AccessibilityService}. The system
@@ -30,6 +47,8 @@
*/
public class AccessibilityServiceInfo implements Parcelable {
+ private static final String TAG_ACCESSIBILITY_SERVICE = "accessibility-service";
+
/**
* Denotes spoken feedback.
*/
@@ -64,7 +83,9 @@
/**
* The event types an {@link AccessibilityService} is interested in.
- *
+ * <p>
+ * <strong>Can be dynamically set at runtime.</strong>
+ * </p>
* @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED
* @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_LONG_CLICKED
* @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_FOCUSED
@@ -77,13 +98,18 @@
/**
* The package names an {@link AccessibilityService} is interested in. Setting
- * to null is equivalent to all packages.
+ * to null is equivalent to all packages.
+ * <p>
+ * <strong>Can be dynamically set at runtime.</strong>
+ * </p>
*/
public String[] packageNames;
/**
* The feedback type an {@link AccessibilityService} provides.
- *
+ * <p>
+ * <strong>Can be dynamically set at runtime.</strong>
+ * </p>
* @see #FEEDBACK_AUDIBLE
* @see #FEEDBACK_GENERIC
* @see #FEEDBACK_HAPTIC
@@ -96,6 +122,9 @@
* The timeout after the most recent event of a given type before an
* {@link AccessibilityService} is notified.
* <p>
+ * <strong>Can be dynamically set at runtime.</strong>.
+ * </p>
+ * <p>
* Note: The event notification timeout is useful to avoid propagating events to the client
* too frequently since this is accomplished via an expensive interprocess call.
* One can think of the timeout as a criteria to determine when event generation has
@@ -106,11 +135,181 @@
/**
* This field represents a set of flags used for configuring an
* {@link AccessibilityService}.
- *
+ * <p>
+ * <strong>Can be dynamically set at runtime.</strong>
+ * </p>
* @see #DEFAULT
*/
public int flags;
+ /**
+ * The unique string Id to identify the accessibility service.
+ */
+ private String mId;
+
+ /**
+ * The Service that implements this accessibility service component.
+ */
+ private ResolveInfo mResolveInfo;
+
+ /**
+ * The accessibility service setting activity's name, used by the system
+ * settings to launch the setting activity of this accessibility service.
+ */
+ private String mSettingsActivityName;
+
+ /**
+ * Flag whether this accessibility service can retrieve screen content.
+ */
+ private boolean mCanRetrieveWindowContent;
+
+ /**
+ * Creates a new instance.
+ */
+ public AccessibilityServiceInfo() {
+ /* do nothing */
+ }
+
+ /**
+ * Creates a new instance.
+ *
+ * @param resolveInfo The service resolve info.
+ * @param context Context for accessing resources.
+ * @throws XmlPullParserException If a XML parsing error occurs.
+ * @throws IOException If a XML parsing error occurs.
+ *
+ * @hide
+ */
+ public AccessibilityServiceInfo(ResolveInfo resolveInfo, Context context)
+ throws XmlPullParserException, IOException {
+ ServiceInfo serviceInfo = resolveInfo.serviceInfo;
+ mId = new ComponentName(serviceInfo.packageName, serviceInfo.name).flattenToShortString();
+ mResolveInfo = resolveInfo;
+
+ String settingsActivityName = null;
+ boolean retrieveScreenContent = false;
+ XmlResourceParser parser = null;
+
+ try {
+ PackageManager packageManager = context.getPackageManager();
+ parser = serviceInfo.loadXmlMetaData(packageManager,
+ AccessibilityService.SERVICE_META_DATA);
+ if (parser == null) {
+ return;
+ }
+
+ int type = 0;
+ while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) {
+ type = parser.next();
+ }
+
+ String nodeName = parser.getName();
+ if (!TAG_ACCESSIBILITY_SERVICE.equals(nodeName)) {
+ throw new XmlPullParserException( "Meta-data does not start with"
+ + TAG_ACCESSIBILITY_SERVICE + " tag");
+ }
+
+ AttributeSet allAttributes = Xml.asAttributeSet(parser);
+ Resources resources = packageManager.getResourcesForApplication(
+ serviceInfo.applicationInfo);
+ TypedArray asAttributes = resources.obtainAttributes(allAttributes,
+ com.android.internal.R.styleable.AccessibilityService);
+ eventTypes = asAttributes.getInt(
+ com.android.internal.R.styleable.AccessibilityService_accessibilityEventTypes,
+ 0);
+ String packageNamez = asAttributes.getString(
+ com.android.internal.R.styleable.AccessibilityService_packageNames);
+ if (packageNamez != null) {
+ packageNames = packageNamez.split("(\\s)*,(\\s)*");
+ }
+ feedbackType = asAttributes.getInt(
+ com.android.internal.R.styleable.AccessibilityService_accessibilityFeedbackType,
+ 0);
+ notificationTimeout = asAttributes.getInt(
+ com.android.internal.R.styleable.AccessibilityService_notificationTimeout,
+ 0);
+ flags = asAttributes.getInt(
+ com.android.internal.R.styleable.AccessibilityService_accessibilityFlags, 0);
+ mSettingsActivityName = asAttributes.getString(
+ com.android.internal.R.styleable.AccessibilityService_settingsActivity);
+ mCanRetrieveWindowContent = asAttributes.getBoolean(
+ com.android.internal.R.styleable.AccessibilityService_canRetrieveWindowContent,
+ false);
+ asAttributes.recycle();
+ } catch (NameNotFoundException e) {
+ throw new XmlPullParserException( "Unable to create context for: "
+ + serviceInfo.packageName);
+ } finally {
+ if (parser != null) {
+ parser.close();
+ }
+ }
+ }
+
+ /**
+ * Updates the properties that an AccessibilitySerivice can change dynamically.
+ *
+ * @param other The info from which to update the properties.
+ *
+ * @hide
+ */
+ public void updateDynamicallyConfigurableProperties(AccessibilityServiceInfo other) {
+ eventTypes = other.eventTypes;
+ packageNames = other.packageNames;
+ feedbackType = other.feedbackType;
+ notificationTimeout = other.notificationTimeout;
+ flags = other.flags;
+ }
+
+ /**
+ * The accessibility service id.
+ * <p>
+ * <strong>Generated by the system.</strong>
+ * </p>
+ * @return The id.
+ */
+ public String getId() {
+ return mId;
+ }
+
+ /**
+ * The service {@link ResolveInfo}.
+ * <p>
+ * <strong>Generated by the system.</strong>
+ * </p>
+ * @return The info.
+ */
+ public ResolveInfo getResolveInfo() {
+ return mResolveInfo;
+ }
+
+ /**
+ * The settings activity name.
+ * <p>
+ * <strong>Statically set from
+ * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
+ * </p>
+ * @return The settings activity name.
+ */
+ public String getSettingsActivityName() {
+ return mSettingsActivityName;
+ }
+
+ /**
+ * Whether this service can retrieve the currently focused window content.
+ * <p>
+ * <strong>Statically set from
+ * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
+ * </p>
+ * @return True screen content is retrieved.
+ */
+ public boolean getCanRetrieveWindowContent() {
+ return mCanRetrieveWindowContent;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public int describeContents() {
return 0;
}
@@ -121,6 +320,142 @@
parcel.writeInt(feedbackType);
parcel.writeLong(notificationTimeout);
parcel.writeInt(flags);
+ parcel.writeString(mId);
+ parcel.writeParcelable(mResolveInfo, 0);
+ parcel.writeString(mSettingsActivityName);
+ parcel.writeInt(mCanRetrieveWindowContent ? 1 : 0);
+ }
+
+ private void initFromParcel(Parcel parcel) {
+ eventTypes = parcel.readInt();
+ packageNames = parcel.readStringArray();
+ feedbackType = parcel.readInt();
+ notificationTimeout = parcel.readLong();
+ flags = parcel.readInt();
+ mId = parcel.readString();
+ mResolveInfo = parcel.readParcelable(null);
+ mSettingsActivityName = parcel.readString();
+ mCanRetrieveWindowContent = (parcel.readInt() == 1);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder stringBuilder = new StringBuilder();
+ appendEventTypes(stringBuilder, eventTypes);
+ stringBuilder.append(", ");
+ appendPackageNames(stringBuilder, packageNames);
+ stringBuilder.append(", ");
+ appendFeedbackTypes(stringBuilder, feedbackType);
+ stringBuilder.append(", ");
+ stringBuilder.append("notificationTimeout: ").append(notificationTimeout);
+ stringBuilder.append(", ");
+ appendFlags(stringBuilder, flags);
+ stringBuilder.append(", ");
+ stringBuilder.append("id: ").append(mId);
+ stringBuilder.append(", ");
+ stringBuilder.append("resolveInfo: ").append(mResolveInfo);
+ stringBuilder.append(", ");
+ stringBuilder.append("settingsActivityName: ").append(mSettingsActivityName);
+ stringBuilder.append(", ");
+ stringBuilder.append("retrieveScreenContent: ").append(mCanRetrieveWindowContent);
+ return stringBuilder.toString();
+ }
+
+ private static void appendFeedbackTypes(StringBuilder stringBuilder, int feedbackTypes) {
+ stringBuilder.append("feedbackTypes:");
+ stringBuilder.append("[");
+ while (feedbackTypes != 0) {
+ final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackTypes));
+ stringBuilder.append(feedbackTypeToString(feedbackTypeBit));
+ feedbackTypes &= ~feedbackTypeBit;
+ if (feedbackTypes != 0) {
+ stringBuilder.append(", ");
+ }
+ }
+ stringBuilder.append("]");
+ }
+
+ private static void appendPackageNames(StringBuilder stringBuilder, String[] packageNames) {
+ stringBuilder.append("packageNames:");
+ stringBuilder.append("[");
+ if (packageNames != null) {
+ final int packageNameCount = packageNames.length;
+ for (int i = 0; i < packageNameCount; i++) {
+ stringBuilder.append(packageNames[i]);
+ if (i < packageNameCount - 1) {
+ stringBuilder.append(", ");
+ }
+ }
+ }
+ stringBuilder.append("]");
+ }
+
+ private static void appendEventTypes(StringBuilder stringBuilder, int eventTypes) {
+ stringBuilder.append("eventTypes:");
+ stringBuilder.append("[");
+ while (eventTypes != 0) {
+ final int eventTypeBit = (1 << Integer.numberOfTrailingZeros(eventTypes));
+ stringBuilder.append(AccessibilityEvent.eventTypeToString(eventTypeBit));
+ eventTypes &= ~eventTypeBit;
+ if (eventTypes != 0) {
+ stringBuilder.append(", ");
+ }
+ }
+ stringBuilder.append("]");
+ }
+
+ private static void appendFlags(StringBuilder stringBuilder, int flags) {
+ stringBuilder.append("flags:");
+ stringBuilder.append("[");
+ while (flags != 0) {
+ final int flagBit = (1 << Integer.numberOfTrailingZeros(flags));
+ stringBuilder.append(flagToString(flagBit));
+ flags &= ~flagBit;
+ if (flags != 0) {
+ stringBuilder.append(", ");
+ }
+ }
+ stringBuilder.append("]");
+ }
+
+ /**
+ * Returns the string representation of a feedback type. For example,
+ * {@link #FEEDBACK_SPOKEN} is represented by the string FEEDBACK_SPOKEN.
+ *
+ * @param feedbackType The feedback type.
+ * @return The string representation.
+ */
+ public static String feedbackTypeToString(int feedbackType) {
+ switch (feedbackType) {
+ case FEEDBACK_AUDIBLE:
+ return "FEEDBACK_AUDIBLE";
+ case FEEDBACK_HAPTIC:
+ return "FEEDBACK_HAPTIC";
+ case FEEDBACK_GENERIC:
+ return "FEEDBACK_GENERIC";
+ case FEEDBACK_SPOKEN:
+ return "FEEDBACK_SPOKEN";
+ case FEEDBACK_VISUAL:
+ return "FEEDBACK_VISUAL";
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Returns the string representation of a flag. For example,
+ * {@link #DEFAULT} is represented by the string DEFAULT.
+ *
+ * @param flag The flag.
+ * @return The string representation.
+ */
+ public static String flagToString(int flag) {
+ switch (flag) {
+ case DEFAULT:
+ return "DEFAULT";
+ default:
+ return null;
+ }
}
/**
@@ -130,11 +465,7 @@
new Parcelable.Creator<AccessibilityServiceInfo>() {
public AccessibilityServiceInfo createFromParcel(Parcel parcel) {
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
- info.eventTypes = parcel.readInt();
- info.packageNames = parcel.readStringArray();
- info.feedbackType = parcel.readInt();
- info.notificationTimeout = parcel.readLong();
- info.flags = parcel.readInt();
+ info.initFromParcel(parcel);
return info;
}
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 5e18f55..7b80797 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -516,9 +516,9 @@
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
- builder.append("; EventType: " + mEventType);
- builder.append("; EventTime: " + mEventTime);
- builder.append("; PackageName: " + mPackageName);
+ builder.append("; EventType: ").append(eventTypeToString(mEventType));
+ builder.append("; EventTime: ").append(mEventTime);
+ builder.append("; PackageName: ").append(mPackageName);
builder.append(" \n{\n");
builder.append(super.toString());
builder.append("\n");
@@ -535,6 +535,42 @@
}
/**
+ * Returns the string representation of an event type. For example,
+ * {@link #TYPE_VIEW_CLICKED} is represented by the string TYPE_VIEW_CLICKED.
+ *
+ * @param feedbackType The event type
+ * @return The string representation.
+ */
+ public static String eventTypeToString(int feedbackType) {
+ switch (feedbackType) {
+ case TYPE_VIEW_CLICKED:
+ return "TYPE_VIEW_CLICKED";
+ case TYPE_VIEW_LONG_CLICKED:
+ return "TYPE_VIEW_LONG_CLICKED";
+ case TYPE_VIEW_SELECTED:
+ return "TYPE_VIEW_SELECTED";
+ case TYPE_VIEW_FOCUSED:
+ return "TYPE_VIEW_FOCUSED";
+ case TYPE_VIEW_TEXT_CHANGED:
+ return "TYPE_VIEW_TEXT_CHANGED";
+ case TYPE_WINDOW_STATE_CHANGED:
+ return "TYPE_WINDOW_STATE_CHANGED";
+ case TYPE_VIEW_HOVER_ENTER:
+ return "TYPE_VIEW_HOVER_ENTER";
+ case TYPE_VIEW_HOVER_EXIT:
+ return "TYPE_VIEW_HOVER_EXIT";
+ case TYPE_NOTIFICATION_STATE_CHANGED:
+ return "TYPE_NOTIFICATION_STATE_CHANGED";
+ case TYPE_TOUCH_EXPLORATION_GESTURE_START:
+ return "TYPE_TOUCH_EXPLORATION_GESTURE_START";
+ case TYPE_TOUCH_EXPLORATION_GESTURE_END:
+ return "TYPE_TOUCH_EXPLORATION_GESTURE_END";
+ default:
+ return null;
+ }
+ }
+
+ /**
* @see Parcelable.Creator
*/
public static final Parcelable.Creator<AccessibilityEvent> CREATOR =
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index dd77193..88f8878 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -16,7 +16,6 @@
package android.view.accessibility;
-import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.Context;
import android.content.pm.ServiceInfo;
@@ -30,6 +29,7 @@
import android.os.SystemClock;
import android.util.Log;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -201,11 +201,30 @@
* Returns the {@link ServiceInfo}s of the installed accessibility services.
*
* @return An unmodifiable list with {@link ServiceInfo}s.
+ *
+ * @deprecated Use {@link #getInstalledAccessibilityServiceList()}
*/
+ @Deprecated
public List<ServiceInfo> getAccessibilityServiceList() {
- List<ServiceInfo> services = null;
+ List<AccessibilityServiceInfo> infos = getInstalledAccessibilityServiceList();
+ List<ServiceInfo> services = new ArrayList<ServiceInfo>();
+ final int infoCount = infos.size();
+ for (int i = 0; i < infoCount; i++) {
+ AccessibilityServiceInfo info = infos.get(i);
+ services.add(info.getResolveInfo().serviceInfo);
+ }
+ return Collections.unmodifiableList(services);
+ }
+
+ /**
+ * Returns the {@link AccessibilityServiceInfo}s of the installed accessibility services.
+ *
+ * @return An unmodifiable list with {@link AccessibilityServiceInfo}s.
+ */
+ public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList() {
+ List<AccessibilityServiceInfo> services = null;
try {
- services = mService.getAccessibilityServiceList();
+ services = mService.getInstalledAccessibilityServiceList();
if (DEBUG) {
Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
}
@@ -216,20 +235,14 @@
}
/**
- * Returns the {@link ServiceInfo}s of the enabled accessibility services
+ * Returns the {@link AccessibilityServiceInfo}s of the enabled accessibility services
* for a given feedback type.
*
- * @param feedbackType The type of feedback.
- * @return An unmodifiable list with {@link ServiceInfo}s.
- *
- * @see AccessibilityServiceInfo#FEEDBACK_AUDIBLE
- * @see AccessibilityServiceInfo#FEEDBACK_HAPTIC
- * @see AccessibilityServiceInfo#FEEDBACK_SPOKEN
- * @see AccessibilityServiceInfo#FEEDBACK_VISUAL
- * @see AccessibilityServiceInfo#FEEDBACK_GENERIC
+ * @param feedbackType The feedback type (can be bitwise or of multiple types).
+ * @return An unmodifiable list with {@link AccessibilityServiceInfo}s.
*/
- public List<ServiceInfo> getEnabledAccessibilityServiceList(int feedbackType) {
- List<ServiceInfo> services = null;
+ public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType) {
+ List<AccessibilityServiceInfo> services = null;
try {
services = mService.getEnabledAccessibilityServiceList(feedbackType);
if (DEBUG) {
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index aaaae32..6b2aae2 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -17,9 +17,9 @@
package android.view.accessibility;
+import android.accessibilityservice.AccessibilityServiceInfo;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.IAccessibilityManagerClient;
-import android.content.pm.ServiceInfo;
/**
* Interface implemented by the AccessibilityManagerService called by
@@ -33,9 +33,9 @@
boolean sendAccessibilityEvent(in AccessibilityEvent uiEvent);
- List<ServiceInfo> getAccessibilityServiceList();
+ List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList();
- List<ServiceInfo> getEnabledAccessibilityServiceList(int feedbackType);
+ List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType);
void interrupt();
}
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index bbbca37..e325b8d 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2147,6 +2147,82 @@
<attr name="imeSubtypeExtraValue" format="string" />
</declare-styleable>
+ <!-- Use <code>accessibility-service</code> as the root tag of the XML resource that
+ describes an {@link android.accessibilityservice.AccessibilityService} service,
+ which is referenced from its
+ {@link android.accessibilityservice.AccessibilityService#SERVICE_META_DATA}
+ meta-data entry. -->
+ <declare-styleable name="AccessibilityService">
+ <!-- The event types this serivce would like to receive as specified in
+ {@link android.view.accessibility.AccessibilityEvent}. This setting
+ can be changed at runtime by calling
+ {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+ <attr name="accessibilityEventTypes">
+ <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} events.-->
+ <flag name="typeViewClicked" value="0x00000001" />
+ <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_LONG_CLICKED} events. -->
+ <flag name="typeViewLongClicked" value="0x00000002" />
+ <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SELECTED} events. -->
+ <flag name="typeViewSelected" value="0x00000004" />
+ <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_FOCUSED} events. -->
+ <flag name="typeViewFocused" value="0x00000008" />
+ <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED} events. -->
+ <flag name="typeViewTextChanged" value="0x00000010" />
+ <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED} events. -->
+ <flag name="typeWindowStateChanged" value="0x00000020" />
+ <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED} events. -->
+ <flag name="typeNotificationStateChanged" value="0x00000040" />
+ <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER} events. -->
+ <flag name="typeViewHoverEnter" value="0x00000080" />
+ <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_EXIT} events. -->
+ <flag name="typeViewHoverExit" value="0x00000100" />
+ <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START} events. -->
+ <flag name="typeTouchExplorationGestureStart" value="0x00000200" />
+ <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END} events. -->
+ <flag name="typeTouchExplorationGestureEnd" value="0x00000400" />
+ <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPES_ALL_MASK} i.e. all events. -->
+ <flag name="typeAllMask" value="0xffffffff" />
+ </attr>
+ <!-- Comma separated package names from which this serivce would like to receive events (leave out for all packages).
+ This setting can be changed at runtime by calling
+ {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+ <attr name="packageNames" format="string" />
+ <!-- The feedback types this serivce provides as specified in
+ {@link android.accessibilityservice.AccessibilityServiceInfo}. This setting
+ can be changed at runtime by calling
+ {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+ <attr name="accessibilityFeedbackType">
+ <!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_SPOKEN} feedback. -->
+ <flag name="feedbackSpoken" value="0x00000001" />
+ <!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_HAPTIC} feedback. -->
+ <flag name="feedbackHaptic" value="0x00000002" />
+ <!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_AUDIBLE} feedback. -->
+ <flag name="feedbackAudible" value="0x00000004" />
+ <!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_VISUAL} feedback. -->
+ <flag name="feedbackVisual" value="0x00000008" />
+ <!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_GENERIC} feedback. -->
+ <flag name="feedbackGeneric" value="0x00000010" />
+ </attr>
+ <!-- The minimal period in milliseconds between two accessibility events are sent
+ to this serivce. This setting can be changed at runtime by calling
+ {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+ <attr name="notificationTimeout" format="integer" />
+ <!-- Additional flags as specified in
+ {@link android.accessibilityservice.AccessibilityServiceInfo}.
+ This setting can be changed at runtime by calling
+ {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+ <attr name="accessibilityFlags">
+ <!-- Has flag {@link android.accessibilityservice.AccessibilityServiceInfo#DEFAULT} -->
+ <flag name="flagDefault" value="0x00000001" />
+ </attr>
+ <!-- Component name of an activity that allows the user to modify
+ the settings for this service. This setting cannot be changed at runtime. -->
+ <attr name="settingsActivity" />
+ <!-- Flag whether the accessibility service wants to be able to retrieve the
+ focused window content. This setting cannot be changed at runtime. -->
+ <attr name="canRetrieveWindowContent" format="boolean" />
+ </declare-styleable>
+
<!-- =============================== -->
<!-- Widget package class attributes -->
<!-- =============================== -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 5f72da5..41a566c 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1686,4 +1686,12 @@
<public type="attr" name="layout_columnWeight" />
<public type="attr" name="isAuxiliary" />
+
+ <public type="attr" name="accessibilityEventTypes" />
+ <public type="attr" name="packageNames" />
+ <public type="attr" name="accessibilityFeedbackType" />
+ <public type="attr" name="notificationTimeout" />
+ <public type="attr" name="accessibilityFlags" />
+ <public type="attr" name="canRetrieveWindowContent" />
+
</resources>
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index d96369b..cc9e532 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -21,6 +21,8 @@
import com.android.internal.os.HandlerCaller.SomeArgs;
import com.android.server.wm.WindowManagerService;
+import org.xmlpull.v1.XmlPullParserException;
+
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.IAccessibilityServiceConnection;
@@ -54,6 +56,7 @@
import android.view.accessibility.IAccessibilityManager;
import android.view.accessibility.IAccessibilityManagerClient;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -96,17 +99,16 @@
final List<IAccessibilityManagerClient> mClients =
new ArrayList<IAccessibilityManagerClient>();
- final Map<ComponentName, Service> mComponentNameToServiceMap =
- new HashMap<ComponentName, Service>();
+ final Map<ComponentName, Service> mComponentNameToServiceMap = new HashMap<ComponentName, Service>();
- private final List<ServiceInfo> mInstalledServices = new ArrayList<ServiceInfo>();
+ private final List<AccessibilityServiceInfo> mInstalledServices = new ArrayList<AccessibilityServiceInfo>();
private final Set<ComponentName> mEnabledServices = new HashSet<ComponentName>();
private final SimpleStringSplitter mStringColonSplitter = new SimpleStringSplitter(':');
- private final SparseArray<List<ServiceInfo>> mFeedbackTypeToEnabledServicesMap =
- new SparseArray<List<ServiceInfo>>();
+ private final SparseArray<List<AccessibilityServiceInfo>> mFeedbackTypeToEnabledServicesMap =
+ new SparseArray<List<AccessibilityServiceInfo>>();
private PackageManager mPackageManager;
@@ -298,20 +300,28 @@
return (OWN_PROCESS_ID != Binder.getCallingPid());
}
- public List<ServiceInfo> getAccessibilityServiceList() {
+ public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList() {
synchronized (mLock) {
return mInstalledServices;
}
}
- public List<ServiceInfo> getEnabledAccessibilityServiceList(int feedbackType) {
+ public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType) {
+ SparseArray<List<AccessibilityServiceInfo>> feedbackTypeToEnabledServicesMap =
+ mFeedbackTypeToEnabledServicesMap;
+ List<AccessibilityServiceInfo> enabledServices = new ArrayList<AccessibilityServiceInfo>();
synchronized (mLock) {
- List<ServiceInfo> enabledServices = mFeedbackTypeToEnabledServicesMap.get(feedbackType);
- if (enabledServices == null) {
- return Collections.emptyList();
+ while (feedbackType != 0) {
+ final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackType));
+ feedbackType &= ~feedbackTypeBit;
+ List<AccessibilityServiceInfo> perFeedbackType =
+ feedbackTypeToEnabledServicesMap.get(feedbackTypeBit);
+ if (perFeedbackType != null) {
+ enabledServices.addAll(perFeedbackType);
+ }
}
- return enabledServices;
}
+ return enabledServices;
}
public void interrupt() {
@@ -345,15 +355,16 @@
Service service = (Service) arguments.arg2;
synchronized (mLock) {
- service.mEventTypes = info.eventTypes;
- service.mFeedbackType = info.feedbackType;
- String[] packageNames = info.packageNames;
- if (packageNames != null) {
- service.mPackageNames.addAll(Arrays.asList(packageNames));
+ // If the XML manifest had data to configure the service its info
+ // should be already set. In such a case update only the dynamically
+ // configurable properties.
+ AccessibilityServiceInfo oldInfo = service.mAccessibilityServiceInfo;
+ if (oldInfo != null) {
+ oldInfo.updateDynamicallyConfigurableProperties(info);
+ service.setAccessibilityServiceInfo(oldInfo);
+ } else {
+ service.setAccessibilityServiceInfo(info);
}
- service.mNotificationTimeout = info.notificationTimeout;
- service.mIsDefault = (info.flags & AccessibilityServiceInfo.DEFAULT) != 0;
-
updateStateOnEnabledService(service);
}
return;
@@ -369,10 +380,20 @@
mInstalledServices.clear();
List<ResolveInfo> installedServices = mPackageManager.queryIntentServices(
- new Intent(AccessibilityService.SERVICE_INTERFACE), PackageManager.GET_SERVICES);
+ new Intent(AccessibilityService.SERVICE_INTERFACE),
+ PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
for (int i = 0, count = installedServices.size(); i < count; i++) {
- mInstalledServices.add(installedServices.get(i).serviceInfo);
+ ResolveInfo resolveInfo = installedServices.get(i);
+ AccessibilityServiceInfo accessibilityServiceInfo;
+ try {
+ accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext);
+ mInstalledServices.add(accessibilityServiceInfo);
+ } catch (XmlPullParserException xppe) {
+ Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", xppe);
+ } catch (IOException ioe) {
+ Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", ioe);
+ }
}
}
@@ -595,22 +616,22 @@
* @param installedServices All installed {@link AccessibilityService}s.
* @param enabledServices The {@link ComponentName}s of the enabled services.
*/
- private void updateServicesStateLocked(List<ServiceInfo> installedServices,
+ private void updateServicesStateLocked(List<AccessibilityServiceInfo> installedServices,
Set<ComponentName> enabledServices) {
Map<ComponentName, Service> componentNameToServiceMap = mComponentNameToServiceMap;
boolean isEnabled = mIsEnabled;
for (int i = 0, count = installedServices.size(); i < count; i++) {
- ServiceInfo intalledService = installedServices.get(i);
- ComponentName componentName = new ComponentName(intalledService.packageName,
- intalledService.name);
+ AccessibilityServiceInfo installedService = installedServices.get(i);
+ ComponentName componentName = ComponentName.unflattenFromString(
+ installedService.getId());
Service service = componentNameToServiceMap.get(componentName);
if (isEnabled) {
if (enabledServices.contains(componentName)) {
if (service == null) {
- service = new Service(componentName, intalledService);
+ service = new Service(installedService);
}
service.bind();
} else if (!enabledServices.contains(componentName)) {
@@ -671,12 +692,13 @@
*/
private void updateStateOnEnabledService(Service service) {
int feedbackType = service.mFeedbackType;
- List<ServiceInfo> enabledServices = mFeedbackTypeToEnabledServicesMap.get(feedbackType);
+ List<AccessibilityServiceInfo> enabledServices =
+ mFeedbackTypeToEnabledServicesMap.get(feedbackType);
if (enabledServices == null) {
- enabledServices = new ArrayList<ServiceInfo>();
+ enabledServices = new ArrayList<AccessibilityServiceInfo>();
mFeedbackTypeToEnabledServicesMap.put(feedbackType, enabledServices);
}
- enabledServices.add(service.mServiceInfo);
+ enabledServices.add(service.mAccessibilityServiceInfo);
// We enable touch exploration if at least one
// enabled service provides spoken feedback.
@@ -688,12 +710,12 @@
}
private void updateStateOnDisabledService(Service service) {
- List<ServiceInfo> enabledServices =
+ List<AccessibilityServiceInfo> enabledServices =
mFeedbackTypeToEnabledServicesMap.get(service.mFeedbackType);
if (enabledServices == null) {
return;
}
- enabledServices.remove(service.mServiceInfo);
+ enabledServices.remove(service.mAccessibilityServiceInfo);
// We disable touch exploration if no
// enabled service provides spoken feedback.
if (enabledServices.isEmpty()
@@ -714,7 +736,7 @@
class Service extends IAccessibilityServiceConnection.Stub implements ServiceConnection {
int mId = 0;
- ServiceInfo mServiceInfo;
+ AccessibilityServiceInfo mAccessibilityServiceInfo;
IBinder mService;
@@ -740,10 +762,9 @@
final SparseArray<AccessibilityEvent> mPendingEvents =
new SparseArray<AccessibilityEvent>();
- Service(ComponentName componentName, ServiceInfo serviceInfo) {
+ Service(AccessibilityServiceInfo accessibilityServiceInfo) {
mId = sIdCounter++;
- mComponentName = componentName;
- mServiceInfo = serviceInfo;
+ setAccessibilityServiceInfo(accessibilityServiceInfo);
mIntent = new Intent().setComponent(mComponentName);
mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
com.android.internal.R.string.accessibility_binding_label);
@@ -751,6 +772,20 @@
mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0));
}
+ public void setAccessibilityServiceInfo(AccessibilityServiceInfo info) {
+ mAccessibilityServiceInfo = info;
+ ServiceInfo serviceInfo = info.getResolveInfo().serviceInfo;
+ mComponentName = new ComponentName(serviceInfo.packageName, serviceInfo.name);
+ mEventTypes = info.eventTypes;
+ mFeedbackType = info.feedbackType;
+ String[] packageNames = info.packageNames;
+ if (packageNames != null) {
+ mPackageNames.addAll(Arrays.asList(packageNames));
+ }
+ mNotificationTimeout = info.notificationTimeout;
+ mIsDefault = (info.flags & AccessibilityServiceInfo.DEFAULT) != 0;
+ }
+
/**
* Binds to the accessibility service.
*
@@ -805,6 +840,9 @@
if (!mServices.contains(this)) {
mServices.add(this);
mComponentNameToServiceMap.put(componentName, this);
+ if (isConfigured()) {
+ updateStateOnEnabledService(this);
+ }
}
}
} catch (RemoteException re) {
diff --git a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
index 2bc6825..302a2d6 100644
--- a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
@@ -150,7 +150,8 @@
String secondMockServiceClassName = MySecondMockAccessibilityService.class.getName();
// look for the two mock services
- for (ServiceInfo serviceInfo : mManagerService.getAccessibilityServiceList()) {
+ for (AccessibilityServiceInfo info : mManagerService.getInstalledAccessibilityServiceList()) {
+ ServiceInfo serviceInfo = info.getResolveInfo().serviceInfo;
if (packageName.equals(serviceInfo.packageName)) {
if (firstMockServiceClassName.equals(serviceInfo.name)) {
firstMockServiceInstalled = true;
diff --git a/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java b/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
index 38fed22..1463d30 100644
--- a/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
@@ -25,6 +25,7 @@
import org.easymock.IArgumentMatcher;
+import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.pm.ServiceInfo;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
@@ -62,20 +63,22 @@
@MediumTest
public void testGetAccessibilityServiceList() throws Exception {
// create a list of installed accessibility services the mock service returns
- List<ServiceInfo> expectedServices = new ArrayList<ServiceInfo>();
- ServiceInfo serviceInfo = new ServiceInfo();
- serviceInfo.name = "TestServiceInfoName";
- expectedServices.add(serviceInfo);
+ List<AccessibilityServiceInfo> expectedServices = new ArrayList<AccessibilityServiceInfo>();
+ AccessibilityServiceInfo accessibilityServiceInfo = new AccessibilityServiceInfo();
+ accessibilityServiceInfo.packageNames = new String[] { "foo.bar" };
+ expectedServices.add(accessibilityServiceInfo);
// configure the mock service behavior
IAccessibilityManager mockServiceInterface = mMockServiceInterface;
expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(true);
- expect(mockServiceInterface.getAccessibilityServiceList()).andReturn(expectedServices);
+ expect(mockServiceInterface.getInstalledAccessibilityServiceList()).andReturn(
+ expectedServices);
replay(mockServiceInterface);
// invoke the method under test
AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface);
- List<ServiceInfo> receivedServices = manager.getAccessibilityServiceList();
+ List<AccessibilityServiceInfo> receivedServices =
+ manager.getInstalledAccessibilityServiceList();
// check expected result (list equals() compares it contents as well)
assertEquals("All expected services must be returned", receivedServices, expectedServices);