summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSvetoslav Ganov <svetoslavganov@google.com>2011-07-14 17:57:06 -0700
committerSvetoslav Ganov <svetoslavganov@google.com>2011-07-18 12:44:08 -0700
commit35bfedeaba724aeadc6f6c890269cb6bf7ef42f5 (patch)
tree1f233a2109d33a10bdf1aaa2417cc7c244cfaf54
parentd94b71de3b465c9c113f5b09c7cd5f221370af23 (diff)
downloadframeworks_base-35bfedeaba724aeadc6f6c890269cb6bf7ef42f5.zip
frameworks_base-35bfedeaba724aeadc6f6c890269cb6bf7ef42f5.tar.gz
frameworks_base-35bfedeaba724aeadc6f6c890269cb6bf7ef42f5.tar.bz2
Touch exploration separate setting and API to poll the latter state.
1. Seperated touch exploration to be a seperate setting rather being magically enabled by the system of accessiiblity is on the there is at leas one accessibility service that speaks enabled. Now there is a setting for requesting touch exploration but still the system will enabled it only if that makes sense i.e. accessibility is on and one accessibility service that speaks is enabled. 2. Added public API for checking of touch exploration is enabled. 3. Added description attribute in accessibility service declaration which will be shown to the user before enabling the service. 4. Added API for quick cloning of AccessibilityNodeInfo. 5. Added clone functionality to SparseArray, SparseIntArray, and SparseBooleanArray. bug:5034010 bug:5033928 Change-Id: Ia442edbe55c20309244061cd9d24e0545c01b54f
-rw-r--r--api/current.txt13
-rw-r--r--core/java/android/accessibilityservice/AccessibilityServiceInfo.java21
-rw-r--r--core/java/android/provider/Settings.java7
-rw-r--r--core/java/android/util/SparseArray.java38
-rw-r--r--core/java/android/util/SparseBooleanArray.java27
-rw-r--r--core/java/android/util/SparseIntArray.java36
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java3
-rw-r--r--core/java/android/view/accessibility/AccessibilityManager.java35
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java39
-rw-r--r--core/java/android/view/accessibility/IAccessibilityManagerClient.aidl1
-rwxr-xr-xcore/res/res/values/attrs.xml2
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityManagerService.java115
-rw-r--r--services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java3
13 files changed, 248 insertions, 92 deletions
diff --git a/api/current.txt b/api/current.txt
index a1e55bd..ecbc9d2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1823,6 +1823,7 @@ package android.accessibilityservice {
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 getDescription();
method public java.lang.String getId();
method public android.content.pm.ResolveInfo getResolveInfo();
method public java.lang.String getSettingsActivityName();
@@ -16702,6 +16703,7 @@ package android.provider {
field public static final java.lang.String SELECTED_INPUT_METHOD_SUBTYPE = "selected_input_method_subtype";
field public static final java.lang.String SETTINGS_CLASSNAME = "settings_classname";
field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_secure_version";
+ field public static final java.lang.String TOUCH_EXPLORATION_REQUESTED = "touch_exploration_requested";
field public static final java.lang.String TTS_DEFAULT_COUNTRY = "tts_default_country";
field public static final java.lang.String TTS_DEFAULT_LANG = "tts_default_lang";
field public static final java.lang.String TTS_DEFAULT_PITCH = "tts_default_pitch";
@@ -20731,11 +20733,12 @@ package android.util {
method public void set(T, V);
}
- public class SparseArray {
+ public class SparseArray implements java.lang.Cloneable {
ctor public SparseArray();
ctor public SparseArray(int);
method public void append(int, E);
method public void clear();
+ method public android.util.SparseArray<E> clone();
method public void delete(int);
method public E get(int);
method public E get(int, E);
@@ -20750,11 +20753,12 @@ package android.util {
method public E valueAt(int);
}
- public class SparseBooleanArray {
+ public class SparseBooleanArray implements java.lang.Cloneable {
ctor public SparseBooleanArray();
ctor public SparseBooleanArray(int);
method public void append(int, boolean);
method public void clear();
+ method public android.util.SparseBooleanArray clone();
method public void delete(int);
method public boolean get(int);
method public boolean get(int, boolean);
@@ -20766,11 +20770,12 @@ package android.util {
method public boolean valueAt(int);
}
- public class SparseIntArray {
+ public class SparseIntArray implements java.lang.Cloneable {
ctor public SparseIntArray();
ctor public SparseIntArray(int);
method public void append(int, int);
method public void clear();
+ method public android.util.SparseIntArray clone();
method public void delete(int);
method public int get(int);
method public int get(int, int);
@@ -23265,6 +23270,7 @@ package android.view.accessibility {
method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList();
method public void interrupt();
method public boolean isEnabled();
+ method public boolean isTouchExplorationEnabled();
method public boolean removeAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener);
method public void sendAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
}
@@ -23301,6 +23307,7 @@ package android.view.accessibility {
method public boolean isSelected();
method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View);
method public static android.view.accessibility.AccessibilityNodeInfo obtain();
+ method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.accessibility.AccessibilityNodeInfo);
method public boolean performAction(int);
method public void recycle();
method public void setBoundsInParent(android.graphics.Rect);
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 5f40f25..a09607a 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -171,6 +171,11 @@ public class AccessibilityServiceInfo implements Parcelable {
private boolean mCanRetrieveWindowContent;
/**
+ * Description of the accessibility service.
+ */
+ private String mDescription;
+
+ /**
* Creates a new instance.
*/
public AccessibilityServiceInfo() {
@@ -240,6 +245,8 @@ public class AccessibilityServiceInfo implements Parcelable {
mCanRetrieveWindowContent = asAttributes.getBoolean(
com.android.internal.R.styleable.AccessibilityService_canRetrieveWindowContent,
false);
+ mDescription = asAttributes.getString(
+ com.android.internal.R.styleable.AccessibilityService_description);
asAttributes.recycle();
} catch (NameNotFoundException e) {
throw new XmlPullParserException( "Unable to create context for: "
@@ -313,6 +320,18 @@ public class AccessibilityServiceInfo implements Parcelable {
}
/**
+ * Description of the accessibility service.
+ * <p>
+ * <strong>Statically set from
+ * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
+ * </p>
+ * @return The description.
+ */
+ public String getDescription() {
+ return mDescription;
+ }
+
+ /**
* {@inheritDoc}
*/
public int describeContents() {
@@ -329,6 +348,7 @@ public class AccessibilityServiceInfo implements Parcelable {
parcel.writeParcelable(mResolveInfo, 0);
parcel.writeString(mSettingsActivityName);
parcel.writeInt(mCanRetrieveWindowContent ? 1 : 0);
+ parcel.writeString(mDescription);
}
private void initFromParcel(Parcel parcel) {
@@ -341,6 +361,7 @@ public class AccessibilityServiceInfo implements Parcelable {
mResolveInfo = parcel.readParcelable(null);
mSettingsActivityName = parcel.readString();
mCanRetrieveWindowContent = (parcel.readInt() == 1);
+ mDescription = parcel.readString();
}
@Override
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 23b53ae..34699e2 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2683,6 +2683,13 @@ public final class Settings {
public static final String ACCESSIBILITY_ENABLED = "accessibility_enabled";
/**
+ * If touch exploration is requested. Touch exploration is enabled if it is
+ * requested by this setting, accessibility is enabled and there is at least
+ * one enabled accessibility serivce that provides spoken feedback.
+ */
+ public static final String TOUCH_EXPLORATION_REQUESTED = "touch_exploration_requested";
+
+ /**
* List of the enabled accessibility providers.
*/
public static final String ENABLED_ACCESSIBILITY_SERVICES =
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
index 7fc43b9..7cf4579 100644
--- a/core/java/android/util/SparseArray.java
+++ b/core/java/android/util/SparseArray.java
@@ -23,10 +23,14 @@ import com.android.internal.util.ArrayUtils;
* there can be gaps in the indices. It is intended to be more efficient
* than using a HashMap to map Integers to Objects.
*/
-public class SparseArray<E> {
+public class SparseArray<E> implements Cloneable {
private static final Object DELETED = new Object();
private boolean mGarbage = false;
+ private int[] mKeys;
+ private Object[] mValues;
+ private int mSize;
+
/**
* Creates a new SparseArray containing no mappings.
*/
@@ -47,6 +51,20 @@ public class SparseArray<E> {
mSize = 0;
}
+ @Override
+ @SuppressWarnings("unchecked")
+ public SparseArray<E> clone() {
+ SparseArray<E> clone = null;
+ try {
+ clone = (SparseArray<E>) super.clone();
+ clone.mKeys = mKeys.clone();
+ clone.mValues = mValues.clone();
+ } catch (CloneNotSupportedException cnse) {
+ /* ignore */
+ }
+ return clone;
+ }
+
/**
* Gets the Object mapped from the specified key, or <code>null</code>
* if no such mapping has been made.
@@ -59,6 +77,7 @@ public class SparseArray<E> {
* Gets the Object mapped from the specified key, or the specified Object
* if no such mapping has been made.
*/
+ @SuppressWarnings("unchecked")
public E get(int key, E valueIfKeyNotFound) {
int i = binarySearch(mKeys, 0, mSize, key);
@@ -209,6 +228,7 @@ public class SparseArray<E> {
* the value from the <code>index</code>th key-value mapping that this
* SparseArray stores.
*/
+ @SuppressWarnings("unchecked")
public E valueAt(int index) {
if (mGarbage) {
gc();
@@ -331,20 +351,4 @@ public class SparseArray<E> {
else
return ~high;
}
-
- private void checkIntegrity() {
- for (int i = 1; i < mSize; i++) {
- if (mKeys[i] <= mKeys[i - 1]) {
- for (int j = 0; j < mSize; j++) {
- Log.e("FAIL", j + ": " + mKeys[j] + " -> " + mValues[j]);
- }
-
- throw new RuntimeException();
- }
- }
- }
-
- private int[] mKeys;
- private Object[] mValues;
- private int mSize;
}
diff --git a/core/java/android/util/SparseBooleanArray.java b/core/java/android/util/SparseBooleanArray.java
index f7799de..76c47c6 100644
--- a/core/java/android/util/SparseBooleanArray.java
+++ b/core/java/android/util/SparseBooleanArray.java
@@ -24,7 +24,7 @@ import com.android.internal.util.ArrayUtils;
* there can be gaps in the indices. It is intended to be more efficient
* than using a HashMap to map Integers to Booleans.
*/
-public class SparseBooleanArray {
+public class SparseBooleanArray implements Cloneable {
/**
* Creates a new SparseBooleanArray containing no mappings.
*/
@@ -45,6 +45,19 @@ public class SparseBooleanArray {
mSize = 0;
}
+ @Override
+ public SparseBooleanArray clone() {
+ SparseBooleanArray clone = null;
+ try {
+ clone = (SparseBooleanArray) super.clone();
+ clone.mKeys = mKeys.clone();
+ clone.mValues = mValues.clone();
+ } catch (CloneNotSupportedException cnse) {
+ /* ignore */
+ }
+ return clone;
+ }
+
/**
* Gets the boolean mapped from the specified key, or <code>false</code>
* if no such mapping has been made.
@@ -227,18 +240,6 @@ public class SparseBooleanArray {
return ~high;
}
- private void checkIntegrity() {
- for (int i = 1; i < mSize; i++) {
- if (mKeys[i] <= mKeys[i - 1]) {
- for (int j = 0; j < mSize; j++) {
- Log.e("FAIL", j + ": " + mKeys[j] + " -> " + mValues[j]);
- }
-
- throw new RuntimeException();
- }
- }
- }
-
private int[] mKeys;
private boolean[] mValues;
private int mSize;
diff --git a/core/java/android/util/SparseIntArray.java b/core/java/android/util/SparseIntArray.java
index 9ab3b53..8d11177 100644
--- a/core/java/android/util/SparseIntArray.java
+++ b/core/java/android/util/SparseIntArray.java
@@ -23,7 +23,12 @@ import com.android.internal.util.ArrayUtils;
* there can be gaps in the indices. It is intended to be more efficient
* than using a HashMap to map Integers to Integers.
*/
-public class SparseIntArray {
+public class SparseIntArray implements Cloneable {
+
+ private int[] mKeys;
+ private int[] mValues;
+ private int mSize;
+
/**
* Creates a new SparseIntArray containing no mappings.
*/
@@ -44,6 +49,19 @@ public class SparseIntArray {
mSize = 0;
}
+ @Override
+ public SparseIntArray clone() {
+ SparseIntArray clone = null;
+ try {
+ clone = (SparseIntArray) super.clone();
+ clone.mKeys = mKeys.clone();
+ clone.mValues = mValues.clone();
+ } catch (CloneNotSupportedException cnse) {
+ /* ignore */
+ }
+ return clone;
+ }
+
/**
* Gets the int mapped from the specified key, or <code>0</code>
* if no such mapping has been made.
@@ -232,20 +250,4 @@ public class SparseIntArray {
else
return ~high;
}
-
- private void checkIntegrity() {
- for (int i = 1; i < mSize; i++) {
- if (mKeys[i] <= mKeys[i - 1]) {
- for (int j = 0; j < mSize; j++) {
- Log.e("FAIL", j + ": " + mKeys[j] + " -> " + mValues[j]);
- }
-
- throw new RuntimeException();
- }
- }
- }
-
- private int[] mKeys;
- private int[] mValues;
- private int mSize;
}
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index ac86769..9be2a67 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -552,7 +552,8 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
/**
* Returns a cached instance if such is available or a new one is
- * initialized with from the given <code>event</code>.
+ * created. The returned instance is initialized from the given
+ * <code>event</code>.
*
* @param event The other event.
* @return An instance.
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 314b7ca..83c73cb 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -71,7 +71,9 @@ public final class AccessibilityManager {
private static AccessibilityManager sInstance;
- private static final int DO_SET_ENABLED = 10;
+ private static final int DO_SET_ACCESSIBILITY_ENABLED = 10;
+
+ private static final int DO_SET_TOUCH_EXPLORATION_ENABLED = 20;
final IAccessibilityManager mService;
@@ -79,6 +81,8 @@ public final class AccessibilityManager {
boolean mIsEnabled;
+ boolean mIsTouchExplorationEnabled;
+
final CopyOnWriteArrayList<AccessibilityStateChangeListener> mAccessibilityStateChangeListeners =
new CopyOnWriteArrayList<AccessibilityStateChangeListener>();
@@ -97,7 +101,12 @@ public final class AccessibilityManager {
final IAccessibilityManagerClient.Stub mClient = new IAccessibilityManagerClient.Stub() {
public void setEnabled(boolean enabled) {
- mHandler.obtainMessage(DO_SET_ENABLED, enabled ? 1 : 0, 0).sendToTarget();
+ mHandler.obtainMessage(DO_SET_ACCESSIBILITY_ENABLED, enabled ? 1 : 0, 0).sendToTarget();
+ }
+
+ public void setTouchExplorationEnabled(boolean enabled) {
+ mHandler.obtainMessage(DO_SET_TOUCH_EXPLORATION_ENABLED,
+ enabled ? 1 : 0, 0).sendToTarget();
}
};
@@ -110,9 +119,14 @@ public final class AccessibilityManager {
@Override
public void handleMessage(Message message) {
switch (message.what) {
- case DO_SET_ENABLED :
- final boolean isEnabled = (message.arg1 == 1);
- setAccessibilityState(isEnabled);
+ case DO_SET_ACCESSIBILITY_ENABLED :
+ final boolean isAccessibilityEnabled = (message.arg1 == 1);
+ setAccessibilityState(isAccessibilityEnabled);
+ return;
+ case DO_SET_TOUCH_EXPLORATION_ENABLED :
+ synchronized (mHandler) {
+ mIsTouchExplorationEnabled = (message.arg1 == 1);
+ }
return;
default :
Log.w(LOG_TAG, "Unknown message type: " + message.what);
@@ -168,6 +182,17 @@ public final class AccessibilityManager {
}
/**
+ * Returns if the touch exploration in the system is enabled.
+ *
+ * @return True if touch exploration is enabled, false otherwise.
+ */
+ public boolean isTouchExplorationEnabled() {
+ synchronized (mHandler) {
+ return mIsTouchExplorationEnabled;
+ }
+ }
+
+ /**
* Returns the client interface this instance registers in
* the centralized accessibility manager service.
*
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 031c6ae..0e04471 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -120,7 +120,7 @@ public class AccessibilityNodeInfo implements Parcelable {
private CharSequence mText;
private CharSequence mContentDescription;
- private final SparseIntArray mChildAccessibilityIds = new SparseIntArray();
+ private SparseIntArray mChildAccessibilityIds = new SparseIntArray();
private int mActions;
private IAccessibilityServiceConnection mConnection;
@@ -873,6 +873,20 @@ public class AccessibilityNodeInfo implements Parcelable {
}
/**
+ * Returns a cached instance if such is available or a new one is
+ * create. The returned instance is initialized from the given
+ * <code>info</code>.
+ *
+ * @param info The other info.
+ * @return An instance.
+ */
+ public static AccessibilityNodeInfo obtain(AccessibilityNodeInfo info) {
+ AccessibilityNodeInfo infoClone = AccessibilityNodeInfo.obtain();
+ infoClone.init(info);
+ return infoClone;
+ }
+
+ /**
* Return an instance back to be reused.
* <p>
* <strong>Note:</strong> You must not touch the object after calling this function.
@@ -945,6 +959,28 @@ public class AccessibilityNodeInfo implements Parcelable {
}
/**
+ * Initializes this instance from another one.
+ *
+ * @param other The other instance.
+ */
+ private void init(AccessibilityNodeInfo other) {
+ mSealed = other.mSealed;
+ mConnection = other.mConnection;
+ mAccessibilityViewId = other.mAccessibilityViewId;
+ mParentAccessibilityViewId = other.mParentAccessibilityViewId;
+ mAccessibilityWindowId = other.mAccessibilityWindowId;
+ mBoundsInParent.set(other.mBoundsInParent);
+ mBoundsInScreen.set(other.mBoundsInScreen);
+ mPackageName = other.mPackageName;
+ mClassName = other.mClassName;
+ mText = other.mText;
+ mContentDescription = other.mContentDescription;
+ mActions= other.mActions;
+ mBooleanProperties = other.mBooleanProperties;
+ mChildAccessibilityIds = other.mChildAccessibilityIds.clone();
+ }
+
+ /**
* Creates a new instance from a {@link Parcel}.
*
* @param parcel A parcel containing the state of a {@link AccessibilityNodeInfo}.
@@ -994,6 +1030,7 @@ public class AccessibilityNodeInfo implements Parcelable {
mConnection = null;
mAccessibilityViewId = View.NO_ID;
mParentAccessibilityViewId = View.NO_ID;
+ mAccessibilityWindowId = View.NO_ID;
mChildAccessibilityIds.clear();
mBoundsInParent.set(0, 0, 0, 0);
mBoundsInScreen.set(0, 0, 0, 0);
diff --git a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
index 1eb60fc..4e69692 100644
--- a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
@@ -26,4 +26,5 @@ oneway interface IAccessibilityManagerClient {
void setEnabled(boolean enabled);
+ void setTouchExplorationEnabled(boolean enabled);
}
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 9613712..d0361ca 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2302,6 +2302,8 @@
<!-- Flag whether the accessibility service wants to be able to retrieve the
active window content. This setting cannot be changed at runtime. -->
<attr name="canRetrieveWindowContent" format="boolean" />
+ <!-- Short description of the accessibility serivce purpose or behavior.-->
+ <attr name="description" />
</declare-styleable>
<!-- =============================== -->
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index a8dc885..bb9d15b 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -127,13 +127,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
private int mHandledFeedbackTypes = 0;
- private boolean mIsEnabled;
+ private boolean mIsAccessibilityEnabled;
+
+ private boolean mIsTouchExplorationRequested;
private AccessibilityInputFilter mInputFilter;
private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList = new ArrayList<AccessibilityServiceInfo>();
- private boolean mHasInputFilter;
+ private boolean mIsTouchExplorationEnabled;
private final WindowManagerService mWindowManagerService;
@@ -230,16 +232,21 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
if (intent.getAction() == Intent.ACTION_BOOT_COMPLETED) {
synchronized (mLock) {
populateAccessibilityServiceListLocked();
- // get the accessibility enabled setting on boot
- mIsEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
+ // get accessibility enabled setting on boot
+ mIsAccessibilityEnabled = Settings.Secure.getInt(
+ mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
-
// if accessibility is enabled inform our clients we are on
- if (mIsEnabled) {
- updateClientsLocked();
+ if (mIsAccessibilityEnabled) {
+ sendAccessibilityEnabledToClientsLocked();
}
-
manageServicesLocked();
+
+ // get touch exploration enabled setting on boot
+ mIsTouchExplorationRequested = Settings.Secure.getInt(
+ mContext.getContentResolver(),
+ Settings.Secure.TOUCH_EXPLORATION_REQUESTED, 0) == 1;
+ updateTouchExplorationEnabledLocked();
}
return;
@@ -264,29 +271,48 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
private void registerSettingsContentObservers() {
ContentResolver contentResolver = mContext.getContentResolver();
- Uri enabledUri = Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_ENABLED);
- contentResolver.registerContentObserver(enabledUri, false,
+ Uri accessibilityEnabledUri = Settings.Secure.getUriFor(
+ Settings.Secure.ACCESSIBILITY_ENABLED);
+ contentResolver.registerContentObserver(accessibilityEnabledUri, false,
new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
synchronized (mLock) {
- mIsEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
+ mIsAccessibilityEnabled = Settings.Secure.getInt(
+ mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
- if (mIsEnabled) {
+ if (mIsAccessibilityEnabled) {
manageServicesLocked();
} else {
unbindAllServicesLocked();
}
- updateClientsLocked();
+ sendAccessibilityEnabledToClientsLocked();
}
}
});
- Uri providersUri =
+ Uri touchExplorationRequestedUri = Settings.Secure.getUriFor(
+ Settings.Secure.TOUCH_EXPLORATION_REQUESTED);
+ contentResolver.registerContentObserver(touchExplorationRequestedUri, false,
+ new ContentObserver(new Handler()) {
+ @Override
+ public void onChange(boolean selfChange) {
+ super.onChange(selfChange);
+
+ synchronized (mLock) {
+ mIsTouchExplorationRequested = Settings.Secure.getInt(
+ mContext.getContentResolver(),
+ Settings.Secure.TOUCH_EXPLORATION_REQUESTED, 0) == 1;
+ updateTouchExplorationEnabledLocked();
+ }
+ }
+ });
+
+ Uri accessibilityServicesUri =
Settings.Secure.getUriFor(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
- contentResolver.registerContentObserver(providersUri, false,
+ contentResolver.registerContentObserver(accessibilityServicesUri, false,
new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
@@ -312,7 +338,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
}
}, 0);
- return mIsEnabled;
+ return mIsAccessibilityEnabled;
}
}
@@ -602,7 +628,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
service.linkToOwnDeath();
mServices.add(service);
mComponentNameToServiceMap.put(service.mComponentName, service);
- updateInputFilterLocked();
+ updateTouchExplorationEnabledLocked();
} catch (RemoteException e) {
/* do nothing */
}
@@ -622,7 +648,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
mComponentNameToServiceMap.remove(service.mComponentName);
mHandler.removeMessages(service.mId);
service.unlinkToOwnDeath();
- updateInputFilterLocked();
+ updateTouchExplorationEnabledLocked();
return removed;
}
@@ -727,7 +753,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
Set<ComponentName> enabledServices) {
Map<ComponentName, Service> componentNameToServiceMap = mComponentNameToServiceMap;
- boolean isEnabled = mIsEnabled;
+ boolean isEnabled = mIsAccessibilityEnabled;
for (int i = 0, count = installedServices.size(); i < count; i++) {
AccessibilityServiceInfo installedService = installedServices.get(i);
@@ -741,7 +767,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
service = new Service(componentName, installedService, false);
}
service.bind();
- } else if (!enabledServices.contains(componentName)) {
+ } else {
if (service != null) {
service.unbind();
}
@@ -757,10 +783,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
/**
* Updates the state of {@link android.view.accessibility.AccessibilityManager} clients.
*/
- private void updateClientsLocked() {
+ private void sendAccessibilityEnabledToClientsLocked() {
for (int i = 0, count = mClients.size(); i < count; i++) {
try {
- mClients.get(i).setEnabled(mIsEnabled);
+ mClients.get(i).setEnabled(mIsAccessibilityEnabled);
} catch (RemoteException re) {
mClients.remove(i);
count--;
@@ -770,29 +796,48 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
/**
- * Updates the input filter state. The filter is enabled if accessibility
- * is enabled and there is at least one accessibility service providing
- * spoken feedback.
+ * Sends the touch exploration state to clients.
*/
- private void updateInputFilterLocked() {
- if (mIsEnabled) {
- final boolean hasSpokenFeedbackServices = !getEnabledAccessibilityServiceList(
- AccessibilityServiceInfo.FEEDBACK_SPOKEN).isEmpty();
- if (hasSpokenFeedbackServices) {
- if (mHasInputFilter) {
- return;
+ private void sendTouchExplorationEnabledToClientsLocked() {
+ for (int i = 0, count = mClients.size(); i < count; i++) {
+ try {
+ mClients.get(i).setTouchExplorationEnabled(mIsTouchExplorationEnabled);
+ } catch (RemoteException re) {
+ mClients.remove(i);
+ count--;
+ i--;
+ }
+ }
+ }
+
+ /**
+ * Updates the touch exploration state. Touch exploration is enabled if it
+ * is requested, accessibility is on and there is at least one enabled
+ * accessibility service providing spoken feedback.
+ */
+ private void updateTouchExplorationEnabledLocked() {
+ if (mIsAccessibilityEnabled && mIsTouchExplorationRequested) {
+ final boolean hasSpeakingServicesEnabled = !getEnabledAccessibilityServiceList(
+ AccessibilityServiceInfo.FEEDBACK_SPOKEN).isEmpty();
+ if (!mIsTouchExplorationEnabled) {
+ if (!hasSpeakingServicesEnabled) {
+ return;
}
if (mInputFilter == null) {
mInputFilter = new AccessibilityInputFilter(mContext);
}
mWindowManagerService.setInputFilter(mInputFilter);
- mHasInputFilter = true;
+ mIsTouchExplorationEnabled = true;
+ sendTouchExplorationEnabledToClientsLocked();
+ return;
+ } else if (hasSpeakingServicesEnabled) {
return;
}
}
- if (mHasInputFilter) {
+ if (mIsTouchExplorationEnabled) {
mWindowManagerService.setInputFilter(null);
- mHasInputFilter = false;
+ mIsTouchExplorationEnabled = false;
+ sendTouchExplorationEnabledToClientsLocked();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
index 302a2d6..1234bfd 100644
--- a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
@@ -542,6 +542,9 @@ public class AccessibilityManagerServiceTest extends AndroidTestCase {
public void setEnabled(boolean enabled) {
mIsEnabled = enabled;
}
+
+ public void setTouchExplorationEnabled(boolean enabled) {
+ }
}
/**