FileDocCategorySizeDatePackage
AccessibilityManager.javaAPI DocAndroid 5.1 API25719Thu Mar 12 22:22:10 GMT 2015android.view.accessibility

AccessibilityManager

public final class AccessibilityManager extends Object
System level service that serves as an event dispatch for {@link AccessibilityEvent}s, and provides facilities for querying the accessibility state of the system. Accessibility events are generated when something notable happens in the user interface, for example an {@link android.app.Activity} starts, the focus or selection of a {@link android.view.View} changes etc. Parties interested in handling accessibility events implement and register an accessibility service which extends {@link android.accessibilityservice.AccessibilityService}.

To obtain a handle to the accessibility manager do the following:

AccessibilityManager accessibilityManager =
(AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);

see
AccessibilityEvent
see
AccessibilityNodeInfo
see
android.accessibilityservice.AccessibilityService
see
Context#getSystemService
see
Context#ACCESSIBILITY_SERVICE

Fields Summary
private static final boolean
DEBUG
private static final String
LOG_TAG
public static final int
STATE_FLAG_ACCESSIBILITY_ENABLED
public static final int
STATE_FLAG_TOUCH_EXPLORATION_ENABLED
public static final int
STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED
public static final int
DALTONIZER_DISABLED
public static final int
DALTONIZER_SIMULATE_MONOCHROMACY
public static final int
DALTONIZER_CORRECT_DEUTERANOMALY
static final Object
sInstanceSync
private static AccessibilityManager
sInstance
private final Object
mLock
private IAccessibilityManager
mService
final int
mUserId
final android.os.Handler
mHandler
boolean
mIsEnabled
boolean
mIsTouchExplorationEnabled
boolean
mIsHighTextContrastEnabled
private final CopyOnWriteArrayList
mAccessibilityStateChangeListeners
private final CopyOnWriteArrayList
mTouchExplorationStateChangeListeners
private final CopyOnWriteArrayList
mHighTextContrastStateChangeListeners
private final IAccessibilityManagerClient.Stub
mClient
Constructors Summary
public AccessibilityManager(android.content.Context context, IAccessibilityManager service, int userId)
Create an instance.

param
context A {@link Context}.
param
service An interface to the backing service.
param
userId User id under which to run.
hide

        mHandler = new MyHandler(context.getMainLooper());
        mService = service;
        mUserId = userId;
        synchronized (mLock) {
            tryConnectToServiceLocked();
        }
    
Methods Summary
public intaddAccessibilityInteractionConnection(android.view.IWindow windowToken, IAccessibilityInteractionConnection connection)
Adds an accessibility interaction connection interface for a given window.

param
windowToken The window token to which a connection is added.
param
connection The connection.
hide

        final IAccessibilityManager service;
        final int userId;
        synchronized (mLock) {
            service = getServiceLocked();
            if (service == null) {
                return View.NO_ID;
            }
            userId = mUserId;
        }
        try {
            return service.addAccessibilityInteractionConnection(windowToken, connection, userId);
        } catch (RemoteException re) {
            Log.e(LOG_TAG, "Error while adding an accessibility interaction connection. ", re);
        }
        return View.NO_ID;
    
public booleanaddAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager$AccessibilityStateChangeListener listener)
Registers an {@link AccessibilityStateChangeListener} for changes in the global accessibility state of the system.

param
listener The listener.
return
True if successfully registered.

        // Final CopyOnWriteArrayList - no lock needed.
        return mAccessibilityStateChangeListeners.add(listener);
    
public booleanaddHighTextContrastStateChangeListener(android.view.accessibility.AccessibilityManager$HighTextContrastChangeListener listener)
Registers a {@link HighTextContrastChangeListener} for changes in the global high text contrast state of the system.

param
listener The listener.
return
True if successfully registered.
hide

        // Final CopyOnWriteArrayList - no lock needed.
        return mHighTextContrastStateChangeListeners.add(listener);
    
public booleanaddTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager$TouchExplorationStateChangeListener listener)
Registers a {@link TouchExplorationStateChangeListener} for changes in the global touch exploration state of the system.

param
listener The listener.
return
True if successfully registered.

        // Final CopyOnWriteArrayList - no lock needed.
        return mTouchExplorationStateChangeListeners.add(listener);
    
public java.util.ListgetAccessibilityServiceList()
Returns the {@link ServiceInfo}s of the installed accessibility services.

return
An unmodifiable list with {@link ServiceInfo}s.
deprecated
Use {@link #getInstalledAccessibilityServiceList()}

        List<AccessibilityServiceInfo> infos = getInstalledAccessibilityServiceList();
        List<ServiceInfo> services = new ArrayList<>();
        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);
    
public IAccessibilityManagerClientgetClient()

hide

        return mClient;
    
public java.util.ListgetEnabledAccessibilityServiceList(int feedbackTypeFlags)
Returns the {@link AccessibilityServiceInfo}s of the enabled accessibility services for a given feedback type.

param
feedbackTypeFlags The feedback type flags.
return
An unmodifiable list with {@link AccessibilityServiceInfo}s.
see
AccessibilityServiceInfo#FEEDBACK_AUDIBLE
see
AccessibilityServiceInfo#FEEDBACK_GENERIC
see
AccessibilityServiceInfo#FEEDBACK_HAPTIC
see
AccessibilityServiceInfo#FEEDBACK_SPOKEN
see
AccessibilityServiceInfo#FEEDBACK_VISUAL
see
AccessibilityServiceInfo#FEEDBACK_BRAILLE

        final IAccessibilityManager service;
        final int userId;
        synchronized (mLock) {
            service = getServiceLocked();
            if (service == null) {
                return Collections.emptyList();
            }
            userId = mUserId;
        }

        List<AccessibilityServiceInfo> services = null;
        try {
            services = service.getEnabledAccessibilityServiceList(feedbackTypeFlags, userId);
            if (DEBUG) {
                Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
            }
        } catch (RemoteException re) {
            Log.e(LOG_TAG, "Error while obtaining the installed AccessibilityServices. ", re);
        }
        if (services != null) {
            return Collections.unmodifiableList(services);
        } else {
            return Collections.emptyList();
        }
    
public java.util.ListgetInstalledAccessibilityServiceList()
Returns the {@link AccessibilityServiceInfo}s of the installed accessibility services.

return
An unmodifiable list with {@link AccessibilityServiceInfo}s.

        final IAccessibilityManager service;
        final int userId;
        synchronized (mLock) {
            service = getServiceLocked();
            if (service == null) {
                return Collections.emptyList();
            }
            userId = mUserId;
        }

        List<AccessibilityServiceInfo> services = null;
        try {
            services = service.getInstalledAccessibilityServiceList(userId);
            if (DEBUG) {
                Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
            }
        } catch (RemoteException re) {
            Log.e(LOG_TAG, "Error while obtaining the installed AccessibilityServices. ", re);
        }
        if (services != null) {
            return Collections.unmodifiableList(services);
        } else {
            return Collections.emptyList();
        }
    
public static android.view.accessibility.AccessibilityManagergetInstance(android.content.Context context)
Get an AccessibilityManager instance (create one if necessary).

param
context Context in which this manager operates.
hide


                          
         
        synchronized (sInstanceSync) {
            if (sInstance == null) {
                final int userId;
                if (Binder.getCallingUid() == Process.SYSTEM_UID
                        || context.checkCallingOrSelfPermission(
                                Manifest.permission.INTERACT_ACROSS_USERS)
                                        == PackageManager.PERMISSION_GRANTED
                        || context.checkCallingOrSelfPermission(
                                Manifest.permission.INTERACT_ACROSS_USERS_FULL)
                                        == PackageManager.PERMISSION_GRANTED) {
                    userId = UserHandle.USER_CURRENT;
                } else {
                    userId = UserHandle.myUserId();
                }
                IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
                IAccessibilityManager service = iBinder == null
                        ? null : IAccessibilityManager.Stub.asInterface(iBinder);
                sInstance = new AccessibilityManager(context, service, userId);
            }
        }
        return sInstance;
    
private IAccessibilityManagergetServiceLocked()

        if (mService == null) {
            tryConnectToServiceLocked();
        }
        return mService;
    
private voidhandleNotifyAccessibilityStateChanged()
Notifies the registered {@link AccessibilityStateChangeListener}s.

        final boolean isEnabled;
        synchronized (mLock) {
            isEnabled = mIsEnabled;
        }
        // Listeners are a final CopyOnWriteArrayList, hence no lock needed.
        for (AccessibilityStateChangeListener listener :mAccessibilityStateChangeListeners) {
            listener.onAccessibilityStateChanged(isEnabled);
        }
    
private voidhandleNotifyHighTextContrastStateChanged()
Notifies the registered {@link HighTextContrastChangeListener}s.

        final boolean isHighTextContrastEnabled;
        synchronized (mLock) {
            isHighTextContrastEnabled = mIsHighTextContrastEnabled;
        }
        // Listeners are a final CopyOnWriteArrayList, hence no lock needed.
        for (HighTextContrastChangeListener listener : mHighTextContrastStateChangeListeners) {
            listener.onHighTextContrastStateChanged(isHighTextContrastEnabled);
        }
    
private voidhandleNotifyTouchExplorationStateChanged()
Notifies the registered {@link TouchExplorationStateChangeListener}s.

        final boolean isTouchExplorationEnabled;
        synchronized (mLock) {
            isTouchExplorationEnabled = mIsTouchExplorationEnabled;
        }
        // Listeners are a final CopyOnWriteArrayList, hence no lock needed.
        for (TouchExplorationStateChangeListener listener :mTouchExplorationStateChangeListeners) {
            listener.onTouchExplorationStateChanged(isTouchExplorationEnabled);
        }
    
public voidinterrupt()
Requests feedback interruption from all accessibility services.

        final IAccessibilityManager service;
        final int userId;
        synchronized (mLock) {
            service = getServiceLocked();
            if (service == null) {
                return;
            }
            if (!mIsEnabled) {
                throw new IllegalStateException("Accessibility off. Did you forget to check that?");
            }
            userId = mUserId;
        }
        try {
            service.interrupt(userId);
            if (DEBUG) {
                Log.i(LOG_TAG, "Requested interrupt from all services");
            }
        } catch (RemoteException re) {
            Log.e(LOG_TAG, "Error while requesting interrupt from all services. ", re);
        }
    
public booleanisEnabled()
Returns if the accessibility in the system is enabled.

return
True if accessibility is enabled, false otherwise.

        synchronized (mLock) {
            IAccessibilityManager service = getServiceLocked();
            if (service == null) {
                return false;
            }
            return mIsEnabled;
        }
    
public booleanisHighTextContrastEnabled()
Returns if the high text contrast in the system is enabled.

Note: You need to query this only if you application is doing its own rendering and does not rely on the platform rendering pipeline.

return
True if high text contrast is enabled, false otherwise.
hide

        synchronized (mLock) {
            IAccessibilityManager service = getServiceLocked();
            if (service == null) {
                return false;
            }
            return mIsHighTextContrastEnabled;
        }
    
public booleanisTouchExplorationEnabled()
Returns if the touch exploration in the system is enabled.

return
True if touch exploration is enabled, false otherwise.

        synchronized (mLock) {
            IAccessibilityManager service = getServiceLocked();
            if (service == null) {
                return false;
            }
            return mIsTouchExplorationEnabled;
        }
    
public voidremoveAccessibilityInteractionConnection(android.view.IWindow windowToken)
Removed an accessibility interaction connection interface for a given window.

param
windowToken The window token to which a connection is removed.
hide

        final IAccessibilityManager service;
        synchronized (mLock) {
            service = getServiceLocked();
            if (service == null) {
                return;
            }
        }
        try {
            service.removeAccessibilityInteractionConnection(windowToken);
        } catch (RemoteException re) {
            Log.e(LOG_TAG, "Error while removing an accessibility interaction connection. ", re);
        }
    
public booleanremoveAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager$AccessibilityStateChangeListener listener)
Unregisters an {@link AccessibilityStateChangeListener}.

param
listener The listener.
return
True if successfully unregistered.

        // Final CopyOnWriteArrayList - no lock needed.
        return mAccessibilityStateChangeListeners.remove(listener);
    
public booleanremoveHighTextContrastStateChangeListener(android.view.accessibility.AccessibilityManager$HighTextContrastChangeListener listener)
Unregisters a {@link HighTextContrastChangeListener}.

param
listener The listener.
return
True if successfully unregistered.
hide

        // Final CopyOnWriteArrayList - no lock needed.
        return mHighTextContrastStateChangeListeners.remove(listener);
    
public booleanremoveTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager$TouchExplorationStateChangeListener listener)
Unregisters a {@link TouchExplorationStateChangeListener}.

param
listener The listener.
return
True if successfully unregistered.

        // Final CopyOnWriteArrayList - no lock needed.
        return mTouchExplorationStateChangeListeners.remove(listener);
    
public voidsendAccessibilityEvent(AccessibilityEvent event)
Sends an {@link AccessibilityEvent}.

param
event The event to send.
throws
IllegalStateException if accessibility is not enabled. Note: The preferred mechanism for sending custom accessibility events is through calling {@link android.view.ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)} instead of this method to allow predecessors to augment/filter events sent by their descendants.

        final IAccessibilityManager service;
        final int userId;
        synchronized (mLock) {
            service = getServiceLocked();
            if (service == null) {
                return;
            }
            if (!mIsEnabled) {
                throw new IllegalStateException("Accessibility off. Did you forget to check that?");
            }
            userId = mUserId;
        }
        boolean doRecycle = false;
        try {
            event.setEventTime(SystemClock.uptimeMillis());
            // it is possible that this manager is in the same process as the service but
            // client using it is called through Binder from another process. Example: MMS
            // app adds a SMS notification and the NotificationManagerService calls this method
            long identityToken = Binder.clearCallingIdentity();
            doRecycle = service.sendAccessibilityEvent(event, userId);
            Binder.restoreCallingIdentity(identityToken);
            if (DEBUG) {
                Log.i(LOG_TAG, event + " sent");
            }
        } catch (RemoteException re) {
            Log.e(LOG_TAG, "Error during sending " + event + " ", re);
        } finally {
            if (doRecycle) {
                event.recycle();
            }
        }
    
private voidsetStateLocked(int stateFlags)
Sets the current state and notifies listeners, if necessary.

param
stateFlags The state flags.

        final boolean enabled = (stateFlags & STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
        final boolean touchExplorationEnabled =
                (stateFlags & STATE_FLAG_TOUCH_EXPLORATION_ENABLED) != 0;
        final boolean highTextContrastEnabled =
                (stateFlags & STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED) != 0;

        final boolean wasEnabled = mIsEnabled;
        final boolean wasTouchExplorationEnabled = mIsTouchExplorationEnabled;
        final boolean wasHighTextContrastEnabled = mIsHighTextContrastEnabled;

        // Ensure listeners get current state from isZzzEnabled() calls.
        mIsEnabled = enabled;
        mIsTouchExplorationEnabled = touchExplorationEnabled;
        mIsHighTextContrastEnabled = highTextContrastEnabled;

        if (wasEnabled != enabled) {
            mHandler.sendEmptyMessage(MyHandler.MSG_NOTIFY_ACCESSIBILITY_STATE_CHANGED);
        }

        if (wasTouchExplorationEnabled != touchExplorationEnabled) {
            mHandler.sendEmptyMessage(MyHandler.MSG_NOTIFY_EXPLORATION_STATE_CHANGED);
        }

        if (wasHighTextContrastEnabled != highTextContrastEnabled) {
            mHandler.sendEmptyMessage(MyHandler.MSG_NOTIFY_HIGH_TEXT_CONTRAST_STATE_CHANGED);
        }
    
private voidtryConnectToServiceLocked()

        IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
        if (iBinder == null) {
            return;
        }
        IAccessibilityManager service = IAccessibilityManager.Stub.asInterface(iBinder);
        try {
            final int stateFlags = service.addClient(mClient, mUserId);
            setStateLocked(stateFlags);
            mService = service;
        } catch (RemoteException re) {
            Log.e(LOG_TAG, "AccessibilityManagerService is dead", re);
        }