diff options
13 files changed, 248 insertions, 92 deletions
diff --git a/api/current.txt b/api/current.txt index a1e55bddebd1..ecbc9d298a5f 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 5f40f25176ed..a09607a7f9ad 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 23b53ae04ba4..34699e26f994 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 7fc43b92c549..7cf45793fe7e 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 f7799dee6ef7..76c47c6aabad 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 9ab3b53169e3..8d111770e8dd 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 ac867690724b..9be2a67be334 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 314b7ca35821..83c73cb85cc8 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 031c6aeffd21..0e044712c0b2 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 1eb60fc61b48..4e69692494c5 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 96137121a193..d0361ca447e7 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 a8dc885a6613..bb9d15b3ca05 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 302a2d60bb07..1234bfd8220e 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) { + } } /** |