blob: a711f48c8c149b105b5e9e9b8ab11995e8e181af [file] [log] [blame]
svetoslavganov75986cf2009-05-14 22:28:01 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view.accessibility;
18
Svetoslav6b25e722013-02-28 16:55:54 -080019import android.Manifest;
Svetoslav Ganov736c2752011-04-22 18:30:36 -070020import android.accessibilityservice.AccessibilityServiceInfo;
svetoslavganov75986cf2009-05-14 22:28:01 -070021import android.content.Context;
Svetoslav6b25e722013-02-28 16:55:54 -080022import android.content.pm.PackageManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070023import android.content.pm.ServiceInfo;
24import android.os.Binder;
25import android.os.Handler;
26import android.os.IBinder;
27import android.os.Looper;
28import android.os.Message;
Svetoslav6b25e722013-02-28 16:55:54 -080029import android.os.Process;
svetoslavganov75986cf2009-05-14 22:28:01 -070030import android.os.RemoteException;
31import android.os.ServiceManager;
32import android.os.SystemClock;
Svetoslav Ganov58d37b52012-09-18 12:04:19 -070033import android.os.UserHandle;
svetoslavganov75986cf2009-05-14 22:28:01 -070034import android.util.Log;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070035import android.view.IWindow;
36import android.view.View;
svetoslavganov75986cf2009-05-14 22:28:01 -070037
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -070038import java.util.ArrayList;
svetoslavganov75986cf2009-05-14 22:28:01 -070039import java.util.Collections;
40import java.util.List;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070041import java.util.concurrent.CopyOnWriteArrayList;
svetoslavganov75986cf2009-05-14 22:28:01 -070042
43/**
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070044 * System level service that serves as an event dispatch for {@link AccessibilityEvent}s,
45 * and provides facilities for querying the accessibility state of the system.
46 * Accessibility events are generated when something notable happens in the user interface,
svetoslavganov75986cf2009-05-14 22:28:01 -070047 * for example an {@link android.app.Activity} starts, the focus or selection of a
48 * {@link android.view.View} changes etc. Parties interested in handling accessibility
49 * events implement and register an accessibility service which extends
50 * {@link android.accessibilityservice.AccessibilityService}.
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070051 * <p>
52 * To obtain a handle to the accessibility manager do the following:
53 * </p>
54 * <p>
55 * <code>
Scott Mainb303d832011-10-12 16:45:18 -070056 * <pre>AccessibilityManager accessibilityManager =
57 * (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);</pre>
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070058 * </code>
59 * </p>
svetoslavganov75986cf2009-05-14 22:28:01 -070060 *
61 * @see AccessibilityEvent
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070062 * @see AccessibilityNodeInfo
svetoslavganov75986cf2009-05-14 22:28:01 -070063 * @see android.accessibilityservice.AccessibilityService
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -070064 * @see Context#getSystemService
65 * @see Context#ACCESSIBILITY_SERVICE
svetoslavganov75986cf2009-05-14 22:28:01 -070066 */
67public final class AccessibilityManager {
Svetoslav Ganov736c2752011-04-22 18:30:36 -070068 private static final boolean DEBUG = false;
69
svetoslavganov75986cf2009-05-14 22:28:01 -070070 private static final String LOG_TAG = "AccessibilityManager";
71
Svetoslav Ganov00aabf72011-07-21 11:35:03 -070072 /** @hide */
73 public static final int STATE_FLAG_ACCESSIBILITY_ENABLED = 0x00000001;
74
75 /** @hide */
76 public static final int STATE_FLAG_TOUCH_EXPLORATION_ENABLED = 0x00000002;
77
Alan Viverette410d4e32013-09-30 15:37:38 -070078 /** @hide */
79 public static final int INVERSION_DISABLED = -1;
80
81 /** @hide */
82 public static final int INVERSION_STANDARD = 0;
83
84 /** @hide */
85 public static final int INVERSION_HUE_ONLY = 1;
86
87 /** @hide */
88 public static final int INVERSION_VALUE_ONLY = 2;
89
90 /** @hide */
91 public static final int DALTONIZER_DISABLED = -1;
92
93 /** @hide */
94 public static final int DALTONIZER_SIMULATE_MONOCHROMACY = 0;
95
96 /** @hide */
97 public static final int DALTONIZER_SIMULATE_PROTANOMALY = 1;
98
99 /** @hide */
100 public static final int DALTONIZER_SIMULATE_DEUTERANOMALY = 2;
101
102 /** @hide */
103 public static final int DALTONIZER_SIMULATE_TRITANOMALY = 3;
104
105 /** @hide */
106 public static final int DALTONIZER_CORRECT_PROTANOMALY = 11;
107
108 /** @hide */
109 public static final int DALTONIZER_CORRECT_DEUTERANOMALY = 12;
110
111 /** @hide */
112 public static final int DALTONIZER_CORRECT_TRITANOMALY = 13;
113
svetoslavganov75986cf2009-05-14 22:28:01 -0700114 static final Object sInstanceSync = new Object();
115
116 private static AccessibilityManager sInstance;
117
Svetoslav Ganov00aabf72011-07-21 11:35:03 -0700118 private static final int DO_SET_STATE = 10;
svetoslavganov75986cf2009-05-14 22:28:01 -0700119
120 final IAccessibilityManager mService;
121
Svetoslav Ganov58d37b52012-09-18 12:04:19 -0700122 final int mUserId;
123
svetoslavganov75986cf2009-05-14 22:28:01 -0700124 final Handler mHandler;
125
126 boolean mIsEnabled;
127
Svetoslav Ganov35bfede2011-07-14 17:57:06 -0700128 boolean mIsTouchExplorationEnabled;
129
Alan Viverette5baeb9a2013-10-09 14:42:05 -0700130 private final CopyOnWriteArrayList<AccessibilityStateChangeListener>
131 mAccessibilityStateChangeListeners = new CopyOnWriteArrayList<
132 AccessibilityStateChangeListener>();
133
134 private final CopyOnWriteArrayList<TouchExplorationStateChangeListener>
135 mTouchExplorationStateChangeListeners = new CopyOnWriteArrayList<
136 TouchExplorationStateChangeListener>();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700137
138 /**
Alan Viverette5baeb9a2013-10-09 14:42:05 -0700139 * Listener for the system accessibility state. To listen for changes to the
140 * accessibility state on the device, implement this interface and register
141 * it with the system by calling {@link #addAccessibilityStateChangeListener}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700142 */
143 public interface AccessibilityStateChangeListener {
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700144
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700145 /**
Alan Viverette5baeb9a2013-10-09 14:42:05 -0700146 * Called when the accessibility enabled state changes.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700147 *
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700148 * @param enabled Whether accessibility is enabled.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700149 */
150 public void onAccessibilityStateChanged(boolean enabled);
151 }
152
Alan Viverette5baeb9a2013-10-09 14:42:05 -0700153 /**
154 * Listener for the system touch exploration state. To listen for changes to
155 * the touch exploration state on the device, implement this interface and
156 * register it with the system by calling
157 * {@link #addTouchExplorationStateChangeListener}.
158 */
159 public interface TouchExplorationStateChangeListener {
160
161 /**
162 * Called when the touch exploration enabled state changes.
163 *
164 * @param enabled Whether touch exploration is enabled.
165 */
166 public void onTouchExplorationStateChanged(boolean enabled);
167 }
168
svetoslavganov75986cf2009-05-14 22:28:01 -0700169 final IAccessibilityManagerClient.Stub mClient = new IAccessibilityManagerClient.Stub() {
Svetoslav Ganov00aabf72011-07-21 11:35:03 -0700170 public void setState(int state) {
171 mHandler.obtainMessage(DO_SET_STATE, state, 0).sendToTarget();
svetoslavganov75986cf2009-05-14 22:28:01 -0700172 }
173 };
174
175 class MyHandler extends Handler {
176
177 MyHandler(Looper mainLooper) {
178 super(mainLooper);
179 }
180
181 @Override
182 public void handleMessage(Message message) {
183 switch (message.what) {
Svetoslav Ganov00aabf72011-07-21 11:35:03 -0700184 case DO_SET_STATE :
185 setState(message.arg1);
svetoslavganov75986cf2009-05-14 22:28:01 -0700186 return;
187 default :
188 Log.w(LOG_TAG, "Unknown message type: " + message.what);
189 }
190 }
191 }
192
193 /**
194 * Get an AccessibilityManager instance (create one if necessary).
195 *
Svetoslav Ganov58d37b52012-09-18 12:04:19 -0700196 * @param context Context in which this manager operates.
197 *
svetoslavganov75986cf2009-05-14 22:28:01 -0700198 * @hide
199 */
200 public static AccessibilityManager getInstance(Context context) {
201 synchronized (sInstanceSync) {
202 if (sInstance == null) {
Svetoslav6b25e722013-02-28 16:55:54 -0800203 final int userId;
204 if (Binder.getCallingUid() == Process.SYSTEM_UID
205 || context.checkCallingOrSelfPermission(
206 Manifest.permission.INTERACT_ACROSS_USERS)
207 == PackageManager.PERMISSION_GRANTED
208 || context.checkCallingOrSelfPermission(
209 Manifest.permission.INTERACT_ACROSS_USERS_FULL)
210 == PackageManager.PERMISSION_GRANTED) {
211 userId = UserHandle.USER_CURRENT;
212 } else {
213 userId = UserHandle.myUserId();
214 }
215 IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
Amith Yamasani91588252013-11-22 08:25:26 -0800216 IAccessibilityManager service = iBinder == null
217 ? null : IAccessibilityManager.Stub.asInterface(iBinder);
Svetoslav6b25e722013-02-28 16:55:54 -0800218 sInstance = new AccessibilityManager(context, service, userId);
svetoslavganov75986cf2009-05-14 22:28:01 -0700219 }
220 }
221 return sInstance;
222 }
223
224 /**
225 * Create an instance.
226 *
227 * @param context A {@link Context}.
Svetoslav Ganovaf7adab2010-04-16 18:07:48 -0700228 * @param service An interface to the backing service.
Svetoslav Ganov58d37b52012-09-18 12:04:19 -0700229 * @param userId User id under which to run.
Svetoslav Ganovaf7adab2010-04-16 18:07:48 -0700230 *
231 * @hide
svetoslavganov75986cf2009-05-14 22:28:01 -0700232 */
Svetoslav Ganov58d37b52012-09-18 12:04:19 -0700233 public AccessibilityManager(Context context, IAccessibilityManager service, int userId) {
svetoslavganov75986cf2009-05-14 22:28:01 -0700234 mHandler = new MyHandler(context.getMainLooper());
Svetoslav Ganovaf7adab2010-04-16 18:07:48 -0700235 mService = service;
Svetoslav Ganov58d37b52012-09-18 12:04:19 -0700236 mUserId = userId;
Amith Yamasani91588252013-11-22 08:25:26 -0800237 if (mService == null) {
238 mIsEnabled = false;
239 }
svetoslavganov75986cf2009-05-14 22:28:01 -0700240 try {
Amith Yamasani91588252013-11-22 08:25:26 -0800241 if (mService != null) {
242 final int stateFlags = mService.addClient(mClient, userId);
243 setState(stateFlags);
244 }
svetoslavganov75986cf2009-05-14 22:28:01 -0700245 } catch (RemoteException re) {
246 Log.e(LOG_TAG, "AccessibilityManagerService is dead", re);
247 }
248 }
249
250 /**
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700251 * Returns if the accessibility in the system is enabled.
svetoslavganov75986cf2009-05-14 22:28:01 -0700252 *
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700253 * @return True if accessibility is enabled, false otherwise.
svetoslavganov75986cf2009-05-14 22:28:01 -0700254 */
255 public boolean isEnabled() {
256 synchronized (mHandler) {
257 return mIsEnabled;
258 }
259 }
260
261 /**
Svetoslav Ganov35bfede2011-07-14 17:57:06 -0700262 * Returns if the touch exploration in the system is enabled.
263 *
264 * @return True if touch exploration is enabled, false otherwise.
265 */
266 public boolean isTouchExplorationEnabled() {
267 synchronized (mHandler) {
268 return mIsTouchExplorationEnabled;
269 }
270 }
271
272 /**
Svetoslav Ganovaf7adab2010-04-16 18:07:48 -0700273 * Returns the client interface this instance registers in
274 * the centralized accessibility manager service.
275 *
276 * @return The client.
277 *
278 * @hide
279 */
280 public IAccessibilityManagerClient getClient() {
Jim Miller4dfecf52011-06-30 15:45:35 -0700281 return (IAccessibilityManagerClient) mClient.asBinder();
Svetoslav Ganovaf7adab2010-04-16 18:07:48 -0700282 }
283
284 /**
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700285 * Sends an {@link AccessibilityEvent}.
svetoslavganov75986cf2009-05-14 22:28:01 -0700286 *
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700287 * @param event The event to send.
svetoslavganov75986cf2009-05-14 22:28:01 -0700288 *
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700289 * @throws IllegalStateException if accessibility is not enabled.
Svetoslav Ganov42138042012-03-20 11:51:39 -0700290 *
291 * <strong>Note:</strong> The preferred mechanism for sending custom accessibility
292 * events is through calling
293 * {@link android.view.ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
294 * instead of this method to allow predecessors to augment/filter events sent by
295 * their descendants.
svetoslavganov75986cf2009-05-14 22:28:01 -0700296 */
297 public void sendAccessibilityEvent(AccessibilityEvent event) {
298 if (!mIsEnabled) {
299 throw new IllegalStateException("Accessibility off. Did you forget to check that?");
300 }
301 boolean doRecycle = false;
302 try {
303 event.setEventTime(SystemClock.uptimeMillis());
304 // it is possible that this manager is in the same process as the service but
305 // client using it is called through Binder from another process. Example: MMS
306 // app adds a SMS notification and the NotificationManagerService calls this method
307 long identityToken = Binder.clearCallingIdentity();
Svetoslav Ganov58d37b52012-09-18 12:04:19 -0700308 doRecycle = mService.sendAccessibilityEvent(event, mUserId);
svetoslavganov75986cf2009-05-14 22:28:01 -0700309 Binder.restoreCallingIdentity(identityToken);
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700310 if (DEBUG) {
svetoslavganov75986cf2009-05-14 22:28:01 -0700311 Log.i(LOG_TAG, event + " sent");
312 }
313 } catch (RemoteException re) {
314 Log.e(LOG_TAG, "Error during sending " + event + " ", re);
315 } finally {
316 if (doRecycle) {
317 event.recycle();
318 }
319 }
320 }
321
322 /**
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700323 * Requests feedback interruption from all accessibility services.
svetoslavganov75986cf2009-05-14 22:28:01 -0700324 */
325 public void interrupt() {
326 if (!mIsEnabled) {
327 throw new IllegalStateException("Accessibility off. Did you forget to check that?");
328 }
329 try {
Svetoslav Ganov58d37b52012-09-18 12:04:19 -0700330 mService.interrupt(mUserId);
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700331 if (DEBUG) {
svetoslavganov75986cf2009-05-14 22:28:01 -0700332 Log.i(LOG_TAG, "Requested interrupt from all services");
333 }
334 } catch (RemoteException re) {
335 Log.e(LOG_TAG, "Error while requesting interrupt from all services. ", re);
336 }
337 }
338
339 /**
340 * Returns the {@link ServiceInfo}s of the installed accessibility services.
341 *
342 * @return An unmodifiable list with {@link ServiceInfo}s.
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700343 *
344 * @deprecated Use {@link #getInstalledAccessibilityServiceList()}
svetoslavganov75986cf2009-05-14 22:28:01 -0700345 */
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700346 @Deprecated
svetoslavganov75986cf2009-05-14 22:28:01 -0700347 public List<ServiceInfo> getAccessibilityServiceList() {
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700348 List<AccessibilityServiceInfo> infos = getInstalledAccessibilityServiceList();
349 List<ServiceInfo> services = new ArrayList<ServiceInfo>();
350 final int infoCount = infos.size();
351 for (int i = 0; i < infoCount; i++) {
352 AccessibilityServiceInfo info = infos.get(i);
353 services.add(info.getResolveInfo().serviceInfo);
354 }
355 return Collections.unmodifiableList(services);
356 }
357
358 /**
359 * Returns the {@link AccessibilityServiceInfo}s of the installed accessibility services.
360 *
361 * @return An unmodifiable list with {@link AccessibilityServiceInfo}s.
362 */
363 public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList() {
364 List<AccessibilityServiceInfo> services = null;
svetoslavganov75986cf2009-05-14 22:28:01 -0700365 try {
Amith Yamasani91588252013-11-22 08:25:26 -0800366 if (mService != null) {
367 services = mService.getInstalledAccessibilityServiceList(mUserId);
368 if (DEBUG) {
369 Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
370 }
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700371 }
372 } catch (RemoteException re) {
373 Log.e(LOG_TAG, "Error while obtaining the installed AccessibilityServices. ", re);
374 }
Amith Yamasani91588252013-11-22 08:25:26 -0800375 return services != null ? Collections.unmodifiableList(services) : Collections.EMPTY_LIST;
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700376 }
377
378 /**
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700379 * Returns the {@link AccessibilityServiceInfo}s of the enabled accessibility services
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700380 * for a given feedback type.
381 *
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700382 * @param feedbackTypeFlags The feedback type flags.
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700383 * @return An unmodifiable list with {@link AccessibilityServiceInfo}s.
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700384 *
385 * @see AccessibilityServiceInfo#FEEDBACK_AUDIBLE
386 * @see AccessibilityServiceInfo#FEEDBACK_GENERIC
387 * @see AccessibilityServiceInfo#FEEDBACK_HAPTIC
388 * @see AccessibilityServiceInfo#FEEDBACK_SPOKEN
389 * @see AccessibilityServiceInfo#FEEDBACK_VISUAL
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700390 */
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700391 public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(
392 int feedbackTypeFlags) {
Svetoslav Ganovcc4053e2011-05-23 13:37:44 -0700393 List<AccessibilityServiceInfo> services = null;
Svetoslav Ganov736c2752011-04-22 18:30:36 -0700394 try {
Amith Yamasani91588252013-11-22 08:25:26 -0800395 if (mService != null) {
396 services = mService.getEnabledAccessibilityServiceList(feedbackTypeFlags, mUserId);
397 if (DEBUG) {
398 Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
399 }
svetoslavganov75986cf2009-05-14 22:28:01 -0700400 }
401 } catch (RemoteException re) {
402 Log.e(LOG_TAG, "Error while obtaining the installed AccessibilityServices. ", re);
403 }
Amith Yamasani91588252013-11-22 08:25:26 -0800404 return services != null ? Collections.unmodifiableList(services) : Collections.EMPTY_LIST;
svetoslavganov75986cf2009-05-14 22:28:01 -0700405 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700406
407 /**
Svetoslav Ganov38e8b4e2011-06-29 20:00:53 -0700408 * Registers an {@link AccessibilityStateChangeListener} for changes in
409 * the global accessibility state of the system.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700410 *
411 * @param listener The listener.
412 * @return True if successfully registered.
413 */
414 public boolean addAccessibilityStateChangeListener(
415 AccessibilityStateChangeListener listener) {
416 return mAccessibilityStateChangeListeners.add(listener);
417 }
418
419 /**
420 * Unregisters an {@link AccessibilityStateChangeListener}.
421 *
422 * @param listener The listener.
423 * @return True if successfully unregistered.
424 */
425 public boolean removeAccessibilityStateChangeListener(
426 AccessibilityStateChangeListener listener) {
427 return mAccessibilityStateChangeListeners.remove(listener);
428 }
429
430 /**
Alan Viverette5baeb9a2013-10-09 14:42:05 -0700431 * Registers a {@link TouchExplorationStateChangeListener} for changes in
432 * the global touch exploration state of the system.
433 *
434 * @param listener The listener.
435 * @return True if successfully registered.
436 */
437 public boolean addTouchExplorationStateChangeListener(
438 TouchExplorationStateChangeListener listener) {
439 return mTouchExplorationStateChangeListeners.add(listener);
440 }
441
442 /**
443 * Unregisters a {@link TouchExplorationStateChangeListener}.
444 *
445 * @param listener The listener.
446 * @return True if successfully unregistered.
447 */
448 public boolean removeTouchExplorationStateChangeListener(
449 TouchExplorationStateChangeListener listener) {
450 return mTouchExplorationStateChangeListeners.remove(listener);
451 }
452
453 /**
454 * Sets the current state and notifies listeners, if necessary.
Svetoslav Ganov00aabf72011-07-21 11:35:03 -0700455 *
456 * @param stateFlags The state flags.
457 */
458 private void setState(int stateFlags) {
Alan Viverette5baeb9a2013-10-09 14:42:05 -0700459 final boolean enabled = (stateFlags & STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
460 final boolean touchExplorationEnabled =
461 (stateFlags & STATE_FLAG_TOUCH_EXPLORATION_ENABLED) != 0;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700462 synchronized (mHandler) {
Alan Viverette7e361d22013-10-09 17:20:43 -0700463 final boolean wasEnabled = mIsEnabled;
464 final boolean wasTouchExplorationEnabled = mIsTouchExplorationEnabled;
465
466 // Ensure listeners get current state from isZzzEnabled() calls.
Alan Viverette5baeb9a2013-10-09 14:42:05 -0700467 mIsEnabled = enabled;
468 mIsTouchExplorationEnabled = touchExplorationEnabled;
469
Alan Viverette7e361d22013-10-09 17:20:43 -0700470 if (wasEnabled != enabled) {
Alan Viverette5baeb9a2013-10-09 14:42:05 -0700471 notifyAccessibilityStateChangedLh();
472 }
473
Alan Viverette7e361d22013-10-09 17:20:43 -0700474 if (wasTouchExplorationEnabled != touchExplorationEnabled) {
Alan Viverette5baeb9a2013-10-09 14:42:05 -0700475 notifyTouchExplorationStateChangedLh();
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700476 }
477 }
478 }
479
480 /**
481 * Notifies the registered {@link AccessibilityStateChangeListener}s.
Alan Viverette5baeb9a2013-10-09 14:42:05 -0700482 * <p>
483 * The caller must be locked on {@link #mHandler}.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700484 */
Alan Viverette5baeb9a2013-10-09 14:42:05 -0700485 private void notifyAccessibilityStateChangedLh() {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700486 final int listenerCount = mAccessibilityStateChangeListeners.size();
487 for (int i = 0; i < listenerCount; i++) {
488 mAccessibilityStateChangeListeners.get(i).onAccessibilityStateChanged(mIsEnabled);
489 }
490 }
491
492 /**
Alan Viverette5baeb9a2013-10-09 14:42:05 -0700493 * Notifies the registered {@link TouchExplorationStateChangeListener}s.
494 * <p>
495 * The caller must be locked on {@link #mHandler}.
496 */
497 private void notifyTouchExplorationStateChangedLh() {
498 final int listenerCount = mTouchExplorationStateChangeListeners.size();
499 for (int i = 0; i < listenerCount; i++) {
500 mTouchExplorationStateChangeListeners.get(i)
501 .onTouchExplorationStateChanged(mIsTouchExplorationEnabled);
502 }
503 }
504
505 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700506 * Adds an accessibility interaction connection interface for a given window.
507 * @param windowToken The window token to which a connection is added.
508 * @param connection The connection.
509 *
510 * @hide
511 */
512 public int addAccessibilityInteractionConnection(IWindow windowToken,
513 IAccessibilityInteractionConnection connection) {
Amith Yamasani91588252013-11-22 08:25:26 -0800514 if (mService == null) {
515 return View.NO_ID;
516 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700517 try {
Svetoslav Ganov58d37b52012-09-18 12:04:19 -0700518 return mService.addAccessibilityInteractionConnection(windowToken, connection, mUserId);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700519 } catch (RemoteException re) {
520 Log.e(LOG_TAG, "Error while adding an accessibility interaction connection. ", re);
521 }
522 return View.NO_ID;
523 }
524
525 /**
526 * Removed an accessibility interaction connection interface for a given window.
527 * @param windowToken The window token to which a connection is removed.
528 *
529 * @hide
530 */
531 public void removeAccessibilityInteractionConnection(IWindow windowToken) {
532 try {
Amith Yamasani91588252013-11-22 08:25:26 -0800533 if (mService != null) {
534 mService.removeAccessibilityInteractionConnection(windowToken);
535 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -0700536 } catch (RemoteException re) {
537 Log.e(LOG_TAG, "Error while removing an accessibility interaction connection. ", re);
538 }
539 }
svetoslavganov75986cf2009-05-14 22:28:01 -0700540}