• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  ** Copyright 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 
17 package com.android.server.accessibility;
18 
19 import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT;
20 
21 import android.Manifest;
22 import android.accessibilityservice.AccessibilityService;
23 import android.accessibilityservice.AccessibilityServiceInfo;
24 import android.accessibilityservice.IAccessibilityServiceClient;
25 import android.accessibilityservice.IAccessibilityServiceConnection;
26 import android.app.AlertDialog;
27 import android.app.PendingIntent;
28 import android.app.StatusBarManager;
29 import android.content.BroadcastReceiver;
30 import android.content.ComponentName;
31 import android.content.ContentResolver;
32 import android.content.Context;
33 import android.content.DialogInterface;
34 import android.content.DialogInterface.OnClickListener;
35 import android.content.Intent;
36 import android.content.IntentFilter;
37 import android.content.ServiceConnection;
38 import android.content.pm.PackageManager;
39 import android.content.pm.ResolveInfo;
40 import android.content.pm.ServiceInfo;
41 import android.content.pm.UserInfo;
42 import android.database.ContentObserver;
43 import android.graphics.Point;
44 import android.graphics.Rect;
45 import android.graphics.Region;
46 import android.hardware.display.DisplayManager;
47 import android.hardware.input.InputManager;
48 import android.net.Uri;
49 import android.os.Binder;
50 import android.os.Build;
51 import android.os.Bundle;
52 import android.os.Handler;
53 import android.os.IBinder;
54 import android.os.Looper;
55 import android.os.Message;
56 import android.os.Process;
57 import android.os.RemoteCallbackList;
58 import android.os.RemoteException;
59 import android.os.ServiceManager;
60 import android.os.SystemClock;
61 import android.os.UserHandle;
62 import android.os.UserManager;
63 import android.provider.Settings;
64 import android.text.TextUtils;
65 import android.text.TextUtils.SimpleStringSplitter;
66 import android.util.Pools.Pool;
67 import android.util.Pools.SimplePool;
68 import android.util.Slog;
69 import android.util.SparseArray;
70 import android.view.Display;
71 import android.view.IWindow;
72 import android.view.InputDevice;
73 import android.view.InputEventConsistencyVerifier;
74 import android.view.KeyCharacterMap;
75 import android.view.KeyEvent;
76 import android.view.MagnificationSpec;
77 import android.view.WindowInfo;
78 import android.view.WindowManager;
79 import android.view.WindowManagerInternal;
80 import android.view.WindowManagerPolicy;
81 import android.view.accessibility.AccessibilityEvent;
82 import android.view.accessibility.AccessibilityInteractionClient;
83 import android.view.accessibility.AccessibilityManager;
84 import android.view.accessibility.AccessibilityNodeInfo;
85 import android.view.accessibility.AccessibilityWindowInfo;
86 import android.view.accessibility.IAccessibilityInteractionConnection;
87 import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
88 import android.view.accessibility.IAccessibilityManager;
89 import android.view.accessibility.IAccessibilityManagerClient;
90 
91 import com.android.internal.R;
92 import com.android.internal.content.PackageMonitor;
93 import com.android.internal.statusbar.IStatusBarService;
94 import com.android.internal.widget.LockPatternUtils;
95 import com.android.server.LocalServices;
96 
97 import org.xmlpull.v1.XmlPullParserException;
98 
99 import java.io.FileDescriptor;
100 import java.io.IOException;
101 import java.io.PrintWriter;
102 import java.util.ArrayList;
103 import java.util.Arrays;
104 import java.util.Collections;
105 import java.util.HashMap;
106 import java.util.HashSet;
107 import java.util.Iterator;
108 import java.util.List;
109 import java.util.Map;
110 import java.util.Set;
111 import java.util.concurrent.CopyOnWriteArrayList;
112 
113 /**
114  * This class is instantiated by the system as a system level service and can be
115  * accessed only by the system. The task of this service is to be a centralized
116  * event dispatch for {@link AccessibilityEvent}s generated across all processes
117  * on the device. Events are dispatched to {@link AccessibilityService}s.
118  */
119 public class AccessibilityManagerService extends IAccessibilityManager.Stub {
120 
121     private static final boolean DEBUG = false;
122 
123     private static final String LOG_TAG = "AccessibilityManagerService";
124 
125     // TODO: This is arbitrary. When there is time implement this by watching
126     //       when that accessibility services are bound.
127     private static final int WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS = 3000;
128 
129     private static final int WAIT_WINDOWS_TIMEOUT_MILLIS = 5000;
130 
131     private static final String FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE =
132         "registerUiTestAutomationService";
133 
134     private static final String TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED =
135             "temporaryEnableAccessibilityStateUntilKeyguardRemoved";
136 
137     private static final String GET_WINDOW_TOKEN = "getWindowToken";
138 
139     private static final ComponentName sFakeAccessibilityServiceComponentName =
140             new ComponentName("foo.bar", "FakeService");
141 
142     private static final String FUNCTION_DUMP = "dump";
143 
144     private static final char COMPONENT_NAME_SEPARATOR = ':';
145 
146     private static final int OWN_PROCESS_ID = android.os.Process.myPid();
147 
148     private static final int MAX_POOL_SIZE = 10;
149 
150     private static final int WINDOW_ID_UNKNOWN = -1;
151 
152     private static int sIdCounter = 0;
153 
154     private static int sNextWindowId;
155 
156     private final Context mContext;
157 
158     private final Object mLock = new Object();
159 
160     private final Pool<PendingEvent> mPendingEventPool =
161             new SimplePool<>(MAX_POOL_SIZE);
162 
163     private final SimpleStringSplitter mStringColonSplitter =
164             new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
165 
166     private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList =
167             new ArrayList<>();
168 
169     private final Region mTempRegion = new Region();
170 
171     private final Rect mTempRect = new Rect();
172 
173     private final Rect mTempRect1 = new Rect();
174 
175     private final Point mTempPoint = new Point();
176 
177     private final PackageManager mPackageManager;
178 
179     private final WindowManagerInternal mWindowManagerService;
180 
181     private final SecurityPolicy mSecurityPolicy;
182 
183     private final MainHandler mMainHandler;
184 
185     private InteractionBridge mInteractionBridge;
186 
187     private AlertDialog mEnableTouchExplorationDialog;
188 
189     private AccessibilityInputFilter mInputFilter;
190 
191     private boolean mHasInputFilter;
192 
193     private final Set<ComponentName> mTempComponentNameSet = new HashSet<>();
194 
195     private final List<AccessibilityServiceInfo> mTempAccessibilityServiceInfoList =
196             new ArrayList<>();
197 
198     private final RemoteCallbackList<IAccessibilityManagerClient> mGlobalClients =
199             new RemoteCallbackList<>();
200 
201     private final SparseArray<AccessibilityConnectionWrapper> mGlobalInteractionConnections =
202             new SparseArray<>();
203 
204     private final SparseArray<IBinder> mGlobalWindowTokens = new SparseArray<>();
205 
206     private final SparseArray<UserState> mUserStates = new SparseArray<>();
207 
208     private final UserManager mUserManager;
209 
210     private final LockPatternUtils mLockPatternUtils;
211 
212     private int mCurrentUserId = UserHandle.USER_OWNER;
213 
214     //TODO: Remove this hack
215     private boolean mInitialized;
216 
217     private WindowsForAccessibilityCallback mWindowsForAccessibilityCallback;
218 
getCurrentUserStateLocked()219     private UserState getCurrentUserStateLocked() {
220         return getUserStateLocked(mCurrentUserId);
221     }
222 
223     /**
224      * Creates a new instance.
225      *
226      * @param context A {@link Context} instance.
227      */
AccessibilityManagerService(Context context)228     public AccessibilityManagerService(Context context) {
229         mContext = context;
230         mPackageManager = mContext.getPackageManager();
231         mWindowManagerService = LocalServices.getService(WindowManagerInternal.class);
232         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
233         mSecurityPolicy = new SecurityPolicy();
234         mMainHandler = new MainHandler(mContext.getMainLooper());
235         mLockPatternUtils = new LockPatternUtils(context);
236         registerBroadcastReceivers();
237         new AccessibilityContentObserver(mMainHandler).register(
238                 context.getContentResolver());
239     }
240 
getUserStateLocked(int userId)241     private UserState getUserStateLocked(int userId) {
242         UserState state = mUserStates.get(userId);
243         if (state == null) {
244             state = new UserState(userId);
245             mUserStates.put(userId, state);
246         }
247         return state;
248     }
249 
registerBroadcastReceivers()250     private void registerBroadcastReceivers() {
251         PackageMonitor monitor = new PackageMonitor() {
252             @Override
253             public void onSomePackagesChanged() {
254                 synchronized (mLock) {
255                     // Only the profile parent can install accessibility services.
256                     // Therefore we ignore packages from linked profiles.
257                     if (getChangingUserId() != mCurrentUserId) {
258                         return;
259                     }
260                     // We will update when the automation service dies.
261                     UserState userState = getCurrentUserStateLocked();
262                     // We have to reload the installed services since some services may
263                     // have different attributes, resolve info (does not support equals),
264                     // etc. Remove them then to force reload. Do it even if automation is
265                     // running since when it goes away, we will have to reload as well.
266                     userState.mInstalledServices.clear();
267                     if (userState.mUiAutomationService == null) {
268                         if (readConfigurationForUserStateLocked(userState)) {
269                             onUserStateChangedLocked(userState);
270                         }
271                     }
272                 }
273             }
274 
275             @Override
276             public void onPackageRemoved(String packageName, int uid) {
277                 synchronized (mLock) {
278                     final int userId = getChangingUserId();
279                     // Only the profile parent can install accessibility services.
280                     // Therefore we ignore packages from linked profiles.
281                     if (userId != mCurrentUserId) {
282                         return;
283                     }
284                     UserState userState = getUserStateLocked(userId);
285                     Iterator<ComponentName> it = userState.mEnabledServices.iterator();
286                     while (it.hasNext()) {
287                         ComponentName comp = it.next();
288                         String compPkg = comp.getPackageName();
289                         if (compPkg.equals(packageName)) {
290                             it.remove();
291                             // Update the enabled services setting.
292                             persistComponentNamesToSettingLocked(
293                                     Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
294                                     userState.mEnabledServices, userId);
295                             // Update the touch exploration granted services setting.
296                             userState.mTouchExplorationGrantedServices.remove(comp);
297                             persistComponentNamesToSettingLocked(
298                                     Settings.Secure.
299                                     TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
300                                     userState.mTouchExplorationGrantedServices, userId);
301                             // We will update when the automation service dies.
302                             if (userState.mUiAutomationService == null) {
303                                 onUserStateChangedLocked(userState);
304                             }
305                             return;
306                         }
307                     }
308                 }
309             }
310 
311             @Override
312             public boolean onHandleForceStop(Intent intent, String[] packages,
313                     int uid, boolean doit) {
314                 synchronized (mLock) {
315                     final int userId = getChangingUserId();
316                     // Only the profile parent can install accessibility services.
317                     // Therefore we ignore packages from linked profiles.
318                     if (userId != mCurrentUserId) {
319                         return false;
320                     }
321                     UserState userState = getUserStateLocked(userId);
322                     Iterator<ComponentName> it = userState.mEnabledServices.iterator();
323                     while (it.hasNext()) {
324                         ComponentName comp = it.next();
325                         String compPkg = comp.getPackageName();
326                         for (String pkg : packages) {
327                             if (compPkg.equals(pkg)) {
328                                 if (!doit) {
329                                     return true;
330                                 }
331                                 it.remove();
332                                 persistComponentNamesToSettingLocked(
333                                         Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
334                                         userState.mEnabledServices, userId);
335                                 // We will update when the automation service dies.
336                                 if (userState.mUiAutomationService == null) {
337                                     onUserStateChangedLocked(userState);
338                                 }
339                             }
340                         }
341                     }
342                     return false;
343                 }
344             }
345         };
346 
347         // package changes
348         monitor.register(mContext, null,  UserHandle.ALL, true);
349 
350         // user change and unlock
351         IntentFilter intentFilter = new IntentFilter();
352         intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
353         intentFilter.addAction(Intent.ACTION_USER_REMOVED);
354         intentFilter.addAction(Intent.ACTION_USER_PRESENT);
355 
356         mContext.registerReceiverAsUser(new BroadcastReceiver() {
357             @Override
358             public void onReceive(Context context, Intent intent) {
359                 String action = intent.getAction();
360                 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
361                     switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
362                 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
363                     removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
364                 } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
365                     // We will update when the automation service dies.
366                     UserState userState = getCurrentUserStateLocked();
367                     if (userState.mUiAutomationService == null) {
368                         if (readConfigurationForUserStateLocked(userState)) {
369                             onUserStateChangedLocked(userState);
370                         }
371                     }
372                 }
373             }
374         }, UserHandle.ALL, intentFilter, null, null);
375     }
376 
377     @Override
addClient(IAccessibilityManagerClient client, int userId)378     public int addClient(IAccessibilityManagerClient client, int userId) {
379         synchronized (mLock) {
380             // We treat calls from a profile as if made by its parent as profiles
381             // share the accessibility state of the parent. The call below
382             // performs the current profile parent resolution.
383             final int resolvedUserId = mSecurityPolicy
384                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
385             // If the client is from a process that runs across users such as
386             // the system UI or the system we add it to the global state that
387             // is shared across users.
388             UserState userState = getUserStateLocked(resolvedUserId);
389             if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
390                 mGlobalClients.register(client);
391                 if (DEBUG) {
392                     Slog.i(LOG_TAG, "Added global client for pid:" + Binder.getCallingPid());
393                 }
394                 return userState.getClientState();
395             } else {
396                 userState.mClients.register(client);
397                 // If this client is not for the current user we do not
398                 // return a state since it is not for the foreground user.
399                 // We will send the state to the client on a user switch.
400                 if (DEBUG) {
401                     Slog.i(LOG_TAG, "Added user client for pid:" + Binder.getCallingPid()
402                             + " and userId:" + mCurrentUserId);
403                 }
404                 return (resolvedUserId == mCurrentUserId) ? userState.getClientState() : 0;
405             }
406         }
407     }
408 
409     @Override
sendAccessibilityEvent(AccessibilityEvent event, int userId)410     public boolean sendAccessibilityEvent(AccessibilityEvent event, int userId) {
411         synchronized (mLock) {
412             // We treat calls from a profile as if made by its parent as profiles
413             // share the accessibility state of the parent. The call below
414             // performs the current profile parent resolution..
415             final int resolvedUserId = mSecurityPolicy
416                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
417             // This method does nothing for a background user.
418             if (resolvedUserId != mCurrentUserId) {
419                 return true; // yes, recycle the event
420             }
421             if (mSecurityPolicy.canDispatchAccessibilityEventLocked(event)) {
422                 mSecurityPolicy.updateActiveAndAccessibilityFocusedWindowLocked(event.getWindowId(),
423                         event.getSourceNodeId(), event.getEventType());
424                 mSecurityPolicy.updateEventSourceLocked(event);
425                 notifyAccessibilityServicesDelayedLocked(event, false);
426                 notifyAccessibilityServicesDelayedLocked(event, true);
427             }
428             if (mHasInputFilter && mInputFilter != null) {
429                 mMainHandler.obtainMessage(MainHandler.MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER,
430                         AccessibilityEvent.obtain(event)).sendToTarget();
431             }
432             event.recycle();
433             getUserStateLocked(resolvedUserId).mHandledFeedbackTypes = 0;
434         }
435         return (OWN_PROCESS_ID != Binder.getCallingPid());
436     }
437 
438     @Override
getInstalledAccessibilityServiceList(int userId)439     public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) {
440         synchronized (mLock) {
441             // We treat calls from a profile as if made by its parent as profiles
442             // share the accessibility state of the parent. The call below
443             // performs the current profile parent resolution.
444             final int resolvedUserId = mSecurityPolicy
445                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
446             // The automation service is a fake one and should not be reported
447             // to clients as being installed - it really is not.
448             UserState userState = getUserStateLocked(resolvedUserId);
449             if (userState.mUiAutomationService != null) {
450                 List<AccessibilityServiceInfo> installedServices = new ArrayList<>();
451                 installedServices.addAll(userState.mInstalledServices);
452                 installedServices.remove(userState.mUiAutomationService.mAccessibilityServiceInfo);
453                 return installedServices;
454             }
455             return userState.mInstalledServices;
456         }
457     }
458 
459     @Override
getEnabledAccessibilityServiceList(int feedbackType, int userId)460     public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType,
461             int userId) {
462         List<AccessibilityServiceInfo> result = null;
463         synchronized (mLock) {
464             // We treat calls from a profile as if made by its parent as profiles
465             // share the accessibility state of the parent. The call below
466             // performs the current profile parent resolution.
467             final int resolvedUserId = mSecurityPolicy
468                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
469 
470             // The automation service is a fake one and should not be reported
471             // to clients as being enabled. The automation service is always the
472             // only active one, if it exists.
473             UserState userState = getUserStateLocked(resolvedUserId);
474             if (userState.mUiAutomationService != null) {
475                 return Collections.emptyList();
476             }
477 
478             result = mEnabledServicesForFeedbackTempList;
479             result.clear();
480             List<Service> services = userState.mBoundServices;
481             while (feedbackType != 0) {
482                 final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackType));
483                 feedbackType &= ~feedbackTypeBit;
484                 final int serviceCount = services.size();
485                 for (int i = 0; i < serviceCount; i++) {
486                     Service service = services.get(i);
487                     if ((service.mFeedbackType & feedbackTypeBit) != 0) {
488                         result.add(service.mAccessibilityServiceInfo);
489                     }
490                 }
491             }
492         }
493         return result;
494     }
495 
496     @Override
interrupt(int userId)497     public void interrupt(int userId) {
498         CopyOnWriteArrayList<Service> services;
499         synchronized (mLock) {
500             // We treat calls from a profile as if made by its parent as profiles
501             // share the accessibility state of the parent. The call below
502             // performs the current profile parent resolution.
503             final int resolvedUserId = mSecurityPolicy
504                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
505             // This method does nothing for a background user.
506             if (resolvedUserId != mCurrentUserId) {
507                 return;
508             }
509             services = getUserStateLocked(resolvedUserId).mBoundServices;
510         }
511         for (int i = 0, count = services.size(); i < count; i++) {
512             Service service = services.get(i);
513             try {
514                 service.mServiceInterface.onInterrupt();
515             } catch (RemoteException re) {
516                 Slog.e(LOG_TAG, "Error during sending interrupt request to "
517                     + service.mService, re);
518             }
519         }
520     }
521 
522     @Override
addAccessibilityInteractionConnection(IWindow windowToken, IAccessibilityInteractionConnection connection, int userId)523     public int addAccessibilityInteractionConnection(IWindow windowToken,
524             IAccessibilityInteractionConnection connection, int userId) throws RemoteException {
525         synchronized (mLock) {
526             // We treat calls from a profile as if made by its parent as profiles
527             // share the accessibility state of the parent. The call below
528             // performs the current profile parent resolution.
529             final int resolvedUserId = mSecurityPolicy
530                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
531             final int windowId = sNextWindowId++;
532             // If the window is from a process that runs across users such as
533             // the system UI or the system we add it to the global state that
534             // is shared across users.
535             if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
536                 AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
537                         windowId, connection, UserHandle.USER_ALL);
538                 wrapper.linkToDeath();
539                 mGlobalInteractionConnections.put(windowId, wrapper);
540                 mGlobalWindowTokens.put(windowId, windowToken.asBinder());
541                 if (DEBUG) {
542                     Slog.i(LOG_TAG, "Added global connection for pid:" + Binder.getCallingPid()
543                             + " with windowId: " + windowId + " and  token: " + windowToken.asBinder());
544                 }
545             } else {
546                 AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
547                         windowId, connection, resolvedUserId);
548                 wrapper.linkToDeath();
549                 UserState userState = getUserStateLocked(resolvedUserId);
550                 userState.mInteractionConnections.put(windowId, wrapper);
551                 userState.mWindowTokens.put(windowId, windowToken.asBinder());
552                 if (DEBUG) {
553                     Slog.i(LOG_TAG, "Added user connection for pid:" + Binder.getCallingPid()
554                             + " with windowId: " + windowId + " and userId:" + mCurrentUserId
555                             + " and  token: " + windowToken.asBinder());
556                 }
557             }
558             return windowId;
559         }
560     }
561 
562     @Override
removeAccessibilityInteractionConnection(IWindow window)563     public void removeAccessibilityInteractionConnection(IWindow window) {
564         synchronized (mLock) {
565             // We treat calls from a profile as if made by its parent as profiles
566             // share the accessibility state of the parent. The call below
567             // performs the current profile parent resolution.
568             mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(
569                     UserHandle.getCallingUserId());
570             IBinder token = window.asBinder();
571             final int removedWindowId = removeAccessibilityInteractionConnectionInternalLocked(
572                     token, mGlobalWindowTokens, mGlobalInteractionConnections);
573             if (removedWindowId >= 0) {
574                 if (DEBUG) {
575                     Slog.i(LOG_TAG, "Removed global connection for pid:" + Binder.getCallingPid()
576                             + " with windowId: " + removedWindowId + " and token: " + window.asBinder());
577                 }
578                 return;
579             }
580             final int userCount = mUserStates.size();
581             for (int i = 0; i < userCount; i++) {
582                 UserState userState = mUserStates.valueAt(i);
583                 final int removedWindowIdForUser =
584                         removeAccessibilityInteractionConnectionInternalLocked(
585                         token, userState.mWindowTokens, userState.mInteractionConnections);
586                 if (removedWindowIdForUser >= 0) {
587                     if (DEBUG) {
588                         Slog.i(LOG_TAG, "Removed user connection for pid:" + Binder.getCallingPid()
589                                 + " with windowId: " + removedWindowIdForUser + " and userId:"
590                                 + mUserStates.keyAt(i) + " and token: " + window.asBinder());
591                     }
592                     return;
593                 }
594             }
595         }
596     }
597 
removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken, SparseArray<IBinder> windowTokens, SparseArray<AccessibilityConnectionWrapper> interactionConnections)598     private int removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken,
599             SparseArray<IBinder> windowTokens,
600             SparseArray<AccessibilityConnectionWrapper> interactionConnections) {
601         final int count = windowTokens.size();
602         for (int i = 0; i < count; i++) {
603             if (windowTokens.valueAt(i) == windowToken) {
604                 final int windowId = windowTokens.keyAt(i);
605                 windowTokens.removeAt(i);
606                 AccessibilityConnectionWrapper wrapper = interactionConnections.get(windowId);
607                 wrapper.unlinkToDeath();
608                 interactionConnections.remove(windowId);
609                 return windowId;
610             }
611         }
612         return -1;
613     }
614 
615     @Override
registerUiTestAutomationService(IBinder owner, IAccessibilityServiceClient serviceClient, AccessibilityServiceInfo accessibilityServiceInfo)616     public void registerUiTestAutomationService(IBinder owner,
617             IAccessibilityServiceClient serviceClient,
618             AccessibilityServiceInfo accessibilityServiceInfo) {
619         mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT,
620                 FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE);
621 
622         accessibilityServiceInfo.setComponentName(sFakeAccessibilityServiceComponentName);
623 
624         synchronized (mLock) {
625             UserState userState = getCurrentUserStateLocked();
626 
627             if (userState.mUiAutomationService != null) {
628                 throw new IllegalStateException("UiAutomationService " + serviceClient
629                         + "already registered!");
630             }
631 
632             try {
633                 owner.linkToDeath(userState.mUiAutomationSerivceOnwerDeathRecipient, 0);
634             } catch (RemoteException re) {
635                 Slog.e(LOG_TAG, "Couldn't register for the death of a"
636                         + " UiTestAutomationService!", re);
637                 return;
638             }
639 
640             userState.mUiAutomationServiceOwner = owner;
641             userState.mUiAutomationServiceClient = serviceClient;
642 
643             // Set the temporary state.
644             userState.mIsAccessibilityEnabled = true;
645             userState.mIsTouchExplorationEnabled = false;
646             userState.mIsEnhancedWebAccessibilityEnabled = false;
647             userState.mIsDisplayMagnificationEnabled = false;
648             userState.mInstalledServices.add(accessibilityServiceInfo);
649             userState.mEnabledServices.clear();
650             userState.mEnabledServices.add(sFakeAccessibilityServiceComponentName);
651             userState.mTouchExplorationGrantedServices.add(sFakeAccessibilityServiceComponentName);
652 
653             // Use the new state instead of settings.
654             onUserStateChangedLocked(userState);
655         }
656     }
657 
658     @Override
unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient)659     public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) {
660         synchronized (mLock) {
661             UserState userState = getCurrentUserStateLocked();
662             // Automation service is not bound, so pretend it died to perform clean up.
663             if (userState.mUiAutomationService != null
664                     && serviceClient != null
665                     && userState.mUiAutomationService.mServiceInterface != null
666                     && userState.mUiAutomationService.mServiceInterface.asBinder()
667                     == serviceClient.asBinder()) {
668                 userState.mUiAutomationService.binderDied();
669             } else {
670                 throw new IllegalStateException("UiAutomationService " + serviceClient
671                         + " not registered!");
672             }
673         }
674     }
675 
676     @Override
temporaryEnableAccessibilityStateUntilKeyguardRemoved( ComponentName service, boolean touchExplorationEnabled)677     public void temporaryEnableAccessibilityStateUntilKeyguardRemoved(
678             ComponentName service, boolean touchExplorationEnabled) {
679         mSecurityPolicy.enforceCallingPermission(
680                 Manifest.permission.TEMPORARY_ENABLE_ACCESSIBILITY,
681                 TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED);
682         if (!mWindowManagerService.isKeyguardLocked()) {
683             return;
684         }
685         synchronized (mLock) {
686             // Set the temporary state.
687             UserState userState = getCurrentUserStateLocked();
688 
689             // This is a nop if UI automation is enabled.
690             if (userState.mUiAutomationService != null) {
691                 return;
692             }
693 
694             userState.mIsAccessibilityEnabled = true;
695             userState.mIsTouchExplorationEnabled = touchExplorationEnabled;
696             userState.mIsEnhancedWebAccessibilityEnabled = false;
697             userState.mIsDisplayMagnificationEnabled = false;
698             userState.mEnabledServices.clear();
699             userState.mEnabledServices.add(service);
700             userState.mBindingServices.clear();
701             userState.mTouchExplorationGrantedServices.clear();
702             userState.mTouchExplorationGrantedServices.add(service);
703 
704             // User the current state instead settings.
705             onUserStateChangedLocked(userState);
706         }
707     }
708 
709     @Override
getWindowToken(int windowId)710     public IBinder getWindowToken(int windowId) {
711         mSecurityPolicy.enforceCallingPermission(
712                 Manifest.permission.RETRIEVE_WINDOW_TOKEN,
713                 GET_WINDOW_TOKEN);
714         synchronized (mLock) {
715             // We treat calls from a profile as if made by its parent as profiles
716             // share the accessibility state of the parent. The call below
717             // performs the current profile parent resolution.
718             final int resolvedUserId = mSecurityPolicy
719                     .resolveCallingUserIdEnforcingPermissionsLocked(
720                             UserHandle.getCallingUserId());
721             if (resolvedUserId != mCurrentUserId) {
722                 return null;
723             }
724             if (mSecurityPolicy.findWindowById(windowId) == null) {
725                 return null;
726             }
727             IBinder token = mGlobalWindowTokens.get(windowId);
728             if (token != null) {
729                 return token;
730             }
731             return getCurrentUserStateLocked().mWindowTokens.get(windowId);
732         }
733     }
734 
onGesture(int gestureId)735     boolean onGesture(int gestureId) {
736         synchronized (mLock) {
737             boolean handled = notifyGestureLocked(gestureId, false);
738             if (!handled) {
739                 handled = notifyGestureLocked(gestureId, true);
740             }
741             return handled;
742         }
743     }
744 
notifyKeyEvent(KeyEvent event, int policyFlags)745     boolean notifyKeyEvent(KeyEvent event, int policyFlags) {
746         synchronized (mLock) {
747             KeyEvent localClone = KeyEvent.obtain(event);
748             boolean handled = notifyKeyEventLocked(localClone, policyFlags, false);
749             if (!handled) {
750                 handled = notifyKeyEventLocked(localClone, policyFlags, true);
751             }
752             return handled;
753         }
754     }
755 
756     /**
757      * Gets a point within the accessibility focused node where we can send down
758      * and up events to perform a click.
759      *
760      * @param outPoint The click point to populate.
761      * @return Whether accessibility a click point was found and set.
762      */
763     // TODO: (multi-display) Make sure this works for multiple displays.
getAccessibilityFocusClickPointInScreen(Point outPoint)764     boolean getAccessibilityFocusClickPointInScreen(Point outPoint) {
765         return getInteractionBridgeLocked()
766                 .getAccessibilityFocusClickPointInScreenNotLocked(outPoint);
767     }
768 
769     /**
770      * Gets the bounds of a window.
771      *
772      * @param outBounds The output to which to write the bounds.
773      */
getWindowBounds(int windowId, Rect outBounds)774     boolean getWindowBounds(int windowId, Rect outBounds) {
775         IBinder token;
776         synchronized (mLock) {
777             token = mGlobalWindowTokens.get(windowId);
778             if (token == null) {
779                 token = getCurrentUserStateLocked().mWindowTokens.get(windowId);
780             }
781         }
782         mWindowManagerService.getWindowFrame(token, outBounds);
783         if (!outBounds.isEmpty()) {
784             return true;
785         }
786         return false;
787     }
788 
accessibilityFocusOnlyInActiveWindow()789     boolean accessibilityFocusOnlyInActiveWindow() {
790         synchronized (mLock) {
791             return mWindowsForAccessibilityCallback == null;
792         }
793     }
794 
getActiveWindowId()795     int getActiveWindowId() {
796         return mSecurityPolicy.getActiveWindowId();
797     }
798 
onTouchInteractionStart()799     void onTouchInteractionStart() {
800         mSecurityPolicy.onTouchInteractionStart();
801     }
802 
onTouchInteractionEnd()803     void onTouchInteractionEnd() {
804         mSecurityPolicy.onTouchInteractionEnd();
805     }
806 
onMagnificationStateChanged()807     void onMagnificationStateChanged() {
808         notifyClearAccessibilityCacheLocked();
809     }
810 
switchUser(int userId)811     private void switchUser(int userId) {
812         synchronized (mLock) {
813             if (mCurrentUserId == userId && mInitialized) {
814                 return;
815             }
816 
817             // Disconnect from services for the old user.
818             UserState oldUserState = getCurrentUserStateLocked();
819             oldUserState.onSwitchToAnotherUser();
820 
821             // Disable the local managers for the old user.
822             if (oldUserState.mClients.getRegisteredCallbackCount() > 0) {
823                 mMainHandler.obtainMessage(MainHandler.MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER,
824                         oldUserState.mUserId, 0).sendToTarget();
825             }
826 
827             // Announce user changes only if more that one exist.
828             UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
829             final boolean announceNewUser = userManager.getUsers().size() > 1;
830 
831             // The user changed.
832             mCurrentUserId = userId;
833 
834             UserState userState = getCurrentUserStateLocked();
835             if (userState.mUiAutomationService != null) {
836                 // Switching users disables the UI automation service.
837                 userState.mUiAutomationService.binderDied();
838             }
839 
840             readConfigurationForUserStateLocked(userState);
841             // Even if reading did not yield change, we have to update
842             // the state since the context in which the current user
843             // state was used has changed since it was inactive.
844             onUserStateChangedLocked(userState);
845 
846             if (announceNewUser) {
847                 // Schedule announcement of the current user if needed.
848                 mMainHandler.sendEmptyMessageDelayed(MainHandler.MSG_ANNOUNCE_NEW_USER_IF_NEEDED,
849                         WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS);
850             }
851         }
852     }
853 
removeUser(int userId)854     private void removeUser(int userId) {
855         synchronized (mLock) {
856             mUserStates.remove(userId);
857         }
858     }
859 
getInteractionBridgeLocked()860     private InteractionBridge getInteractionBridgeLocked() {
861         if (mInteractionBridge == null) {
862             mInteractionBridge = new InteractionBridge();
863         }
864         return mInteractionBridge;
865     }
866 
notifyGestureLocked(int gestureId, boolean isDefault)867     private boolean notifyGestureLocked(int gestureId, boolean isDefault) {
868         // TODO: Now we are giving the gestures to the last enabled
869         //       service that can handle them which is the last one
870         //       in our list since we write the last enabled as the
871         //       last record in the enabled services setting. Ideally,
872         //       the user should make the call which service handles
873         //       gestures. However, only one service should handle
874         //       gestures to avoid user frustration when different
875         //       behavior is observed from different combinations of
876         //       enabled accessibility services.
877         UserState state = getCurrentUserStateLocked();
878         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
879             Service service = state.mBoundServices.get(i);
880             if (service.mRequestTouchExplorationMode && service.mIsDefault == isDefault) {
881                 service.notifyGesture(gestureId);
882                 return true;
883             }
884         }
885         return false;
886     }
887 
notifyKeyEventLocked(KeyEvent event, int policyFlags, boolean isDefault)888     private boolean notifyKeyEventLocked(KeyEvent event, int policyFlags, boolean isDefault) {
889         // TODO: Now we are giving the key events to the last enabled
890         //       service that can handle them Ideally, the user should
891         //       make the call which service handles key events. However,
892         //       only one service should handle key events to avoid user
893         //       frustration when different behavior is observed from
894         //       different combinations of enabled accessibility services.
895         UserState state = getCurrentUserStateLocked();
896         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
897             Service service = state.mBoundServices.get(i);
898             // Key events are handled only by services that declared
899             // this capability and requested to filter key events.
900             if (!service.mRequestFilterKeyEvents ||
901                     (service.mAccessibilityServiceInfo.getCapabilities() & AccessibilityServiceInfo
902                             .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) == 0) {
903                 continue;
904             }
905             if (service.mIsDefault == isDefault) {
906                 service.notifyKeyEvent(event, policyFlags);
907                 return true;
908             }
909         }
910         return false;
911     }
912 
notifyClearAccessibilityCacheLocked()913     private void notifyClearAccessibilityCacheLocked() {
914         UserState state = getCurrentUserStateLocked();
915         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
916             Service service = state.mBoundServices.get(i);
917             service.notifyClearAccessibilityNodeInfoCache();
918         }
919     }
920 
921     /**
922      * Removes an AccessibilityInteractionConnection.
923      *
924      * @param windowId The id of the window to which the connection is targeted.
925      * @param userId The id of the user owning the connection. UserHandle.USER_ALL
926      *     if global.
927      */
removeAccessibilityInteractionConnectionLocked(int windowId, int userId)928     private void removeAccessibilityInteractionConnectionLocked(int windowId, int userId) {
929         if (userId == UserHandle.USER_ALL) {
930             mGlobalWindowTokens.remove(windowId);
931             mGlobalInteractionConnections.remove(windowId);
932         } else {
933             UserState userState = getCurrentUserStateLocked();
934             userState.mWindowTokens.remove(windowId);
935             userState.mInteractionConnections.remove(windowId);
936         }
937         if (DEBUG) {
938             Slog.i(LOG_TAG, "Removing interaction connection to windowId: " + windowId);
939         }
940     }
941 
readInstalledAccessibilityServiceLocked(UserState userState)942     private boolean readInstalledAccessibilityServiceLocked(UserState userState) {
943         mTempAccessibilityServiceInfoList.clear();
944 
945         List<ResolveInfo> installedServices = mPackageManager.queryIntentServicesAsUser(
946                 new Intent(AccessibilityService.SERVICE_INTERFACE),
947                 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
948                 mCurrentUserId);
949 
950         for (int i = 0, count = installedServices.size(); i < count; i++) {
951             ResolveInfo resolveInfo = installedServices.get(i);
952             ServiceInfo serviceInfo = resolveInfo.serviceInfo;
953             if (!android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE.equals(
954                     serviceInfo.permission)) {
955                 Slog.w(LOG_TAG, "Skipping accessibilty service " + new ComponentName(
956                         serviceInfo.packageName, serviceInfo.name).flattenToShortString()
957                         + ": it does not require the permission "
958                         + android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE);
959                 continue;
960             }
961             AccessibilityServiceInfo accessibilityServiceInfo;
962             try {
963                 accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext);
964                 mTempAccessibilityServiceInfoList.add(accessibilityServiceInfo);
965             } catch (XmlPullParserException | IOException xppe) {
966                 Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", xppe);
967             }
968         }
969 
970         if (!mTempAccessibilityServiceInfoList.equals(userState.mInstalledServices)) {
971             userState.mInstalledServices.clear();
972             userState.mInstalledServices.addAll(mTempAccessibilityServiceInfoList);
973             mTempAccessibilityServiceInfoList.clear();
974             return true;
975         }
976 
977         mTempAccessibilityServiceInfoList.clear();
978         return false;
979     }
980 
readEnabledAccessibilityServicesLocked(UserState userState)981     private boolean readEnabledAccessibilityServicesLocked(UserState userState) {
982         mTempComponentNameSet.clear();
983         readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
984                 userState.mUserId, mTempComponentNameSet);
985         if (!mTempComponentNameSet.equals(userState.mEnabledServices)) {
986             userState.mEnabledServices.clear();
987             userState.mEnabledServices.addAll(mTempComponentNameSet);
988             mTempComponentNameSet.clear();
989             return true;
990         }
991         mTempComponentNameSet.clear();
992         return false;
993     }
994 
readTouchExplorationGrantedAccessibilityServicesLocked( UserState userState)995     private boolean readTouchExplorationGrantedAccessibilityServicesLocked(
996             UserState userState) {
997         mTempComponentNameSet.clear();
998         readComponentNamesFromSettingLocked(
999                 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
1000                 userState.mUserId, mTempComponentNameSet);
1001         if (!mTempComponentNameSet.equals(userState.mTouchExplorationGrantedServices)) {
1002             userState.mTouchExplorationGrantedServices.clear();
1003             userState.mTouchExplorationGrantedServices.addAll(mTempComponentNameSet);
1004             mTempComponentNameSet.clear();
1005             return true;
1006         }
1007         mTempComponentNameSet.clear();
1008         return false;
1009     }
1010 
1011     /**
1012      * Performs {@link AccessibilityService}s delayed notification. The delay is configurable
1013      * and denotes the period after the last event before notifying the service.
1014      *
1015      * @param event The event.
1016      * @param isDefault True to notify default listeners, not default services.
1017      */
notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event, boolean isDefault)1018     private void notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event,
1019             boolean isDefault) {
1020         try {
1021             UserState state = getCurrentUserStateLocked();
1022             for (int i = 0, count = state.mBoundServices.size(); i < count; i++) {
1023                 Service service = state.mBoundServices.get(i);
1024 
1025                 if (service.mIsDefault == isDefault) {
1026                     if (canDispatchEventToServiceLocked(service, event,
1027                             state.mHandledFeedbackTypes)) {
1028                         state.mHandledFeedbackTypes |= service.mFeedbackType;
1029                         service.notifyAccessibilityEvent(event);
1030                     }
1031                 }
1032             }
1033         } catch (IndexOutOfBoundsException oobe) {
1034             // An out of bounds exception can happen if services are going away
1035             // as the for loop is running. If that happens, just bail because
1036             // there are no more services to notify.
1037         }
1038     }
1039 
addServiceLocked(Service service, UserState userState)1040     private void addServiceLocked(Service service, UserState userState) {
1041         try {
1042             service.onAdded();
1043             userState.mBoundServices.add(service);
1044             userState.mComponentNameToServiceMap.put(service.mComponentName, service);
1045         } catch (RemoteException re) {
1046             /* do nothing */
1047         }
1048     }
1049 
1050     /**
1051      * Removes a service.
1052      *
1053      * @param service The service.
1054      */
removeServiceLocked(Service service, UserState userState)1055     private void removeServiceLocked(Service service, UserState userState) {
1056         userState.mBoundServices.remove(service);
1057         userState.mComponentNameToServiceMap.remove(service.mComponentName);
1058         service.onRemoved();
1059     }
1060 
1061     /**
1062      * Determines if given event can be dispatched to a service based on the package of the
1063      * event source and already notified services for that event type. Specifically, a
1064      * service is notified if it is interested in events from the package and no other service
1065      * providing the same feedback type has been notified. Exception are services the
1066      * provide generic feedback (feedback type left as a safety net for unforeseen feedback
1067      * types) which are always notified.
1068      *
1069      * @param service The potential receiver.
1070      * @param event The event.
1071      * @param handledFeedbackTypes The feedback types for which services have been notified.
1072      * @return True if the listener should be notified, false otherwise.
1073      */
canDispatchEventToServiceLocked(Service service, AccessibilityEvent event, int handledFeedbackTypes)1074     private boolean canDispatchEventToServiceLocked(Service service, AccessibilityEvent event,
1075             int handledFeedbackTypes) {
1076 
1077         if (!service.canReceiveEventsLocked()) {
1078             return false;
1079         }
1080 
1081         if (event.getWindowId() != WINDOW_ID_UNKNOWN && !event.isImportantForAccessibility()
1082                 && (service.mFetchFlags
1083                         & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
1084             return false;
1085         }
1086 
1087         int eventType = event.getEventType();
1088         if ((service.mEventTypes & eventType) != eventType) {
1089             return false;
1090         }
1091 
1092         Set<String> packageNames = service.mPackageNames;
1093         String packageName = (event.getPackageName() != null)
1094                 ? event.getPackageName().toString() : null;
1095 
1096         if (packageNames.isEmpty() || packageNames.contains(packageName)) {
1097             int feedbackType = service.mFeedbackType;
1098             if ((handledFeedbackTypes & feedbackType) != feedbackType
1099                     || feedbackType == AccessibilityServiceInfo.FEEDBACK_GENERIC) {
1100                 return true;
1101             }
1102         }
1103 
1104         return false;
1105     }
1106 
unbindAllServicesLocked(UserState userState)1107     private void unbindAllServicesLocked(UserState userState) {
1108         List<Service> services = userState.mBoundServices;
1109         for (int i = 0, count = services.size(); i < count; i++) {
1110             Service service = services.get(i);
1111             if (service.unbindLocked()) {
1112                 i--;
1113                 count--;
1114             }
1115         }
1116     }
1117 
1118     /**
1119      * Populates a set with the {@link ComponentName}s stored in a colon
1120      * separated value setting for a given user.
1121      *
1122      * @param settingName The setting to parse.
1123      * @param userId The user id.
1124      * @param outComponentNames The output component names.
1125      */
readComponentNamesFromSettingLocked(String settingName, int userId, Set<ComponentName> outComponentNames)1126     private void readComponentNamesFromSettingLocked(String settingName, int userId,
1127             Set<ComponentName> outComponentNames) {
1128         String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(),
1129                 settingName, userId);
1130         outComponentNames.clear();
1131         if (settingValue != null) {
1132             TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
1133             splitter.setString(settingValue);
1134             while (splitter.hasNext()) {
1135                 String str = splitter.next();
1136                 if (str == null || str.length() <= 0) {
1137                     continue;
1138                 }
1139                 ComponentName enabledService = ComponentName.unflattenFromString(str);
1140                 if (enabledService != null) {
1141                     outComponentNames.add(enabledService);
1142                 }
1143             }
1144         }
1145     }
1146 
1147     /**
1148      * Persists the component names in the specified setting in a
1149      * colon separated fashion.
1150      *
1151      * @param settingName The setting name.
1152      * @param componentNames The component names.
1153      */
persistComponentNamesToSettingLocked(String settingName, Set<ComponentName> componentNames, int userId)1154     private void persistComponentNamesToSettingLocked(String settingName,
1155             Set<ComponentName> componentNames, int userId) {
1156         StringBuilder builder = new StringBuilder();
1157         for (ComponentName componentName : componentNames) {
1158             if (builder.length() > 0) {
1159                 builder.append(COMPONENT_NAME_SEPARATOR);
1160             }
1161             builder.append(componentName.flattenToShortString());
1162         }
1163         Settings.Secure.putStringForUser(mContext.getContentResolver(),
1164                 settingName, builder.toString(), userId);
1165     }
1166 
manageServicesLocked(UserState userState)1167     private void manageServicesLocked(UserState userState) {
1168         Map<ComponentName, Service> componentNameToServiceMap =
1169                 userState.mComponentNameToServiceMap;
1170         boolean isEnabled = userState.mIsAccessibilityEnabled;
1171 
1172         for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) {
1173             AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i);
1174             ComponentName componentName = ComponentName.unflattenFromString(
1175                     installedService.getId());
1176             Service service = componentNameToServiceMap.get(componentName);
1177 
1178             if (isEnabled) {
1179                 // Wait for the binding if it is in process.
1180                 if (userState.mBindingServices.contains(componentName)) {
1181                     continue;
1182                 }
1183                 if (userState.mEnabledServices.contains(componentName)) {
1184                     if (service == null) {
1185                         service = new Service(userState.mUserId, componentName, installedService);
1186                     } else if (userState.mBoundServices.contains(service)) {
1187                         continue;
1188                     }
1189                     service.bindLocked();
1190                 } else {
1191                     if (service != null) {
1192                         service.unbindLocked();
1193                     }
1194                 }
1195             } else {
1196                 if (service != null) {
1197                     service.unbindLocked();
1198                 } else {
1199                     userState.mBindingServices.remove(componentName);
1200                 }
1201             }
1202         }
1203 
1204         // No enabled installed services => disable accessibility to avoid
1205         // sending accessibility events with no recipient across processes.
1206         if (isEnabled && userState.mBoundServices.isEmpty()
1207                 && userState.mBindingServices.isEmpty()) {
1208             userState.mIsAccessibilityEnabled = false;
1209             Settings.Secure.putIntForUser(mContext.getContentResolver(),
1210                     Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId);
1211         }
1212     }
1213 
scheduleUpdateClientsIfNeededLocked(UserState userState)1214     private void scheduleUpdateClientsIfNeededLocked(UserState userState) {
1215         final int clientState = userState.getClientState();
1216         if (userState.mLastSentClientState != clientState
1217                 && (mGlobalClients.getRegisteredCallbackCount() > 0
1218                         || userState.mClients.getRegisteredCallbackCount() > 0)) {
1219             userState.mLastSentClientState = clientState;
1220             mMainHandler.obtainMessage(MainHandler.MSG_SEND_STATE_TO_CLIENTS,
1221                     clientState, userState.mUserId) .sendToTarget();
1222         }
1223     }
1224 
scheduleUpdateInputFilter(UserState userState)1225     private void scheduleUpdateInputFilter(UserState userState) {
1226         mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_INPUT_FILTER, userState).sendToTarget();
1227     }
1228 
updateInputFilter(UserState userState)1229     private void updateInputFilter(UserState userState) {
1230         boolean setInputFilter = false;
1231         AccessibilityInputFilter inputFilter = null;
1232         synchronized (mLock) {
1233             int flags = 0;
1234             if (userState.mIsDisplayMagnificationEnabled) {
1235                 flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER;
1236             }
1237             // Touch exploration without accessibility makes no sense.
1238             if (userState.mIsAccessibilityEnabled && userState.mIsTouchExplorationEnabled) {
1239                 flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION;
1240             }
1241             if (userState.mIsFilterKeyEventsEnabled) {
1242                 flags |= AccessibilityInputFilter.FLAG_FEATURE_FILTER_KEY_EVENTS;
1243             }
1244             if (flags != 0) {
1245                 if (!mHasInputFilter) {
1246                     mHasInputFilter = true;
1247                     if (mInputFilter == null) {
1248                         mInputFilter = new AccessibilityInputFilter(mContext,
1249                                 AccessibilityManagerService.this);
1250                     }
1251                     inputFilter = mInputFilter;
1252                     setInputFilter = true;
1253                 }
1254                 mInputFilter.setEnabledFeatures(flags);
1255             } else {
1256                 if (mHasInputFilter) {
1257                     mHasInputFilter = false;
1258                     mInputFilter.disableFeatures();
1259                     inputFilter = null;
1260                     setInputFilter = true;
1261                 }
1262             }
1263         }
1264         if (setInputFilter) {
1265             mWindowManagerService.setInputFilter(inputFilter);
1266         }
1267     }
1268 
showEnableTouchExplorationDialog(final Service service)1269     private void showEnableTouchExplorationDialog(final Service service) {
1270         synchronized (mLock) {
1271             String label = service.mResolveInfo.loadLabel(
1272             mContext.getPackageManager()).toString();
1273 
1274             final UserState state = getCurrentUserStateLocked();
1275             if (state.mIsTouchExplorationEnabled) {
1276                 return;
1277             }
1278             if (mEnableTouchExplorationDialog != null
1279                     && mEnableTouchExplorationDialog.isShowing()) {
1280                 return;
1281             }
1282             mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext)
1283                 .setIconAttribute(android.R.attr.alertDialogIcon)
1284                 .setPositiveButton(android.R.string.ok, new OnClickListener() {
1285                      @Override
1286                      public void onClick(DialogInterface dialog, int which) {
1287                          // The user allowed the service to toggle touch exploration.
1288                          state.mTouchExplorationGrantedServices.add(service.mComponentName);
1289                          persistComponentNamesToSettingLocked(
1290                                  Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
1291                                  state.mTouchExplorationGrantedServices, state.mUserId);
1292                          // Enable touch exploration.
1293                          UserState userState = getUserStateLocked(service.mUserId);
1294                          userState.mIsTouchExplorationEnabled = true;
1295                          Settings.Secure.putIntForUser(mContext.getContentResolver(),
1296                                  Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1,
1297                                  service.mUserId);
1298                          onUserStateChangedLocked(userState);
1299                      }
1300                  })
1301                  .setNegativeButton(android.R.string.cancel, new OnClickListener() {
1302                      @Override
1303                      public void onClick(DialogInterface dialog, int which) {
1304                          dialog.dismiss();
1305                      }
1306                  })
1307                  .setTitle(R.string.enable_explore_by_touch_warning_title)
1308                  .setMessage(mContext.getString(
1309                          R.string.enable_explore_by_touch_warning_message, label))
1310                  .create();
1311              mEnableTouchExplorationDialog.getWindow().setType(
1312                      WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
1313              mEnableTouchExplorationDialog.getWindow().getAttributes().privateFlags
1314                      |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
1315              mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true);
1316              mEnableTouchExplorationDialog.show();
1317         }
1318     }
1319 
onUserStateChangedLocked(UserState userState)1320     private void onUserStateChangedLocked(UserState userState) {
1321         // TODO: Remove this hack
1322         mInitialized = true;
1323         updateLegacyCapabilitiesLocked(userState);
1324         updateServicesLocked(userState);
1325         updateWindowsForAccessibilityCallbackLocked(userState);
1326         updateAccessibilityFocusBehaviorLocked(userState);
1327         updateFilterKeyEventsLocked(userState);
1328         updateTouchExplorationLocked(userState);
1329         updateEnhancedWebAccessibilityLocked(userState);
1330         updateDisplayColorAdjustmentSettingsLocked(userState);
1331         scheduleUpdateInputFilter(userState);
1332         scheduleUpdateClientsIfNeededLocked(userState);
1333     }
1334 
updateAccessibilityFocusBehaviorLocked(UserState userState)1335     private void updateAccessibilityFocusBehaviorLocked(UserState userState) {
1336         // If there is no service that can operate with interactive windows
1337         // then we keep the old behavior where a window loses accessibility
1338         // focus if it is no longer active. This still changes the behavior
1339         // for services that do not operate with interactive windows and run
1340         // at the same time as the one(s) which does. In practice however,
1341         // there is only one service that uses accessibility focus and it
1342         // is typically the one that operates with interactive windows, So,
1343         // this is fine. Note that to allow a service to work across windows
1344         // we have to allow accessibility focus stay in any of them. Sigh...
1345         List<Service> boundServices = userState.mBoundServices;
1346         final int boundServiceCount = boundServices.size();
1347         for (int i = 0; i < boundServiceCount; i++) {
1348             Service boundService = boundServices.get(i);
1349             if (boundService.canRetrieveInteractiveWindowsLocked()) {
1350                 userState.mAccessibilityFocusOnlyInActiveWindow = false;
1351                 return;
1352             }
1353         }
1354         userState.mAccessibilityFocusOnlyInActiveWindow = true;
1355     }
1356 
updateWindowsForAccessibilityCallbackLocked(UserState userState)1357     private void updateWindowsForAccessibilityCallbackLocked(UserState userState) {
1358         if (userState.mIsAccessibilityEnabled) {
1359             // We observe windows for accessibility only if there is at least
1360             // one bound service that can retrieve window content that specified
1361             // it is interested in accessing such windows. For services that are
1362             // binding we do an update pass after each bind event, so we run this
1363             // code and register the callback if needed.
1364             boolean boundServiceCanRetrieveInteractiveWindows = false;
1365 
1366             List<Service> boundServices = userState.mBoundServices;
1367             final int boundServiceCount = boundServices.size();
1368             for (int i = 0; i < boundServiceCount; i++) {
1369                 Service boundService = boundServices.get(i);
1370                 if (boundService.canRetrieveInteractiveWindowsLocked()) {
1371                     boundServiceCanRetrieveInteractiveWindows = true;
1372                     break;
1373                 }
1374             }
1375 
1376             if (boundServiceCanRetrieveInteractiveWindows) {
1377                 if (mWindowsForAccessibilityCallback == null) {
1378                     mWindowsForAccessibilityCallback = new WindowsForAccessibilityCallback();
1379                     mWindowManagerService.setWindowsForAccessibilityCallback(
1380                             mWindowsForAccessibilityCallback);
1381                 }
1382                 return;
1383             }
1384         }
1385 
1386         if (mWindowsForAccessibilityCallback != null) {
1387             mWindowsForAccessibilityCallback = null;
1388             mWindowManagerService.setWindowsForAccessibilityCallback(null);
1389             // Drop all windows we know about.
1390             mSecurityPolicy.clearWindowsLocked();
1391         }
1392     }
1393 
updateLegacyCapabilitiesLocked(UserState userState)1394     private void updateLegacyCapabilitiesLocked(UserState userState) {
1395         // Up to JB-MR1 we had a white list with services that can enable touch
1396         // exploration. When a service is first started we show a dialog to the
1397         // use to get a permission to white list the service.
1398         final int installedServiceCount = userState.mInstalledServices.size();
1399         for (int i = 0; i < installedServiceCount; i++) {
1400             AccessibilityServiceInfo serviceInfo = userState.mInstalledServices.get(i);
1401             ResolveInfo resolveInfo = serviceInfo.getResolveInfo();
1402             if ((serviceInfo.getCapabilities()
1403                         & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) == 0
1404                     && resolveInfo.serviceInfo.applicationInfo.targetSdkVersion
1405                         <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
1406                 ComponentName componentName = new ComponentName(
1407                         resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
1408                 if (userState.mTouchExplorationGrantedServices.contains(componentName)) {
1409                     serviceInfo.setCapabilities(serviceInfo.getCapabilities()
1410                             | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION);
1411                 }
1412             }
1413         }
1414     }
1415 
updateFilterKeyEventsLocked(UserState userState)1416     private void updateFilterKeyEventsLocked(UserState userState) {
1417         final int serviceCount = userState.mBoundServices.size();
1418         for (int i = 0; i < serviceCount; i++) {
1419             Service service = userState.mBoundServices.get(i);
1420             if (service.mRequestFilterKeyEvents
1421                     && (service.mAccessibilityServiceInfo.getCapabilities()
1422                             & AccessibilityServiceInfo
1423                             .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) != 0) {
1424                 userState.mIsFilterKeyEventsEnabled = true;
1425                 return;
1426             }
1427         }
1428         userState.mIsFilterKeyEventsEnabled = false;
1429     }
1430 
updateServicesLocked(UserState userState)1431     private void updateServicesLocked(UserState userState) {
1432         if (userState.mIsAccessibilityEnabled) {
1433             manageServicesLocked(userState);
1434         } else {
1435             unbindAllServicesLocked(userState);
1436         }
1437     }
1438 
readConfigurationForUserStateLocked(UserState userState)1439     private boolean readConfigurationForUserStateLocked(UserState userState) {
1440         boolean somthingChanged = readAccessibilityEnabledSettingLocked(userState);
1441         somthingChanged |= readInstalledAccessibilityServiceLocked(userState);
1442         somthingChanged |= readEnabledAccessibilityServicesLocked(userState);
1443         somthingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState);
1444         somthingChanged |= readTouchExplorationEnabledSettingLocked(userState);
1445         somthingChanged |= readHighTextContrastEnabledSettingLocked(userState);
1446         somthingChanged |= readEnhancedWebAccessibilityEnabledChangedLocked(userState);
1447         somthingChanged |= readDisplayMagnificationEnabledSettingLocked(userState);
1448         somthingChanged |= readDisplayColorAdjustmentSettingsLocked(userState);
1449         return somthingChanged;
1450     }
1451 
readAccessibilityEnabledSettingLocked(UserState userState)1452     private boolean readAccessibilityEnabledSettingLocked(UserState userState) {
1453         final boolean accessibilityEnabled = Settings.Secure.getIntForUser(
1454                mContext.getContentResolver(),
1455                Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId) == 1;
1456         if (accessibilityEnabled != userState.mIsAccessibilityEnabled) {
1457             userState.mIsAccessibilityEnabled = accessibilityEnabled;
1458             return true;
1459         }
1460         return false;
1461     }
1462 
readTouchExplorationEnabledSettingLocked(UserState userState)1463     private boolean readTouchExplorationEnabledSettingLocked(UserState userState) {
1464         final boolean touchExplorationEnabled = Settings.Secure.getIntForUser(
1465                 mContext.getContentResolver(),
1466                 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId) == 1;
1467         if (touchExplorationEnabled != userState.mIsTouchExplorationEnabled) {
1468             userState.mIsTouchExplorationEnabled = touchExplorationEnabled;
1469             return true;
1470         }
1471         return false;
1472     }
1473 
readDisplayMagnificationEnabledSettingLocked(UserState userState)1474     private boolean readDisplayMagnificationEnabledSettingLocked(UserState userState) {
1475         final boolean displayMagnificationEnabled = Settings.Secure.getIntForUser(
1476                 mContext.getContentResolver(),
1477                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
1478                 0, userState.mUserId) == 1;
1479         if (displayMagnificationEnabled != userState.mIsDisplayMagnificationEnabled) {
1480             userState.mIsDisplayMagnificationEnabled = displayMagnificationEnabled;
1481             return true;
1482         }
1483         return false;
1484     }
1485 
readEnhancedWebAccessibilityEnabledChangedLocked(UserState userState)1486     private boolean readEnhancedWebAccessibilityEnabledChangedLocked(UserState userState) {
1487          final boolean enhancedWeAccessibilityEnabled = Settings.Secure.getIntForUser(
1488                 mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION,
1489                 0, userState.mUserId) == 1;
1490          if (enhancedWeAccessibilityEnabled != userState.mIsEnhancedWebAccessibilityEnabled) {
1491              userState.mIsEnhancedWebAccessibilityEnabled = enhancedWeAccessibilityEnabled;
1492              return true;
1493          }
1494          return false;
1495     }
1496 
readDisplayColorAdjustmentSettingsLocked(UserState userState)1497     private boolean readDisplayColorAdjustmentSettingsLocked(UserState userState) {
1498         final boolean displayAdjustmentsEnabled = DisplayAdjustmentUtils.hasAdjustments(mContext,
1499                 userState.mUserId);
1500         if (displayAdjustmentsEnabled != userState.mHasDisplayColorAdjustment) {
1501             userState.mHasDisplayColorAdjustment = displayAdjustmentsEnabled;
1502             return true;
1503         }
1504         // If display adjustment is enabled, always assume there was a change in
1505         // the adjustment settings.
1506         return displayAdjustmentsEnabled;
1507     }
1508 
readHighTextContrastEnabledSettingLocked(UserState userState)1509     private boolean readHighTextContrastEnabledSettingLocked(UserState userState) {
1510         final boolean highTextContrastEnabled = Settings.Secure.getIntForUser(
1511                 mContext.getContentResolver(),
1512                 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 0,
1513                 userState.mUserId) == 1;
1514         if (highTextContrastEnabled != userState.mIsTextHighContrastEnabled) {
1515             userState.mIsTextHighContrastEnabled = highTextContrastEnabled;
1516             return true;
1517         }
1518         return false;
1519     }
1520 
updateTouchExplorationLocked(UserState userState)1521     private void updateTouchExplorationLocked(UserState userState) {
1522         boolean enabled = false;
1523         final int serviceCount = userState.mBoundServices.size();
1524         for (int i = 0; i < serviceCount; i++) {
1525             Service service = userState.mBoundServices.get(i);
1526             if (canRequestAndRequestsTouchExplorationLocked(service)) {
1527                 enabled = true;
1528                 break;
1529             }
1530         }
1531         if (enabled != userState.mIsTouchExplorationEnabled) {
1532             userState.mIsTouchExplorationEnabled = enabled;
1533             Settings.Secure.putIntForUser(mContext.getContentResolver(),
1534                     Settings.Secure.TOUCH_EXPLORATION_ENABLED, enabled ? 1 : 0,
1535                     userState.mUserId);
1536         }
1537     }
1538 
canRequestAndRequestsTouchExplorationLocked(Service service)1539     private boolean canRequestAndRequestsTouchExplorationLocked(Service service) {
1540         // Service not ready or cannot request the feature - well nothing to do.
1541         if (!service.canReceiveEventsLocked() || !service.mRequestTouchExplorationMode) {
1542             return false;
1543         }
1544         // UI test automation service can always enable it.
1545         if (service.mIsAutomation) {
1546             return true;
1547         }
1548         if (service.mResolveInfo.serviceInfo.applicationInfo.targetSdkVersion
1549                 <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
1550             // Up to JB-MR1 we had a white list with services that can enable touch
1551             // exploration. When a service is first started we show a dialog to the
1552             // use to get a permission to white list the service.
1553             UserState userState = getUserStateLocked(service.mUserId);
1554             if (userState.mTouchExplorationGrantedServices.contains(service.mComponentName)) {
1555                 return true;
1556             } else if (mEnableTouchExplorationDialog == null
1557                     || !mEnableTouchExplorationDialog.isShowing()) {
1558                 mMainHandler.obtainMessage(
1559                         MainHandler.MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG,
1560                         service).sendToTarget();
1561             }
1562         } else {
1563             // Starting in JB-MR2 we request an accessibility service to declare
1564             // certain capabilities in its meta-data to allow it to enable the
1565             // corresponding features.
1566             if ((service.mAccessibilityServiceInfo.getCapabilities()
1567                     & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) != 0) {
1568                 return true;
1569             }
1570         }
1571         return false;
1572     }
1573 
updateEnhancedWebAccessibilityLocked(UserState userState)1574     private void updateEnhancedWebAccessibilityLocked(UserState userState) {
1575         boolean enabled = false;
1576         final int serviceCount = userState.mBoundServices.size();
1577         for (int i = 0; i < serviceCount; i++) {
1578             Service service = userState.mBoundServices.get(i);
1579             if (canRequestAndRequestsEnhancedWebAccessibilityLocked(service)) {
1580                 enabled = true;
1581                 break;
1582             }
1583         }
1584         if (enabled != userState.mIsEnhancedWebAccessibilityEnabled) {
1585             userState.mIsEnhancedWebAccessibilityEnabled = enabled;
1586             Settings.Secure.putIntForUser(mContext.getContentResolver(),
1587                     Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, enabled ? 1 : 0,
1588                     userState.mUserId);
1589         }
1590     }
1591 
canRequestAndRequestsEnhancedWebAccessibilityLocked(Service service)1592     private boolean canRequestAndRequestsEnhancedWebAccessibilityLocked(Service service) {
1593         if (!service.canReceiveEventsLocked() || !service.mRequestEnhancedWebAccessibility ) {
1594             return false;
1595         }
1596         if (service.mIsAutomation || (service.mAccessibilityServiceInfo.getCapabilities()
1597                & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY) != 0) {
1598             return true;
1599         }
1600         return false;
1601     }
1602 
updateDisplayColorAdjustmentSettingsLocked(UserState userState)1603     private void updateDisplayColorAdjustmentSettingsLocked(UserState userState) {
1604         DisplayAdjustmentUtils.applyAdjustments(mContext, userState.mUserId);
1605     }
1606 
hasRunningServicesLocked(UserState userState)1607     private boolean hasRunningServicesLocked(UserState userState) {
1608         return !userState.mBoundServices.isEmpty() || !userState.mBindingServices.isEmpty();
1609     }
1610 
getCompatibleMagnificationSpecLocked(int windowId)1611     private MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId) {
1612         IBinder windowToken = mGlobalWindowTokens.get(windowId);
1613         if (windowToken == null) {
1614             windowToken = getCurrentUserStateLocked().mWindowTokens.get(windowId);
1615         }
1616         if (windowToken != null) {
1617             return mWindowManagerService.getCompatibleMagnificationSpecForWindow(
1618                     windowToken);
1619         }
1620         return null;
1621     }
1622 
1623     @Override
dump(FileDescriptor fd, final PrintWriter pw, String[] args)1624     public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
1625         mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
1626         synchronized (mLock) {
1627             pw.println("ACCESSIBILITY MANAGER (dumpsys accessibility)");
1628             pw.println();
1629             final int userCount = mUserStates.size();
1630             for (int i = 0; i < userCount; i++) {
1631                 UserState userState = mUserStates.valueAt(i);
1632                 pw.append("User state[attributes:{id=" + userState.mUserId);
1633                 pw.append(", currentUser=" + (userState.mUserId == mCurrentUserId));
1634                 pw.append(", accessibilityEnabled=" + userState.mIsAccessibilityEnabled);
1635                 pw.append(", touchExplorationEnabled=" + userState.mIsTouchExplorationEnabled);
1636                 pw.append(", displayMagnificationEnabled="
1637                         + userState.mIsDisplayMagnificationEnabled);
1638                 if (userState.mUiAutomationService != null) {
1639                     pw.append(", ");
1640                     userState.mUiAutomationService.dump(fd, pw, args);
1641                     pw.println();
1642                 }
1643                 pw.append("}");
1644                 pw.println();
1645                 pw.append("           services:{");
1646                 final int serviceCount = userState.mBoundServices.size();
1647                 for (int j = 0; j < serviceCount; j++) {
1648                     if (j > 0) {
1649                         pw.append(", ");
1650                         pw.println();
1651                         pw.append("                     ");
1652                     }
1653                     Service service = userState.mBoundServices.get(j);
1654                     service.dump(fd, pw, args);
1655                 }
1656                 pw.println("}]");
1657                 pw.println();
1658             }
1659             if (mSecurityPolicy.mWindows != null) {
1660                 final int windowCount = mSecurityPolicy.mWindows.size();
1661                 for (int j = 0; j < windowCount; j++) {
1662                     if (j > 0) {
1663                         pw.append(',');
1664                         pw.println();
1665                     }
1666                     pw.append("Window[");
1667                     AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(j);
1668                     pw.append(window.toString());
1669                     pw.append(']');
1670                 }
1671             }
1672         }
1673     }
1674 
1675     private class AccessibilityConnectionWrapper implements DeathRecipient {
1676         private final int mWindowId;
1677         private final int mUserId;
1678         private final IAccessibilityInteractionConnection mConnection;
1679 
AccessibilityConnectionWrapper(int windowId, IAccessibilityInteractionConnection connection, int userId)1680         public AccessibilityConnectionWrapper(int windowId,
1681                 IAccessibilityInteractionConnection connection, int userId) {
1682             mWindowId = windowId;
1683             mUserId = userId;
1684             mConnection = connection;
1685         }
1686 
linkToDeath()1687         public void linkToDeath() throws RemoteException {
1688             mConnection.asBinder().linkToDeath(this, 0);
1689         }
1690 
unlinkToDeath()1691         public void unlinkToDeath() {
1692             mConnection.asBinder().unlinkToDeath(this, 0);
1693         }
1694 
1695         @Override
binderDied()1696         public void binderDied() {
1697             unlinkToDeath();
1698             synchronized (mLock) {
1699                 removeAccessibilityInteractionConnectionLocked(mWindowId, mUserId);
1700             }
1701         }
1702     }
1703 
1704     private final class MainHandler extends Handler {
1705         public static final int MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER = 1;
1706         public static final int MSG_SEND_STATE_TO_CLIENTS = 2;
1707         public static final int MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER = 3;
1708         public static final int MSG_ANNOUNCE_NEW_USER_IF_NEEDED = 5;
1709         public static final int MSG_UPDATE_INPUT_FILTER = 6;
1710         public static final int MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG = 7;
1711         public static final int MSG_SEND_KEY_EVENT_TO_INPUT_FILTER = 8;
1712         public static final int MSG_CLEAR_ACCESSIBILITY_FOCUS = 9;
1713 
MainHandler(Looper looper)1714         public MainHandler(Looper looper) {
1715             super(looper);
1716         }
1717 
1718         @Override
handleMessage(Message msg)1719         public void handleMessage(Message msg) {
1720             final int type = msg.what;
1721             switch (type) {
1722                 case MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER: {
1723                     AccessibilityEvent event = (AccessibilityEvent) msg.obj;
1724                     synchronized (mLock) {
1725                         if (mHasInputFilter && mInputFilter != null) {
1726                             mInputFilter.notifyAccessibilityEvent(event);
1727                         }
1728                     }
1729                     event.recycle();
1730                 } break;
1731 
1732                 case MSG_SEND_KEY_EVENT_TO_INPUT_FILTER: {
1733                     KeyEvent event = (KeyEvent) msg.obj;
1734                     final int policyFlags = msg.arg1;
1735                     synchronized (mLock) {
1736                         if (mHasInputFilter && mInputFilter != null) {
1737                             mInputFilter.sendInputEvent(event, policyFlags);
1738                         }
1739                     }
1740                     event.recycle();
1741                 } break;
1742 
1743                 case MSG_SEND_STATE_TO_CLIENTS: {
1744                     final int clientState = msg.arg1;
1745                     final int userId = msg.arg2;
1746                     sendStateToClients(clientState, mGlobalClients);
1747                     sendStateToClientsForUser(clientState, userId);
1748                 } break;
1749 
1750                 case MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER: {
1751                     final int userId = msg.arg1;
1752                     sendStateToClientsForUser(0, userId);
1753                 } break;
1754 
1755                 case MSG_ANNOUNCE_NEW_USER_IF_NEEDED: {
1756                     announceNewUserIfNeeded();
1757                 } break;
1758 
1759                 case MSG_UPDATE_INPUT_FILTER: {
1760                     UserState userState = (UserState) msg.obj;
1761                     updateInputFilter(userState);
1762                 } break;
1763 
1764                 case MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG: {
1765                     Service service = (Service) msg.obj;
1766                     showEnableTouchExplorationDialog(service);
1767                 } break;
1768 
1769                 case MSG_CLEAR_ACCESSIBILITY_FOCUS: {
1770                     final int windowId = msg.arg1;
1771                     InteractionBridge bridge;
1772                     synchronized (mLock) {
1773                         bridge = getInteractionBridgeLocked();
1774                     }
1775                     bridge.clearAccessibilityFocusNotLocked(windowId);
1776                 } break;
1777             }
1778         }
1779 
announceNewUserIfNeeded()1780         private void announceNewUserIfNeeded() {
1781             synchronized (mLock) {
1782                 UserState userState = getCurrentUserStateLocked();
1783                 if (userState.mIsAccessibilityEnabled) {
1784                     UserManager userManager = (UserManager) mContext.getSystemService(
1785                             Context.USER_SERVICE);
1786                     String message = mContext.getString(R.string.user_switched,
1787                             userManager.getUserInfo(mCurrentUserId).name);
1788                     AccessibilityEvent event = AccessibilityEvent.obtain(
1789                             AccessibilityEvent.TYPE_ANNOUNCEMENT);
1790                     event.getText().add(message);
1791                     sendAccessibilityEvent(event, mCurrentUserId);
1792                 }
1793             }
1794         }
1795 
sendStateToClientsForUser(int clientState, int userId)1796         private void sendStateToClientsForUser(int clientState, int userId) {
1797             final UserState userState;
1798             synchronized (mLock) {
1799                 userState = getUserStateLocked(userId);
1800             }
1801             sendStateToClients(clientState, userState.mClients);
1802         }
1803 
sendStateToClients(int clientState, RemoteCallbackList<IAccessibilityManagerClient> clients)1804         private void sendStateToClients(int clientState,
1805                 RemoteCallbackList<IAccessibilityManagerClient> clients) {
1806             try {
1807                 final int userClientCount = clients.beginBroadcast();
1808                 for (int i = 0; i < userClientCount; i++) {
1809                     IAccessibilityManagerClient client = clients.getBroadcastItem(i);
1810                     try {
1811                         client.setState(clientState);
1812                     } catch (RemoteException re) {
1813                         /* ignore */
1814                     }
1815                 }
1816             } finally {
1817                 clients.finishBroadcast();
1818             }
1819         }
1820     }
1821 
obtainPendingEventLocked(KeyEvent event, int policyFlags, int sequence)1822     private PendingEvent obtainPendingEventLocked(KeyEvent event, int policyFlags, int sequence) {
1823         PendingEvent pendingEvent = mPendingEventPool.acquire();
1824         if (pendingEvent == null) {
1825             pendingEvent = new PendingEvent();
1826         }
1827         pendingEvent.event = event;
1828         pendingEvent.policyFlags = policyFlags;
1829         pendingEvent.sequence = sequence;
1830         return pendingEvent;
1831     }
1832 
recyclePendingEventLocked(PendingEvent pendingEvent)1833     private void recyclePendingEventLocked(PendingEvent pendingEvent) {
1834         pendingEvent.clear();
1835         mPendingEventPool.release(pendingEvent);
1836     }
1837 
findWindowIdLocked(IBinder token)1838     private int findWindowIdLocked(IBinder token) {
1839         final int globalIndex = mGlobalWindowTokens.indexOfValue(token);
1840         if (globalIndex >= 0) {
1841             return mGlobalWindowTokens.keyAt(globalIndex);
1842         }
1843         UserState userState = getCurrentUserStateLocked();
1844         final int userIndex = userState.mWindowTokens.indexOfValue(token);
1845         if (userIndex >= 0) {
1846             return userState.mWindowTokens.keyAt(userIndex);
1847         }
1848         return -1;
1849     }
1850 
ensureWindowsAvailableTimed()1851     private void ensureWindowsAvailableTimed() {
1852         synchronized (mLock) {
1853             if (mSecurityPolicy.mWindows != null) {
1854                 return;
1855             }
1856             // If we have no registered callback, update the state we
1857             // we may have to register one but it didn't happen yet.
1858             if (mWindowsForAccessibilityCallback == null) {
1859                 UserState userState = getCurrentUserStateLocked();
1860                 onUserStateChangedLocked(userState);
1861             }
1862             // We have no windows but do not care about them, done.
1863             if (mWindowsForAccessibilityCallback == null) {
1864                 return;
1865             }
1866 
1867             // Wait for the windows with a timeout.
1868             final long startMillis = SystemClock.uptimeMillis();
1869             while (mSecurityPolicy.mWindows == null) {
1870                 final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
1871                 final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis;
1872                 if (remainMillis <= 0) {
1873                     return;
1874                 }
1875                 try {
1876                     mLock.wait(remainMillis);
1877                 } catch (InterruptedException ie) {
1878                     /* ignore */
1879                 }
1880             }
1881         }
1882     }
1883 
1884     /**
1885      * This class represents an accessibility service. It stores all per service
1886      * data required for the service management, provides API for starting/stopping the
1887      * service and is responsible for adding/removing the service in the data structures
1888      * for service management. The class also exposes configuration interface that is
1889      * passed to the service it represents as soon it is bound. It also serves as the
1890      * connection for the service.
1891      */
1892     class Service extends IAccessibilityServiceConnection.Stub
1893             implements ServiceConnection, DeathRecipient {;
1894 
1895         final int mUserId;
1896 
1897         int mId = 0;
1898 
1899         AccessibilityServiceInfo mAccessibilityServiceInfo;
1900 
1901         IBinder mService;
1902 
1903         IAccessibilityServiceClient mServiceInterface;
1904 
1905         int mEventTypes;
1906 
1907         int mFeedbackType;
1908 
1909         Set<String> mPackageNames = new HashSet<>();
1910 
1911         boolean mIsDefault;
1912 
1913         boolean mRequestTouchExplorationMode;
1914 
1915         boolean mRequestEnhancedWebAccessibility;
1916 
1917         boolean mRequestFilterKeyEvents;
1918 
1919         boolean mRetrieveInteractiveWindows;
1920 
1921         int mFetchFlags;
1922 
1923         long mNotificationTimeout;
1924 
1925         ComponentName mComponentName;
1926 
1927         Intent mIntent;
1928 
1929         boolean mIsAutomation;
1930 
1931         final ResolveInfo mResolveInfo;
1932 
1933         final IBinder mOverlayWindowToken = new Binder();
1934 
1935         // the events pending events to be dispatched to this service
1936         final SparseArray<AccessibilityEvent> mPendingEvents =
1937             new SparseArray<>();
1938 
1939         final KeyEventDispatcher mKeyEventDispatcher = new KeyEventDispatcher();
1940 
1941         boolean mWasConnectedAndDied;
1942 
1943         // Handler only for dispatching accessibility events since we use event
1944         // types as message types allowing us to remove messages per event type.
1945         public Handler mEventDispatchHandler = new Handler(mMainHandler.getLooper()) {
1946             @Override
1947             public void handleMessage(Message message) {
1948                 final int eventType =  message.what;
1949                 notifyAccessibilityEventInternal(eventType);
1950             }
1951         };
1952 
1953         // Handler for scheduling method invocations on the main thread.
1954         public InvocationHandler mInvocationHandler = new InvocationHandler(
1955                 mMainHandler.getLooper());
1956 
Service(int userId, ComponentName componentName, AccessibilityServiceInfo accessibilityServiceInfo)1957         public Service(int userId, ComponentName componentName,
1958                 AccessibilityServiceInfo accessibilityServiceInfo) {
1959             mUserId = userId;
1960             mResolveInfo = accessibilityServiceInfo.getResolveInfo();
1961             mId = sIdCounter++;
1962             mComponentName = componentName;
1963             mAccessibilityServiceInfo = accessibilityServiceInfo;
1964             mIsAutomation = (sFakeAccessibilityServiceComponentName.equals(componentName));
1965             if (!mIsAutomation) {
1966                 mIntent = new Intent().setComponent(mComponentName);
1967                 mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
1968                         com.android.internal.R.string.accessibility_binding_label);
1969                 mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
1970                         mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0));
1971             }
1972             setDynamicallyConfigurableProperties(accessibilityServiceInfo);
1973         }
1974 
setDynamicallyConfigurableProperties(AccessibilityServiceInfo info)1975         public void setDynamicallyConfigurableProperties(AccessibilityServiceInfo info) {
1976             mEventTypes = info.eventTypes;
1977             mFeedbackType = info.feedbackType;
1978             String[] packageNames = info.packageNames;
1979             if (packageNames != null) {
1980                 mPackageNames.addAll(Arrays.asList(packageNames));
1981             }
1982             mNotificationTimeout = info.notificationTimeout;
1983             mIsDefault = (info.flags & DEFAULT) != 0;
1984 
1985             if (mIsAutomation || info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion
1986                     >= Build.VERSION_CODES.JELLY_BEAN) {
1987                 if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) {
1988                     mFetchFlags |= AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
1989                 } else {
1990                     mFetchFlags &= ~AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
1991                 }
1992             }
1993 
1994             if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) {
1995                 mFetchFlags |= AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;
1996             } else {
1997                 mFetchFlags &= ~AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;
1998             }
1999 
2000             mRequestTouchExplorationMode = (info.flags
2001                     & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0;
2002             mRequestEnhancedWebAccessibility = (info.flags
2003                     & AccessibilityServiceInfo.FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY) != 0;
2004             mRequestFilterKeyEvents = (info.flags
2005                     & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0;
2006             mRetrieveInteractiveWindows = (info.flags
2007                     & AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0;
2008         }
2009 
2010         /**
2011          * Binds to the accessibility service.
2012          *
2013          * @return True if binding is successful.
2014          */
bindLocked()2015         public boolean bindLocked() {
2016             UserState userState = getUserStateLocked(mUserId);
2017             if (!mIsAutomation) {
2018                 if (mService == null && mContext.bindServiceAsUser(
2019                         mIntent, this, Context.BIND_AUTO_CREATE, new UserHandle(mUserId))) {
2020                     userState.mBindingServices.add(mComponentName);
2021                 }
2022             } else {
2023                 userState.mBindingServices.add(mComponentName);
2024                 mService = userState.mUiAutomationServiceClient.asBinder();
2025                 mMainHandler.post(new Runnable() {
2026                     @Override
2027                     public void run() {
2028                         // Simulate asynchronous connection since in onServiceConnected
2029                         // we may modify the state data in case of an error but bind is
2030                         // called while iterating over the data and bad things can happen.
2031                         onServiceConnected(mComponentName, mService);
2032                     }
2033                 });
2034                 userState.mUiAutomationService = this;
2035             }
2036             return false;
2037         }
2038 
2039         /**
2040          * Unbinds form the accessibility service and removes it from the data
2041          * structures for service management.
2042          *
2043          * @return True if unbinding is successful.
2044          */
unbindLocked()2045         public boolean unbindLocked() {
2046             if (mService == null) {
2047                 return false;
2048             }
2049             UserState userState = getUserStateLocked(mUserId);
2050             mKeyEventDispatcher.flush();
2051             if (!mIsAutomation) {
2052                 mContext.unbindService(this);
2053             } else {
2054                 userState.destroyUiAutomationService();
2055             }
2056             removeServiceLocked(this, userState);
2057             resetLocked();
2058             return true;
2059         }
2060 
canReceiveEventsLocked()2061         public boolean canReceiveEventsLocked() {
2062             return (mEventTypes != 0 && mFeedbackType != 0 && mService != null);
2063         }
2064 
2065         @Override
setOnKeyEventResult(boolean handled, int sequence)2066         public void setOnKeyEventResult(boolean handled, int sequence) {
2067             mKeyEventDispatcher.setOnKeyEventResult(handled, sequence);
2068         }
2069 
2070         @Override
getServiceInfo()2071         public AccessibilityServiceInfo getServiceInfo() {
2072             synchronized (mLock) {
2073                 return mAccessibilityServiceInfo;
2074             }
2075         }
2076 
canRetrieveInteractiveWindowsLocked()2077         public boolean canRetrieveInteractiveWindowsLocked() {
2078             return mSecurityPolicy.canRetrieveWindowContentLocked(this)
2079                     && mRetrieveInteractiveWindows;
2080         }
2081 
2082         @Override
setServiceInfo(AccessibilityServiceInfo info)2083         public void setServiceInfo(AccessibilityServiceInfo info) {
2084             final long identity = Binder.clearCallingIdentity();
2085             try {
2086                 synchronized (mLock) {
2087                     // If the XML manifest had data to configure the service its info
2088                     // should be already set. In such a case update only the dynamically
2089                     // configurable properties.
2090                     AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo;
2091                     if (oldInfo != null) {
2092                         oldInfo.updateDynamicallyConfigurableProperties(info);
2093                         setDynamicallyConfigurableProperties(oldInfo);
2094                     } else {
2095                         setDynamicallyConfigurableProperties(info);
2096                     }
2097                     UserState userState = getUserStateLocked(mUserId);
2098                     onUserStateChangedLocked(userState);
2099                 }
2100             } finally {
2101                 Binder.restoreCallingIdentity(identity);
2102             }
2103         }
2104 
2105         @Override
onServiceConnected(ComponentName componentName, IBinder service)2106         public void onServiceConnected(ComponentName componentName, IBinder service) {
2107             synchronized (mLock) {
2108                 mService = service;
2109                 mServiceInterface = IAccessibilityServiceClient.Stub.asInterface(service);
2110                 UserState userState = getUserStateLocked(mUserId);
2111                 addServiceLocked(this, userState);
2112                 if (userState.mBindingServices.contains(mComponentName) || mWasConnectedAndDied) {
2113                     userState.mBindingServices.remove(mComponentName);
2114                     mWasConnectedAndDied = false;
2115                     try {
2116                        mServiceInterface.init(this, mId, mOverlayWindowToken);
2117                        onUserStateChangedLocked(userState);
2118                     } catch (RemoteException re) {
2119                         Slog.w(LOG_TAG, "Error while setting connection for service: "
2120                                 + service, re);
2121                         binderDied();
2122                     }
2123                 } else {
2124                     binderDied();
2125                 }
2126             }
2127         }
2128 
2129         @Override
getWindows()2130         public List<AccessibilityWindowInfo> getWindows() {
2131             ensureWindowsAvailableTimed();
2132             synchronized (mLock) {
2133                 // We treat calls from a profile as if made by its perent as profiles
2134                 // share the accessibility state of the parent. The call below
2135                 // performs the current profile parent resolution.
2136                 final int resolvedUserId = mSecurityPolicy
2137                         .resolveCallingUserIdEnforcingPermissionsLocked(
2138                                 UserHandle.USER_CURRENT);
2139                 if (resolvedUserId != mCurrentUserId) {
2140                     return null;
2141                 }
2142                 final boolean permissionGranted =
2143                         mSecurityPolicy.canRetrieveWindowsLocked(this);
2144                 if (!permissionGranted) {
2145                     return null;
2146                 }
2147                 if (mSecurityPolicy.mWindows == null) {
2148                     return null;
2149                 }
2150                 List<AccessibilityWindowInfo> windows = new ArrayList<>();
2151                 final int windowCount = mSecurityPolicy.mWindows.size();
2152                 for (int i = 0; i < windowCount; i++) {
2153                     AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(i);
2154                     AccessibilityWindowInfo windowClone =
2155                             AccessibilityWindowInfo.obtain(window);
2156                     windowClone.setConnectionId(mId);
2157                     windows.add(windowClone);
2158                 }
2159                 return windows;
2160             }
2161         }
2162 
2163         @Override
getWindow(int windowId)2164         public AccessibilityWindowInfo getWindow(int windowId) {
2165             ensureWindowsAvailableTimed();
2166             synchronized (mLock) {
2167                 // We treat calls from a profile as if made by its parent as profiles
2168                 // share the accessibility state of the parent. The call below
2169                 // performs the current profile parent resolution.
2170                 final int resolvedUserId = mSecurityPolicy
2171                         .resolveCallingUserIdEnforcingPermissionsLocked(
2172                                 UserHandle.USER_CURRENT);
2173                 if (resolvedUserId != mCurrentUserId) {
2174                     return null;
2175                 }
2176                 final boolean permissionGranted =
2177                         mSecurityPolicy.canRetrieveWindowsLocked(this);
2178                 if (!permissionGranted) {
2179                     return null;
2180                 }
2181                 AccessibilityWindowInfo window = mSecurityPolicy.findWindowById(windowId);
2182                 if (window != null) {
2183                     AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window);
2184                     windowClone.setConnectionId(mId);
2185                     return windowClone;
2186                 }
2187                 return null;
2188             }
2189         }
2190 
2191         @Override
findAccessibilityNodeInfosByViewId(int accessibilityWindowId, long accessibilityNodeId, String viewIdResName, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)2192         public boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
2193                 long accessibilityNodeId, String viewIdResName, int interactionId,
2194                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
2195                 throws RemoteException {
2196             final int resolvedWindowId;
2197             IAccessibilityInteractionConnection connection = null;
2198             Region partialInteractiveRegion = mTempRegion;
2199             synchronized (mLock) {
2200                 // We treat calls from a profile as if made by its parent as profiles
2201                 // share the accessibility state of the parent. The call below
2202                 // performs the current profile parent resolution.
2203                 final int resolvedUserId = mSecurityPolicy
2204                         .resolveCallingUserIdEnforcingPermissionsLocked(
2205                                 UserHandle.USER_CURRENT);
2206                 if (resolvedUserId != mCurrentUserId) {
2207                     return false;
2208                 }
2209                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
2210                 final boolean permissionGranted =
2211                         mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
2212                 if (!permissionGranted) {
2213                     return false;
2214                 } else {
2215                     connection = getConnectionLocked(resolvedWindowId);
2216                     if (connection == null) {
2217                         return false;
2218                     }
2219                 }
2220                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
2221                         resolvedWindowId, partialInteractiveRegion)) {
2222                     partialInteractiveRegion = null;
2223                 }
2224             }
2225             final int interrogatingPid = Binder.getCallingPid();
2226             final long identityToken = Binder.clearCallingIdentity();
2227             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
2228             try {
2229                 connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName,
2230                         partialInteractiveRegion, interactionId, callback, mFetchFlags,
2231                         interrogatingPid, interrogatingTid, spec);
2232                 return true;
2233             } catch (RemoteException re) {
2234                 if (DEBUG) {
2235                     Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId().");
2236                 }
2237             } finally {
2238                 Binder.restoreCallingIdentity(identityToken);
2239             }
2240             return false;
2241         }
2242 
2243         @Override
findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId, String text, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)2244         public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId,
2245                 long accessibilityNodeId, String text, int interactionId,
2246                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
2247                 throws RemoteException {
2248             final int resolvedWindowId;
2249             IAccessibilityInteractionConnection connection = null;
2250             Region partialInteractiveRegion = mTempRegion;
2251             synchronized (mLock) {
2252                 // We treat calls from a profile as if made by its parent as profiles
2253                 // share the accessibility state of the parent. The call below
2254                 // performs the current profile parent resolution.
2255                 final int resolvedUserId = mSecurityPolicy
2256                         .resolveCallingUserIdEnforcingPermissionsLocked(
2257                                 UserHandle.USER_CURRENT);
2258                 if (resolvedUserId != mCurrentUserId) {
2259                     return false;
2260                 }
2261                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
2262                 final boolean permissionGranted =
2263                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
2264                 if (!permissionGranted) {
2265                     return false;
2266                 } else {
2267                     connection = getConnectionLocked(resolvedWindowId);
2268                     if (connection == null) {
2269                         return false;
2270                     }
2271                 }
2272                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
2273                         resolvedWindowId, partialInteractiveRegion)) {
2274                     partialInteractiveRegion = null;
2275                 }
2276             }
2277             final int interrogatingPid = Binder.getCallingPid();
2278             final long identityToken = Binder.clearCallingIdentity();
2279             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
2280             try {
2281                 connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
2282                         partialInteractiveRegion, interactionId, callback, mFetchFlags,
2283                         interrogatingPid, interrogatingTid, spec);
2284                 return true;
2285             } catch (RemoteException re) {
2286                 if (DEBUG) {
2287                     Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()");
2288                 }
2289             } finally {
2290                 Binder.restoreCallingIdentity(identityToken);
2291             }
2292             return false;
2293         }
2294 
2295         @Override
findAccessibilityNodeInfoByAccessibilityId( int accessibilityWindowId, long accessibilityNodeId, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, long interrogatingTid)2296         public boolean findAccessibilityNodeInfoByAccessibilityId(
2297                 int accessibilityWindowId, long accessibilityNodeId, int interactionId,
2298                 IAccessibilityInteractionConnectionCallback callback, int flags,
2299                 long interrogatingTid) throws RemoteException {
2300             final int resolvedWindowId;
2301             IAccessibilityInteractionConnection connection = null;
2302             Region partialInteractiveRegion = mTempRegion;
2303             synchronized (mLock) {
2304                 // We treat calls from a profile as if made by its parent as profiles
2305                 // share the accessibility state of the parent. The call below
2306                 // performs the current profile parent resolution.
2307                 final int resolvedUserId = mSecurityPolicy
2308                         .resolveCallingUserIdEnforcingPermissionsLocked(
2309                                 UserHandle.USER_CURRENT);
2310                 if (resolvedUserId != mCurrentUserId) {
2311                     return false;
2312                 }
2313                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
2314                 final boolean permissionGranted =
2315                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
2316                 if (!permissionGranted) {
2317                     return false;
2318                 } else {
2319                     connection = getConnectionLocked(resolvedWindowId);
2320                     if (connection == null) {
2321                         return false;
2322                     }
2323                 }
2324                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
2325                         resolvedWindowId, partialInteractiveRegion)) {
2326                     partialInteractiveRegion = null;
2327                 }
2328             }
2329             final int interrogatingPid = Binder.getCallingPid();
2330             final long identityToken = Binder.clearCallingIdentity();
2331             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
2332             try {
2333                 connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId,
2334                         partialInteractiveRegion, interactionId, callback, mFetchFlags | flags,
2335                         interrogatingPid, interrogatingTid, spec);
2336                 return true;
2337             } catch (RemoteException re) {
2338                 if (DEBUG) {
2339                     Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
2340                 }
2341             } finally {
2342                 Binder.restoreCallingIdentity(identityToken);
2343             }
2344             return false;
2345         }
2346 
2347         @Override
findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)2348         public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId,
2349                 int focusType, int interactionId,
2350                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
2351                 throws RemoteException {
2352             final int resolvedWindowId;
2353             IAccessibilityInteractionConnection connection = null;
2354             Region partialInteractiveRegion = mTempRegion;
2355             synchronized (mLock) {
2356                 // We treat calls from a profile as if made by its parent as profiles
2357                 // share the accessibility state of the parent. The call below
2358                 // performs the current profile parent resolution.
2359                 final int resolvedUserId = mSecurityPolicy
2360                         .resolveCallingUserIdEnforcingPermissionsLocked(
2361                                 UserHandle.USER_CURRENT);
2362                 if (resolvedUserId != mCurrentUserId) {
2363                     return false;
2364                 }
2365                 resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked(
2366                         accessibilityWindowId, focusType);
2367                 final boolean permissionGranted =
2368                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
2369                 if (!permissionGranted) {
2370                     return false;
2371                 } else {
2372                     connection = getConnectionLocked(resolvedWindowId);
2373                     if (connection == null) {
2374                         return false;
2375                     }
2376                 }
2377                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
2378                         resolvedWindowId, partialInteractiveRegion)) {
2379                     partialInteractiveRegion = null;
2380                 }
2381             }
2382             final int interrogatingPid = Binder.getCallingPid();
2383             final long identityToken = Binder.clearCallingIdentity();
2384             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
2385             try {
2386                 connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion,
2387                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
2388                         spec);
2389                 return true;
2390             } catch (RemoteException re) {
2391                 if (DEBUG) {
2392                     Slog.e(LOG_TAG, "Error calling findFocus()");
2393                 }
2394             } finally {
2395                 Binder.restoreCallingIdentity(identityToken);
2396             }
2397             return false;
2398         }
2399 
2400         @Override
focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)2401         public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId,
2402                 int direction, int interactionId,
2403                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
2404                 throws RemoteException {
2405             final int resolvedWindowId;
2406             IAccessibilityInteractionConnection connection = null;
2407             Region partialInteractiveRegion = mTempRegion;
2408             synchronized (mLock) {
2409                 // We treat calls from a profile as if made by its parent as profiles
2410                 // share the accessibility state of the parent. The call below
2411                 // performs the current profile parent resolution.
2412                 final int resolvedUserId = mSecurityPolicy
2413                         .resolveCallingUserIdEnforcingPermissionsLocked(
2414                                 UserHandle.USER_CURRENT);
2415                 if (resolvedUserId != mCurrentUserId) {
2416                     return false;
2417                 }
2418                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
2419                 final boolean permissionGranted =
2420                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
2421                 if (!permissionGranted) {
2422                     return false;
2423                 } else {
2424                     connection = getConnectionLocked(resolvedWindowId);
2425                     if (connection == null) {
2426                         return false;
2427                     }
2428                 }
2429                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
2430                         resolvedWindowId, partialInteractiveRegion)) {
2431                     partialInteractiveRegion = null;
2432                 }
2433             }
2434             final int interrogatingPid = Binder.getCallingPid();
2435             final long identityToken = Binder.clearCallingIdentity();
2436             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
2437             try {
2438                 connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion,
2439                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
2440                         spec);
2441                 return true;
2442             } catch (RemoteException re) {
2443                 if (DEBUG) {
2444                     Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()");
2445                 }
2446             } finally {
2447                 Binder.restoreCallingIdentity(identityToken);
2448             }
2449             return false;
2450         }
2451 
2452         @Override
performAccessibilityAction(int accessibilityWindowId, long accessibilityNodeId, int action, Bundle arguments, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)2453         public boolean performAccessibilityAction(int accessibilityWindowId,
2454                 long accessibilityNodeId, int action, Bundle arguments, int interactionId,
2455                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
2456                 throws RemoteException {
2457             final int resolvedWindowId;
2458             IAccessibilityInteractionConnection connection = null;
2459             synchronized (mLock) {
2460                 // We treat calls from a profile as if made by its parent as profiles
2461                 // share the accessibility state of the parent. The call below
2462                 // performs the current profile parent resolution.
2463                 final int resolvedUserId = mSecurityPolicy
2464                         .resolveCallingUserIdEnforcingPermissionsLocked(
2465                                 UserHandle.USER_CURRENT);
2466                 if (resolvedUserId != mCurrentUserId) {
2467                     return false;
2468                 }
2469                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
2470                 final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked(
2471                         this, resolvedWindowId);
2472                 if (!permissionGranted) {
2473                     return false;
2474                 } else {
2475                     connection = getConnectionLocked(resolvedWindowId);
2476                     if (connection == null) {
2477                         return false;
2478                     }
2479                 }
2480             }
2481             final int interrogatingPid = Binder.getCallingPid();
2482             final long identityToken = Binder.clearCallingIdentity();
2483             try {
2484                 connection.performAccessibilityAction(accessibilityNodeId, action, arguments,
2485                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid);
2486             } catch (RemoteException re) {
2487                 if (DEBUG) {
2488                     Slog.e(LOG_TAG, "Error calling performAccessibilityAction()");
2489                 }
2490             } finally {
2491                 Binder.restoreCallingIdentity(identityToken);
2492             }
2493             return true;
2494         }
2495 
2496         @Override
performGlobalAction(int action)2497         public boolean performGlobalAction(int action) {
2498             synchronized (mLock) {
2499                 // We treat calls from a profile as if made by its parent as profiles
2500                 // share the accessibility state of the parent. The call below
2501                 // performs the current profile parent resolution.
2502                 final int resolvedUserId = mSecurityPolicy
2503                         .resolveCallingUserIdEnforcingPermissionsLocked(
2504                                 UserHandle.USER_CURRENT);
2505                 if (resolvedUserId != mCurrentUserId) {
2506                     return false;
2507                 }
2508             }
2509             final long identity = Binder.clearCallingIdentity();
2510             try {
2511                 switch (action) {
2512                     case AccessibilityService.GLOBAL_ACTION_BACK: {
2513                         sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK);
2514                     } return true;
2515                     case AccessibilityService.GLOBAL_ACTION_HOME: {
2516                         sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME);
2517                     } return true;
2518                     case AccessibilityService.GLOBAL_ACTION_RECENTS: {
2519                         openRecents();
2520                     } return true;
2521                     case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: {
2522                         expandNotifications();
2523                     } return true;
2524                     case AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS: {
2525                         expandQuickSettings();
2526                     } return true;
2527                     case AccessibilityService.GLOBAL_ACTION_POWER_DIALOG: {
2528                         showGlobalActions();
2529                     } return true;
2530                 }
2531                 return false;
2532             } finally {
2533                 Binder.restoreCallingIdentity(identity);
2534             }
2535         }
2536 
2537         @Override
dump(FileDescriptor fd, final PrintWriter pw, String[] args)2538         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
2539             mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
2540             synchronized (mLock) {
2541                 pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo()
2542                         .loadLabel(mContext.getPackageManager()));
2543                 pw.append(", feedbackType"
2544                         + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType));
2545                 pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities());
2546                 pw.append(", eventTypes="
2547                         + AccessibilityEvent.eventTypeToString(mEventTypes));
2548                 pw.append(", notificationTimeout=" + mNotificationTimeout);
2549                 pw.append("]");
2550             }
2551         }
2552 
2553         @Override
onServiceDisconnected(ComponentName componentName)2554         public void onServiceDisconnected(ComponentName componentName) {
2555             /* do nothing - #binderDied takes care */
2556         }
2557 
onAdded()2558         public void onAdded() throws RemoteException {
2559             linkToOwnDeathLocked();
2560             final long identity = Binder.clearCallingIdentity();
2561             try {
2562                 mWindowManagerService.addWindowToken(mOverlayWindowToken,
2563                         WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY);
2564             } finally {
2565                 Binder.restoreCallingIdentity(identity);
2566             }
2567         }
2568 
onRemoved()2569         public void onRemoved() {
2570             final long identity = Binder.clearCallingIdentity();
2571             try {
2572                 mWindowManagerService.removeWindowToken(mOverlayWindowToken, true);
2573             } finally {
2574                 Binder.restoreCallingIdentity(identity);
2575             }
2576             unlinkToOwnDeathLocked();
2577         }
2578 
linkToOwnDeathLocked()2579         public void linkToOwnDeathLocked() throws RemoteException {
2580             mService.linkToDeath(this, 0);
2581         }
2582 
unlinkToOwnDeathLocked()2583         public void unlinkToOwnDeathLocked() {
2584             mService.unlinkToDeath(this, 0);
2585         }
2586 
resetLocked()2587         public void resetLocked() {
2588             try {
2589                 // Clear the proxy in the other process so this
2590                 // IAccessibilityServiceConnection can be garbage collected.
2591                 mServiceInterface.init(null, mId, null);
2592             } catch (RemoteException re) {
2593                 /* ignore */
2594             }
2595             mService = null;
2596             mServiceInterface = null;
2597         }
2598 
isConnectedLocked()2599         public boolean isConnectedLocked() {
2600             return (mService != null);
2601         }
2602 
binderDied()2603         public void binderDied() {
2604             synchronized (mLock) {
2605                 // It is possible that this service's package was force stopped during
2606                 // whose handling the death recipient is unlinked and still get a call
2607                 // on binderDied since the call was made before we unlink but was
2608                 // waiting on the lock we held during the force stop handling.
2609                 if (!isConnectedLocked()) {
2610                     return;
2611                 }
2612                 mWasConnectedAndDied = true;
2613                 mKeyEventDispatcher.flush();
2614                 UserState userState = getUserStateLocked(mUserId);
2615                 // The death recipient is unregistered in removeServiceLocked
2616                 removeServiceLocked(this, userState);
2617                 resetLocked();
2618                 if (mIsAutomation) {
2619                     // We no longer have an automation service, so restore
2620                     // the state based on values in the settings database.
2621                     userState.mInstalledServices.remove(mAccessibilityServiceInfo);
2622                     userState.mEnabledServices.remove(mComponentName);
2623                     userState.destroyUiAutomationService();
2624                     if (readConfigurationForUserStateLocked(userState)) {
2625                         onUserStateChangedLocked(userState);
2626                     }
2627                 }
2628             }
2629         }
2630 
2631         /**
2632          * Performs a notification for an {@link AccessibilityEvent}.
2633          *
2634          * @param event The event.
2635          */
notifyAccessibilityEvent(AccessibilityEvent event)2636         public void notifyAccessibilityEvent(AccessibilityEvent event) {
2637             synchronized (mLock) {
2638                 final int eventType = event.getEventType();
2639                 // Make a copy since during dispatch it is possible the event to
2640                 // be modified to remove its source if the receiving service does
2641                 // not have permission to access the window content.
2642                 AccessibilityEvent newEvent = AccessibilityEvent.obtain(event);
2643                 AccessibilityEvent oldEvent = mPendingEvents.get(eventType);
2644                 mPendingEvents.put(eventType, newEvent);
2645 
2646                 final int what = eventType;
2647                 if (oldEvent != null) {
2648                     mEventDispatchHandler.removeMessages(what);
2649                     oldEvent.recycle();
2650                 }
2651 
2652                 Message message = mEventDispatchHandler.obtainMessage(what);
2653                 mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout);
2654             }
2655         }
2656 
2657         /**
2658          * Notifies an accessibility service client for a scheduled event given the event type.
2659          *
2660          * @param eventType The type of the event to dispatch.
2661          */
notifyAccessibilityEventInternal(int eventType)2662         private void notifyAccessibilityEventInternal(int eventType) {
2663             IAccessibilityServiceClient listener;
2664             AccessibilityEvent event;
2665 
2666             synchronized (mLock) {
2667                 listener = mServiceInterface;
2668 
2669                 // If the service died/was disabled while the message for dispatching
2670                 // the accessibility event was propagating the listener may be null.
2671                 if (listener == null) {
2672                     return;
2673                 }
2674 
2675                 event = mPendingEvents.get(eventType);
2676 
2677                 // Check for null here because there is a concurrent scenario in which this
2678                 // happens: 1) A binder thread calls notifyAccessibilityServiceDelayedLocked
2679                 // which posts a message for dispatching an event. 2) The message is pulled
2680                 // from the queue by the handler on the service thread and the latter is
2681                 // just about to acquire the lock and call this method. 3) Now another binder
2682                 // thread acquires the lock calling notifyAccessibilityServiceDelayedLocked
2683                 // so the service thread waits for the lock; 4) The binder thread replaces
2684                 // the event with a more recent one (assume the same event type) and posts a
2685                 // dispatch request releasing the lock. 5) Now the main thread is unblocked and
2686                 // dispatches the event which is removed from the pending ones. 6) And ... now
2687                 // the service thread handles the last message posted by the last binder call
2688                 // but the event is already dispatched and hence looking it up in the pending
2689                 // ones yields null. This check is much simpler that keeping count for each
2690                 // event type of each service to catch such a scenario since only one message
2691                 // is processed at a time.
2692                 if (event == null) {
2693                     return;
2694                 }
2695 
2696                 mPendingEvents.remove(eventType);
2697                 if (mSecurityPolicy.canRetrieveWindowContentLocked(this)) {
2698                     event.setConnectionId(mId);
2699                 } else {
2700                     event.setSource(null);
2701                 }
2702                 event.setSealed(true);
2703             }
2704 
2705             try {
2706                 listener.onAccessibilityEvent(event);
2707                 if (DEBUG) {
2708                     Slog.i(LOG_TAG, "Event " + event + " sent to " + listener);
2709                 }
2710             } catch (RemoteException re) {
2711                 Slog.e(LOG_TAG, "Error during sending " + event + " to " + listener, re);
2712             } finally {
2713                 event.recycle();
2714             }
2715         }
2716 
notifyGesture(int gestureId)2717         public void notifyGesture(int gestureId) {
2718             mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE,
2719                     gestureId, 0).sendToTarget();
2720         }
2721 
notifyKeyEvent(KeyEvent event, int policyFlags)2722         public void notifyKeyEvent(KeyEvent event, int policyFlags) {
2723             mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_KEY_EVENT,
2724                     policyFlags, 0, event).sendToTarget();
2725         }
2726 
notifyClearAccessibilityNodeInfoCache()2727         public void notifyClearAccessibilityNodeInfoCache() {
2728             mInvocationHandler.sendEmptyMessage(
2729                     InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE);
2730         }
2731 
notifyGestureInternal(int gestureId)2732         private void notifyGestureInternal(int gestureId) {
2733             final IAccessibilityServiceClient listener;
2734             synchronized (mLock) {
2735                 listener = mServiceInterface;
2736             }
2737             if (listener != null) {
2738                 try {
2739                     listener.onGesture(gestureId);
2740                 } catch (RemoteException re) {
2741                     Slog.e(LOG_TAG, "Error during sending gesture " + gestureId
2742                             + " to " + mService, re);
2743                 }
2744             }
2745         }
2746 
notifyKeyEventInternal(KeyEvent event, int policyFlags)2747         private void notifyKeyEventInternal(KeyEvent event, int policyFlags) {
2748             mKeyEventDispatcher.notifyKeyEvent(event, policyFlags);
2749         }
2750 
notifyClearAccessibilityCacheInternal()2751         private void notifyClearAccessibilityCacheInternal() {
2752             final IAccessibilityServiceClient listener;
2753             synchronized (mLock) {
2754                 listener = mServiceInterface;
2755             }
2756             if (listener != null) {
2757                 try {
2758                     listener.clearAccessibilityCache();
2759                 } catch (RemoteException re) {
2760                     Slog.e(LOG_TAG, "Error during requesting accessibility info cache"
2761                             + " to be cleared.", re);
2762                 }
2763             }
2764         }
2765 
sendDownAndUpKeyEvents(int keyCode)2766         private void sendDownAndUpKeyEvents(int keyCode) {
2767             final long token = Binder.clearCallingIdentity();
2768 
2769             // Inject down.
2770             final long downTime = SystemClock.uptimeMillis();
2771             KeyEvent down = KeyEvent.obtain(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode, 0, 0,
2772                     KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
2773                     InputDevice.SOURCE_KEYBOARD, null);
2774             InputManager.getInstance().injectInputEvent(down,
2775                     InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
2776             down.recycle();
2777 
2778             // Inject up.
2779             final long upTime = SystemClock.uptimeMillis();
2780             KeyEvent up = KeyEvent.obtain(downTime, upTime, KeyEvent.ACTION_UP, keyCode, 0, 0,
2781                     KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
2782                     InputDevice.SOURCE_KEYBOARD, null);
2783             InputManager.getInstance().injectInputEvent(up,
2784                     InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
2785             up.recycle();
2786 
2787             Binder.restoreCallingIdentity(token);
2788         }
2789 
expandNotifications()2790         private void expandNotifications() {
2791             final long token = Binder.clearCallingIdentity();
2792 
2793             StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService(
2794                     android.app.Service.STATUS_BAR_SERVICE);
2795             statusBarManager.expandNotificationsPanel();
2796 
2797             Binder.restoreCallingIdentity(token);
2798         }
2799 
expandQuickSettings()2800         private void expandQuickSettings() {
2801             final long token = Binder.clearCallingIdentity();
2802 
2803             StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService(
2804                     android.app.Service.STATUS_BAR_SERVICE);
2805             statusBarManager.expandSettingsPanel();
2806 
2807             Binder.restoreCallingIdentity(token);
2808         }
2809 
openRecents()2810         private void openRecents() {
2811             final long token = Binder.clearCallingIdentity();
2812 
2813             IStatusBarService statusBarService = IStatusBarService.Stub.asInterface(
2814                     ServiceManager.getService("statusbar"));
2815             try {
2816                 statusBarService.toggleRecentApps();
2817             } catch (RemoteException e) {
2818                 Slog.e(LOG_TAG, "Error toggling recent apps.");
2819             }
2820 
2821             Binder.restoreCallingIdentity(token);
2822         }
2823 
showGlobalActions()2824         private void showGlobalActions() {
2825             mWindowManagerService.showGlobalActions();
2826         }
2827 
getConnectionLocked(int windowId)2828         private IAccessibilityInteractionConnection getConnectionLocked(int windowId) {
2829             if (DEBUG) {
2830                 Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId);
2831             }
2832             AccessibilityConnectionWrapper wrapper = mGlobalInteractionConnections.get(windowId);
2833             if (wrapper == null) {
2834                 wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId);
2835             }
2836             if (wrapper != null && wrapper.mConnection != null) {
2837                 return wrapper.mConnection;
2838             }
2839             if (DEBUG) {
2840                 Slog.e(LOG_TAG, "No interaction connection to window: " + windowId);
2841             }
2842             return null;
2843         }
2844 
resolveAccessibilityWindowIdLocked(int accessibilityWindowId)2845         private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) {
2846             if (accessibilityWindowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) {
2847                 return mSecurityPolicy.getActiveWindowId();
2848             }
2849             return accessibilityWindowId;
2850         }
2851 
resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType)2852         private int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) {
2853             if (windowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) {
2854                 return mSecurityPolicy.mActiveWindowId;
2855             }
2856             if (windowId == AccessibilityNodeInfo.ANY_WINDOW_ID) {
2857                 if (focusType == AccessibilityNodeInfo.FOCUS_INPUT) {
2858                     return mSecurityPolicy.mFocusedWindowId;
2859                 } else if (focusType == AccessibilityNodeInfo.FOCUS_ACCESSIBILITY) {
2860                     return mSecurityPolicy.mAccessibilityFocusedWindowId;
2861                 }
2862             }
2863             return windowId;
2864         }
2865 
2866         private final class InvocationHandler extends Handler {
2867             public static final int MSG_ON_GESTURE = 1;
2868             public static final int MSG_ON_KEY_EVENT = 2;
2869             public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 3;
2870             public static final int MSG_ON_KEY_EVENT_TIMEOUT = 4;
2871 
InvocationHandler(Looper looper)2872             public InvocationHandler(Looper looper) {
2873                 super(looper, null, true);
2874             }
2875 
2876             @Override
handleMessage(Message message)2877             public void handleMessage(Message message) {
2878                 final int type = message.what;
2879                 switch (type) {
2880                     case MSG_ON_GESTURE: {
2881                         final int gestureId = message.arg1;
2882                         notifyGestureInternal(gestureId);
2883                     } break;
2884 
2885                     case MSG_ON_KEY_EVENT: {
2886                         KeyEvent event = (KeyEvent) message.obj;
2887                         final int policyFlags = message.arg1;
2888                         notifyKeyEventInternal(event, policyFlags);
2889                     } break;
2890 
2891                     case MSG_CLEAR_ACCESSIBILITY_CACHE: {
2892                         notifyClearAccessibilityCacheInternal();
2893                     } break;
2894 
2895                     case MSG_ON_KEY_EVENT_TIMEOUT: {
2896                         PendingEvent eventState = (PendingEvent) message.obj;
2897                         setOnKeyEventResult(false, eventState.sequence);
2898                     } break;
2899 
2900                     default: {
2901                         throw new IllegalArgumentException("Unknown message: " + type);
2902                     }
2903                 }
2904             }
2905         }
2906 
2907         private final class KeyEventDispatcher {
2908 
2909             private static final long ON_KEY_EVENT_TIMEOUT_MILLIS = 500;
2910 
2911             private PendingEvent mPendingEvents;
2912 
2913             private final InputEventConsistencyVerifier mSentEventsVerifier =
2914                     InputEventConsistencyVerifier.isInstrumentationEnabled()
2915                             ? new InputEventConsistencyVerifier(
2916                                     this, 0, KeyEventDispatcher.class.getSimpleName()) : null;
2917 
notifyKeyEvent(KeyEvent event, int policyFlags)2918             public void notifyKeyEvent(KeyEvent event, int policyFlags) {
2919                 final PendingEvent pendingEvent;
2920 
2921                 synchronized (mLock) {
2922                     pendingEvent = addPendingEventLocked(event, policyFlags);
2923                 }
2924 
2925                 Message message = mInvocationHandler.obtainMessage(
2926                         InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT, pendingEvent);
2927                 mInvocationHandler.sendMessageDelayed(message, ON_KEY_EVENT_TIMEOUT_MILLIS);
2928 
2929                 try {
2930                     // Accessibility services are exclusively not in the system
2931                     // process, therefore no need to clone the motion event to
2932                     // prevent tampering. It will be cloned in the IPC call.
2933                     mServiceInterface.onKeyEvent(pendingEvent.event, pendingEvent.sequence);
2934                 } catch (RemoteException re) {
2935                     setOnKeyEventResult(false, pendingEvent.sequence);
2936                 }
2937             }
2938 
setOnKeyEventResult(boolean handled, int sequence)2939             public void setOnKeyEventResult(boolean handled, int sequence) {
2940                 synchronized (mLock) {
2941                     PendingEvent pendingEvent = removePendingEventLocked(sequence);
2942                     if (pendingEvent != null) {
2943                         mInvocationHandler.removeMessages(
2944                                 InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT,
2945                                 pendingEvent);
2946                         pendingEvent.handled = handled;
2947                         finishPendingEventLocked(pendingEvent);
2948                     }
2949                 }
2950             }
2951 
flush()2952             public void flush() {
2953                 synchronized (mLock) {
2954                     cancelAllPendingEventsLocked();
2955                     if (mSentEventsVerifier != null) {
2956                         mSentEventsVerifier.reset();
2957                     }
2958                 }
2959             }
2960 
addPendingEventLocked(KeyEvent event, int policyFlags)2961             private PendingEvent addPendingEventLocked(KeyEvent event, int policyFlags) {
2962                 final int sequence = event.getSequenceNumber();
2963                 PendingEvent pendingEvent = obtainPendingEventLocked(event, policyFlags, sequence);
2964                 pendingEvent.next = mPendingEvents;
2965                 mPendingEvents = pendingEvent;
2966                 return pendingEvent;
2967             }
2968 
removePendingEventLocked(int sequence)2969             private PendingEvent removePendingEventLocked(int sequence) {
2970                 PendingEvent previous = null;
2971                 PendingEvent current = mPendingEvents;
2972 
2973                 while (current != null) {
2974                     if (current.sequence == sequence) {
2975                         if (previous != null) {
2976                             previous.next = current.next;
2977                         } else {
2978                             mPendingEvents = current.next;
2979                         }
2980                         current.next = null;
2981                         return current;
2982                     }
2983                     previous = current;
2984                     current = current.next;
2985                 }
2986                 return null;
2987             }
2988 
finishPendingEventLocked(PendingEvent pendingEvent)2989             private void finishPendingEventLocked(PendingEvent pendingEvent) {
2990                 if (!pendingEvent.handled) {
2991                     sendKeyEventToInputFilter(pendingEvent.event, pendingEvent.policyFlags);
2992                 }
2993                 // Nullify the event since we do not want it to be
2994                 // recycled yet. It will be sent to the input filter.
2995                 pendingEvent.event = null;
2996                 recyclePendingEventLocked(pendingEvent);
2997             }
2998 
sendKeyEventToInputFilter(KeyEvent event, int policyFlags)2999             private void sendKeyEventToInputFilter(KeyEvent event, int policyFlags) {
3000                 if (DEBUG) {
3001                     Slog.i(LOG_TAG, "Injecting event: " + event);
3002                 }
3003                 if (mSentEventsVerifier != null) {
3004                     mSentEventsVerifier.onKeyEvent(event, 0);
3005                 }
3006                 policyFlags |= WindowManagerPolicy.FLAG_PASS_TO_USER;
3007                 mMainHandler.obtainMessage(MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER,
3008                         policyFlags, 0, event).sendToTarget();
3009             }
3010 
cancelAllPendingEventsLocked()3011             private void cancelAllPendingEventsLocked() {
3012                 while (mPendingEvents != null) {
3013                     PendingEvent pendingEvent = removePendingEventLocked(mPendingEvents.sequence);
3014                     pendingEvent.handled = false;
3015                     mInvocationHandler.removeMessages(InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT,
3016                             pendingEvent);
3017                     finishPendingEventLocked(pendingEvent);
3018                 }
3019             }
3020         }
3021     }
3022 
3023     private static final class PendingEvent {
3024         PendingEvent next;
3025 
3026         KeyEvent event;
3027         int policyFlags;
3028         int sequence;
3029         boolean handled;
3030 
clear()3031         public void clear() {
3032             if (event != null) {
3033                 event.recycle();
3034                 event = null;
3035             }
3036             next = null;
3037             policyFlags = 0;
3038             sequence = 0;
3039             handled = false;
3040         }
3041     }
3042 
3043     final class WindowsForAccessibilityCallback implements
3044             WindowManagerInternal.WindowsForAccessibilityCallback {
3045 
3046         @Override
onWindowsForAccessibilityChanged(List<WindowInfo> windows)3047         public void onWindowsForAccessibilityChanged(List<WindowInfo> windows) {
3048             synchronized (mLock) {
3049                 // Populate the windows to report.
3050                 List<AccessibilityWindowInfo> reportedWindows = new ArrayList<>();
3051                 final int receivedWindowCount = windows.size();
3052                 for (int i = 0; i < receivedWindowCount; i++) {
3053                     WindowInfo receivedWindow = windows.get(i);
3054                     AccessibilityWindowInfo reportedWindow = populateReportedWindow(
3055                             receivedWindow);
3056                     if (reportedWindow != null) {
3057                         reportedWindows.add(reportedWindow);
3058                     }
3059                 }
3060 
3061                 if (DEBUG) {
3062                     Slog.i(LOG_TAG, "Windows changed: " + reportedWindows);
3063                 }
3064 
3065                 // Let the policy update the focused and active windows.
3066                 mSecurityPolicy.updateWindowsLocked(reportedWindows);
3067 
3068                 // Someone may be waiting for the windows - advertise it.
3069                 mLock.notifyAll();
3070             }
3071         }
3072 
populateReportedWindow(WindowInfo window)3073         private AccessibilityWindowInfo populateReportedWindow(WindowInfo window) {
3074             final int windowId = findWindowIdLocked(window.token);
3075             if (windowId < 0) {
3076                 return null;
3077             }
3078 
3079             AccessibilityWindowInfo reportedWindow = AccessibilityWindowInfo.obtain();
3080 
3081             reportedWindow.setId(windowId);
3082             reportedWindow.setType(getTypeForWindowManagerWindowType(window.type));
3083             reportedWindow.setLayer(window.layer);
3084             reportedWindow.setFocused(window.focused);
3085             reportedWindow.setBoundsInScreen(window.boundsInScreen);
3086 
3087             final int parentId = findWindowIdLocked(window.parentToken);
3088             if (parentId >= 0) {
3089                 reportedWindow.setParentId(parentId);
3090             }
3091 
3092             if (window.childTokens != null) {
3093                 final int childCount = window.childTokens.size();
3094                 for (int i = 0; i < childCount; i++) {
3095                     IBinder childToken = window.childTokens.get(i);
3096                     final int childId = findWindowIdLocked(childToken);
3097                     if (childId >= 0) {
3098                         reportedWindow.addChild(childId);
3099                     }
3100                 }
3101             }
3102 
3103             return reportedWindow;
3104         }
3105 
getTypeForWindowManagerWindowType(int windowType)3106         private int getTypeForWindowManagerWindowType(int windowType) {
3107             switch (windowType) {
3108                 case WindowManager.LayoutParams.TYPE_APPLICATION:
3109                 case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA:
3110                 case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL:
3111                 case WindowManager.LayoutParams.TYPE_APPLICATION_STARTING:
3112                 case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL:
3113                 case WindowManager.LayoutParams.TYPE_BASE_APPLICATION:
3114                 case WindowManager.LayoutParams.TYPE_PHONE:
3115                 case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE:
3116                 case WindowManager.LayoutParams.TYPE_TOAST:
3117                 case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG: {
3118                     return AccessibilityWindowInfo.TYPE_APPLICATION;
3119                 }
3120 
3121                 case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
3122                 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: {
3123                     return AccessibilityWindowInfo.TYPE_INPUT_METHOD;
3124                 }
3125 
3126                 case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG:
3127                 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
3128                 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL:
3129                 case WindowManager.LayoutParams.TYPE_SEARCH_BAR:
3130                 case WindowManager.LayoutParams.TYPE_STATUS_BAR:
3131                 case WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL:
3132                 case WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL:
3133                 case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY:
3134                 case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
3135                 case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
3136                 case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
3137                 case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY: {
3138                     return AccessibilityWindowInfo.TYPE_SYSTEM;
3139                 }
3140 
3141                 case WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY: {
3142                     return AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY;
3143                 }
3144 
3145                 default: {
3146                     return -1;
3147                 }
3148             }
3149         }
3150     }
3151 
3152     private final class InteractionBridge {
3153         private final Display mDefaultDisplay;
3154         private final int mConnectionId;
3155         private final AccessibilityInteractionClient mClient;
3156 
InteractionBridge()3157         public InteractionBridge() {
3158             AccessibilityServiceInfo info = new AccessibilityServiceInfo();
3159             info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
3160             info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
3161             info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
3162             Service service = new Service(UserHandle.USER_NULL,
3163                     sFakeAccessibilityServiceComponentName, info);
3164 
3165             mConnectionId = service.mId;
3166 
3167             mClient = AccessibilityInteractionClient.getInstance();
3168             mClient.addConnection(mConnectionId, service);
3169 
3170             //TODO: (multi-display) We need to support multiple displays.
3171             DisplayManager displayManager = (DisplayManager)
3172                     mContext.getSystemService(Context.DISPLAY_SERVICE);
3173             mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
3174         }
3175 
clearAccessibilityFocusNotLocked(int windowId)3176         public void clearAccessibilityFocusNotLocked(int windowId) {
3177             AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked(windowId);
3178             if (focus != null) {
3179                 focus.performAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
3180             }
3181         }
3182 
getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint)3183         public boolean getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint) {
3184             AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked();
3185             if (focus == null) {
3186                 return false;
3187             }
3188 
3189             synchronized (mLock) {
3190                 Rect boundsInScreen = mTempRect;
3191                 focus.getBoundsInScreen(boundsInScreen);
3192 
3193                 // Clip to the window bounds.
3194                 Rect windowBounds = mTempRect1;
3195                 getWindowBounds(focus.getWindowId(), windowBounds);
3196                 boundsInScreen.intersect(windowBounds);
3197                 if (boundsInScreen.isEmpty()) {
3198                     return false;
3199                 }
3200 
3201                 // Apply magnification if needed.
3202                 MagnificationSpec spec = getCompatibleMagnificationSpecLocked(focus.getWindowId());
3203                 if (spec != null && !spec.isNop()) {
3204                     boundsInScreen.offset((int) -spec.offsetX, (int) -spec.offsetY);
3205                     boundsInScreen.scale(1 / spec.scale);
3206                 }
3207 
3208                 // Clip to the screen bounds.
3209                 Point screenSize = mTempPoint;
3210                 mDefaultDisplay.getRealSize(screenSize);
3211                 boundsInScreen.intersect(0, 0, screenSize.x, screenSize.y);
3212                 if (boundsInScreen.isEmpty()) {
3213                     return false;
3214                 }
3215 
3216                 outPoint.set(boundsInScreen.centerX(), boundsInScreen.centerY());
3217             }
3218 
3219             return true;
3220         }
3221 
getAccessibilityFocusNotLocked()3222         private AccessibilityNodeInfo getAccessibilityFocusNotLocked() {
3223             final int focusedWindowId;
3224             synchronized (mLock) {
3225                 focusedWindowId = mSecurityPolicy.mAccessibilityFocusedWindowId;
3226                 if (focusedWindowId == SecurityPolicy.INVALID_WINDOW_ID) {
3227                     return null;
3228                 }
3229             }
3230             return getAccessibilityFocusNotLocked(focusedWindowId);
3231         }
3232 
getAccessibilityFocusNotLocked(int windowId)3233         private AccessibilityNodeInfo getAccessibilityFocusNotLocked(int windowId) {
3234             return mClient.findFocus(mConnectionId,
3235                     windowId, AccessibilityNodeInfo.ROOT_NODE_ID,
3236                     AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
3237         }
3238     }
3239 
3240     final class SecurityPolicy {
3241         public static final int INVALID_WINDOW_ID = -1;
3242 
3243         private static final int RETRIEVAL_ALLOWING_EVENT_TYPES =
3244             AccessibilityEvent.TYPE_VIEW_CLICKED
3245             | AccessibilityEvent.TYPE_VIEW_FOCUSED
3246             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
3247             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
3248             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
3249             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
3250             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
3251             | AccessibilityEvent.TYPE_VIEW_SELECTED
3252             | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
3253             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
3254             | AccessibilityEvent.TYPE_VIEW_SCROLLED
3255             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
3256             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED
3257             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
3258 
3259         public List<AccessibilityWindowInfo> mWindows;
3260 
3261         public int mActiveWindowId = INVALID_WINDOW_ID;
3262         public int mFocusedWindowId = INVALID_WINDOW_ID;
3263         public int mAccessibilityFocusedWindowId = INVALID_WINDOW_ID;
3264         public long mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
3265 
3266         private boolean mTouchInteractionInProgress;
3267 
canDispatchAccessibilityEventLocked(AccessibilityEvent event)3268         private boolean canDispatchAccessibilityEventLocked(AccessibilityEvent event) {
3269             final int eventType = event.getEventType();
3270             switch (eventType) {
3271                 // All events that are for changes in a global window
3272                 // state should *always* be dispatched.
3273                 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
3274                 case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
3275                 case AccessibilityEvent.TYPE_ANNOUNCEMENT:
3276                 // All events generated by the user touching the
3277                 // screen should *always* be dispatched.
3278                 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START:
3279                 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END:
3280                 case AccessibilityEvent.TYPE_GESTURE_DETECTION_START:
3281                 case AccessibilityEvent.TYPE_GESTURE_DETECTION_END:
3282                 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START:
3283                 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END:
3284                 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER:
3285                 case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT:
3286                 // Also windows changing should always be anounced.
3287                 case AccessibilityEvent.TYPE_WINDOWS_CHANGED: {
3288                     return true;
3289                 }
3290                 // All events for changes in window content should be
3291                 // dispatched *only* if this window is one of the windows
3292                 // the accessibility layer reports which are windows
3293                 // that a sighted user can touch.
3294                 default: {
3295                     return isRetrievalAllowingWindow(event.getWindowId());
3296                 }
3297             }
3298         }
3299 
clearWindowsLocked()3300         public void clearWindowsLocked() {
3301             List<AccessibilityWindowInfo> windows = Collections.emptyList();
3302             final int activeWindowId = mActiveWindowId;
3303             updateWindowsLocked(windows);
3304             mActiveWindowId = activeWindowId;
3305             mWindows = null;
3306         }
3307 
updateWindowsLocked(List<AccessibilityWindowInfo> windows)3308         public void updateWindowsLocked(List<AccessibilityWindowInfo> windows) {
3309             if (mWindows == null) {
3310                 mWindows = new ArrayList<>();
3311             }
3312 
3313             final int oldWindowCount = mWindows.size();
3314             for (int i = oldWindowCount - 1; i >= 0; i--) {
3315                 mWindows.remove(i).recycle();
3316             }
3317 
3318             mFocusedWindowId = INVALID_WINDOW_ID;
3319             if (!mTouchInteractionInProgress) {
3320                 mActiveWindowId = INVALID_WINDOW_ID;
3321             }
3322 
3323             // If the active window goes away while the user is touch exploring we
3324             // reset the active window id and wait for the next hover event from
3325             // under the user's finger to determine which one is the new one. It
3326             // is possible that the finger is not moving and the input system
3327             // filters out such events.
3328             boolean activeWindowGone = true;
3329 
3330             final int windowCount = windows.size();
3331             if (windowCount > 0) {
3332                 for (int i = 0; i < windowCount; i++) {
3333                     AccessibilityWindowInfo window = windows.get(i);
3334                     final int windowId = window.getId();
3335                     if (window.isFocused()) {
3336                         mFocusedWindowId = windowId;
3337                         if (!mTouchInteractionInProgress) {
3338                             mActiveWindowId = windowId;
3339                             window.setActive(true);
3340                         } else if (windowId == mActiveWindowId) {
3341                             activeWindowGone = false;
3342                         }
3343                     }
3344                     mWindows.add(window);
3345                 }
3346 
3347                 if (mTouchInteractionInProgress && activeWindowGone) {
3348                     mActiveWindowId = mFocusedWindowId;
3349                 }
3350 
3351                 // Focused window may change the active one, so set the
3352                 // active window once we decided which it is.
3353                 for (int i = 0; i < windowCount; i++) {
3354                     AccessibilityWindowInfo window = mWindows.get(i);
3355                     if (window.getId() == mActiveWindowId) {
3356                         window.setActive(true);
3357                     }
3358                     if (window.getId() == mAccessibilityFocusedWindowId) {
3359                         window.setAccessibilityFocused(true);
3360                     }
3361                 }
3362             }
3363 
3364             notifyWindowsChanged();
3365         }
3366 
computePartialInteractiveRegionForWindowLocked(int windowId, Region outRegion)3367         public boolean computePartialInteractiveRegionForWindowLocked(int windowId,
3368                 Region outRegion) {
3369             if (mWindows == null) {
3370                 return false;
3371             }
3372 
3373             // Windows are ordered in z order so start from the bottom and find
3374             // the window of interest. After that all windows that cover it should
3375             // be subtracted from the resulting region. Note that for accessibility
3376             // we are returning only interactive windows.
3377             Region windowInteractiveRegion = null;
3378             boolean windowInteractiveRegionChanged = false;
3379 
3380             final int windowCount = mWindows.size();
3381             for (int i = windowCount - 1; i >= 0; i--) {
3382                 AccessibilityWindowInfo currentWindow = mWindows.get(i);
3383                 if (windowInteractiveRegion == null) {
3384                     if (currentWindow.getId() == windowId) {
3385                         Rect currentWindowBounds = mTempRect;
3386                         currentWindow.getBoundsInScreen(currentWindowBounds);
3387                         outRegion.set(currentWindowBounds);
3388                         windowInteractiveRegion = outRegion;
3389                         continue;
3390                     }
3391                 } else if (currentWindow.getType()
3392                         != AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY) {
3393                     Rect currentWindowBounds = mTempRect;
3394                     currentWindow.getBoundsInScreen(currentWindowBounds);
3395                     if (windowInteractiveRegion.op(currentWindowBounds, Region.Op.DIFFERENCE)) {
3396                         windowInteractiveRegionChanged = true;
3397                     }
3398                 }
3399             }
3400 
3401             return windowInteractiveRegionChanged;
3402         }
3403 
updateEventSourceLocked(AccessibilityEvent event)3404         public void updateEventSourceLocked(AccessibilityEvent event) {
3405             if ((event.getEventType() & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) {
3406                 event.setSource(null);
3407             }
3408         }
3409 
updateActiveAndAccessibilityFocusedWindowLocked(int windowId, long nodeId, int eventType)3410         public void updateActiveAndAccessibilityFocusedWindowLocked(int windowId, long nodeId,
3411                 int eventType) {
3412             // The active window is either the window that has input focus or
3413             // the window that the user is currently touching. If the user is
3414             // touching a window that does not have input focus as soon as the
3415             // the user stops touching that window the focused window becomes
3416             // the active one. Here we detect the touched window and make it
3417             // active. In updateWindowsLocked() we update the focused window
3418             // and if the user is not touching the screen, we make the focused
3419             // window the active one.
3420             switch (eventType) {
3421                 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: {
3422                     // If no service has the capability to introspect screen,
3423                     // we do not register callback in the window manager for
3424                     // window changes, so we have to ask the window manager
3425                     // what the focused window is to update the active one.
3426                     // The active window also determined events from which
3427                     // windows are delivered.
3428                     synchronized (mLock) {
3429                         if (mWindowsForAccessibilityCallback == null) {
3430                             mFocusedWindowId = getFocusedWindowId();
3431                             if (windowId == mFocusedWindowId) {
3432                                 mActiveWindowId = windowId;
3433                             }
3434                         }
3435                     }
3436                 } break;
3437 
3438                 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: {
3439                     // Do not allow delayed hover events to confuse us
3440                     // which the active window is.
3441                     synchronized (mLock) {
3442                         if (mTouchInteractionInProgress && mActiveWindowId != windowId) {
3443                             setActiveWindowLocked(windowId);
3444                         }
3445                     }
3446                 } break;
3447 
3448                 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
3449                     synchronized (mLock) {
3450                         if (mAccessibilityFocusedWindowId != windowId) {
3451                             mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS,
3452                                     mAccessibilityFocusedWindowId, 0).sendToTarget();
3453                             mSecurityPolicy.setAccessibilityFocusedWindowLocked(windowId);
3454                             mAccessibilityFocusNodeId = nodeId;
3455                         }
3456                     }
3457                 } break;
3458 
3459                 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
3460                     synchronized (mLock) {
3461                         if (mAccessibilityFocusNodeId == nodeId) {
3462                             mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
3463                         }
3464                         if (mAccessibilityFocusNodeId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID
3465                                 && mAccessibilityFocusedWindowId == windowId) {
3466                             mAccessibilityFocusedWindowId = INVALID_WINDOW_ID;
3467                         }
3468                     }
3469                 } break;
3470             }
3471         }
3472 
onTouchInteractionStart()3473         public void onTouchInteractionStart() {
3474             synchronized (mLock) {
3475                 mTouchInteractionInProgress = true;
3476             }
3477         }
3478 
onTouchInteractionEnd()3479         public void onTouchInteractionEnd() {
3480             synchronized (mLock) {
3481                 mTouchInteractionInProgress = false;
3482                 // We want to set the active window to be current immediately
3483                 // after the user has stopped touching the screen since if the
3484                 // user types with the IME he should get a feedback for the
3485                 // letter typed in the text view which is in the input focused
3486                 // window. Note that we always deliver hover accessibility events
3487                 // (they are a result of user touching the screen) so change of
3488                 // the active window before all hover accessibility events from
3489                 // the touched window are delivered is fine.
3490                 final int oldActiveWindow = mSecurityPolicy.mActiveWindowId;
3491                 setActiveWindowLocked(mFocusedWindowId);
3492 
3493                 // If there is no service that can operate with active windows
3494                 // we keep accessibility focus behavior to constrain it only in
3495                 // the active window. Look at updateAccessibilityFocusBehaviorLocked
3496                 // for details.
3497                 if (oldActiveWindow != mSecurityPolicy.mActiveWindowId
3498                         && mAccessibilityFocusedWindowId == oldActiveWindow
3499                         && getCurrentUserStateLocked().mAccessibilityFocusOnlyInActiveWindow) {
3500                     mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS,
3501                             oldActiveWindow, 0).sendToTarget();
3502                 }
3503             }
3504         }
3505 
getActiveWindowId()3506         public int getActiveWindowId() {
3507             if (mActiveWindowId == INVALID_WINDOW_ID && !mTouchInteractionInProgress) {
3508                 mActiveWindowId = getFocusedWindowId();
3509             }
3510             return mActiveWindowId;
3511         }
3512 
setActiveWindowLocked(int windowId)3513         private void setActiveWindowLocked(int windowId) {
3514             if (mActiveWindowId != windowId) {
3515                 mActiveWindowId = windowId;
3516                 if (mWindows != null) {
3517                     final int windowCount = mWindows.size();
3518                     for (int i = 0; i < windowCount; i++) {
3519                         AccessibilityWindowInfo window = mWindows.get(i);
3520                         window.setActive(window.getId() == windowId);
3521                     }
3522                 }
3523                 notifyWindowsChanged();
3524             }
3525         }
3526 
setAccessibilityFocusedWindowLocked(int windowId)3527         private void setAccessibilityFocusedWindowLocked(int windowId) {
3528             if (mAccessibilityFocusedWindowId != windowId) {
3529                 mAccessibilityFocusedWindowId = windowId;
3530                 if (mWindows != null) {
3531                     final int windowCount = mWindows.size();
3532                     for (int i = 0; i < windowCount; i++) {
3533                         AccessibilityWindowInfo window = mWindows.get(i);
3534                         window.setAccessibilityFocused(window.getId() == windowId);
3535                     }
3536                 }
3537 
3538                 notifyWindowsChanged();
3539             }
3540         }
3541 
notifyWindowsChanged()3542         private void notifyWindowsChanged() {
3543             if (mWindowsForAccessibilityCallback == null) {
3544                 return;
3545             }
3546             final long identity = Binder.clearCallingIdentity();
3547             try {
3548                 // Let the client know the windows changed.
3549                 AccessibilityEvent event = AccessibilityEvent.obtain(
3550                         AccessibilityEvent.TYPE_WINDOWS_CHANGED);
3551                 event.setEventTime(SystemClock.uptimeMillis());
3552                 sendAccessibilityEvent(event, mCurrentUserId);
3553             } finally {
3554                 Binder.restoreCallingIdentity(identity);
3555             }
3556         }
3557 
canGetAccessibilityNodeInfoLocked(Service service, int windowId)3558         public boolean canGetAccessibilityNodeInfoLocked(Service service, int windowId) {
3559             return canRetrieveWindowContentLocked(service) && isRetrievalAllowingWindow(windowId);
3560         }
3561 
canRetrieveWindowsLocked(Service service)3562         public boolean canRetrieveWindowsLocked(Service service) {
3563             return canRetrieveWindowContentLocked(service) && service.mRetrieveInteractiveWindows;
3564         }
3565 
canRetrieveWindowContentLocked(Service service)3566         public boolean canRetrieveWindowContentLocked(Service service) {
3567             return (service.mAccessibilityServiceInfo.getCapabilities()
3568                     & AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0;
3569         }
3570 
resolveProfileParentLocked(int userId)3571         private int resolveProfileParentLocked(int userId) {
3572             if (userId != mCurrentUserId) {
3573                 final long identity = Binder.clearCallingIdentity();
3574                 try {
3575                     UserInfo parent = mUserManager.getProfileParent(userId);
3576                     if (parent != null) {
3577                         return parent.getUserHandle().getIdentifier();
3578                     }
3579                 } finally {
3580                     Binder.restoreCallingIdentity(identity);
3581                 }
3582             }
3583             return userId;
3584         }
3585 
resolveCallingUserIdEnforcingPermissionsLocked(int userId)3586         public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) {
3587             final int callingUid = Binder.getCallingUid();
3588             if (callingUid == 0
3589                     || callingUid == Process.SYSTEM_UID
3590                     || callingUid == Process.SHELL_UID) {
3591                 if (userId == UserHandle.USER_CURRENT
3592                         || userId == UserHandle.USER_CURRENT_OR_SELF) {
3593                     return mCurrentUserId;
3594                 }
3595                 return resolveProfileParentLocked(userId);
3596             }
3597             final int callingUserId = UserHandle.getUserId(callingUid);
3598             if (callingUserId == userId) {
3599                 return resolveProfileParentLocked(userId);
3600             }
3601             final int callingUserParentId = resolveProfileParentLocked(callingUserId);
3602             if (callingUserParentId == mCurrentUserId &&
3603                     (userId == UserHandle.USER_CURRENT
3604                             || userId == UserHandle.USER_CURRENT_OR_SELF)) {
3605                 return mCurrentUserId;
3606             }
3607             if (!hasPermission(Manifest.permission.INTERACT_ACROSS_USERS)
3608                     && !hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) {
3609                 throw new SecurityException("Call from user " + callingUserId + " as user "
3610                         + userId + " without permission INTERACT_ACROSS_USERS or "
3611                         + "INTERACT_ACROSS_USERS_FULL not allowed.");
3612             }
3613             if (userId == UserHandle.USER_CURRENT
3614                     || userId == UserHandle.USER_CURRENT_OR_SELF) {
3615                 return mCurrentUserId;
3616             }
3617             throw new IllegalArgumentException("Calling user can be changed to only "
3618                     + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF.");
3619         }
3620 
isCallerInteractingAcrossUsers(int userId)3621         public boolean isCallerInteractingAcrossUsers(int userId) {
3622             final int callingUid = Binder.getCallingUid();
3623             return (Binder.getCallingPid() == android.os.Process.myPid()
3624                     || callingUid == Process.SHELL_UID
3625                     || userId == UserHandle.USER_CURRENT
3626                     || userId == UserHandle.USER_CURRENT_OR_SELF);
3627         }
3628 
isRetrievalAllowingWindow(int windowId)3629         private boolean isRetrievalAllowingWindow(int windowId) {
3630             // The system gets to interact with any window it wants.
3631             if (Binder.getCallingUid() == Process.SYSTEM_UID) {
3632                 return true;
3633             }
3634             if (windowId == mActiveWindowId) {
3635                 return true;
3636             }
3637             return findWindowById(windowId) != null;
3638         }
3639 
findWindowById(int windowId)3640         private AccessibilityWindowInfo findWindowById(int windowId) {
3641             if (mWindows != null) {
3642                 final int windowCount = mWindows.size();
3643                 for (int i = 0; i < windowCount; i++) {
3644                     AccessibilityWindowInfo window = mWindows.get(i);
3645                     if (window.getId() == windowId) {
3646                         return window;
3647                     }
3648                 }
3649             }
3650             return null;
3651         }
3652 
enforceCallingPermission(String permission, String function)3653         private void enforceCallingPermission(String permission, String function) {
3654             if (OWN_PROCESS_ID == Binder.getCallingPid()) {
3655                 return;
3656             }
3657             if (!hasPermission(permission)) {
3658                 throw new SecurityException("You do not have " + permission
3659                         + " required to call " + function + " from pid="
3660                         + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
3661             }
3662         }
3663 
hasPermission(String permission)3664         private boolean hasPermission(String permission) {
3665             return mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED;
3666         }
3667 
getFocusedWindowId()3668         private int getFocusedWindowId() {
3669             IBinder token = mWindowManagerService.getFocusedWindowToken();
3670             synchronized (mLock) {
3671                 return findWindowIdLocked(token);
3672             }
3673         }
3674     }
3675 
3676     private class UserState {
3677         public final int mUserId;
3678 
3679         // Non-transient state.
3680 
3681         public final RemoteCallbackList<IAccessibilityManagerClient> mClients =
3682             new RemoteCallbackList<>();
3683 
3684         public final SparseArray<AccessibilityConnectionWrapper> mInteractionConnections =
3685                 new SparseArray<>();
3686 
3687         public final SparseArray<IBinder> mWindowTokens = new SparseArray<>();
3688 
3689         // Transient state.
3690 
3691         public final CopyOnWriteArrayList<Service> mBoundServices =
3692                 new CopyOnWriteArrayList<>();
3693 
3694         public final Map<ComponentName, Service> mComponentNameToServiceMap =
3695                 new HashMap<>();
3696 
3697         public final List<AccessibilityServiceInfo> mInstalledServices =
3698                 new ArrayList<>();
3699 
3700         public final Set<ComponentName> mBindingServices = new HashSet<>();
3701 
3702         public final Set<ComponentName> mEnabledServices = new HashSet<>();
3703 
3704         public final Set<ComponentName> mTouchExplorationGrantedServices =
3705                 new HashSet<>();
3706 
3707         public int mHandledFeedbackTypes = 0;
3708 
3709         public int mLastSentClientState = -1;
3710 
3711         public boolean mIsAccessibilityEnabled;
3712         public boolean mIsTouchExplorationEnabled;
3713         public boolean mIsTextHighContrastEnabled;
3714         public boolean mIsEnhancedWebAccessibilityEnabled;
3715         public boolean mIsDisplayMagnificationEnabled;
3716         public boolean mIsFilterKeyEventsEnabled;
3717         public boolean mHasDisplayColorAdjustment;
3718         public boolean mAccessibilityFocusOnlyInActiveWindow;
3719 
3720         private Service mUiAutomationService;
3721         private IAccessibilityServiceClient mUiAutomationServiceClient;
3722 
3723         private IBinder mUiAutomationServiceOwner;
3724         private final DeathRecipient mUiAutomationSerivceOnwerDeathRecipient =
3725                 new DeathRecipient() {
3726             @Override
3727             public void binderDied() {
3728                 mUiAutomationServiceOwner.unlinkToDeath(
3729                         mUiAutomationSerivceOnwerDeathRecipient, 0);
3730                 mUiAutomationServiceOwner = null;
3731                 if (mUiAutomationService != null) {
3732                     mUiAutomationService.binderDied();
3733                 }
3734             }
3735         };
3736 
UserState(int userId)3737         public UserState(int userId) {
3738             mUserId = userId;
3739         }
3740 
getClientState()3741         public int getClientState() {
3742             int clientState = 0;
3743             if (mIsAccessibilityEnabled) {
3744                 clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
3745             }
3746             // Touch exploration relies on enabled accessibility.
3747             if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) {
3748                 clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
3749             }
3750             if (mIsTextHighContrastEnabled) {
3751                 clientState |= AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED;
3752             }
3753             return clientState;
3754         }
3755 
onSwitchToAnotherUser()3756         public void onSwitchToAnotherUser() {
3757             // Clear UI test automation state.
3758             if (mUiAutomationService != null) {
3759                 mUiAutomationService.binderDied();
3760             }
3761 
3762             // Unbind all services.
3763             unbindAllServicesLocked(this);
3764 
3765             // Clear service management state.
3766             mBoundServices.clear();
3767             mBindingServices.clear();
3768 
3769             // Clear event management state.
3770             mHandledFeedbackTypes = 0;
3771             mLastSentClientState = -1;
3772 
3773             // Clear state persisted in settings.
3774             mEnabledServices.clear();
3775             mTouchExplorationGrantedServices.clear();
3776             mIsAccessibilityEnabled = false;
3777             mIsTouchExplorationEnabled = false;
3778             mIsEnhancedWebAccessibilityEnabled = false;
3779             mIsDisplayMagnificationEnabled = false;
3780         }
3781 
destroyUiAutomationService()3782         public void destroyUiAutomationService() {
3783             mUiAutomationService = null;
3784             mUiAutomationServiceClient = null;
3785             if (mUiAutomationServiceOwner != null) {
3786                 mUiAutomationServiceOwner.unlinkToDeath(
3787                         mUiAutomationSerivceOnwerDeathRecipient, 0);
3788                 mUiAutomationServiceOwner = null;
3789             }
3790         }
3791     }
3792 
3793     private final class AccessibilityContentObserver extends ContentObserver {
3794 
3795         private final Uri mAccessibilityEnabledUri = Settings.Secure.getUriFor(
3796                 Settings.Secure.ACCESSIBILITY_ENABLED);
3797 
3798         private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor(
3799                 Settings.Secure.TOUCH_EXPLORATION_ENABLED);
3800 
3801         private final Uri mDisplayMagnificationEnabledUri = Settings.Secure.getUriFor(
3802                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
3803 
3804         private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor(
3805                 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
3806 
3807         private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure
3808                 .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
3809 
3810         private final Uri mEnhancedWebAccessibilityUri = Settings.Secure
3811                 .getUriFor(Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION);
3812 
3813         private final Uri mDisplayInversionEnabledUri = Settings.Secure.getUriFor(
3814                 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
3815 
3816         private final Uri mDisplayDaltonizerEnabledUri = Settings.Secure.getUriFor(
3817                 Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED);
3818 
3819         private final Uri mDisplayDaltonizerUri = Settings.Secure.getUriFor(
3820                 Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER);
3821 
3822         private final Uri mHighTextContrastUri = Settings.Secure.getUriFor(
3823                 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED);
3824 
AccessibilityContentObserver(Handler handler)3825         public AccessibilityContentObserver(Handler handler) {
3826             super(handler);
3827         }
3828 
register(ContentResolver contentResolver)3829         public void register(ContentResolver contentResolver) {
3830             contentResolver.registerContentObserver(mAccessibilityEnabledUri,
3831                     false, this, UserHandle.USER_ALL);
3832             contentResolver.registerContentObserver(mTouchExplorationEnabledUri,
3833                     false, this, UserHandle.USER_ALL);
3834             contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri,
3835                     false, this, UserHandle.USER_ALL);
3836             contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri,
3837                     false, this, UserHandle.USER_ALL);
3838             contentResolver.registerContentObserver(
3839                     mTouchExplorationGrantedAccessibilityServicesUri,
3840                     false, this, UserHandle.USER_ALL);
3841             contentResolver.registerContentObserver(mEnhancedWebAccessibilityUri,
3842                     false, this, UserHandle.USER_ALL);
3843             contentResolver.registerContentObserver(
3844                     mDisplayInversionEnabledUri, false, this, UserHandle.USER_ALL);
3845             contentResolver.registerContentObserver(
3846                     mDisplayDaltonizerEnabledUri, false, this, UserHandle.USER_ALL);
3847             contentResolver.registerContentObserver(
3848                     mDisplayDaltonizerUri, false, this, UserHandle.USER_ALL);
3849             contentResolver.registerContentObserver(
3850                     mHighTextContrastUri, false, this, UserHandle.USER_ALL);
3851         }
3852 
3853         @Override
onChange(boolean selfChange, Uri uri)3854         public void onChange(boolean selfChange, Uri uri) {
3855             synchronized (mLock) {
3856                 // Profiles share the accessibility state of the parent. Therefore,
3857                 // we are checking for changes only the parent settings.
3858                 UserState userState = getCurrentUserStateLocked();
3859 
3860                 // We will update when the automation service dies.
3861                 if (userState.mUiAutomationService != null) {
3862                     return;
3863                 }
3864 
3865                 if (mAccessibilityEnabledUri.equals(uri)) {
3866                     if (readAccessibilityEnabledSettingLocked(userState)) {
3867                         onUserStateChangedLocked(userState);
3868                     }
3869                 } else if (mTouchExplorationEnabledUri.equals(uri)) {
3870                     if (readTouchExplorationEnabledSettingLocked(userState)) {
3871                         onUserStateChangedLocked(userState);
3872                     }
3873                 } else if (mDisplayMagnificationEnabledUri.equals(uri)) {
3874                     if (readDisplayMagnificationEnabledSettingLocked(userState)) {
3875                         onUserStateChangedLocked(userState);
3876                     }
3877                 } else if (mEnabledAccessibilityServicesUri.equals(uri)) {
3878                     if (readEnabledAccessibilityServicesLocked(userState)) {
3879                         onUserStateChangedLocked(userState);
3880                     }
3881                 } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) {
3882                     if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) {
3883                         onUserStateChangedLocked(userState);
3884                     }
3885                 } else if (mEnhancedWebAccessibilityUri.equals(uri)) {
3886                     if (readEnhancedWebAccessibilityEnabledChangedLocked(userState)) {
3887                         onUserStateChangedLocked(userState);
3888                     }
3889                 } else if (mDisplayInversionEnabledUri.equals(uri)
3890                         || mDisplayDaltonizerEnabledUri.equals(uri)
3891                         || mDisplayDaltonizerUri.equals(uri)) {
3892                     if (readDisplayColorAdjustmentSettingsLocked(userState)) {
3893                         updateDisplayColorAdjustmentSettingsLocked(userState);
3894                     }
3895                 } else if (mHighTextContrastUri.equals(uri)) {
3896                     if (readHighTextContrastEnabledSettingLocked(userState)) {
3897                         onUserStateChangedLocked(userState);
3898                     }
3899                 }
3900             }
3901         }
3902     }
3903 }
3904