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 import static android.view.Display.DEFAULT_DISPLAY;
21 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
22 
23 import android.Manifest;
24 import android.accessibilityservice.AccessibilityService;
25 import android.accessibilityservice.AccessibilityServiceInfo;
26 import android.accessibilityservice.GestureDescription;
27 import android.accessibilityservice.IAccessibilityServiceClient;
28 import android.accessibilityservice.IAccessibilityServiceConnection;
29 import android.annotation.NonNull;
30 import android.app.AlertDialog;
31 import android.app.PendingIntent;
32 import android.app.StatusBarManager;
33 import android.app.UiAutomation;
34 import android.content.BroadcastReceiver;
35 import android.content.ComponentName;
36 import android.content.ContentResolver;
37 import android.content.Context;
38 import android.content.DialogInterface;
39 import android.content.DialogInterface.OnClickListener;
40 import android.content.Intent;
41 import android.content.IntentFilter;
42 import android.content.ServiceConnection;
43 import android.content.pm.PackageManager;
44 import android.content.pm.ParceledListSlice;
45 import android.content.pm.ResolveInfo;
46 import android.content.pm.ServiceInfo;
47 import android.content.pm.UserInfo;
48 import android.database.ContentObserver;
49 import android.graphics.Point;
50 import android.graphics.Rect;
51 import android.graphics.Region;
52 import android.hardware.display.DisplayManager;
53 import android.hardware.fingerprint.IFingerprintService;
54 import android.hardware.input.InputManager;
55 import android.media.AudioManagerInternal;
56 import android.net.Uri;
57 import android.os.Binder;
58 import android.os.Build;
59 import android.os.Bundle;
60 import android.os.Handler;
61 import android.os.IBinder;
62 import android.os.Looper;
63 import android.os.Message;
64 import android.os.PowerManager;
65 import android.os.Process;
66 import android.os.RemoteCallbackList;
67 import android.os.RemoteException;
68 import android.os.ServiceManager;
69 import android.os.SystemClock;
70 import android.os.UserHandle;
71 import android.os.UserManager;
72 import android.os.UserManagerInternal;
73 import android.provider.Settings;
74 import android.provider.SettingsStringUtil;
75 import android.provider.SettingsStringUtil.ComponentNameSet;
76 import android.provider.SettingsStringUtil.SettingStringHelper;
77 import android.text.TextUtils;
78 import android.text.TextUtils.SimpleStringSplitter;
79 import android.util.IntArray;
80 import android.util.Slog;
81 import android.util.SparseArray;
82 import android.view.Display;
83 import android.view.IWindow;
84 import android.view.InputDevice;
85 import android.view.KeyCharacterMap;
86 import android.view.KeyEvent;
87 import android.view.MagnificationSpec;
88 import android.view.View;
89 import android.view.WindowInfo;
90 import android.view.WindowManager;
91 import android.view.WindowManagerInternal;
92 import android.view.accessibility.AccessibilityCache;
93 import android.view.accessibility.AccessibilityEvent;
94 import android.view.accessibility.AccessibilityInteractionClient;
95 import android.view.accessibility.AccessibilityManager;
96 import android.view.accessibility.AccessibilityNodeInfo;
97 import android.view.accessibility.AccessibilityWindowInfo;
98 import android.view.accessibility.IAccessibilityInteractionConnection;
99 import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
100 import android.view.accessibility.IAccessibilityManager;
101 import android.view.accessibility.IAccessibilityManagerClient;
102 
103 import com.android.internal.R;
104 import com.android.internal.annotations.GuardedBy;
105 import com.android.internal.content.PackageMonitor;
106 import com.android.internal.os.SomeArgs;
107 import com.android.internal.util.DumpUtils;
108 import com.android.internal.util.IntPair;
109 import com.android.server.LocalServices;
110 import com.android.server.policy.AccessibilityShortcutController;
111 import com.android.server.statusbar.StatusBarManagerInternal;
112 
113 import org.xmlpull.v1.XmlPullParserException;
114 
115 import java.io.FileDescriptor;
116 import java.io.IOException;
117 import java.io.PrintWriter;
118 import java.util.ArrayList;
119 import java.util.Arrays;
120 import java.util.Collections;
121 import java.util.HashMap;
122 import java.util.HashSet;
123 import java.util.Iterator;
124 import java.util.List;
125 import java.util.Map;
126 import java.util.Set;
127 import java.util.concurrent.CopyOnWriteArrayList;
128 import java.util.function.Consumer;
129 
130 /**
131  * This class is instantiated by the system as a system level service and can be
132  * accessed only by the system. The task of this service is to be a centralized
133  * event dispatch for {@link AccessibilityEvent}s generated across all processes
134  * on the device. Events are dispatched to {@link AccessibilityService}s.
135  */
136 public class AccessibilityManagerService extends IAccessibilityManager.Stub {
137 
138     private static final boolean DEBUG = false;
139 
140     private static final String LOG_TAG = "AccessibilityManagerService";
141 
142     // TODO: This is arbitrary. When there is time implement this by watching
143     //       when that accessibility services are bound.
144     private static final int WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS = 3000;
145 
146     private static final int WAIT_WINDOWS_TIMEOUT_MILLIS = 5000;
147 
148     // TODO: Restructure service initialization so services aren't connected before all of
149     //       their capabilities are ready.
150     private static final int WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS = 1000;
151 
152     private static final String FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE =
153         "registerUiTestAutomationService";
154 
155     private static final String TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED =
156             "temporaryEnableAccessibilityStateUntilKeyguardRemoved";
157 
158     private static final String GET_WINDOW_TOKEN = "getWindowToken";
159 
160     private static final String SET_PIP_ACTION_REPLACEMENT =
161             "setPictureInPictureActionReplacingConnection";
162 
163     private static final ComponentName sFakeAccessibilityServiceComponentName =
164             new ComponentName("foo.bar", "FakeService");
165 
166     private static final String FUNCTION_DUMP = "dump";
167 
168     private static final char COMPONENT_NAME_SEPARATOR = ':';
169 
170     private static final int OWN_PROCESS_ID = android.os.Process.myPid();
171 
172     // Each service has an ID. Also provide one for magnification gesture handling
173     public static final int MAGNIFICATION_GESTURE_HANDLER_ID = 0;
174 
175     private static int sIdCounter = MAGNIFICATION_GESTURE_HANDLER_ID + 1;
176 
177     private static int sNextWindowId;
178 
179     private final Context mContext;
180 
181     private final Object mLock = new Object();
182 
183     private final SimpleStringSplitter mStringColonSplitter =
184             new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
185 
186     private final Rect mTempRect = new Rect();
187 
188     private final Rect mTempRect1 = new Rect();
189 
190     private final Point mTempPoint = new Point();
191 
192     private final PackageManager mPackageManager;
193 
194     private final PowerManager mPowerManager;
195 
196     private final WindowManagerInternal mWindowManagerService;
197 
198     private final SecurityPolicy mSecurityPolicy;
199 
200     private final MainHandler mMainHandler;
201 
202     private MagnificationController mMagnificationController;
203 
204     private InteractionBridge mInteractionBridge;
205 
206     private AlertDialog mEnableTouchExplorationDialog;
207 
208     private AccessibilityInputFilter mInputFilter;
209 
210     private boolean mHasInputFilter;
211 
212     private KeyEventDispatcher mKeyEventDispatcher;
213 
214     private MotionEventInjector mMotionEventInjector;
215 
216     private FingerprintGestureDispatcher mFingerprintGestureDispatcher;
217 
218     private final Set<ComponentName> mTempComponentNameSet = new HashSet<>();
219 
220     private final List<AccessibilityServiceInfo> mTempAccessibilityServiceInfoList =
221             new ArrayList<>();
222 
223     private final IntArray mTempIntArray = new IntArray(0);
224 
225     private final RemoteCallbackList<IAccessibilityManagerClient> mGlobalClients =
226             new RemoteCallbackList<>();
227 
228     private final SparseArray<AccessibilityConnectionWrapper> mGlobalInteractionConnections =
229             new SparseArray<>();
230 
231     private AccessibilityConnectionWrapper mPictureInPictureActionReplacingConnection;
232 
233     private final SparseArray<IBinder> mGlobalWindowTokens = new SparseArray<>();
234 
235     private final SparseArray<UserState> mUserStates = new SparseArray<>();
236 
237     private final UserManager mUserManager;
238 
239     private int mCurrentUserId = UserHandle.USER_SYSTEM;
240 
241     //TODO: Remove this hack
242     private boolean mInitialized;
243 
244     private WindowsForAccessibilityCallback mWindowsForAccessibilityCallback;
245 
246     private boolean mIsAccessibilityButtonShown;
247 
getCurrentUserStateLocked()248     private UserState getCurrentUserStateLocked() {
249         return getUserStateLocked(mCurrentUserId);
250     }
251 
252     /**
253      * Creates a new instance.
254      *
255      * @param context A {@link Context} instance.
256      */
AccessibilityManagerService(Context context)257     public AccessibilityManagerService(Context context) {
258         mContext = context;
259         mPackageManager = mContext.getPackageManager();
260         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
261         mWindowManagerService = LocalServices.getService(WindowManagerInternal.class);
262         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
263         mSecurityPolicy = new SecurityPolicy();
264         mMainHandler = new MainHandler(mContext.getMainLooper());
265         registerBroadcastReceivers();
266         new AccessibilityContentObserver(mMainHandler).register(
267                 context.getContentResolver());
268     }
269 
getUserStateLocked(int userId)270     private UserState getUserStateLocked(int userId) {
271         UserState state = mUserStates.get(userId);
272         if (state == null) {
273             state = new UserState(userId);
274             mUserStates.put(userId, state);
275         }
276         return state;
277     }
278 
registerBroadcastReceivers()279     private void registerBroadcastReceivers() {
280         PackageMonitor monitor = new PackageMonitor() {
281             @Override
282             public void onSomePackagesChanged() {
283                 synchronized (mLock) {
284                     // Only the profile parent can install accessibility services.
285                     // Therefore we ignore packages from linked profiles.
286                     if (getChangingUserId() != mCurrentUserId) {
287                         return;
288                     }
289                     // We will update when the automation service dies.
290                     UserState userState = getCurrentUserStateLocked();
291                     // We have to reload the installed services since some services may
292                     // have different attributes, resolve info (does not support equals),
293                     // etc. Remove them then to force reload.
294                     userState.mInstalledServices.clear();
295                     if (!userState.isUiAutomationSuppressingOtherServices()) {
296                         if (readConfigurationForUserStateLocked(userState)) {
297                             onUserStateChangedLocked(userState);
298                         }
299                     }
300                 }
301             }
302 
303             @Override
304             public void onPackageUpdateFinished(String packageName, int uid) {
305                 // Unbind all services from this package, and then update the user state to
306                 // re-bind new versions of them.
307                 synchronized (mLock) {
308                     final int userId = getChangingUserId();
309                     if (userId != mCurrentUserId) {
310                         return;
311                     }
312                     UserState userState = getUserStateLocked(userId);
313                     boolean unboundAService = false;
314                     for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
315                         Service boundService = userState.mBoundServices.get(i);
316                         String servicePkg = boundService.mComponentName.getPackageName();
317                         if (servicePkg.equals(packageName)) {
318                             boundService.unbindLocked();
319                             unboundAService = true;
320                         }
321                     }
322                     if (unboundAService) {
323                         onUserStateChangedLocked(userState);
324                     }
325                 }
326             }
327 
328             @Override
329             public void onPackageRemoved(String packageName, int uid) {
330                 synchronized (mLock) {
331                     final int userId = getChangingUserId();
332                     // Only the profile parent can install accessibility services.
333                     // Therefore we ignore packages from linked profiles.
334                     if (userId != mCurrentUserId) {
335                         return;
336                     }
337                     UserState userState = getUserStateLocked(userId);
338                     Iterator<ComponentName> it = userState.mEnabledServices.iterator();
339                     while (it.hasNext()) {
340                         ComponentName comp = it.next();
341                         String compPkg = comp.getPackageName();
342                         if (compPkg.equals(packageName)) {
343                             it.remove();
344                             // Update the enabled services setting.
345                             persistComponentNamesToSettingLocked(
346                                     Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
347                                     userState.mEnabledServices, userId);
348                             // Update the touch exploration granted services setting.
349                             userState.mTouchExplorationGrantedServices.remove(comp);
350                             persistComponentNamesToSettingLocked(
351                                     Settings.Secure.
352                                     TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
353                                     userState.mTouchExplorationGrantedServices, userId);
354                             // We will update when the automation service dies.
355                             if (!userState.isUiAutomationSuppressingOtherServices()) {
356                                 onUserStateChangedLocked(userState);
357                             }
358                             return;
359                         }
360                     }
361                 }
362             }
363 
364             @Override
365             public boolean onHandleForceStop(Intent intent, String[] packages,
366                     int uid, boolean doit) {
367                 synchronized (mLock) {
368                     final int userId = getChangingUserId();
369                     // Only the profile parent can install accessibility services.
370                     // Therefore we ignore packages from linked profiles.
371                     if (userId != mCurrentUserId) {
372                         return false;
373                     }
374                     UserState userState = getUserStateLocked(userId);
375                     Iterator<ComponentName> it = userState.mEnabledServices.iterator();
376                     while (it.hasNext()) {
377                         ComponentName comp = it.next();
378                         String compPkg = comp.getPackageName();
379                         for (String pkg : packages) {
380                             if (compPkg.equals(pkg)) {
381                                 if (!doit) {
382                                     return true;
383                                 }
384                                 it.remove();
385                                 persistComponentNamesToSettingLocked(
386                                         Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
387                                         userState.mEnabledServices, userId);
388                                 // We will update when the automation service dies.
389                                 if (!userState.isUiAutomationSuppressingOtherServices()) {
390                                     onUserStateChangedLocked(userState);
391                                 }
392                             }
393                         }
394                     }
395                     return false;
396                 }
397             }
398         };
399 
400         // package changes
401         monitor.register(mContext, null,  UserHandle.ALL, true);
402 
403         // user change and unlock
404         IntentFilter intentFilter = new IntentFilter();
405         intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
406         intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
407         intentFilter.addAction(Intent.ACTION_USER_REMOVED);
408         intentFilter.addAction(Intent.ACTION_USER_PRESENT);
409         intentFilter.addAction(Intent.ACTION_SETTING_RESTORED);
410 
411         mContext.registerReceiverAsUser(new BroadcastReceiver() {
412             @Override
413             public void onReceive(Context context, Intent intent) {
414                 String action = intent.getAction();
415                 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
416                     switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
417                 } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
418                     unlockUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
419                 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
420                     removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
421                 } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
422                     // We will update when the automation service dies.
423                     synchronized (mLock) {
424                         UserState userState = getCurrentUserStateLocked();
425                         if (!userState.isUiAutomationSuppressingOtherServices()) {
426                             if (readConfigurationForUserStateLocked(userState)) {
427                                 onUserStateChangedLocked(userState);
428                             }
429                         }
430                     }
431                 } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
432                     final String which = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
433                     if (Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(which)) {
434                         synchronized (mLock) {
435                             restoreEnabledAccessibilityServicesLocked(
436                                     intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
437                                     intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
438                         }
439                     }
440                 }
441             }
442         }, UserHandle.ALL, intentFilter, null, null);
443     }
444 
445     @Override
addClient(IAccessibilityManagerClient client, int userId)446     public long addClient(IAccessibilityManagerClient client, int userId) {
447         synchronized (mLock) {
448             // We treat calls from a profile as if made by its parent as profiles
449             // share the accessibility state of the parent. The call below
450             // performs the current profile parent resolution.
451             final int resolvedUserId = mSecurityPolicy
452                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
453             // If the client is from a process that runs across users such as
454             // the system UI or the system we add it to the global state that
455             // is shared across users.
456             UserState userState = getUserStateLocked(resolvedUserId);
457             if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
458                 mGlobalClients.register(client);
459                 if (DEBUG) {
460                     Slog.i(LOG_TAG, "Added global client for pid:" + Binder.getCallingPid());
461                 }
462                 return IntPair.of(
463                         userState.getClientState(), userState.mLastSentRelevantEventTypes);
464             } else {
465                 userState.mUserClients.register(client);
466                 // If this client is not for the current user we do not
467                 // return a state since it is not for the foreground user.
468                 // We will send the state to the client on a user switch.
469                 if (DEBUG) {
470                     Slog.i(LOG_TAG, "Added user client for pid:" + Binder.getCallingPid()
471                             + " and userId:" + mCurrentUserId);
472                 }
473                 return IntPair.of(
474                         (resolvedUserId == mCurrentUserId) ? userState.getClientState() : 0,
475                         userState.mLastSentRelevantEventTypes);
476             }
477         }
478     }
479 
480     @Override
sendAccessibilityEvent(AccessibilityEvent event, int userId)481     public void sendAccessibilityEvent(AccessibilityEvent event, int userId) {
482         boolean dispatchEvent = false;
483 
484         synchronized (mLock) {
485             if (event.getWindowId() ==
486                 AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID) {
487                 // The replacer window isn't shown to services. Move its events into the pip.
488                 AccessibilityWindowInfo pip = mSecurityPolicy.getPictureInPictureWindow();
489                 if (pip != null) {
490                     int pipId = pip.getId();
491                     event.setWindowId(pipId);
492                     event.setSealed(true);
493                     AccessibilityNodeInfo info = event.getSource();
494                     info.setSealed(false);
495                     event.setSealed(false);
496                     if (info != null) {
497                         info.setSourceNodeId(info.getSourceNodeId(), pipId);
498                         event.setSource(info);
499                         info.recycle();
500                     }
501                 }
502             }
503 
504             // We treat calls from a profile as if made by its parent as profiles
505             // share the accessibility state of the parent. The call below
506             // performs the current profile parent resolution..
507             final int resolvedUserId = mSecurityPolicy
508                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
509             // This method does nothing for a background user.
510             if (resolvedUserId == mCurrentUserId) {
511                 if (mSecurityPolicy.canDispatchAccessibilityEventLocked(event)) {
512                     mSecurityPolicy.updateActiveAndAccessibilityFocusedWindowLocked(
513                             event.getWindowId(), event.getSourceNodeId(),
514                             event.getEventType(), event.getAction());
515                     mSecurityPolicy.updateEventSourceLocked(event);
516                     dispatchEvent = true;
517                 }
518                 if (mHasInputFilter && mInputFilter != null) {
519                     mMainHandler.obtainMessage(
520                             MainHandler.MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER,
521                             AccessibilityEvent.obtain(event)).sendToTarget();
522                 }
523             }
524         }
525 
526         if (dispatchEvent) {
527             // Make sure clients receiving this event will be able to get the
528             // current state of the windows as the window manager may be delaying
529             // the computation for performance reasons.
530             if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
531                     && mWindowsForAccessibilityCallback != null) {
532                 WindowManagerInternal wm = LocalServices.getService(WindowManagerInternal.class);
533                 wm.computeWindowsForAccessibility();
534             }
535             synchronized (mLock) {
536                 notifyAccessibilityServicesDelayedLocked(event, false);
537                 notifyAccessibilityServicesDelayedLocked(event, true);
538             }
539         }
540 
541         if (OWN_PROCESS_ID != Binder.getCallingPid()) {
542             event.recycle();
543         }
544     }
545 
546     @Override
getInstalledAccessibilityServiceList(int userId)547     public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) {
548         synchronized (mLock) {
549             // We treat calls from a profile as if made by its parent as profiles
550             // share the accessibility state of the parent. The call below
551             // performs the current profile parent resolution.
552             final int resolvedUserId = mSecurityPolicy
553                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
554             // The automation service is a fake one and should not be reported
555             // to clients as being installed - it really is not.
556             UserState userState = getUserStateLocked(resolvedUserId);
557             if (userState.mUiAutomationService != null) {
558                 List<AccessibilityServiceInfo> installedServices = new ArrayList<>();
559                 installedServices.addAll(userState.mInstalledServices);
560                 installedServices.remove(userState.mUiAutomationService.mAccessibilityServiceInfo);
561                 return installedServices;
562             }
563             return userState.mInstalledServices;
564         }
565     }
566 
567     @Override
getEnabledAccessibilityServiceList(int feedbackType, int userId)568     public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType,
569             int userId) {
570         synchronized (mLock) {
571             // We treat calls from a profile as if made by its parent as profiles
572             // share the accessibility state of the parent. The call below
573             // performs the current profile parent resolution.
574             final int resolvedUserId = mSecurityPolicy
575                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
576 
577             // The automation service can suppress other services.
578             final UserState userState = getUserStateLocked(resolvedUserId);
579             if (userState.isUiAutomationSuppressingOtherServices()) {
580                 return Collections.emptyList();
581             }
582 
583             final List<Service> services = userState.mBoundServices;
584             final int serviceCount = services.size();
585             final List<AccessibilityServiceInfo> result = new ArrayList<>(serviceCount);
586             for (int i = 0; i < serviceCount; ++i) {
587                 final Service service = services.get(i);
588                 // Don't report the UIAutomation (fake service)
589                 if (!sFakeAccessibilityServiceComponentName.equals(service.mComponentName)
590                         && (service.mFeedbackType & feedbackType) != 0) {
591                     result.add(service.mAccessibilityServiceInfo);
592                 }
593             }
594             return result;
595         }
596     }
597 
598     @Override
interrupt(int userId)599     public void interrupt(int userId) {
600         List<IAccessibilityServiceClient> interfacesToInterrupt;
601         synchronized (mLock) {
602             // We treat calls from a profile as if made by its parent as profiles
603             // share the accessibility state of the parent. The call below
604             // performs the current profile parent resolution.
605             final int resolvedUserId = mSecurityPolicy
606                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
607             // This method does nothing for a background user.
608             if (resolvedUserId != mCurrentUserId) {
609                 return;
610             }
611             List<Service> services = getUserStateLocked(resolvedUserId).mBoundServices;
612             int numServices = services.size();
613             interfacesToInterrupt = new ArrayList<>(numServices);
614             for (int i = 0; i < numServices; i++) {
615                 Service service = services.get(i);
616                 IBinder a11yServiceBinder = service.mService;
617                 IAccessibilityServiceClient a11yServiceInterface = service.mServiceInterface;
618                 if ((a11yServiceBinder != null) && (a11yServiceInterface != null)) {
619                     interfacesToInterrupt.add(a11yServiceInterface);
620                 }
621             }
622         }
623         for (int i = 0, count = interfacesToInterrupt.size(); i < count; i++) {
624             try {
625                 interfacesToInterrupt.get(i).onInterrupt();
626             } catch (RemoteException re) {
627                 Slog.e(LOG_TAG, "Error sending interrupt request to "
628                         + interfacesToInterrupt.get(i), re);
629             }
630         }
631     }
632 
633     @Override
addAccessibilityInteractionConnection(IWindow windowToken, IAccessibilityInteractionConnection connection, int userId)634     public int addAccessibilityInteractionConnection(IWindow windowToken,
635             IAccessibilityInteractionConnection connection, int userId) throws RemoteException {
636         synchronized (mLock) {
637             // We treat calls from a profile as if made by its parent as profiles
638             // share the accessibility state of the parent. The call below
639             // performs the current profile parent resolution.
640             final int resolvedUserId = mSecurityPolicy
641                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
642             final int windowId = sNextWindowId++;
643             // If the window is from a process that runs across users such as
644             // the system UI or the system we add it to the global state that
645             // is shared across users.
646             if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
647                 AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
648                         windowId, connection, UserHandle.USER_ALL);
649                 wrapper.linkToDeath();
650                 mGlobalInteractionConnections.put(windowId, wrapper);
651                 mGlobalWindowTokens.put(windowId, windowToken.asBinder());
652                 if (DEBUG) {
653                     Slog.i(LOG_TAG, "Added global connection for pid:" + Binder.getCallingPid()
654                             + " with windowId: " + windowId + " and  token: " + windowToken.asBinder());
655                 }
656             } else {
657                 AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
658                         windowId, connection, resolvedUserId);
659                 wrapper.linkToDeath();
660                 UserState userState = getUserStateLocked(resolvedUserId);
661                 userState.mInteractionConnections.put(windowId, wrapper);
662                 userState.mWindowTokens.put(windowId, windowToken.asBinder());
663                 if (DEBUG) {
664                     Slog.i(LOG_TAG, "Added user connection for pid:" + Binder.getCallingPid()
665                             + " with windowId: " + windowId + " and userId:" + mCurrentUserId
666                             + " and  token: " + windowToken.asBinder());
667                 }
668             }
669             return windowId;
670         }
671     }
672 
673     @Override
removeAccessibilityInteractionConnection(IWindow window)674     public void removeAccessibilityInteractionConnection(IWindow window) {
675         synchronized (mLock) {
676             // We treat calls from a profile as if made by its parent as profiles
677             // share the accessibility state of the parent. The call below
678             // performs the current profile parent resolution.
679             mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(
680                     UserHandle.getCallingUserId());
681             IBinder token = window.asBinder();
682             final int removedWindowId = removeAccessibilityInteractionConnectionInternalLocked(
683                     token, mGlobalWindowTokens, mGlobalInteractionConnections);
684             if (removedWindowId >= 0) {
685                 if (DEBUG) {
686                     Slog.i(LOG_TAG, "Removed global connection for pid:" + Binder.getCallingPid()
687                             + " with windowId: " + removedWindowId + " and token: " + window.asBinder());
688                 }
689                 return;
690             }
691             final int userCount = mUserStates.size();
692             for (int i = 0; i < userCount; i++) {
693                 UserState userState = mUserStates.valueAt(i);
694                 final int removedWindowIdForUser =
695                         removeAccessibilityInteractionConnectionInternalLocked(
696                         token, userState.mWindowTokens, userState.mInteractionConnections);
697                 if (removedWindowIdForUser >= 0) {
698                     if (DEBUG) {
699                         Slog.i(LOG_TAG, "Removed user connection for pid:" + Binder.getCallingPid()
700                                 + " with windowId: " + removedWindowIdForUser + " and userId:"
701                                 + mUserStates.keyAt(i) + " and token: " + window.asBinder());
702                     }
703                     return;
704                 }
705             }
706         }
707     }
708 
removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken, SparseArray<IBinder> windowTokens, SparseArray<AccessibilityConnectionWrapper> interactionConnections)709     private int removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken,
710             SparseArray<IBinder> windowTokens,
711             SparseArray<AccessibilityConnectionWrapper> interactionConnections) {
712         final int count = windowTokens.size();
713         for (int i = 0; i < count; i++) {
714             if (windowTokens.valueAt(i) == windowToken) {
715                 final int windowId = windowTokens.keyAt(i);
716                 windowTokens.removeAt(i);
717                 AccessibilityConnectionWrapper wrapper = interactionConnections.get(windowId);
718                 wrapper.unlinkToDeath();
719                 interactionConnections.remove(windowId);
720                 return windowId;
721             }
722         }
723         return -1;
724     }
725 
726     @Override
setPictureInPictureActionReplacingConnection( IAccessibilityInteractionConnection connection)727     public void setPictureInPictureActionReplacingConnection(
728             IAccessibilityInteractionConnection connection) throws RemoteException {
729         mSecurityPolicy.enforceCallingPermission(Manifest.permission.MODIFY_ACCESSIBILITY_DATA,
730                 SET_PIP_ACTION_REPLACEMENT);
731         synchronized (mLock) {
732             if (mPictureInPictureActionReplacingConnection != null) {
733                 mPictureInPictureActionReplacingConnection.unlinkToDeath();
734                 mPictureInPictureActionReplacingConnection = null;
735             }
736             if (connection != null) {
737                 AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
738                         AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID,
739                         connection, UserHandle.USER_ALL);
740                 mPictureInPictureActionReplacingConnection = wrapper;
741                 wrapper.linkToDeath();
742             }
743             mSecurityPolicy.notifyWindowsChanged();
744         }
745     }
746 
747     @Override
registerUiTestAutomationService(IBinder owner, IAccessibilityServiceClient serviceClient, AccessibilityServiceInfo accessibilityServiceInfo, int flags)748     public void registerUiTestAutomationService(IBinder owner,
749             IAccessibilityServiceClient serviceClient,
750             AccessibilityServiceInfo accessibilityServiceInfo,
751             int flags) {
752         mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT,
753                 FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE);
754 
755         accessibilityServiceInfo.setComponentName(sFakeAccessibilityServiceComponentName);
756 
757         synchronized (mLock) {
758             UserState userState = getCurrentUserStateLocked();
759 
760             if (userState.mUiAutomationService != null) {
761                 throw new IllegalStateException("UiAutomationService " + serviceClient
762                         + "already registered!");
763             }
764 
765             try {
766                 owner.linkToDeath(userState.mUiAutomationSerivceOnwerDeathRecipient, 0);
767             } catch (RemoteException re) {
768                 Slog.e(LOG_TAG, "Couldn't register for the death of a"
769                         + " UiTestAutomationService!", re);
770                 return;
771             }
772 
773             userState.mUiAutomationServiceOwner = owner;
774             userState.mUiAutomationServiceClient = serviceClient;
775             userState.mUiAutomationFlags = flags;
776             userState.mInstalledServices.add(accessibilityServiceInfo);
777             if ((flags & UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) == 0) {
778                 // Set the temporary state, and use it instead of settings
779                 userState.mIsTouchExplorationEnabled = false;
780                 userState.mIsDisplayMagnificationEnabled = false;
781                 userState.mIsNavBarMagnificationEnabled = false;
782                 userState.mIsAutoclickEnabled = false;
783                 userState.mEnabledServices.clear();
784             }
785             userState.mEnabledServices.add(sFakeAccessibilityServiceComponentName);
786             userState.mTouchExplorationGrantedServices.add(sFakeAccessibilityServiceComponentName);
787 
788             // Use the new state instead of settings.
789             onUserStateChangedLocked(userState);
790         }
791     }
792 
793     @Override
unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient)794     public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) {
795         synchronized (mLock) {
796             UserState userState = getCurrentUserStateLocked();
797             // Automation service is not bound, so pretend it died to perform clean up.
798             if (userState.mUiAutomationService != null
799                     && serviceClient != null
800                     && userState.mUiAutomationService.mServiceInterface != null
801                     && userState.mUiAutomationService.mServiceInterface.asBinder()
802                     == serviceClient.asBinder()) {
803                 userState.mUiAutomationService.binderDied();
804             } else {
805                 throw new IllegalStateException("UiAutomationService " + serviceClient
806                         + " not registered!");
807             }
808         }
809     }
810 
811     @Override
temporaryEnableAccessibilityStateUntilKeyguardRemoved( ComponentName service, boolean touchExplorationEnabled)812     public void temporaryEnableAccessibilityStateUntilKeyguardRemoved(
813             ComponentName service, boolean touchExplorationEnabled) {
814         mSecurityPolicy.enforceCallingPermission(
815                 Manifest.permission.TEMPORARY_ENABLE_ACCESSIBILITY,
816                 TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED);
817         if (!mWindowManagerService.isKeyguardLocked()) {
818             return;
819         }
820         synchronized (mLock) {
821             // Set the temporary state.
822             UserState userState = getCurrentUserStateLocked();
823 
824             // This is a nop if UI automation is enabled.
825             if (userState.isUiAutomationSuppressingOtherServices()) {
826                 return;
827             }
828 
829             userState.mIsTouchExplorationEnabled = touchExplorationEnabled;
830             userState.mIsDisplayMagnificationEnabled = false;
831             userState.mIsNavBarMagnificationEnabled = false;
832             userState.mIsAutoclickEnabled = false;
833             userState.mEnabledServices.clear();
834             userState.mEnabledServices.add(service);
835             userState.mBindingServices.clear();
836             userState.mTouchExplorationGrantedServices.clear();
837             userState.mTouchExplorationGrantedServices.add(service);
838 
839             // User the current state instead settings.
840             onUserStateChangedLocked(userState);
841         }
842     }
843 
844     @Override
getWindowToken(int windowId, int userId)845     public IBinder getWindowToken(int windowId, int userId) {
846         mSecurityPolicy.enforceCallingPermission(
847                 Manifest.permission.RETRIEVE_WINDOW_TOKEN,
848                 GET_WINDOW_TOKEN);
849         synchronized (mLock) {
850             // We treat calls from a profile as if made by its parent as profiles
851             // share the accessibility state of the parent. The call below
852             // performs the current profile parent resolution.
853             final int resolvedUserId = mSecurityPolicy
854                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
855             if (resolvedUserId != mCurrentUserId) {
856                 return null;
857             }
858             if (mSecurityPolicy.findWindowById(windowId) == null) {
859                 return null;
860             }
861             IBinder token = mGlobalWindowTokens.get(windowId);
862             if (token != null) {
863                 return token;
864             }
865             return getCurrentUserStateLocked().mWindowTokens.get(windowId);
866         }
867     }
868 
869     /**
870      * Invoked remotely over AIDL by SysUi when the accessibility button within the system's
871      * navigation area has been clicked.
872      */
873     @Override
notifyAccessibilityButtonClicked()874     public void notifyAccessibilityButtonClicked() {
875         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE)
876                 != PackageManager.PERMISSION_GRANTED) {
877             throw new SecurityException("Caller does not hold permission "
878                     + android.Manifest.permission.STATUS_BAR_SERVICE);
879         }
880         synchronized (mLock) {
881             notifyAccessibilityButtonClickedLocked();
882         }
883     }
884 
885     /**
886      * Invoked remotely over AIDL by SysUi when the visibility of the accessibility
887      * button within the system's navigation area has changed.
888      *
889      * @param shown {@code true} if the accessibility button is shown to the
890      *                  user, {@code false} otherwise
891      */
892     @Override
notifyAccessibilityButtonVisibilityChanged(boolean shown)893     public void notifyAccessibilityButtonVisibilityChanged(boolean shown) {
894         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE)
895                 != PackageManager.PERMISSION_GRANTED) {
896             throw new SecurityException("Caller does not hold permission "
897                     + android.Manifest.permission.STATUS_BAR_SERVICE);
898         }
899         synchronized (mLock) {
900             notifyAccessibilityButtonVisibilityChangedLocked(shown);
901         }
902     }
903 
904 
onGesture(int gestureId)905     boolean onGesture(int gestureId) {
906         synchronized (mLock) {
907             boolean handled = notifyGestureLocked(gestureId, false);
908             if (!handled) {
909                 handled = notifyGestureLocked(gestureId, true);
910             }
911             return handled;
912         }
913     }
914 
notifyKeyEvent(KeyEvent event, int policyFlags)915     boolean notifyKeyEvent(KeyEvent event, int policyFlags) {
916         synchronized (mLock) {
917             List<Service> boundServices = getCurrentUserStateLocked().mBoundServices;
918             if (boundServices.isEmpty()) {
919                 return false;
920             }
921             return getKeyEventDispatcher().notifyKeyEventLocked(event, policyFlags, boundServices);
922         }
923     }
924 
925     /**
926      * Called by the MagnificationController when the state of display
927      * magnification changes.
928      *
929      * @param region the new magnified region, may be empty if
930      *               magnification is not enabled (e.g. scale is 1)
931      * @param scale the new scale
932      * @param centerX the new screen-relative center X coordinate
933      * @param centerY the new screen-relative center Y coordinate
934      */
notifyMagnificationChanged(@onNull Region region, float scale, float centerX, float centerY)935     public void notifyMagnificationChanged(@NonNull Region region,
936             float scale, float centerX, float centerY) {
937         synchronized (mLock) {
938             notifyClearAccessibilityCacheLocked();
939             notifyMagnificationChangedLocked(region, scale, centerX, centerY);
940         }
941     }
942 
943     /**
944      * Called by AccessibilityInputFilter when it creates or destroys the motionEventInjector.
945      * Not using a getter because the AccessibilityInputFilter isn't thread-safe
946      *
947      * @param motionEventInjector The new value of the motionEventInjector. May be null.
948      */
setMotionEventInjector(MotionEventInjector motionEventInjector)949     void setMotionEventInjector(MotionEventInjector motionEventInjector) {
950         synchronized (mLock) {
951             mMotionEventInjector = motionEventInjector;
952             // We may be waiting on this object being set
953             mLock.notifyAll();
954         }
955     }
956 
957     /**
958      * Gets a point within the accessibility focused node where we can send down
959      * and up events to perform a click.
960      *
961      * @param outPoint The click point to populate.
962      * @return Whether accessibility a click point was found and set.
963      */
964     // TODO: (multi-display) Make sure this works for multiple displays.
getAccessibilityFocusClickPointInScreen(Point outPoint)965     boolean getAccessibilityFocusClickPointInScreen(Point outPoint) {
966         return getInteractionBridge().getAccessibilityFocusClickPointInScreenNotLocked(outPoint);
967     }
968 
969     /**
970      * Perform an accessibility action on the view that currently has accessibility focus.
971      * Has no effect if no item has accessibility focus, if the item with accessibility
972      * focus does not expose the specified action, or if the action fails.
973      *
974      * @param actionId The id of the action to perform.
975      *
976      * @return {@code true} if the action was performed. {@code false} if it was not.
977      */
performActionOnAccessibilityFocusedItem( AccessibilityNodeInfo.AccessibilityAction action)978     public boolean performActionOnAccessibilityFocusedItem(
979             AccessibilityNodeInfo.AccessibilityAction action) {
980         return getInteractionBridge().performActionOnAccessibilityFocusedItemNotLocked(action);
981     }
982 
983     /**
984      * Gets the bounds of a window.
985      *
986      * @param outBounds The output to which to write the bounds.
987      */
getWindowBounds(int windowId, Rect outBounds)988     boolean getWindowBounds(int windowId, Rect outBounds) {
989         IBinder token;
990         synchronized (mLock) {
991             token = mGlobalWindowTokens.get(windowId);
992             if (token == null) {
993                 token = getCurrentUserStateLocked().mWindowTokens.get(windowId);
994             }
995         }
996         mWindowManagerService.getWindowFrame(token, outBounds);
997         if (!outBounds.isEmpty()) {
998             return true;
999         }
1000         return false;
1001     }
1002 
accessibilityFocusOnlyInActiveWindow()1003     boolean accessibilityFocusOnlyInActiveWindow() {
1004         synchronized (mLock) {
1005             return mWindowsForAccessibilityCallback == null;
1006         }
1007     }
1008 
getActiveWindowId()1009     int getActiveWindowId() {
1010         return mSecurityPolicy.getActiveWindowId();
1011     }
1012 
onTouchInteractionStart()1013     void onTouchInteractionStart() {
1014         mSecurityPolicy.onTouchInteractionStart();
1015     }
1016 
onTouchInteractionEnd()1017     void onTouchInteractionEnd() {
1018         mSecurityPolicy.onTouchInteractionEnd();
1019     }
1020 
switchUser(int userId)1021     private void switchUser(int userId) {
1022         synchronized (mLock) {
1023             if (mCurrentUserId == userId && mInitialized) {
1024                 return;
1025             }
1026 
1027             // Disconnect from services for the old user.
1028             UserState oldUserState = getCurrentUserStateLocked();
1029             oldUserState.onSwitchToAnotherUser();
1030 
1031             // Disable the local managers for the old user.
1032             if (oldUserState.mUserClients.getRegisteredCallbackCount() > 0) {
1033                 mMainHandler.obtainMessage(MainHandler.MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER,
1034                         oldUserState.mUserId, 0).sendToTarget();
1035             }
1036 
1037             // Announce user changes only if more that one exist.
1038             UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1039             final boolean announceNewUser = userManager.getUsers().size() > 1;
1040 
1041             // The user changed.
1042             mCurrentUserId = userId;
1043 
1044             UserState userState = getCurrentUserStateLocked();
1045             if (userState.mUiAutomationService != null) {
1046                 // Switching users disables the UI automation service.
1047                 userState.mUiAutomationService.binderDied();
1048             }
1049 
1050             readConfigurationForUserStateLocked(userState);
1051             // Even if reading did not yield change, we have to update
1052             // the state since the context in which the current user
1053             // state was used has changed since it was inactive.
1054             onUserStateChangedLocked(userState);
1055 
1056             if (announceNewUser) {
1057                 // Schedule announcement of the current user if needed.
1058                 mMainHandler.sendEmptyMessageDelayed(MainHandler.MSG_ANNOUNCE_NEW_USER_IF_NEEDED,
1059                         WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS);
1060             }
1061         }
1062     }
1063 
unlockUser(int userId)1064     private void unlockUser(int userId) {
1065         synchronized (mLock) {
1066             int parentUserId = mSecurityPolicy.resolveProfileParentLocked(userId);
1067             if (parentUserId == mCurrentUserId) {
1068                 UserState userState = getUserStateLocked(mCurrentUserId);
1069                 onUserStateChangedLocked(userState);
1070             }
1071         }
1072     }
1073 
removeUser(int userId)1074     private void removeUser(int userId) {
1075         synchronized (mLock) {
1076             mUserStates.remove(userId);
1077         }
1078     }
1079 
1080     // Called only during settings restore; currently supports only the owner user
1081     // TODO: http://b/22388012
restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting)1082     void restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting) {
1083         readComponentNamesFromStringLocked(oldSetting, mTempComponentNameSet, false);
1084         readComponentNamesFromStringLocked(newSetting, mTempComponentNameSet, true);
1085 
1086         UserState userState = getUserStateLocked(UserHandle.USER_SYSTEM);
1087         userState.mEnabledServices.clear();
1088         userState.mEnabledServices.addAll(mTempComponentNameSet);
1089         persistComponentNamesToSettingLocked(
1090                 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
1091                 userState.mEnabledServices,
1092                 UserHandle.USER_SYSTEM);
1093         onUserStateChangedLocked(userState);
1094     }
1095 
getInteractionBridge()1096     private InteractionBridge getInteractionBridge() {
1097         synchronized (mLock) {
1098             if (mInteractionBridge == null) {
1099                 mInteractionBridge = new InteractionBridge();
1100             }
1101             return mInteractionBridge;
1102         }
1103     }
1104 
notifyGestureLocked(int gestureId, boolean isDefault)1105     private boolean notifyGestureLocked(int gestureId, boolean isDefault) {
1106         // TODO: Now we are giving the gestures to the last enabled
1107         //       service that can handle them which is the last one
1108         //       in our list since we write the last enabled as the
1109         //       last record in the enabled services setting. Ideally,
1110         //       the user should make the call which service handles
1111         //       gestures. However, only one service should handle
1112         //       gestures to avoid user frustration when different
1113         //       behavior is observed from different combinations of
1114         //       enabled accessibility services.
1115         UserState state = getCurrentUserStateLocked();
1116         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1117             Service service = state.mBoundServices.get(i);
1118             if (service.mRequestTouchExplorationMode && service.mIsDefault == isDefault) {
1119                 service.notifyGesture(gestureId);
1120                 return true;
1121             }
1122         }
1123         return false;
1124     }
1125 
notifyClearAccessibilityCacheLocked()1126     private void notifyClearAccessibilityCacheLocked() {
1127         UserState state = getCurrentUserStateLocked();
1128         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1129             Service service = state.mBoundServices.get(i);
1130             service.notifyClearAccessibilityNodeInfoCache();
1131         }
1132     }
1133 
notifyMagnificationChangedLocked(@onNull Region region, float scale, float centerX, float centerY)1134     private void notifyMagnificationChangedLocked(@NonNull Region region,
1135             float scale, float centerX, float centerY) {
1136         final UserState state = getCurrentUserStateLocked();
1137         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1138             final Service service = state.mBoundServices.get(i);
1139             service.notifyMagnificationChangedLocked(region, scale, centerX, centerY);
1140         }
1141     }
1142 
notifySoftKeyboardShowModeChangedLocked(int showMode)1143     private void notifySoftKeyboardShowModeChangedLocked(int showMode) {
1144         final UserState state = getCurrentUserStateLocked();
1145         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1146             final Service service = state.mBoundServices.get(i);
1147             service.notifySoftKeyboardShowModeChangedLocked(showMode);
1148         }
1149     }
1150 
notifyAccessibilityButtonClickedLocked()1151     private void notifyAccessibilityButtonClickedLocked() {
1152         final UserState state = getCurrentUserStateLocked();
1153 
1154         int potentialTargets = state.mIsNavBarMagnificationEnabled ? 1 : 0;
1155         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1156             final Service service = state.mBoundServices.get(i);
1157             if (service.mRequestAccessibilityButton) {
1158                 potentialTargets++;
1159             }
1160         }
1161 
1162         if (potentialTargets == 0) {
1163             return;
1164         }
1165         if (potentialTargets == 1) {
1166             if (state.mIsNavBarMagnificationEnabled) {
1167                 mMainHandler.obtainMessage(
1168                         MainHandler.MSG_SEND_ACCESSIBILITY_BUTTON_TO_INPUT_FILTER).sendToTarget();
1169                 return;
1170             } else {
1171                 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1172                     final Service service = state.mBoundServices.get(i);
1173                     if (service.mRequestAccessibilityButton) {
1174                         service.notifyAccessibilityButtonClickedLocked();
1175                         return;
1176                     }
1177                 }
1178             }
1179         } else {
1180             if (state.mServiceAssignedToAccessibilityButton == null
1181                     && !state.mIsNavBarMagnificationAssignedToAccessibilityButton) {
1182                 mMainHandler.obtainMessage(
1183                         MainHandler.MSG_SHOW_ACCESSIBILITY_BUTTON_CHOOSER).sendToTarget();
1184             } else if (state.mIsNavBarMagnificationEnabled
1185                     && state.mIsNavBarMagnificationAssignedToAccessibilityButton) {
1186                 mMainHandler.obtainMessage(
1187                         MainHandler.MSG_SEND_ACCESSIBILITY_BUTTON_TO_INPUT_FILTER).sendToTarget();
1188                 return;
1189             } else {
1190                 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1191                     final Service service = state.mBoundServices.get(i);
1192                     if (service.mRequestAccessibilityButton && (service.mComponentName.equals(
1193                             state.mServiceAssignedToAccessibilityButton))) {
1194                         service.notifyAccessibilityButtonClickedLocked();
1195                         return;
1196                     }
1197                 }
1198             }
1199             // The user may have turned off the assigned service or feature
1200             mMainHandler.obtainMessage(
1201                     MainHandler.MSG_SHOW_ACCESSIBILITY_BUTTON_CHOOSER).sendToTarget();
1202         }
1203     }
1204 
notifyAccessibilityButtonVisibilityChangedLocked(boolean available)1205     private void notifyAccessibilityButtonVisibilityChangedLocked(boolean available) {
1206         final UserState state = getCurrentUserStateLocked();
1207         mIsAccessibilityButtonShown = available;
1208         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1209             final Service service = state.mBoundServices.get(i);
1210             if (service.mRequestAccessibilityButton) {
1211                 service.notifyAccessibilityButtonAvailabilityChangedLocked(
1212                         service.isAccessibilityButtonAvailableLocked(state));
1213             }
1214         }
1215     }
1216 
1217     /**
1218      * Removes an AccessibilityInteractionConnection.
1219      *
1220      * @param windowId The id of the window to which the connection is targeted.
1221      * @param userId The id of the user owning the connection. UserHandle.USER_ALL
1222      *     if global.
1223      */
removeAccessibilityInteractionConnectionLocked(int windowId, int userId)1224     private void removeAccessibilityInteractionConnectionLocked(int windowId, int userId) {
1225         if (userId == UserHandle.USER_ALL) {
1226             mGlobalWindowTokens.remove(windowId);
1227             mGlobalInteractionConnections.remove(windowId);
1228         } else {
1229             UserState userState = getCurrentUserStateLocked();
1230             userState.mWindowTokens.remove(windowId);
1231             userState.mInteractionConnections.remove(windowId);
1232         }
1233         if (DEBUG) {
1234             Slog.i(LOG_TAG, "Removing interaction connection to windowId: " + windowId);
1235         }
1236     }
1237 
readInstalledAccessibilityServiceLocked(UserState userState)1238     private boolean readInstalledAccessibilityServiceLocked(UserState userState) {
1239         mTempAccessibilityServiceInfoList.clear();
1240 
1241         List<ResolveInfo> installedServices = mPackageManager.queryIntentServicesAsUser(
1242                 new Intent(AccessibilityService.SERVICE_INTERFACE),
1243                 PackageManager.GET_SERVICES
1244                         | PackageManager.GET_META_DATA
1245                         | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
1246                         | PackageManager.MATCH_DIRECT_BOOT_AWARE
1247                         | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
1248                 mCurrentUserId);
1249 
1250         for (int i = 0, count = installedServices.size(); i < count; i++) {
1251             ResolveInfo resolveInfo = installedServices.get(i);
1252             ServiceInfo serviceInfo = resolveInfo.serviceInfo;
1253             if (!android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE.equals(
1254                     serviceInfo.permission)) {
1255                 Slog.w(LOG_TAG, "Skipping accessibilty service " + new ComponentName(
1256                         serviceInfo.packageName, serviceInfo.name).flattenToShortString()
1257                         + ": it does not require the permission "
1258                         + android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE);
1259                 continue;
1260             }
1261             AccessibilityServiceInfo accessibilityServiceInfo;
1262             try {
1263                 accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext);
1264                 mTempAccessibilityServiceInfoList.add(accessibilityServiceInfo);
1265             } catch (XmlPullParserException | IOException xppe) {
1266                 Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", xppe);
1267             }
1268         }
1269 
1270         if (!mTempAccessibilityServiceInfoList.equals(userState.mInstalledServices)) {
1271             userState.mInstalledServices.clear();
1272             userState.mInstalledServices.addAll(mTempAccessibilityServiceInfoList);
1273             mTempAccessibilityServiceInfoList.clear();
1274             return true;
1275         }
1276 
1277         mTempAccessibilityServiceInfoList.clear();
1278         return false;
1279     }
1280 
readEnabledAccessibilityServicesLocked(UserState userState)1281     private boolean readEnabledAccessibilityServicesLocked(UserState userState) {
1282         mTempComponentNameSet.clear();
1283         readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
1284                 userState.mUserId, mTempComponentNameSet);
1285         if (!mTempComponentNameSet.equals(userState.mEnabledServices)) {
1286             userState.mEnabledServices.clear();
1287             userState.mEnabledServices.addAll(mTempComponentNameSet);
1288             if (userState.mUiAutomationService != null) {
1289                 userState.mEnabledServices.add(sFakeAccessibilityServiceComponentName);
1290             }
1291             mTempComponentNameSet.clear();
1292             return true;
1293         }
1294         mTempComponentNameSet.clear();
1295         return false;
1296     }
1297 
readTouchExplorationGrantedAccessibilityServicesLocked( UserState userState)1298     private boolean readTouchExplorationGrantedAccessibilityServicesLocked(
1299             UserState userState) {
1300         mTempComponentNameSet.clear();
1301         readComponentNamesFromSettingLocked(
1302                 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
1303                 userState.mUserId, mTempComponentNameSet);
1304         if (!mTempComponentNameSet.equals(userState.mTouchExplorationGrantedServices)) {
1305             userState.mTouchExplorationGrantedServices.clear();
1306             userState.mTouchExplorationGrantedServices.addAll(mTempComponentNameSet);
1307             mTempComponentNameSet.clear();
1308             return true;
1309         }
1310         mTempComponentNameSet.clear();
1311         return false;
1312     }
1313 
1314     /**
1315      * Performs {@link AccessibilityService}s delayed notification. The delay is configurable
1316      * and denotes the period after the last event before notifying the service.
1317      *
1318      * @param event The event.
1319      * @param isDefault True to notify default listeners, not default services.
1320      */
notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event, boolean isDefault)1321     private void notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event,
1322             boolean isDefault) {
1323         try {
1324             UserState state = getCurrentUserStateLocked();
1325             for (int i = 0, count = state.mBoundServices.size(); i < count; i++) {
1326                 Service service = state.mBoundServices.get(i);
1327 
1328                 if (service.mIsDefault == isDefault) {
1329                     if (doesServiceWantEventLocked(service, event)) {
1330                         service.notifyAccessibilityEvent(event, true);
1331                     } else if (service.mUsesAccessibilityCache
1332                             && (AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK
1333                                 & event.getEventType()) != 0) {
1334                         service.notifyAccessibilityEvent(event, false);
1335                     }
1336                 }
1337             }
1338         } catch (IndexOutOfBoundsException oobe) {
1339             // An out of bounds exception can happen if services are going away
1340             // as the for loop is running. If that happens, just bail because
1341             // there are no more services to notify.
1342         }
1343     }
1344 
addServiceLocked(Service service, UserState userState)1345     private void addServiceLocked(Service service, UserState userState) {
1346         try {
1347             if (!userState.mBoundServices.contains(service)) {
1348                 service.onAdded();
1349                 userState.mBoundServices.add(service);
1350                 userState.mComponentNameToServiceMap.put(service.mComponentName, service);
1351                 scheduleNotifyClientsOfServicesStateChange(userState);
1352             }
1353         } catch (RemoteException re) {
1354             /* do nothing */
1355         }
1356     }
1357 
1358     /**
1359      * Removes a service.
1360      *
1361      * @param service The service.
1362      */
removeServiceLocked(Service service, UserState userState)1363     private void removeServiceLocked(Service service, UserState userState) {
1364         userState.mBoundServices.remove(service);
1365         service.onRemoved();
1366         // It may be possible to bind a service twice, which confuses the map. Rebuild the map
1367         // to make sure we can still reach a service
1368         userState.mComponentNameToServiceMap.clear();
1369         for (int i = 0; i < userState.mBoundServices.size(); i++) {
1370             Service boundService = userState.mBoundServices.get(i);
1371             userState.mComponentNameToServiceMap.put(boundService.mComponentName, boundService);
1372         }
1373         scheduleNotifyClientsOfServicesStateChange(userState);
1374     }
1375 
updateRelevantEventsLocked(UserState userState)1376     private void updateRelevantEventsLocked(UserState userState) {
1377         int relevantEventTypes = AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK;
1378         for (Service service : userState.mBoundServices) {
1379             relevantEventTypes |= service.mEventTypes;
1380         }
1381         int finalRelevantEventTypes = relevantEventTypes;
1382 
1383         if (userState.mLastSentRelevantEventTypes != finalRelevantEventTypes) {
1384             userState.mLastSentRelevantEventTypes = finalRelevantEventTypes;
1385             mMainHandler.obtainMessage(MainHandler.MSG_SEND_RELEVANT_EVENTS_CHANGED_TO_CLIENTS,
1386                     userState.mUserId, finalRelevantEventTypes);
1387             mMainHandler.post(() -> {
1388                 broadcastToClients(userState, (client) -> {
1389                     try {
1390                         client.setRelevantEventTypes(finalRelevantEventTypes);
1391                     } catch (RemoteException re) {
1392                         /* ignore */
1393                     }
1394                 });
1395             });
1396         }
1397     }
1398 
broadcastToClients( UserState userState, Consumer<IAccessibilityManagerClient> clientAction)1399     private void broadcastToClients(
1400             UserState userState, Consumer<IAccessibilityManagerClient> clientAction) {
1401         mGlobalClients.broadcast(clientAction);
1402         userState.mUserClients.broadcast(clientAction);
1403     }
1404 
1405     /**
1406      * Determines if given event can be dispatched to a service based on the package of the
1407      * event source. Specifically, a service is notified if it is interested in events from the
1408      * package.
1409      *
1410      * @param service The potential receiver.
1411      * @param event The event.
1412      * @return True if the listener should be notified, false otherwise.
1413      */
doesServiceWantEventLocked(Service service, AccessibilityEvent event)1414     private boolean doesServiceWantEventLocked(Service service, AccessibilityEvent event) {
1415 
1416         if (!service.canReceiveEventsLocked()) {
1417             return false;
1418         }
1419 
1420         if ((event.getWindowId() != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)
1421                 && !event.isImportantForAccessibility()
1422                 && (service.mFetchFlags & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS)
1423                         == 0) {
1424             return false;
1425         }
1426 
1427         int eventType = event.getEventType();
1428         if ((service.mEventTypes & eventType) != eventType) {
1429             return false;
1430         }
1431 
1432         Set<String> packageNames = service.mPackageNames;
1433         String packageName = (event.getPackageName() != null)
1434                 ? event.getPackageName().toString() : null;
1435 
1436         return (packageNames.isEmpty() || packageNames.contains(packageName));
1437     }
1438 
unbindAllServicesLocked(UserState userState)1439     private void unbindAllServicesLocked(UserState userState) {
1440         List<Service> services = userState.mBoundServices;
1441         for (int i = 0, count = services.size(); i < count; i++) {
1442             Service service = services.get(i);
1443             if (service.unbindLocked()) {
1444                 i--;
1445                 count--;
1446             }
1447         }
1448     }
1449 
1450     /**
1451      * Populates a set with the {@link ComponentName}s stored in a colon
1452      * separated value setting for a given user.
1453      *
1454      * @param settingName The setting to parse.
1455      * @param userId The user id.
1456      * @param outComponentNames The output component names.
1457      */
readComponentNamesFromSettingLocked(String settingName, int userId, Set<ComponentName> outComponentNames)1458     private void readComponentNamesFromSettingLocked(String settingName, int userId,
1459             Set<ComponentName> outComponentNames) {
1460         String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(),
1461                 settingName, userId);
1462         readComponentNamesFromStringLocked(settingValue, outComponentNames, false);
1463     }
1464 
1465     /**
1466      * Populates a set with the {@link ComponentName}s contained in a colon-delimited string.
1467      *
1468      * @param names The colon-delimited string to parse.
1469      * @param outComponentNames The set of component names to be populated based on
1470      *    the contents of the <code>names</code> string.
1471      * @param doMerge If true, the parsed component names will be merged into the output
1472      *    set, rather than replacing the set's existing contents entirely.
1473      */
readComponentNamesFromStringLocked(String names, Set<ComponentName> outComponentNames, boolean doMerge)1474     private void readComponentNamesFromStringLocked(String names,
1475             Set<ComponentName> outComponentNames,
1476             boolean doMerge) {
1477         if (!doMerge) {
1478             outComponentNames.clear();
1479         }
1480         if (names != null) {
1481             TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
1482             splitter.setString(names);
1483             while (splitter.hasNext()) {
1484                 String str = splitter.next();
1485                 if (str == null || str.length() <= 0) {
1486                     continue;
1487                 }
1488                 ComponentName enabledService = ComponentName.unflattenFromString(str);
1489                 if (enabledService != null) {
1490                     outComponentNames.add(enabledService);
1491                 }
1492             }
1493         }
1494     }
1495 
1496     /**
1497      * Persists the component names in the specified setting in a
1498      * colon separated fashion.
1499      *
1500      * @param settingName The setting name.
1501      * @param componentNames The component names.
1502      */
persistComponentNamesToSettingLocked(String settingName, Set<ComponentName> componentNames, int userId)1503     private void persistComponentNamesToSettingLocked(String settingName,
1504             Set<ComponentName> componentNames, int userId) {
1505         StringBuilder builder = new StringBuilder();
1506         for (ComponentName componentName : componentNames) {
1507             if (builder.length() > 0) {
1508                 builder.append(COMPONENT_NAME_SEPARATOR);
1509             }
1510             builder.append(componentName.flattenToShortString());
1511         }
1512         final long identity = Binder.clearCallingIdentity();
1513         try {
1514             Settings.Secure.putStringForUser(mContext.getContentResolver(),
1515                     settingName, builder.toString(), userId);
1516         } finally {
1517             Binder.restoreCallingIdentity(identity);
1518         }
1519     }
1520 
updateServicesLocked(UserState userState)1521     private void updateServicesLocked(UserState userState) {
1522         Map<ComponentName, Service> componentNameToServiceMap =
1523                 userState.mComponentNameToServiceMap;
1524         boolean isUnlockingOrUnlocked = LocalServices.getService(UserManagerInternal.class)
1525                     .isUserUnlockingOrUnlocked(userState.mUserId);
1526 
1527         for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) {
1528             AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i);
1529             ComponentName componentName = ComponentName.unflattenFromString(
1530                     installedService.getId());
1531 
1532             Service service = componentNameToServiceMap.get(componentName);
1533 
1534             // Ignore non-encryption-aware services until user is unlocked
1535             if (!isUnlockingOrUnlocked && !installedService.isDirectBootAware()) {
1536                 Slog.d(LOG_TAG, "Ignoring non-encryption-aware service " + componentName);
1537                 continue;
1538             }
1539 
1540             // Wait for the binding if it is in process.
1541             if (userState.mBindingServices.contains(componentName)) {
1542                 continue;
1543             }
1544             if (userState.mEnabledServices.contains(componentName)) {
1545                 if (service == null) {
1546                     service = new Service(userState.mUserId, componentName, installedService);
1547                 } else if (userState.mBoundServices.contains(service)) {
1548                     continue;
1549                 }
1550                 service.bindLocked();
1551             } else {
1552                 if (service != null) {
1553                     service.unbindLocked();
1554                 }
1555             }
1556         }
1557 
1558         final int count = userState.mBoundServices.size();
1559         mTempIntArray.clear();
1560         for (int i = 0; i < count; i++) {
1561             final ResolveInfo resolveInfo =
1562                     userState.mBoundServices.get(i).mAccessibilityServiceInfo.getResolveInfo();
1563             if (resolveInfo != null) {
1564                 mTempIntArray.add(resolveInfo.serviceInfo.applicationInfo.uid);
1565             }
1566         }
1567         // Calling out with lock held, but to a lower-level service
1568         final AudioManagerInternal audioManager =
1569                 LocalServices.getService(AudioManagerInternal.class);
1570         if (audioManager != null) {
1571             audioManager.setAccessibilityServiceUids(mTempIntArray);
1572         }
1573         updateAccessibilityEnabledSetting(userState);
1574     }
1575 
scheduleUpdateClientsIfNeededLocked(UserState userState)1576     private void scheduleUpdateClientsIfNeededLocked(UserState userState) {
1577         final int clientState = userState.getClientState();
1578         if (userState.mLastSentClientState != clientState
1579                 && (mGlobalClients.getRegisteredCallbackCount() > 0
1580                         || userState.mUserClients.getRegisteredCallbackCount() > 0)) {
1581             userState.mLastSentClientState = clientState;
1582             mMainHandler.obtainMessage(MainHandler.MSG_SEND_STATE_TO_CLIENTS,
1583                     clientState, userState.mUserId).sendToTarget();
1584         }
1585     }
1586 
showAccessibilityButtonTargetSelection()1587     private void showAccessibilityButtonTargetSelection() {
1588         Intent intent = new Intent(AccessibilityManager.ACTION_CHOOSE_ACCESSIBILITY_BUTTON);
1589         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1590         mContext.startActivityAsUser(intent, UserHandle.of(mCurrentUserId));
1591     }
1592 
scheduleNotifyClientsOfServicesStateChange(UserState userState)1593     private void scheduleNotifyClientsOfServicesStateChange(UserState userState) {
1594         mMainHandler.obtainMessage(MainHandler.MSG_SEND_SERVICES_STATE_CHANGED_TO_CLIENTS,
1595                 userState.mUserId).sendToTarget();
1596     }
1597 
scheduleUpdateInputFilter(UserState userState)1598     private void scheduleUpdateInputFilter(UserState userState) {
1599         mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_INPUT_FILTER, userState).sendToTarget();
1600     }
1601 
scheduleUpdateFingerprintGestureHandling(UserState userState)1602     private void scheduleUpdateFingerprintGestureHandling(UserState userState) {
1603         mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_FINGERPRINT, userState).sendToTarget();
1604     }
1605 
updateInputFilter(UserState userState)1606     private void updateInputFilter(UserState userState) {
1607         boolean setInputFilter = false;
1608         AccessibilityInputFilter inputFilter = null;
1609         synchronized (mLock) {
1610             int flags = 0;
1611             if (userState.mIsDisplayMagnificationEnabled) {
1612                 flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER;
1613             }
1614             if (userState.mIsNavBarMagnificationEnabled) {
1615                 flags |= AccessibilityInputFilter.FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER;
1616             }
1617             if (userHasMagnificationServicesLocked(userState)) {
1618                 flags |= AccessibilityInputFilter.FLAG_FEATURE_CONTROL_SCREEN_MAGNIFIER;
1619             }
1620             // Touch exploration without accessibility makes no sense.
1621             if (userState.isHandlingAccessibilityEvents()
1622                     && userState.mIsTouchExplorationEnabled) {
1623                 flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION;
1624             }
1625             if (userState.mIsFilterKeyEventsEnabled) {
1626                 flags |= AccessibilityInputFilter.FLAG_FEATURE_FILTER_KEY_EVENTS;
1627             }
1628             if (userState.mIsAutoclickEnabled) {
1629                 flags |= AccessibilityInputFilter.FLAG_FEATURE_AUTOCLICK;
1630             }
1631             if (userState.mIsPerformGesturesEnabled) {
1632                 flags |= AccessibilityInputFilter.FLAG_FEATURE_INJECT_MOTION_EVENTS;
1633             }
1634             if (flags != 0) {
1635                 if (!mHasInputFilter) {
1636                     mHasInputFilter = true;
1637                     if (mInputFilter == null) {
1638                         mInputFilter = new AccessibilityInputFilter(mContext,
1639                                 AccessibilityManagerService.this);
1640                     }
1641                     inputFilter = mInputFilter;
1642                     setInputFilter = true;
1643                 }
1644                 mInputFilter.setUserAndEnabledFeatures(userState.mUserId, flags);
1645             } else {
1646                 if (mHasInputFilter) {
1647                     mHasInputFilter = false;
1648                     mInputFilter.setUserAndEnabledFeatures(userState.mUserId, 0);
1649                     inputFilter = null;
1650                     setInputFilter = true;
1651                 }
1652             }
1653         }
1654         if (setInputFilter) {
1655             mWindowManagerService.setInputFilter(inputFilter);
1656         }
1657     }
1658 
showEnableTouchExplorationDialog(final Service service)1659     private void showEnableTouchExplorationDialog(final Service service) {
1660         synchronized (mLock) {
1661             String label = service.mResolveInfo.loadLabel(
1662             mContext.getPackageManager()).toString();
1663 
1664             final UserState state = getCurrentUserStateLocked();
1665             if (state.mIsTouchExplorationEnabled) {
1666                 return;
1667             }
1668             if (mEnableTouchExplorationDialog != null
1669                     && mEnableTouchExplorationDialog.isShowing()) {
1670                 return;
1671             }
1672             mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext)
1673                 .setIconAttribute(android.R.attr.alertDialogIcon)
1674                 .setPositiveButton(android.R.string.ok, new OnClickListener() {
1675                      @Override
1676                      public void onClick(DialogInterface dialog, int which) {
1677                          // The user allowed the service to toggle touch exploration.
1678                          state.mTouchExplorationGrantedServices.add(service.mComponentName);
1679                          persistComponentNamesToSettingLocked(
1680                                  Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
1681                                  state.mTouchExplorationGrantedServices, state.mUserId);
1682                          // Enable touch exploration.
1683                          UserState userState = getUserStateLocked(service.mUserId);
1684                          userState.mIsTouchExplorationEnabled = true;
1685                          final long identity = Binder.clearCallingIdentity();
1686                          try {
1687                              Settings.Secure.putIntForUser(mContext.getContentResolver(),
1688                                      Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1,
1689                                      service.mUserId);
1690                          } finally {
1691                              Binder.restoreCallingIdentity(identity);
1692                          }
1693                          onUserStateChangedLocked(userState);
1694                      }
1695                  })
1696                  .setNegativeButton(android.R.string.cancel, new OnClickListener() {
1697                      @Override
1698                      public void onClick(DialogInterface dialog, int which) {
1699                          dialog.dismiss();
1700                      }
1701                  })
1702                  .setTitle(R.string.enable_explore_by_touch_warning_title)
1703                  .setMessage(mContext.getString(
1704                          R.string.enable_explore_by_touch_warning_message, label))
1705                  .create();
1706              mEnableTouchExplorationDialog.getWindow().setType(
1707                      WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
1708              mEnableTouchExplorationDialog.getWindow().getAttributes().privateFlags
1709                      |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
1710              mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true);
1711              mEnableTouchExplorationDialog.show();
1712         }
1713     }
1714 
1715     /**
1716      * Called when any property of the user state has changed.
1717      *
1718      * @param userState the new user state
1719      */
onUserStateChangedLocked(UserState userState)1720     private void onUserStateChangedLocked(UserState userState) {
1721         // TODO: Remove this hack
1722         mInitialized = true;
1723         updateLegacyCapabilitiesLocked(userState);
1724         updateServicesLocked(userState);
1725         updateAccessibilityShortcutLocked(userState);
1726         updateWindowsForAccessibilityCallbackLocked(userState);
1727         updateAccessibilityFocusBehaviorLocked(userState);
1728         updateFilterKeyEventsLocked(userState);
1729         updateTouchExplorationLocked(userState);
1730         updatePerformGesturesLocked(userState);
1731         updateDisplayDaltonizerLocked(userState);
1732         updateDisplayInversionLocked(userState);
1733         updateMagnificationLocked(userState);
1734         updateSoftKeyboardShowModeLocked(userState);
1735         scheduleUpdateFingerprintGestureHandling(userState);
1736         scheduleUpdateInputFilter(userState);
1737         scheduleUpdateClientsIfNeededLocked(userState);
1738         updateRelevantEventsLocked(userState);
1739         updateAccessibilityButtonTargetsLocked(userState);
1740     }
1741 
updateAccessibilityFocusBehaviorLocked(UserState userState)1742     private void updateAccessibilityFocusBehaviorLocked(UserState userState) {
1743         // If there is no service that can operate with interactive windows
1744         // then we keep the old behavior where a window loses accessibility
1745         // focus if it is no longer active. This still changes the behavior
1746         // for services that do not operate with interactive windows and run
1747         // at the same time as the one(s) which does. In practice however,
1748         // there is only one service that uses accessibility focus and it
1749         // is typically the one that operates with interactive windows, So,
1750         // this is fine. Note that to allow a service to work across windows
1751         // we have to allow accessibility focus stay in any of them. Sigh...
1752         List<Service> boundServices = userState.mBoundServices;
1753         final int boundServiceCount = boundServices.size();
1754         for (int i = 0; i < boundServiceCount; i++) {
1755             Service boundService = boundServices.get(i);
1756             if (boundService.canRetrieveInteractiveWindowsLocked()) {
1757                 userState.mAccessibilityFocusOnlyInActiveWindow = false;
1758                 return;
1759             }
1760         }
1761         userState.mAccessibilityFocusOnlyInActiveWindow = true;
1762     }
1763 
updateWindowsForAccessibilityCallbackLocked(UserState userState)1764     private void updateWindowsForAccessibilityCallbackLocked(UserState userState) {
1765         // We observe windows for accessibility only if there is at least
1766         // one bound service that can retrieve window content that specified
1767         // it is interested in accessing such windows. For services that are
1768         // binding we do an update pass after each bind event, so we run this
1769         // code and register the callback if needed.
1770 
1771         List<Service> boundServices = userState.mBoundServices;
1772         final int boundServiceCount = boundServices.size();
1773         for (int i = 0; i < boundServiceCount; i++) {
1774             Service boundService = boundServices.get(i);
1775             if (boundService.canRetrieveInteractiveWindowsLocked()) {
1776                 if (mWindowsForAccessibilityCallback == null) {
1777                     mWindowsForAccessibilityCallback = new WindowsForAccessibilityCallback();
1778                     mWindowManagerService.setWindowsForAccessibilityCallback(
1779                             mWindowsForAccessibilityCallback);
1780                 }
1781                 return;
1782             }
1783         }
1784 
1785         if (mWindowsForAccessibilityCallback != null) {
1786             mWindowsForAccessibilityCallback = null;
1787             mWindowManagerService.setWindowsForAccessibilityCallback(null);
1788             // Drop all windows we know about.
1789             mSecurityPolicy.clearWindowsLocked();
1790         }
1791     }
1792 
updateLegacyCapabilitiesLocked(UserState userState)1793     private void updateLegacyCapabilitiesLocked(UserState userState) {
1794         // Up to JB-MR1 we had a white list with services that can enable touch
1795         // exploration. When a service is first started we show a dialog to the
1796         // use to get a permission to white list the service.
1797         final int installedServiceCount = userState.mInstalledServices.size();
1798         for (int i = 0; i < installedServiceCount; i++) {
1799             AccessibilityServiceInfo serviceInfo = userState.mInstalledServices.get(i);
1800             ResolveInfo resolveInfo = serviceInfo.getResolveInfo();
1801             if ((serviceInfo.getCapabilities()
1802                         & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) == 0
1803                     && resolveInfo.serviceInfo.applicationInfo.targetSdkVersion
1804                         <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
1805                 ComponentName componentName = new ComponentName(
1806                         resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
1807                 if (userState.mTouchExplorationGrantedServices.contains(componentName)) {
1808                     serviceInfo.setCapabilities(serviceInfo.getCapabilities()
1809                             | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION);
1810                 }
1811             }
1812         }
1813     }
1814 
updatePerformGesturesLocked(UserState userState)1815     private void updatePerformGesturesLocked(UserState userState) {
1816         final int serviceCount = userState.mBoundServices.size();
1817         for (int i = 0; i < serviceCount; i++) {
1818             Service service = userState.mBoundServices.get(i);
1819             if ((service.mAccessibilityServiceInfo.getCapabilities()
1820                     & AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0) {
1821                 userState.mIsPerformGesturesEnabled = true;
1822                 return;
1823             }
1824         }
1825         userState.mIsPerformGesturesEnabled = false;
1826     }
1827 
updateFilterKeyEventsLocked(UserState userState)1828     private void updateFilterKeyEventsLocked(UserState userState) {
1829         final int serviceCount = userState.mBoundServices.size();
1830         for (int i = 0; i < serviceCount; i++) {
1831             Service service = userState.mBoundServices.get(i);
1832             if (service.mRequestFilterKeyEvents
1833                     && (service.mAccessibilityServiceInfo.getCapabilities()
1834                             & AccessibilityServiceInfo
1835                             .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) != 0) {
1836                 userState.mIsFilterKeyEventsEnabled = true;
1837                 return;
1838             }
1839         }
1840         userState.mIsFilterKeyEventsEnabled = false;
1841     }
1842 
readConfigurationForUserStateLocked(UserState userState)1843     private boolean readConfigurationForUserStateLocked(UserState userState) {
1844         boolean somethingChanged = readInstalledAccessibilityServiceLocked(userState);
1845         somethingChanged |= readEnabledAccessibilityServicesLocked(userState);
1846         somethingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState);
1847         somethingChanged |= readTouchExplorationEnabledSettingLocked(userState);
1848         somethingChanged |= readHighTextContrastEnabledSettingLocked(userState);
1849         somethingChanged |= readMagnificationEnabledSettingsLocked(userState);
1850         somethingChanged |= readAutoclickEnabledSettingLocked(userState);
1851         somethingChanged |= readAccessibilityShortcutSettingLocked(userState);
1852         somethingChanged |= readAccessibilityButtonSettingsLocked(userState);
1853         return somethingChanged;
1854     }
1855 
updateAccessibilityEnabledSetting(UserState userState)1856     private void updateAccessibilityEnabledSetting(UserState userState) {
1857         final long identity = Binder.clearCallingIdentity();
1858         try {
1859             Settings.Secure.putIntForUser(mContext.getContentResolver(),
1860                     Settings.Secure.ACCESSIBILITY_ENABLED,
1861                     userState.isHandlingAccessibilityEvents() ? 1 : 0,
1862                     userState.mUserId);
1863         } finally {
1864             Binder.restoreCallingIdentity(identity);
1865         }
1866     }
1867 
readTouchExplorationEnabledSettingLocked(UserState userState)1868     private boolean readTouchExplorationEnabledSettingLocked(UserState userState) {
1869         final boolean touchExplorationEnabled = Settings.Secure.getIntForUser(
1870                 mContext.getContentResolver(),
1871                 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId) == 1;
1872         if (touchExplorationEnabled != userState.mIsTouchExplorationEnabled) {
1873             userState.mIsTouchExplorationEnabled = touchExplorationEnabled;
1874             return true;
1875         }
1876         return false;
1877     }
1878 
readMagnificationEnabledSettingsLocked(UserState userState)1879     private boolean readMagnificationEnabledSettingsLocked(UserState userState) {
1880         final boolean displayMagnificationEnabled = Settings.Secure.getIntForUser(
1881                 mContext.getContentResolver(),
1882                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
1883                 0, userState.mUserId) == 1;
1884         final boolean navBarMagnificationEnabled = Settings.Secure.getIntForUser(
1885                 mContext.getContentResolver(),
1886                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED,
1887                 0, userState.mUserId) == 1;
1888         if ((displayMagnificationEnabled != userState.mIsDisplayMagnificationEnabled)
1889                 || (navBarMagnificationEnabled != userState.mIsNavBarMagnificationEnabled)) {
1890             userState.mIsDisplayMagnificationEnabled = displayMagnificationEnabled;
1891             userState.mIsNavBarMagnificationEnabled = navBarMagnificationEnabled;
1892             return true;
1893         }
1894         return false;
1895     }
1896 
readAutoclickEnabledSettingLocked(UserState userState)1897     private boolean readAutoclickEnabledSettingLocked(UserState userState) {
1898         final boolean autoclickEnabled = Settings.Secure.getIntForUser(
1899                 mContext.getContentResolver(),
1900                 Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED,
1901                 0, userState.mUserId) == 1;
1902         if (autoclickEnabled != userState.mIsAutoclickEnabled) {
1903             userState.mIsAutoclickEnabled = autoclickEnabled;
1904             return true;
1905         }
1906         return false;
1907     }
1908 
readHighTextContrastEnabledSettingLocked(UserState userState)1909     private boolean readHighTextContrastEnabledSettingLocked(UserState userState) {
1910         final boolean highTextContrastEnabled = Settings.Secure.getIntForUser(
1911                 mContext.getContentResolver(),
1912                 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 0,
1913                 userState.mUserId) == 1;
1914         if (highTextContrastEnabled != userState.mIsTextHighContrastEnabled) {
1915             userState.mIsTextHighContrastEnabled = highTextContrastEnabled;
1916             return true;
1917         }
1918         return false;
1919     }
1920 
readSoftKeyboardShowModeChangedLocked(UserState userState)1921     private boolean readSoftKeyboardShowModeChangedLocked(UserState userState) {
1922         final int softKeyboardShowMode = Settings.Secure.getIntForUser(
1923                 mContext.getContentResolver(),
1924                 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0,
1925                 userState.mUserId);
1926         if (softKeyboardShowMode != userState.mSoftKeyboardShowMode) {
1927             userState.mSoftKeyboardShowMode = softKeyboardShowMode;
1928             return true;
1929         }
1930         return false;
1931     }
1932 
updateTouchExplorationLocked(UserState userState)1933     private void updateTouchExplorationLocked(UserState userState) {
1934         boolean enabled = false;
1935         final int serviceCount = userState.mBoundServices.size();
1936         for (int i = 0; i < serviceCount; i++) {
1937             Service service = userState.mBoundServices.get(i);
1938             if (canRequestAndRequestsTouchExplorationLocked(service)) {
1939                 enabled = true;
1940                 break;
1941             }
1942         }
1943         if (enabled != userState.mIsTouchExplorationEnabled) {
1944             userState.mIsTouchExplorationEnabled = enabled;
1945             final long identity = Binder.clearCallingIdentity();
1946             try {
1947                 Settings.Secure.putIntForUser(mContext.getContentResolver(),
1948                         Settings.Secure.TOUCH_EXPLORATION_ENABLED, enabled ? 1 : 0,
1949                         userState.mUserId);
1950             } finally {
1951                 Binder.restoreCallingIdentity(identity);
1952             }
1953         }
1954     }
1955 
readAccessibilityShortcutSettingLocked(UserState userState)1956     private boolean readAccessibilityShortcutSettingLocked(UserState userState) {
1957         String componentNameToEnableString = AccessibilityShortcutController
1958                 .getTargetServiceComponentNameString(mContext, userState.mUserId);
1959         if ((componentNameToEnableString == null) || componentNameToEnableString.isEmpty()) {
1960             if (userState.mServiceToEnableWithShortcut == null) {
1961                 return false;
1962             }
1963             userState.mServiceToEnableWithShortcut = null;
1964             return true;
1965         }
1966         ComponentName componentNameToEnable =
1967             ComponentName.unflattenFromString(componentNameToEnableString);
1968         if ((componentNameToEnable != null)
1969                 && componentNameToEnable.equals(userState.mServiceToEnableWithShortcut)) {
1970             return false;
1971         }
1972         userState.mServiceToEnableWithShortcut = componentNameToEnable;
1973         return true;
1974     }
1975 
readAccessibilityButtonSettingsLocked(UserState userState)1976     private boolean readAccessibilityButtonSettingsLocked(UserState userState) {
1977         String componentId = Settings.Secure.getStringForUser(mContext.getContentResolver(),
1978                 Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, userState.mUserId);
1979         if (TextUtils.isEmpty(componentId)) {
1980             if ((userState.mServiceAssignedToAccessibilityButton == null)
1981                     && !userState.mIsNavBarMagnificationAssignedToAccessibilityButton) {
1982                 return false;
1983             }
1984             userState.mServiceAssignedToAccessibilityButton = null;
1985             userState.mIsNavBarMagnificationAssignedToAccessibilityButton = false;
1986             return true;
1987         }
1988 
1989         if (componentId.equals(MagnificationController.class.getName())) {
1990             if (userState.mIsNavBarMagnificationAssignedToAccessibilityButton) {
1991                 return false;
1992             }
1993             userState.mServiceAssignedToAccessibilityButton = null;
1994             userState.mIsNavBarMagnificationAssignedToAccessibilityButton = true;
1995             return true;
1996         }
1997 
1998         ComponentName componentName = ComponentName.unflattenFromString(componentId);
1999         if (componentName.equals(userState.mServiceAssignedToAccessibilityButton)) {
2000             return false;
2001         }
2002         userState.mServiceAssignedToAccessibilityButton = componentName;
2003         userState.mIsNavBarMagnificationAssignedToAccessibilityButton = false;
2004         return true;
2005     }
2006 
2007     /**
2008      * Check if the service that will be enabled by the shortcut is installed. If it isn't,
2009      * clear the value and the associated setting so a sideloaded service can't spoof the
2010      * package name of the default service.
2011      *
2012      * @param userState
2013      */
updateAccessibilityShortcutLocked(UserState userState)2014     private void updateAccessibilityShortcutLocked(UserState userState) {
2015         if (userState.mServiceToEnableWithShortcut == null) {
2016             return;
2017         }
2018         boolean shortcutServiceIsInstalled = false;
2019         for (int i = 0; i < userState.mInstalledServices.size(); i++) {
2020             if (userState.mInstalledServices.get(i).getComponentName()
2021                     .equals(userState.mServiceToEnableWithShortcut)) {
2022                 shortcutServiceIsInstalled = true;
2023             }
2024         }
2025         if (!shortcutServiceIsInstalled) {
2026             userState.mServiceToEnableWithShortcut = null;
2027             final long identity = Binder.clearCallingIdentity();
2028             try {
2029                 Settings.Secure.putStringForUser(mContext.getContentResolver(),
2030                         Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, null, userState.mUserId);
2031 
2032                 Settings.Secure.putIntForUser(mContext.getContentResolver(),
2033                         Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 0, userState.mUserId);
2034             } finally {
2035                 Binder.restoreCallingIdentity(identity);
2036             }
2037         }
2038     }
2039 
canRequestAndRequestsTouchExplorationLocked(Service service)2040     private boolean canRequestAndRequestsTouchExplorationLocked(Service service) {
2041         // Service not ready or cannot request the feature - well nothing to do.
2042         if (!service.canReceiveEventsLocked() || !service.mRequestTouchExplorationMode) {
2043             return false;
2044         }
2045         // UI test automation service can always enable it.
2046         if (service.mIsAutomation) {
2047             return true;
2048         }
2049         if (service.mResolveInfo.serviceInfo.applicationInfo.targetSdkVersion
2050                 <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
2051             // Up to JB-MR1 we had a white list with services that can enable touch
2052             // exploration. When a service is first started we show a dialog to the
2053             // use to get a permission to white list the service.
2054             UserState userState = getUserStateLocked(service.mUserId);
2055             if (userState.mTouchExplorationGrantedServices.contains(service.mComponentName)) {
2056                 return true;
2057             } else if (mEnableTouchExplorationDialog == null
2058                     || !mEnableTouchExplorationDialog.isShowing()) {
2059                 mMainHandler.obtainMessage(
2060                         MainHandler.MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG,
2061                         service).sendToTarget();
2062             }
2063         } else {
2064             // Starting in JB-MR2 we request an accessibility service to declare
2065             // certain capabilities in its meta-data to allow it to enable the
2066             // corresponding features.
2067             if ((service.mAccessibilityServiceInfo.getCapabilities()
2068                     & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) != 0) {
2069                 return true;
2070             }
2071         }
2072         return false;
2073     }
2074 
updateDisplayDaltonizerLocked(UserState userState)2075     private void updateDisplayDaltonizerLocked(UserState userState) {
2076         DisplayAdjustmentUtils.applyDaltonizerSetting(mContext, userState.mUserId);
2077     }
2078 
updateDisplayInversionLocked(UserState userState)2079     private void updateDisplayInversionLocked(UserState userState) {
2080         DisplayAdjustmentUtils.applyInversionSetting(mContext, userState.mUserId);
2081     }
2082 
updateMagnificationLocked(UserState userState)2083     private void updateMagnificationLocked(UserState userState) {
2084         if (userState.mUserId != mCurrentUserId) {
2085             return;
2086         }
2087 
2088         if (userState.mIsDisplayMagnificationEnabled || userState.mIsNavBarMagnificationEnabled
2089                 || userHasListeningMagnificationServicesLocked(userState)) {
2090             // Initialize the magnification controller if necessary
2091             getMagnificationController();
2092             mMagnificationController.register();
2093         } else if (mMagnificationController != null) {
2094             mMagnificationController.unregister();
2095         }
2096     }
2097 
2098     /**
2099      * Returns whether the specified user has any services that are capable of
2100      * controlling magnification.
2101      */
userHasMagnificationServicesLocked(UserState userState)2102     private boolean userHasMagnificationServicesLocked(UserState userState) {
2103         final List<Service> services = userState.mBoundServices;
2104         for (int i = 0, count = services.size(); i < count; i++) {
2105             final Service service = services.get(i);
2106             if (mSecurityPolicy.canControlMagnification(service)) {
2107                 return true;
2108             }
2109         }
2110         return false;
2111     }
2112 
2113     /**
2114      * Returns whether the specified user has any services that are capable of
2115      * controlling magnification and are actively listening for magnification updates.
2116      */
userHasListeningMagnificationServicesLocked(UserState userState)2117     private boolean userHasListeningMagnificationServicesLocked(UserState userState) {
2118         final List<Service> services = userState.mBoundServices;
2119         for (int i = 0, count = services.size(); i < count; i++) {
2120             final Service service = services.get(i);
2121             if (mSecurityPolicy.canControlMagnification(service)
2122                     && service.mInvocationHandler.mIsMagnificationCallbackEnabled) {
2123                 return true;
2124             }
2125         }
2126         return false;
2127     }
2128 
updateSoftKeyboardShowModeLocked(UserState userState)2129     private void updateSoftKeyboardShowModeLocked(UserState userState) {
2130         final int userId = userState.mUserId;
2131         // Only check whether we need to reset the soft keyboard mode if it is not set to the
2132         // default.
2133         if ((userId == mCurrentUserId) && (userState.mSoftKeyboardShowMode != 0)) {
2134             // Check whether the last Accessibility Service that changed the soft keyboard mode to
2135             // something other than the default is still enabled and, if not, remove flag and
2136             // reset to the default soft keyboard behavior.
2137             boolean serviceChangingSoftKeyboardModeIsEnabled =
2138                     userState.mEnabledServices.contains(userState.mServiceChangingSoftKeyboardMode);
2139 
2140             if (!serviceChangingSoftKeyboardModeIsEnabled) {
2141                 final long identity = Binder.clearCallingIdentity();
2142                 try {
2143                     Settings.Secure.putIntForUser(mContext.getContentResolver(),
2144                             Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
2145                             0,
2146                             userState.mUserId);
2147                 } finally {
2148                     Binder.restoreCallingIdentity(identity);
2149                 }
2150                 userState.mSoftKeyboardShowMode = 0;
2151                 userState.mServiceChangingSoftKeyboardMode = null;
2152                 notifySoftKeyboardShowModeChangedLocked(userState.mSoftKeyboardShowMode);
2153             }
2154         }
2155     }
2156 
updateFingerprintGestureHandling(UserState userState)2157     private void updateFingerprintGestureHandling(UserState userState) {
2158         final List<Service> services;
2159         synchronized (mLock) {
2160             services = userState.mBoundServices;
2161             if ((mFingerprintGestureDispatcher == null)
2162                     &&  mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
2163                 // Only create the controller when a service wants to use the feature
2164                 int numServices = services.size();
2165                 for (int i = 0; i < numServices; i++) {
2166                     if (services.get(i).isCapturingFingerprintGestures()) {
2167                         final long identity = Binder.clearCallingIdentity();
2168                         IFingerprintService service = null;
2169                         try {
2170                             service = IFingerprintService.Stub.asInterface(
2171                                     ServiceManager.getService(Context.FINGERPRINT_SERVICE));
2172                         } finally {
2173                             Binder.restoreCallingIdentity(identity);
2174                         }
2175                         if (service != null) {
2176                             mFingerprintGestureDispatcher = new FingerprintGestureDispatcher(
2177                                     service, mLock);
2178                             break;
2179                         }
2180                     }
2181                 }
2182             }
2183         }
2184         if (mFingerprintGestureDispatcher != null) {
2185             mFingerprintGestureDispatcher.updateClientList(services);
2186         }
2187     }
2188 
updateAccessibilityButtonTargetsLocked(UserState userState)2189     private void updateAccessibilityButtonTargetsLocked(UserState userState) {
2190         for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
2191             final Service service = userState.mBoundServices.get(i);
2192             if (service.mRequestAccessibilityButton) {
2193                 service.notifyAccessibilityButtonAvailabilityChangedLocked(
2194                         service.isAccessibilityButtonAvailableLocked(userState));
2195             }
2196         }
2197     }
2198 
2199     @GuardedBy("mLock")
getCompatibleMagnificationSpecLocked(int windowId)2200     private MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId) {
2201         IBinder windowToken = mGlobalWindowTokens.get(windowId);
2202         if (windowToken == null) {
2203             windowToken = getCurrentUserStateLocked().mWindowTokens.get(windowId);
2204         }
2205         if (windowToken != null) {
2206             return mWindowManagerService.getCompatibleMagnificationSpecForWindow(
2207                     windowToken);
2208         }
2209         return null;
2210     }
2211 
getKeyEventDispatcher()2212     private KeyEventDispatcher getKeyEventDispatcher() {
2213         if (mKeyEventDispatcher == null) {
2214             mKeyEventDispatcher = new KeyEventDispatcher(
2215                     mMainHandler, MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER, mLock,
2216                     mPowerManager);
2217         }
2218         return mKeyEventDispatcher;
2219     }
2220 
2221     /**
2222      * AIDL-exposed method to be called when the accessibility shortcut is enabled. Requires
2223      * permission to write secure settings, since someone with that permission can enable
2224      * accessibility services themselves.
2225      */
performAccessibilityShortcut()2226     public void performAccessibilityShortcut() {
2227         if ((UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID)
2228                 && (mContext.checkCallingPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
2229                 != PackageManager.PERMISSION_GRANTED)) {
2230             throw new SecurityException(
2231                     "performAccessibilityShortcut requires the WRITE_SECURE_SETTINGS permission");
2232         }
2233         synchronized(mLock) {
2234             UserState userState = getUserStateLocked(mCurrentUserId);
2235             ComponentName serviceName = userState.mServiceToEnableWithShortcut;
2236             if (serviceName == null) {
2237                 return;
2238             }
2239             final long identity = Binder.clearCallingIdentity();
2240             try {
2241                 if (userState.mComponentNameToServiceMap.get(serviceName) == null) {
2242                     enableAccessibilityServiceLocked(serviceName, mCurrentUserId);
2243                 } else {
2244                     disableAccessibilityServiceLocked(serviceName, mCurrentUserId);
2245                 }
2246             } finally {
2247                 Binder.restoreCallingIdentity(identity);
2248             }
2249         }
2250     };
2251 
2252     /**
2253      * Enables accessibility service specified by {@param componentName} for the {@param userId}.
2254      */
enableAccessibilityServiceLocked(ComponentName componentName, int userId)2255     private void enableAccessibilityServiceLocked(ComponentName componentName, int userId) {
2256         final SettingStringHelper setting =
2257                 new SettingStringHelper(
2258                         mContext.getContentResolver(),
2259                         Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
2260                         userId);
2261         setting.write(ComponentNameSet.add(setting.read(), componentName));
2262 
2263         UserState userState = getUserStateLocked(userId);
2264         if (userState.mEnabledServices.add(componentName)) {
2265             onUserStateChangedLocked(userState);
2266         }
2267     }
2268 
2269     /**
2270      * Disables accessibility service specified by {@param componentName} for the {@param userId}.
2271      */
disableAccessibilityServiceLocked(ComponentName componentName, int userId)2272     private void disableAccessibilityServiceLocked(ComponentName componentName, int userId) {
2273         final SettingsStringUtil.SettingStringHelper setting =
2274                 new SettingStringHelper(
2275                         mContext.getContentResolver(),
2276                         Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
2277                         userId);
2278         setting.write(ComponentNameSet.remove(setting.read(), componentName));
2279 
2280         UserState userState = getUserStateLocked(userId);
2281         if (userState.mEnabledServices.remove(componentName)) {
2282             onUserStateChangedLocked(userState);
2283         }
2284     }
2285 
2286     /**
2287      * AIDL-exposed method. System only.
2288      * Inform accessibility that a fingerprint gesture was performed
2289      *
2290      * @param gestureKeyCode The key code corresponding to the fingerprint gesture.
2291      * @return {@code true} if accessibility consumes the fingerprint gesture, {@code false} if it
2292      * doesn't.
2293      */
2294     @Override
sendFingerprintGesture(int gestureKeyCode)2295     public boolean sendFingerprintGesture(int gestureKeyCode) {
2296         synchronized(mLock) {
2297             if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) {
2298                 throw new SecurityException("Only SYSTEM can call sendFingerprintGesture");
2299             }
2300         }
2301         if (mFingerprintGestureDispatcher == null) {
2302             return false;
2303         }
2304         return mFingerprintGestureDispatcher.onFingerprintGesture(gestureKeyCode);
2305     }
2306 
2307     @Override
dump(FileDescriptor fd, final PrintWriter pw, String[] args)2308     public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
2309         if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
2310         synchronized (mLock) {
2311             pw.println("ACCESSIBILITY MANAGER (dumpsys accessibility)");
2312             pw.println();
2313             final int userCount = mUserStates.size();
2314             for (int i = 0; i < userCount; i++) {
2315                 UserState userState = mUserStates.valueAt(i);
2316                 pw.append("User state[attributes:{id=" + userState.mUserId);
2317                 pw.append(", currentUser=" + (userState.mUserId == mCurrentUserId));
2318                 pw.append(", touchExplorationEnabled=" + userState.mIsTouchExplorationEnabled);
2319                 pw.append(", displayMagnificationEnabled="
2320                         + userState.mIsDisplayMagnificationEnabled);
2321                 pw.append(", navBarMagnificationEnabled="
2322                         + userState.mIsNavBarMagnificationEnabled);
2323                 pw.append(", autoclickEnabled=" + userState.mIsAutoclickEnabled);
2324                 if (userState.mUiAutomationService != null) {
2325                     pw.append(", ");
2326                     userState.mUiAutomationService.dump(fd, pw, args);
2327                     pw.println();
2328                 }
2329                 pw.append("}");
2330                 pw.println();
2331                 pw.append("           services:{");
2332                 final int serviceCount = userState.mBoundServices.size();
2333                 for (int j = 0; j < serviceCount; j++) {
2334                     if (j > 0) {
2335                         pw.append(", ");
2336                         pw.println();
2337                         pw.append("                     ");
2338                     }
2339                     Service service = userState.mBoundServices.get(j);
2340                     service.dump(fd, pw, args);
2341                 }
2342                 pw.println("}]");
2343                 pw.println();
2344             }
2345             if (mSecurityPolicy.mWindows != null) {
2346                 final int windowCount = mSecurityPolicy.mWindows.size();
2347                 for (int j = 0; j < windowCount; j++) {
2348                     if (j > 0) {
2349                         pw.append(',');
2350                         pw.println();
2351                     }
2352                     pw.append("Window[");
2353                     AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(j);
2354                     pw.append(window.toString());
2355                     pw.append(']');
2356                 }
2357             }
2358         }
2359     }
2360 
2361     private class AccessibilityConnectionWrapper implements DeathRecipient {
2362         private final int mWindowId;
2363         private final int mUserId;
2364         private final IAccessibilityInteractionConnection mConnection;
2365 
AccessibilityConnectionWrapper(int windowId, IAccessibilityInteractionConnection connection, int userId)2366         public AccessibilityConnectionWrapper(int windowId,
2367                 IAccessibilityInteractionConnection connection, int userId) {
2368             mWindowId = windowId;
2369             mUserId = userId;
2370             mConnection = connection;
2371         }
2372 
linkToDeath()2373         public void linkToDeath() throws RemoteException {
2374             mConnection.asBinder().linkToDeath(this, 0);
2375         }
2376 
unlinkToDeath()2377         public void unlinkToDeath() {
2378             mConnection.asBinder().unlinkToDeath(this, 0);
2379         }
2380 
2381         @Override
binderDied()2382         public void binderDied() {
2383             unlinkToDeath();
2384             synchronized (mLock) {
2385                 removeAccessibilityInteractionConnectionLocked(mWindowId, mUserId);
2386             }
2387         }
2388     }
2389 
2390     private final class MainHandler extends Handler {
2391         public static final int MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER = 1;
2392         public static final int MSG_SEND_STATE_TO_CLIENTS = 2;
2393         public static final int MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER = 3;
2394         public static final int MSG_ANNOUNCE_NEW_USER_IF_NEEDED = 5;
2395         public static final int MSG_UPDATE_INPUT_FILTER = 6;
2396         public static final int MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG = 7;
2397         public static final int MSG_SEND_KEY_EVENT_TO_INPUT_FILTER = 8;
2398         public static final int MSG_CLEAR_ACCESSIBILITY_FOCUS = 9;
2399         public static final int MSG_SEND_SERVICES_STATE_CHANGED_TO_CLIENTS = 10;
2400         public static final int MSG_UPDATE_FINGERPRINT = 11;
2401         public static final int MSG_SEND_RELEVANT_EVENTS_CHANGED_TO_CLIENTS = 12;
2402         public static final int MSG_SEND_ACCESSIBILITY_BUTTON_TO_INPUT_FILTER = 13;
2403         public static final int MSG_SHOW_ACCESSIBILITY_BUTTON_CHOOSER = 14;
2404 
MainHandler(Looper looper)2405         public MainHandler(Looper looper) {
2406             super(looper);
2407         }
2408 
2409         @Override
handleMessage(Message msg)2410         public void handleMessage(Message msg) {
2411             final int type = msg.what;
2412             switch (type) {
2413                 case MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER: {
2414                     AccessibilityEvent event = (AccessibilityEvent) msg.obj;
2415                     synchronized (mLock) {
2416                         if (mHasInputFilter && mInputFilter != null) {
2417                             mInputFilter.notifyAccessibilityEvent(event);
2418                         }
2419                     }
2420                     event.recycle();
2421                 } break;
2422 
2423                 case MSG_SEND_KEY_EVENT_TO_INPUT_FILTER: {
2424                     KeyEvent event = (KeyEvent) msg.obj;
2425                     final int policyFlags = msg.arg1;
2426                     synchronized (mLock) {
2427                         if (mHasInputFilter && mInputFilter != null) {
2428                             mInputFilter.sendInputEvent(event, policyFlags);
2429                         }
2430                     }
2431                     event.recycle();
2432                 } break;
2433 
2434                 case MSG_SEND_STATE_TO_CLIENTS: {
2435                     final int clientState = msg.arg1;
2436                     final int userId = msg.arg2;
2437                     sendStateToClients(clientState, mGlobalClients);
2438                     sendStateToClients(clientState, getUserClientsForId(userId));
2439                 } break;
2440 
2441                 case MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER: {
2442                     final int userId = msg.arg1;
2443                     sendStateToClients(0, getUserClientsForId(userId));
2444                 } break;
2445 
2446                 case MSG_ANNOUNCE_NEW_USER_IF_NEEDED: {
2447                     announceNewUserIfNeeded();
2448                 } break;
2449 
2450                 case MSG_UPDATE_INPUT_FILTER: {
2451                     UserState userState = (UserState) msg.obj;
2452                     updateInputFilter(userState);
2453                 } break;
2454 
2455                 case MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG: {
2456                     Service service = (Service) msg.obj;
2457                     showEnableTouchExplorationDialog(service);
2458                 } break;
2459 
2460                 case MSG_CLEAR_ACCESSIBILITY_FOCUS: {
2461                     final int windowId = msg.arg1;
2462                     getInteractionBridge().clearAccessibilityFocusNotLocked(windowId);
2463                 } break;
2464 
2465                 case MSG_SEND_SERVICES_STATE_CHANGED_TO_CLIENTS: {
2466                     final int userId = msg.arg1;
2467                     notifyClientsOfServicesStateChange(mGlobalClients);
2468                     notifyClientsOfServicesStateChange(getUserClientsForId(userId));
2469                 } break;
2470 
2471                 case MSG_UPDATE_FINGERPRINT: {
2472                     updateFingerprintGestureHandling((UserState) msg.obj);
2473                 } break;
2474 
2475                 case MSG_SEND_RELEVANT_EVENTS_CHANGED_TO_CLIENTS: {
2476                     final int userId = msg.arg1;
2477                     final int relevantEventTypes = msg.arg2;
2478                     final UserState userState;
2479                     synchronized (mLock) {
2480                         userState = getUserStateLocked(userId);
2481                     }
2482                     broadcastToClients(userState, (client) -> {
2483                         try {
2484                             client.setRelevantEventTypes(relevantEventTypes);
2485                         } catch (RemoteException re) {
2486                             /* ignore */
2487                         }
2488                     });
2489                 } break;
2490 
2491                case MSG_SEND_ACCESSIBILITY_BUTTON_TO_INPUT_FILTER: {
2492                     synchronized (mLock) {
2493                         if (mHasInputFilter && mInputFilter != null) {
2494                             mInputFilter.notifyAccessibilityButtonClicked();
2495                         }
2496                     }
2497                 } break;
2498 
2499                 case MSG_SHOW_ACCESSIBILITY_BUTTON_CHOOSER: {
2500                     showAccessibilityButtonTargetSelection();
2501                 } break;
2502             }
2503         }
2504 
announceNewUserIfNeeded()2505         private void announceNewUserIfNeeded() {
2506             synchronized (mLock) {
2507                 UserState userState = getCurrentUserStateLocked();
2508                 if (userState.isHandlingAccessibilityEvents()) {
2509                     UserManager userManager = (UserManager) mContext.getSystemService(
2510                             Context.USER_SERVICE);
2511                     String message = mContext.getString(R.string.user_switched,
2512                             userManager.getUserInfo(mCurrentUserId).name);
2513                     AccessibilityEvent event = AccessibilityEvent.obtain(
2514                             AccessibilityEvent.TYPE_ANNOUNCEMENT);
2515                     event.getText().add(message);
2516                     sendAccessibilityEvent(event, mCurrentUserId);
2517                 }
2518             }
2519         }
2520 
getUserClientsForId(int userId)2521         private RemoteCallbackList<IAccessibilityManagerClient> getUserClientsForId(int userId) {
2522             final UserState userState;
2523             synchronized (mLock) {
2524                 userState = getUserStateLocked(userId);
2525             }
2526             return userState.mUserClients;
2527         }
2528 
sendStateToClients(int clientState, RemoteCallbackList<IAccessibilityManagerClient> clients)2529         private void sendStateToClients(int clientState,
2530                 RemoteCallbackList<IAccessibilityManagerClient> clients) {
2531             clients.broadcast((client) -> {
2532                 try {
2533                     client.setState(clientState);
2534                 } catch (RemoteException re) {
2535                     /* ignore */
2536                 }
2537             });
2538         }
2539 
notifyClientsOfServicesStateChange( RemoteCallbackList<IAccessibilityManagerClient> clients)2540         private void notifyClientsOfServicesStateChange(
2541                 RemoteCallbackList<IAccessibilityManagerClient> clients) {
2542             try {
2543                 final int userClientCount = clients.beginBroadcast();
2544                 for (int i = 0; i < userClientCount; i++) {
2545                     IAccessibilityManagerClient client = clients.getBroadcastItem(i);
2546                     try {
2547                         client.notifyServicesStateChanged();
2548                     } catch (RemoteException re) {
2549                         /* ignore */
2550                     }
2551                 }
2552             } finally {
2553                 clients.finishBroadcast();
2554             }
2555         }
2556     }
2557 
findWindowIdLocked(IBinder token)2558     private int findWindowIdLocked(IBinder token) {
2559         final int globalIndex = mGlobalWindowTokens.indexOfValue(token);
2560         if (globalIndex >= 0) {
2561             return mGlobalWindowTokens.keyAt(globalIndex);
2562         }
2563         UserState userState = getCurrentUserStateLocked();
2564         final int userIndex = userState.mWindowTokens.indexOfValue(token);
2565         if (userIndex >= 0) {
2566             return userState.mWindowTokens.keyAt(userIndex);
2567         }
2568         return -1;
2569     }
2570 
ensureWindowsAvailableTimed()2571     private void ensureWindowsAvailableTimed() {
2572         synchronized (mLock) {
2573             if (mSecurityPolicy.mWindows != null) {
2574                 return;
2575             }
2576             // If we have no registered callback, update the state we
2577             // we may have to register one but it didn't happen yet.
2578             if (mWindowsForAccessibilityCallback == null) {
2579                 UserState userState = getCurrentUserStateLocked();
2580                 onUserStateChangedLocked(userState);
2581             }
2582             // We have no windows but do not care about them, done.
2583             if (mWindowsForAccessibilityCallback == null) {
2584                 return;
2585             }
2586 
2587             // Wait for the windows with a timeout.
2588             final long startMillis = SystemClock.uptimeMillis();
2589             while (mSecurityPolicy.mWindows == null) {
2590                 final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
2591                 final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis;
2592                 if (remainMillis <= 0) {
2593                     return;
2594                 }
2595                 try {
2596                     mLock.wait(remainMillis);
2597                 } catch (InterruptedException ie) {
2598                     /* ignore */
2599                 }
2600             }
2601         }
2602     }
2603 
getMagnificationController()2604     MagnificationController getMagnificationController() {
2605         synchronized (mLock) {
2606             if (mMagnificationController == null) {
2607                 mMagnificationController = new MagnificationController(mContext, this, mLock);
2608                 mMagnificationController.setUserId(mCurrentUserId);
2609             }
2610             return mMagnificationController;
2611         }
2612     }
2613 
2614     /**
2615      * This class represents an accessibility service. It stores all per service
2616      * data required for the service management, provides API for starting/stopping the
2617      * service and is responsible for adding/removing the service in the data structures
2618      * for service management. The class also exposes configuration interface that is
2619      * passed to the service it represents as soon it is bound. It also serves as the
2620      * connection for the service.
2621      */
2622     class Service extends IAccessibilityServiceConnection.Stub
2623             implements ServiceConnection, DeathRecipient, KeyEventDispatcher.KeyEventFilter,
2624             FingerprintGestureDispatcher.FingerprintGestureClient {
2625 
2626         final int mUserId;
2627 
2628         int mId = 0;
2629 
2630         AccessibilityServiceInfo mAccessibilityServiceInfo;
2631 
2632         // The service that's bound to this instance. Whenever this value is non-null, this
2633         // object is registered as a death recipient
2634         IBinder mService;
2635 
2636         IAccessibilityServiceClient mServiceInterface;
2637 
2638         int mEventTypes;
2639 
2640         int mFeedbackType;
2641 
2642         Set<String> mPackageNames = new HashSet<>();
2643 
2644         boolean mIsDefault;
2645 
2646         boolean mRequestTouchExplorationMode;
2647 
2648         boolean mRequestFilterKeyEvents;
2649 
2650         boolean mRetrieveInteractiveWindows;
2651 
2652         boolean mCaptureFingerprintGestures;
2653 
2654         boolean mRequestAccessibilityButton;
2655 
2656         boolean mReceivedAccessibilityButtonCallbackSinceBind;
2657 
2658         boolean mLastAccessibilityButtonCallbackState;
2659 
2660         int mFetchFlags;
2661 
2662         long mNotificationTimeout;
2663 
2664         ComponentName mComponentName;
2665 
2666         Intent mIntent;
2667 
2668         boolean mIsAutomation;
2669 
2670         final ResolveInfo mResolveInfo;
2671 
2672         final IBinder mOverlayWindowToken = new Binder();
2673 
2674         // the events pending events to be dispatched to this service
2675         final SparseArray<AccessibilityEvent> mPendingEvents =
2676             new SparseArray<>();
2677 
2678         boolean mWasConnectedAndDied;
2679 
2680         /** Whether this service relies on its {@link AccessibilityCache} being up to date */
2681         boolean mUsesAccessibilityCache = false;
2682 
2683         // Handler only for dispatching accessibility events since we use event
2684         // types as message types allowing us to remove messages per event type.
2685         public Handler mEventDispatchHandler = new Handler(mMainHandler.getLooper()) {
2686             @Override
2687             public void handleMessage(Message message) {
2688                 final int eventType =  message.what;
2689                 AccessibilityEvent event = (AccessibilityEvent) message.obj;
2690                 boolean serviceWantsEvent = message.arg1 != 0;
2691                 notifyAccessibilityEventInternal(eventType, event, serviceWantsEvent);
2692             }
2693         };
2694 
2695         // Handler for scheduling method invocations on the main thread.
2696         public final InvocationHandler mInvocationHandler = new InvocationHandler(
2697                 mMainHandler.getLooper());
2698 
Service(int userId, ComponentName componentName, AccessibilityServiceInfo accessibilityServiceInfo)2699         public Service(int userId, ComponentName componentName,
2700                 AccessibilityServiceInfo accessibilityServiceInfo) {
2701             mUserId = userId;
2702             mResolveInfo = accessibilityServiceInfo.getResolveInfo();
2703             mId = sIdCounter++;
2704             mComponentName = componentName;
2705             mAccessibilityServiceInfo = accessibilityServiceInfo;
2706             mIsAutomation = (sFakeAccessibilityServiceComponentName.equals(componentName));
2707             if (!mIsAutomation) {
2708                 mIntent = new Intent().setComponent(mComponentName);
2709                 mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
2710                         com.android.internal.R.string.accessibility_binding_label);
2711                 final long idendtity = Binder.clearCallingIdentity();
2712                 try {
2713                     mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
2714                             mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0));
2715                 } finally {
2716                     Binder.restoreCallingIdentity(idendtity);
2717                 }
2718             }
2719             setDynamicallyConfigurableProperties(accessibilityServiceInfo);
2720         }
2721 
2722         @Override
onKeyEvent(KeyEvent keyEvent, int sequenceNumber)2723         public boolean onKeyEvent(KeyEvent keyEvent, int sequenceNumber) {
2724             if (!mRequestFilterKeyEvents || (mServiceInterface == null)) {
2725                 return false;
2726             }
2727             if((mAccessibilityServiceInfo.getCapabilities()
2728                     & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) == 0) {
2729                 return false;
2730             }
2731             try {
2732                 mServiceInterface.onKeyEvent(keyEvent, sequenceNumber);
2733             } catch (RemoteException e) {
2734                 return false;
2735             }
2736             return true;
2737         }
2738 
2739         @Override
isCapturingFingerprintGestures()2740         public boolean isCapturingFingerprintGestures() {
2741             return (mServiceInterface != null)
2742                     && mSecurityPolicy.canCaptureFingerprintGestures(this)
2743                     && mCaptureFingerprintGestures;
2744         }
2745 
2746         @Override
onFingerprintGestureDetectionActiveChanged(boolean active)2747         public void onFingerprintGestureDetectionActiveChanged(boolean active) {
2748             if (!isCapturingFingerprintGestures()) {
2749                 return;
2750             }
2751             IAccessibilityServiceClient serviceInterface;
2752             synchronized (mLock) {
2753                 serviceInterface = mServiceInterface;
2754             }
2755             if (serviceInterface != null) {
2756                 try {
2757                     mServiceInterface.onFingerprintCapturingGesturesChanged(active);
2758                 } catch (RemoteException e) {
2759                 }
2760             }
2761         }
2762 
2763         @Override
onFingerprintGesture(int gesture)2764         public void onFingerprintGesture(int gesture) {
2765             if (!isCapturingFingerprintGestures()) {
2766                 return;
2767             }
2768             IAccessibilityServiceClient serviceInterface;
2769             synchronized (mLock) {
2770                 serviceInterface = mServiceInterface;
2771             }
2772             if (serviceInterface != null) {
2773                 try {
2774                     mServiceInterface.onFingerprintGesture(gesture);
2775                 } catch (RemoteException e) {
2776                 }
2777             }
2778         }
2779 
setDynamicallyConfigurableProperties(AccessibilityServiceInfo info)2780         public void setDynamicallyConfigurableProperties(AccessibilityServiceInfo info) {
2781             mEventTypes = info.eventTypes;
2782             mFeedbackType = info.feedbackType;
2783             String[] packageNames = info.packageNames;
2784             if (packageNames != null) {
2785                 mPackageNames.addAll(Arrays.asList(packageNames));
2786             }
2787             mNotificationTimeout = info.notificationTimeout;
2788             mIsDefault = (info.flags & DEFAULT) != 0;
2789 
2790             if (mIsAutomation || info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion
2791                     >= Build.VERSION_CODES.JELLY_BEAN) {
2792                 if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) {
2793                     mFetchFlags |= AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
2794                 } else {
2795                     mFetchFlags &= ~AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
2796                 }
2797             }
2798 
2799             if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) {
2800                 mFetchFlags |= AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;
2801             } else {
2802                 mFetchFlags &= ~AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;
2803             }
2804 
2805             mRequestTouchExplorationMode = (info.flags
2806                     & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0;
2807             mRequestFilterKeyEvents = (info.flags
2808                     & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0;
2809             mRetrieveInteractiveWindows = (info.flags
2810                     & AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0;
2811             mCaptureFingerprintGestures = (info.flags
2812                     & AccessibilityServiceInfo.FLAG_REQUEST_FINGERPRINT_GESTURES) != 0;
2813             mRequestAccessibilityButton = (info.flags
2814                     & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
2815         }
2816 
2817         /**
2818          * Binds to the accessibility service.
2819          *
2820          * @return True if binding is successful.
2821          */
bindLocked()2822         public boolean bindLocked() {
2823             UserState userState = getUserStateLocked(mUserId);
2824             if (!mIsAutomation) {
2825                 final long identity = Binder.clearCallingIdentity();
2826                 try {
2827                     if (mService == null && mContext.bindServiceAsUser(
2828                             mIntent, this,
2829                             Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
2830                             new UserHandle(mUserId))) {
2831                         userState.mBindingServices.add(mComponentName);
2832                     }
2833                 } finally {
2834                     Binder.restoreCallingIdentity(identity);
2835                 }
2836             } else {
2837                 userState.mBindingServices.add(mComponentName);
2838                 mMainHandler.post(new Runnable() {
2839                     @Override
2840                     public void run() {
2841                         // Simulate asynchronous connection since in onServiceConnected
2842                         // we may modify the state data in case of an error but bind is
2843                         // called while iterating over the data and bad things can happen.
2844                         onServiceConnected(mComponentName,
2845                                 userState.mUiAutomationServiceClient.asBinder());
2846                     }
2847                 });
2848                 userState.mUiAutomationService = this;
2849             }
2850             return false;
2851         }
2852 
2853         /**
2854          * Unbinds from the accessibility service and removes it from the data
2855          * structures for service management.
2856          *
2857          * @return True if unbinding is successful.
2858          */
unbindLocked()2859         public boolean unbindLocked() {
2860             UserState userState = getUserStateLocked(mUserId);
2861             getKeyEventDispatcher().flush(this);
2862             if (!mIsAutomation) {
2863                 mContext.unbindService(this);
2864             } else {
2865                 userState.destroyUiAutomationService();
2866             }
2867             removeServiceLocked(this, userState);
2868             resetLocked();
2869             return true;
2870         }
2871 
2872         @Override
disableSelf()2873         public void disableSelf() {
2874             synchronized(mLock) {
2875                 UserState userState = getUserStateLocked(mUserId);
2876                 if (userState.mEnabledServices.remove(mComponentName)) {
2877                     final long identity = Binder.clearCallingIdentity();
2878                     try {
2879                         persistComponentNamesToSettingLocked(
2880                                 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
2881                                 userState.mEnabledServices, mUserId);
2882                     } finally {
2883                         Binder.restoreCallingIdentity(identity);
2884                     }
2885                     onUserStateChangedLocked(userState);
2886                 }
2887             }
2888         }
2889 
canReceiveEventsLocked()2890         public boolean canReceiveEventsLocked() {
2891             return (mEventTypes != 0 && mFeedbackType != 0 && mService != null);
2892         }
2893 
2894         @Override
setOnKeyEventResult(boolean handled, int sequence)2895         public void setOnKeyEventResult(boolean handled, int sequence) {
2896             getKeyEventDispatcher().setOnKeyEventResult(this, handled, sequence);
2897         }
2898 
2899         @Override
getServiceInfo()2900         public AccessibilityServiceInfo getServiceInfo() {
2901             synchronized (mLock) {
2902                 return mAccessibilityServiceInfo;
2903             }
2904         }
2905 
canRetrieveInteractiveWindowsLocked()2906         public boolean canRetrieveInteractiveWindowsLocked() {
2907             return mSecurityPolicy.canRetrieveWindowContentLocked(this)
2908                     && mRetrieveInteractiveWindows;
2909         }
2910 
2911         @Override
setServiceInfo(AccessibilityServiceInfo info)2912         public void setServiceInfo(AccessibilityServiceInfo info) {
2913             final long identity = Binder.clearCallingIdentity();
2914             try {
2915                 synchronized (mLock) {
2916                     // If the XML manifest had data to configure the service its info
2917                     // should be already set. In such a case update only the dynamically
2918                     // configurable properties.
2919                     AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo;
2920                     if (oldInfo != null) {
2921                         oldInfo.updateDynamicallyConfigurableProperties(info);
2922                         setDynamicallyConfigurableProperties(oldInfo);
2923                     } else {
2924                         setDynamicallyConfigurableProperties(info);
2925                     }
2926                     UserState userState = getUserStateLocked(mUserId);
2927                     onUserStateChangedLocked(userState);
2928                     scheduleNotifyClientsOfServicesStateChange(userState);
2929                 }
2930             } finally {
2931                 Binder.restoreCallingIdentity(identity);
2932             }
2933         }
2934 
2935         @Override
onServiceConnected(ComponentName componentName, IBinder service)2936         public void onServiceConnected(ComponentName componentName, IBinder service) {
2937             synchronized (mLock) {
2938                 if (mService != service) {
2939                     if (mService != null) {
2940                         mService.unlinkToDeath(this, 0);
2941                     }
2942                     mService = service;
2943                     try {
2944                         mService.linkToDeath(this, 0);
2945                     } catch (RemoteException re) {
2946                         Slog.e(LOG_TAG, "Failed registering death link");
2947                         binderDied();
2948                         return;
2949                     }
2950                 }
2951                 mServiceInterface = IAccessibilityServiceClient.Stub.asInterface(service);
2952                 UserState userState = getUserStateLocked(mUserId);
2953                 addServiceLocked(this, userState);
2954                 if (userState.mBindingServices.contains(mComponentName) || mWasConnectedAndDied) {
2955                     userState.mBindingServices.remove(mComponentName);
2956                     mWasConnectedAndDied = false;
2957                     try {
2958                        mServiceInterface.init(this, mId, mOverlayWindowToken);
2959                        onUserStateChangedLocked(userState);
2960                     } catch (RemoteException re) {
2961                         Slog.w(LOG_TAG, "Error while setting connection for service: "
2962                                 + service, re);
2963                         binderDied();
2964                     }
2965                 } else {
2966                     binderDied();
2967                 }
2968             }
2969         }
2970 
isCalledForCurrentUserLocked()2971         private boolean isCalledForCurrentUserLocked() {
2972             // We treat calls from a profile as if made by its parent as profiles
2973             // share the accessibility state of the parent. The call below
2974             // performs the current profile parent resolution.
2975             final int resolvedUserId = mSecurityPolicy
2976                     .resolveCallingUserIdEnforcingPermissionsLocked(UserHandle.USER_CURRENT);
2977             return resolvedUserId == mCurrentUserId;
2978         }
2979 
2980         @Override
getWindows()2981         public List<AccessibilityWindowInfo> getWindows() {
2982             ensureWindowsAvailableTimed();
2983             synchronized (mLock) {
2984                 if (!isCalledForCurrentUserLocked()) {
2985                     return null;
2986                 }
2987                 final boolean permissionGranted =
2988                         mSecurityPolicy.canRetrieveWindowsLocked(this);
2989                 if (!permissionGranted) {
2990                     return null;
2991                 }
2992                 if (mSecurityPolicy.mWindows == null) {
2993                     return null;
2994                 }
2995                 List<AccessibilityWindowInfo> windows = new ArrayList<>();
2996                 final int windowCount = mSecurityPolicy.mWindows.size();
2997                 for (int i = 0; i < windowCount; i++) {
2998                     AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(i);
2999                     AccessibilityWindowInfo windowClone =
3000                             AccessibilityWindowInfo.obtain(window);
3001                     windowClone.setConnectionId(mId);
3002                     windows.add(windowClone);
3003                 }
3004                 return windows;
3005             }
3006         }
3007 
3008         @Override
getWindow(int windowId)3009         public AccessibilityWindowInfo getWindow(int windowId) {
3010             ensureWindowsAvailableTimed();
3011             synchronized (mLock) {
3012                 if (!isCalledForCurrentUserLocked()) {
3013                     return null;
3014                 }
3015                 final boolean permissionGranted =
3016                         mSecurityPolicy.canRetrieveWindowsLocked(this);
3017                 if (!permissionGranted) {
3018                     return null;
3019                 }
3020                 AccessibilityWindowInfo window = mSecurityPolicy.findWindowById(windowId);
3021                 if (window != null) {
3022                     AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window);
3023                     windowClone.setConnectionId(mId);
3024                     return windowClone;
3025                 }
3026                 return null;
3027             }
3028         }
3029 
3030         @Override
findAccessibilityNodeInfosByViewId(int accessibilityWindowId, long accessibilityNodeId, String viewIdResName, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)3031         public boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
3032                 long accessibilityNodeId, String viewIdResName, int interactionId,
3033                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
3034                 throws RemoteException {
3035             final int resolvedWindowId;
3036             IAccessibilityInteractionConnection connection = null;
3037             Region partialInteractiveRegion = Region.obtain();
3038             MagnificationSpec spec;
3039             synchronized (mLock) {
3040                 mUsesAccessibilityCache = true;
3041                 if (!isCalledForCurrentUserLocked()) {
3042                     return false;
3043                 }
3044                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
3045                 final boolean permissionGranted =
3046                         mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
3047                 if (!permissionGranted) {
3048                     return false;
3049                 } else {
3050                     connection = getConnectionLocked(resolvedWindowId);
3051                     if (connection == null) {
3052                         return false;
3053                     }
3054                 }
3055                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
3056                         resolvedWindowId, partialInteractiveRegion)) {
3057                     partialInteractiveRegion.recycle();
3058                     partialInteractiveRegion = null;
3059                 }
3060                 spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
3061             }
3062             final int interrogatingPid = Binder.getCallingPid();
3063             callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
3064                     interrogatingPid, interrogatingTid);
3065             final long identityToken = Binder.clearCallingIdentity();
3066             try {
3067                 connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName,
3068                         partialInteractiveRegion, interactionId, callback, mFetchFlags,
3069                         interrogatingPid, interrogatingTid, spec);
3070                 return true;
3071             } catch (RemoteException re) {
3072                 if (DEBUG) {
3073                     Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId().");
3074                 }
3075             } finally {
3076                 Binder.restoreCallingIdentity(identityToken);
3077                 // Recycle if passed to another process.
3078                 if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
3079                     partialInteractiveRegion.recycle();
3080                 }
3081             }
3082             return false;
3083         }
3084 
3085         @Override
findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId, String text, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)3086         public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId,
3087                 long accessibilityNodeId, String text, int interactionId,
3088                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
3089                 throws RemoteException {
3090             final int resolvedWindowId;
3091             IAccessibilityInteractionConnection connection = null;
3092             Region partialInteractiveRegion = Region.obtain();
3093             MagnificationSpec spec;
3094             synchronized (mLock) {
3095                 mUsesAccessibilityCache = true;
3096                 if (!isCalledForCurrentUserLocked()) {
3097                     return false;
3098                 }
3099                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
3100                 final boolean permissionGranted =
3101                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
3102                 if (!permissionGranted) {
3103                     return false;
3104                 } else {
3105                     connection = getConnectionLocked(resolvedWindowId);
3106                     if (connection == null) {
3107                         return false;
3108                     }
3109                 }
3110                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
3111                         resolvedWindowId, partialInteractiveRegion)) {
3112                     partialInteractiveRegion.recycle();
3113                     partialInteractiveRegion = null;
3114                 }
3115                 spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
3116             }
3117             final int interrogatingPid = Binder.getCallingPid();
3118             callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
3119                     interrogatingPid, interrogatingTid);
3120             final long identityToken = Binder.clearCallingIdentity();
3121             try {
3122                 connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
3123                         partialInteractiveRegion, interactionId, callback, mFetchFlags,
3124                         interrogatingPid, interrogatingTid, spec);
3125                 return true;
3126             } catch (RemoteException re) {
3127                 if (DEBUG) {
3128                     Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()");
3129                 }
3130             } finally {
3131                 Binder.restoreCallingIdentity(identityToken);
3132                 // Recycle if passed to another process.
3133                 if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
3134                     partialInteractiveRegion.recycle();
3135                 }
3136             }
3137             return false;
3138         }
3139 
3140         @Override
findAccessibilityNodeInfoByAccessibilityId( int accessibilityWindowId, long accessibilityNodeId, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, long interrogatingTid, Bundle arguments)3141         public boolean findAccessibilityNodeInfoByAccessibilityId(
3142                 int accessibilityWindowId, long accessibilityNodeId, int interactionId,
3143                 IAccessibilityInteractionConnectionCallback callback, int flags,
3144                 long interrogatingTid, Bundle arguments) throws RemoteException {
3145             final int resolvedWindowId;
3146             IAccessibilityInteractionConnection connection = null;
3147             Region partialInteractiveRegion = Region.obtain();
3148             MagnificationSpec spec;
3149             synchronized (mLock) {
3150                 mUsesAccessibilityCache = true;
3151                 if (!isCalledForCurrentUserLocked()) {
3152                     return false;
3153                 }
3154                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
3155                 final boolean permissionGranted =
3156                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
3157                 if (!permissionGranted) {
3158                     return false;
3159                 } else {
3160                     connection = getConnectionLocked(resolvedWindowId);
3161                     if (connection == null) {
3162                         return false;
3163                     }
3164                 }
3165                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
3166                         resolvedWindowId, partialInteractiveRegion)) {
3167                     partialInteractiveRegion.recycle();
3168                     partialInteractiveRegion = null;
3169                 }
3170                 spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
3171             }
3172             final int interrogatingPid = Binder.getCallingPid();
3173             callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
3174                     interrogatingPid, interrogatingTid);
3175             final long identityToken = Binder.clearCallingIdentity();
3176             try {
3177                 connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId,
3178                         partialInteractiveRegion, interactionId, callback, mFetchFlags | flags,
3179                         interrogatingPid, interrogatingTid, spec, arguments);
3180                 return true;
3181             } catch (RemoteException re) {
3182                 if (DEBUG) {
3183                     Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
3184                 }
3185             } finally {
3186                 Binder.restoreCallingIdentity(identityToken);
3187                 // Recycle if passed to another process.
3188                 if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
3189                     partialInteractiveRegion.recycle();
3190                 }
3191             }
3192             return false;
3193         }
3194 
3195         @Override
findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)3196         public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId,
3197                 int focusType, int interactionId,
3198                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
3199                 throws RemoteException {
3200             final int resolvedWindowId;
3201             IAccessibilityInteractionConnection connection = null;
3202             Region partialInteractiveRegion = Region.obtain();
3203             MagnificationSpec spec;
3204             synchronized (mLock) {
3205                 if (!isCalledForCurrentUserLocked()) {
3206                     return false;
3207                 }
3208                 resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked(
3209                         accessibilityWindowId, focusType);
3210                 final boolean permissionGranted =
3211                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
3212                 if (!permissionGranted) {
3213                     return false;
3214                 } else {
3215                     connection = getConnectionLocked(resolvedWindowId);
3216                     if (connection == null) {
3217                         return false;
3218                     }
3219                 }
3220                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
3221                         resolvedWindowId, partialInteractiveRegion)) {
3222                     partialInteractiveRegion.recycle();
3223                     partialInteractiveRegion = null;
3224                 }
3225                 spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
3226             }
3227             final int interrogatingPid = Binder.getCallingPid();
3228             callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
3229                     interrogatingPid, interrogatingTid);
3230             final long identityToken = Binder.clearCallingIdentity();
3231             try {
3232                 connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion,
3233                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
3234                         spec);
3235                 return true;
3236             } catch (RemoteException re) {
3237                 if (DEBUG) {
3238                     Slog.e(LOG_TAG, "Error calling findFocus()");
3239                 }
3240             } finally {
3241                 Binder.restoreCallingIdentity(identityToken);
3242                 // Recycle if passed to another process.
3243                 if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
3244                     partialInteractiveRegion.recycle();
3245                 }
3246             }
3247             return false;
3248         }
3249 
3250         @Override
focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)3251         public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId,
3252                 int direction, int interactionId,
3253                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
3254                 throws RemoteException {
3255             final int resolvedWindowId;
3256             IAccessibilityInteractionConnection connection = null;
3257             Region partialInteractiveRegion = Region.obtain();
3258             MagnificationSpec spec;
3259             synchronized (mLock) {
3260                 if (!isCalledForCurrentUserLocked()) {
3261                     return false;
3262                 }
3263                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
3264                 final boolean permissionGranted =
3265                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
3266                 if (!permissionGranted) {
3267                     return false;
3268                 } else {
3269                     connection = getConnectionLocked(resolvedWindowId);
3270                     if (connection == null) {
3271                         return false;
3272                     }
3273                 }
3274                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
3275                         resolvedWindowId, partialInteractiveRegion)) {
3276                     partialInteractiveRegion.recycle();
3277                     partialInteractiveRegion = null;
3278                 }
3279                 spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
3280             }
3281             final int interrogatingPid = Binder.getCallingPid();
3282             callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
3283                     interrogatingPid, interrogatingTid);
3284             final long identityToken = Binder.clearCallingIdentity();
3285             try {
3286                 connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion,
3287                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
3288                         spec);
3289                 return true;
3290             } catch (RemoteException re) {
3291                 if (DEBUG) {
3292                     Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()");
3293                 }
3294             } finally {
3295                 Binder.restoreCallingIdentity(identityToken);
3296                 // Recycle if passed to another process.
3297                 if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
3298                     partialInteractiveRegion.recycle();
3299                 }
3300             }
3301             return false;
3302         }
3303 
3304         @Override
sendGesture(int sequence, ParceledListSlice gestureSteps)3305         public void sendGesture(int sequence, ParceledListSlice gestureSteps) {
3306             synchronized (mLock) {
3307                 if (mSecurityPolicy.canPerformGestures(this)) {
3308                     final long endMillis =
3309                             SystemClock.uptimeMillis() + WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS;
3310                     while ((mMotionEventInjector == null)
3311                             && (SystemClock.uptimeMillis() < endMillis)) {
3312                         try {
3313                             mLock.wait(endMillis - SystemClock.uptimeMillis());
3314                         } catch (InterruptedException ie) {
3315                             /* ignore */
3316                         }
3317                     }
3318                     if (mMotionEventInjector != null) {
3319                         List<GestureDescription.GestureStep> steps = gestureSteps.getList();
3320                          mMotionEventInjector.injectEvents(steps, mServiceInterface, sequence);
3321                          return;
3322                     } else {
3323                         Slog.e(LOG_TAG, "MotionEventInjector installation timed out");
3324                     }
3325                 }
3326             }
3327             try {
3328                 mServiceInterface.onPerformGestureResult(sequence, false);
3329             } catch (RemoteException re) {
3330                 Slog.e(LOG_TAG, "Error sending motion event injection failure to "
3331                         + mServiceInterface, re);
3332             }
3333         }
3334 
3335         @Override
performAccessibilityAction(int accessibilityWindowId, long accessibilityNodeId, int action, Bundle arguments, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)3336         public boolean performAccessibilityAction(int accessibilityWindowId,
3337                 long accessibilityNodeId, int action, Bundle arguments, int interactionId,
3338                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
3339                 throws RemoteException {
3340             final int resolvedWindowId;
3341             IAccessibilityInteractionConnection connection = null;
3342             synchronized (mLock) {
3343                 if (!isCalledForCurrentUserLocked()) {
3344                     return false;
3345                 }
3346                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
3347                 final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked(
3348                         this, resolvedWindowId);
3349                 if (!permissionGranted) {
3350                     return false;
3351                 } else {
3352                     connection = getConnectionLocked(resolvedWindowId);
3353                     if (connection == null) {
3354                         return false;
3355                     }
3356                     AccessibilityWindowInfo windowInfo =
3357                             mSecurityPolicy.findWindowById(resolvedWindowId);
3358                     if ((windowInfo != null) && windowInfo.inPictureInPicture()) {
3359                         boolean isA11yFocusAction =
3360                                 (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS)
3361                                 || (action ==
3362                                         AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
3363                         if ((mPictureInPictureActionReplacingConnection != null)
3364                                 && !isA11yFocusAction) {
3365                             connection = mPictureInPictureActionReplacingConnection.mConnection;
3366                         }
3367                     }
3368                 }
3369             }
3370             final int interrogatingPid = Binder.getCallingPid();
3371             final long identityToken = Binder.clearCallingIdentity();
3372             try {
3373                 // Regardless of whether or not the action succeeds, it was generated by an
3374                 // accessibility service that is driven by user actions, so note user activity.
3375                 mPowerManager.userActivity(SystemClock.uptimeMillis(),
3376                         PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);
3377 
3378                 connection.performAccessibilityAction(accessibilityNodeId, action, arguments,
3379                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid);
3380             } catch (RemoteException re) {
3381                 if (DEBUG) {
3382                     Slog.e(LOG_TAG, "Error calling performAccessibilityAction()");
3383                 }
3384             } finally {
3385                 Binder.restoreCallingIdentity(identityToken);
3386             }
3387             return true;
3388         }
3389 
3390         @Override
performGlobalAction(int action)3391         public boolean performGlobalAction(int action) {
3392             synchronized (mLock) {
3393                 if (!isCalledForCurrentUserLocked()) {
3394                     return false;
3395                 }
3396             }
3397             final long identity = Binder.clearCallingIdentity();
3398             try {
3399                 mPowerManager.userActivity(SystemClock.uptimeMillis(),
3400                         PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);
3401                 switch (action) {
3402                     case AccessibilityService.GLOBAL_ACTION_BACK: {
3403                         sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK);
3404                     } return true;
3405                     case AccessibilityService.GLOBAL_ACTION_HOME: {
3406                         sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME);
3407                     } return true;
3408                     case AccessibilityService.GLOBAL_ACTION_RECENTS: {
3409                         return openRecents();
3410                     }
3411                     case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: {
3412                         expandNotifications();
3413                     } return true;
3414                     case AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS: {
3415                         expandQuickSettings();
3416                     } return true;
3417                     case AccessibilityService.GLOBAL_ACTION_POWER_DIALOG: {
3418                         showGlobalActions();
3419                     } return true;
3420                     case AccessibilityService.GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN: {
3421                         toggleSplitScreen();
3422                     } return true;
3423                 }
3424                 return false;
3425             } finally {
3426                 Binder.restoreCallingIdentity(identity);
3427             }
3428         }
3429 
3430         @Override
isFingerprintGestureDetectionAvailable()3431         public boolean isFingerprintGestureDetectionAvailable() {
3432             return isCapturingFingerprintGestures()
3433                     && (mFingerprintGestureDispatcher != null)
3434                     && mFingerprintGestureDispatcher.isFingerprintGestureDetectionAvailable();
3435         }
3436 
3437         @Override
getMagnificationScale()3438         public float getMagnificationScale() {
3439             synchronized (mLock) {
3440                 if (!isCalledForCurrentUserLocked()) {
3441                     return 1.0f;
3442                 }
3443             }
3444             final long identity = Binder.clearCallingIdentity();
3445             try {
3446                 return getMagnificationController().getScale();
3447             } finally {
3448                 Binder.restoreCallingIdentity(identity);
3449             }
3450         }
3451 
3452         @Override
getMagnificationRegion()3453         public Region getMagnificationRegion() {
3454             synchronized (mLock) {
3455                 final Region region = Region.obtain();
3456                 if (!isCalledForCurrentUserLocked()) {
3457                     return region;
3458                 }
3459                 MagnificationController magnificationController = getMagnificationController();
3460                 boolean forceRegistration = mSecurityPolicy.canControlMagnification(this);
3461                 boolean initiallyRegistered = magnificationController.isRegisteredLocked();
3462                 if (!initiallyRegistered && forceRegistration) {
3463                     magnificationController.register();
3464                 }
3465                 final long identity = Binder.clearCallingIdentity();
3466                 try {
3467                     magnificationController.getMagnificationRegion(region);
3468                     return region;
3469                 } finally {
3470                     Binder.restoreCallingIdentity(identity);
3471                     if (!initiallyRegistered && forceRegistration) {
3472                         magnificationController.unregister();
3473                     }
3474                 }
3475             }
3476         }
3477 
3478         @Override
getMagnificationCenterX()3479         public float getMagnificationCenterX() {
3480             synchronized (mLock) {
3481                 if (!isCalledForCurrentUserLocked()) {
3482                     return 0.0f;
3483                 }
3484             }
3485             final long identity = Binder.clearCallingIdentity();
3486             try {
3487                 return getMagnificationController().getCenterX();
3488             } finally {
3489                 Binder.restoreCallingIdentity(identity);
3490             }
3491         }
3492 
3493         @Override
getMagnificationCenterY()3494         public float getMagnificationCenterY() {
3495             synchronized (mLock) {
3496                 if (!isCalledForCurrentUserLocked()) {
3497                     return 0.0f;
3498                 }
3499             }
3500             final long identity = Binder.clearCallingIdentity();
3501             try {
3502                 return getMagnificationController().getCenterY();
3503             } finally {
3504                 Binder.restoreCallingIdentity(identity);
3505             }
3506         }
3507 
3508         @Override
resetMagnification(boolean animate)3509         public boolean resetMagnification(boolean animate) {
3510             synchronized (mLock) {
3511                 if (!isCalledForCurrentUserLocked()) {
3512                     return false;
3513                 }
3514                 final boolean permissionGranted = mSecurityPolicy.canControlMagnification(this);
3515                 if (!permissionGranted) {
3516                     return false;
3517                 }
3518             }
3519             final long identity = Binder.clearCallingIdentity();
3520             try {
3521                 return getMagnificationController().reset(animate);
3522             } finally {
3523                 Binder.restoreCallingIdentity(identity);
3524             }
3525         }
3526 
3527         @Override
setMagnificationScaleAndCenter(float scale, float centerX, float centerY, boolean animate)3528         public boolean setMagnificationScaleAndCenter(float scale, float centerX, float centerY,
3529                 boolean animate) {
3530             synchronized (mLock) {
3531                 if (!isCalledForCurrentUserLocked()) {
3532                     return false;
3533                 }
3534                 final boolean permissionGranted = mSecurityPolicy.canControlMagnification(this);
3535                 if (!permissionGranted) {
3536                     return false;
3537                 }
3538                 final long identity = Binder.clearCallingIdentity();
3539                 try {
3540                     MagnificationController magnificationController = getMagnificationController();
3541                     if (!magnificationController.isRegisteredLocked()) {
3542                         magnificationController.register();
3543                     }
3544                     return magnificationController
3545                             .setScaleAndCenter(scale, centerX, centerY, animate, mId);
3546                 } finally {
3547                     Binder.restoreCallingIdentity(identity);
3548                 }
3549             }
3550         }
3551 
3552         @Override
setMagnificationCallbackEnabled(boolean enabled)3553         public void setMagnificationCallbackEnabled(boolean enabled) {
3554             mInvocationHandler.setMagnificationCallbackEnabled(enabled);
3555         }
3556 
3557         @Override
setSoftKeyboardShowMode(int showMode)3558         public boolean setSoftKeyboardShowMode(int showMode) {
3559             final UserState userState;
3560             synchronized (mLock) {
3561                 if (!isCalledForCurrentUserLocked()) {
3562                     return false;
3563                 }
3564 
3565                 userState = getCurrentUserStateLocked();
3566             }
3567 
3568             final long identity = Binder.clearCallingIdentity();
3569             try {
3570                 // Keep track of the last service to request a non-default show mode. The show mode
3571                 // should be restored to default should this service be disabled.
3572                 if (showMode == Settings.Secure.SHOW_MODE_AUTO) {
3573                     userState.mServiceChangingSoftKeyboardMode = null;
3574                 } else {
3575                     userState.mServiceChangingSoftKeyboardMode = mComponentName;
3576                 }
3577 
3578                 Settings.Secure.putIntForUser(mContext.getContentResolver(),
3579                         Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, showMode,
3580                         userState.mUserId);
3581             } finally {
3582                 Binder.restoreCallingIdentity(identity);
3583             }
3584             return true;
3585         }
3586 
3587         @Override
setSoftKeyboardCallbackEnabled(boolean enabled)3588         public void setSoftKeyboardCallbackEnabled(boolean enabled) {
3589             mInvocationHandler.setSoftKeyboardCallbackEnabled(enabled);
3590         }
3591 
3592         @Override
isAccessibilityButtonAvailable()3593         public boolean isAccessibilityButtonAvailable() {
3594             final UserState userState;
3595             synchronized (mLock) {
3596                 if (!isCalledForCurrentUserLocked()) {
3597                     return false;
3598                 }
3599                 userState = getCurrentUserStateLocked();
3600                 return isAccessibilityButtonAvailableLocked(userState);
3601             }
3602         }
3603 
3604         @Override
dump(FileDescriptor fd, final PrintWriter pw, String[] args)3605         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
3606             if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
3607             synchronized (mLock) {
3608                 pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo()
3609                         .loadLabel(mContext.getPackageManager()));
3610                 pw.append(", feedbackType"
3611                         + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType));
3612                 pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities());
3613                 pw.append(", eventTypes="
3614                         + AccessibilityEvent.eventTypeToString(mEventTypes));
3615                 pw.append(", notificationTimeout=" + mNotificationTimeout);
3616                 pw.append("]");
3617             }
3618         }
3619 
3620         @Override
onServiceDisconnected(ComponentName componentName)3621         public void onServiceDisconnected(ComponentName componentName) {
3622             binderDied();
3623         }
3624 
onAdded()3625         public void onAdded() throws RemoteException {
3626             final long identity = Binder.clearCallingIdentity();
3627             try {
3628                 mWindowManagerService.addWindowToken(mOverlayWindowToken,
3629                         TYPE_ACCESSIBILITY_OVERLAY, DEFAULT_DISPLAY);
3630             } finally {
3631                 Binder.restoreCallingIdentity(identity);
3632             }
3633         }
3634 
onRemoved()3635         public void onRemoved() {
3636             final long identity = Binder.clearCallingIdentity();
3637             try {
3638                 mWindowManagerService.removeWindowToken(mOverlayWindowToken, true, DEFAULT_DISPLAY);
3639             } finally {
3640                 Binder.restoreCallingIdentity(identity);
3641             }
3642         }
3643 
resetLocked()3644         public void resetLocked() {
3645             try {
3646                 // Clear the proxy in the other process so this
3647                 // IAccessibilityServiceConnection can be garbage collected.
3648                 if (mServiceInterface != null) {
3649                     mServiceInterface.init(null, mId, null);
3650                 }
3651             } catch (RemoteException re) {
3652                 /* ignore */
3653             }
3654             if (mService != null) {
3655                 mService.unlinkToDeath(this, 0);
3656                 mService = null;
3657             }
3658             mServiceInterface = null;
3659             mReceivedAccessibilityButtonCallbackSinceBind = false;
3660         }
3661 
isConnectedLocked()3662         public boolean isConnectedLocked() {
3663             return (mService != null);
3664         }
3665 
binderDied()3666         public void binderDied() {
3667             synchronized (mLock) {
3668                 // It is possible that this service's package was force stopped during
3669                 // whose handling the death recipient is unlinked and still get a call
3670                 // on binderDied since the call was made before we unlink but was
3671                 // waiting on the lock we held during the force stop handling.
3672                 if (!isConnectedLocked()) {
3673                     return;
3674                 }
3675                 mWasConnectedAndDied = true;
3676                 getKeyEventDispatcher().flush(this);
3677                 UserState userState = getUserStateLocked(mUserId);
3678                 resetLocked();
3679                 if (mIsAutomation) {
3680                     // This is typically done when unbinding, but UiAutomation isn't bound.
3681                     removeServiceLocked(this, userState);
3682                     // We no longer have an automation service, so restore
3683                     // the state based on values in the settings database.
3684                     userState.mInstalledServices.remove(mAccessibilityServiceInfo);
3685                     userState.mEnabledServices.remove(mComponentName);
3686                     userState.destroyUiAutomationService();
3687                     readConfigurationForUserStateLocked(userState);
3688                 }
3689                 if (mId == getMagnificationController().getIdOfLastServiceToMagnify()) {
3690                     getMagnificationController().resetIfNeeded(true);
3691                 }
3692                 onUserStateChangedLocked(userState);
3693             }
3694         }
3695 
3696         /**
3697          * Performs a notification for an {@link AccessibilityEvent}.
3698          *
3699          * @param event The event.
3700          * @param serviceWantsEvent whether the event should be received by
3701          *  {@link AccessibilityService#onAccessibilityEvent} (true),
3702          *  as opposed to just {@link AccessibilityInteractionClient#onAccessibilityEvent} (false)
3703          */
notifyAccessibilityEvent(AccessibilityEvent event, boolean serviceWantsEvent)3704         public void notifyAccessibilityEvent(AccessibilityEvent event, boolean serviceWantsEvent) {
3705             synchronized (mLock) {
3706                 final int eventType = event.getEventType();
3707                 // Make a copy since during dispatch it is possible the event to
3708                 // be modified to remove its source if the receiving service does
3709                 // not have permission to access the window content.
3710                 AccessibilityEvent newEvent = AccessibilityEvent.obtain(event);
3711                 Message message;
3712                 if ((mNotificationTimeout > 0)
3713                         && (eventType != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)) {
3714                     // Allow at most one pending event
3715                     final AccessibilityEvent oldEvent = mPendingEvents.get(eventType);
3716                     mPendingEvents.put(eventType, newEvent);
3717                     if (oldEvent != null) {
3718                         mEventDispatchHandler.removeMessages(eventType);
3719                         oldEvent.recycle();
3720                     }
3721                     message = mEventDispatchHandler.obtainMessage(eventType);
3722                 } else {
3723                     // Send all messages, bypassing mPendingEvents
3724                     message = mEventDispatchHandler.obtainMessage(eventType, newEvent);
3725                 }
3726                 message.arg1 = serviceWantsEvent ? 1 : 0;
3727 
3728                 mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout);
3729             }
3730         }
3731 
isAccessibilityButtonAvailableLocked(UserState userState)3732         private boolean isAccessibilityButtonAvailableLocked(UserState userState) {
3733             // If the service does not request the accessibility button, it isn't available
3734             if (!mRequestAccessibilityButton) {
3735                 return false;
3736             }
3737 
3738             // If the accessibility button isn't currently shown, it cannot be available to services
3739             if (!mIsAccessibilityButtonShown) {
3740                 return false;
3741             }
3742 
3743             // If magnification is on and assigned to the accessibility button, services cannot be
3744             if (userState.mIsNavBarMagnificationEnabled
3745                     && userState.mIsNavBarMagnificationAssignedToAccessibilityButton) {
3746                 return false;
3747             }
3748 
3749             int requestingServices = 0;
3750             for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
3751                 final Service service = userState.mBoundServices.get(i);
3752                 if (service.mRequestAccessibilityButton) {
3753                     requestingServices++;
3754                 }
3755             }
3756 
3757             if (requestingServices == 1) {
3758                 // If only a single service is requesting, it must be this service, and the
3759                 // accessibility button is available to it
3760                 return true;
3761             } else {
3762                 // With more than one active service, we derive the target from the user's settings
3763                 if (userState.mServiceAssignedToAccessibilityButton == null) {
3764                     // If the user has not made an assignment, we treat the button as available to
3765                     // all services until the user interacts with the button to make an assignment
3766                     return true;
3767                 } else {
3768                     // If an assignment was made, it defines availability
3769                     return mComponentName.equals(userState.mServiceAssignedToAccessibilityButton);
3770                 }
3771             }
3772         }
3773 
3774         /**
3775          * Notifies an accessibility service client for a scheduled event given the event type.
3776          *
3777          * @param eventType The type of the event to dispatch.
3778          */
notifyAccessibilityEventInternal( int eventType, AccessibilityEvent event, boolean serviceWantsEvent)3779         private void notifyAccessibilityEventInternal(
3780                 int eventType,
3781                 AccessibilityEvent event,
3782                 boolean serviceWantsEvent) {
3783             IAccessibilityServiceClient listener;
3784 
3785             synchronized (mLock) {
3786                 listener = mServiceInterface;
3787 
3788                 // If the service died/was disabled while the message for dispatching
3789                 // the accessibility event was propagating the listener may be null.
3790                 if (listener == null) {
3791                     return;
3792                 }
3793 
3794                 // There are two ways we notify for events, throttled and non-throttled. If we
3795                 // are not throttling, then messages come with events, which we handle with
3796                 // minimal fuss.
3797                 if (event == null) {
3798                     // We are throttling events, so we'll send the event for this type in
3799                     // mPendingEvents as long as it it's null. It can only null due to a race
3800                     // condition:
3801                     //
3802                     //   1) A binder thread calls notifyAccessibilityServiceDelayedLocked
3803                     //      which posts a message for dispatching an event and stores the event
3804                     //      in mPendingEvents.
3805                     //   2) The message is pulled from the queue by the handler on the service
3806                     //      thread and this method is just about to acquire the lock.
3807                     //   3) Another binder thread acquires the lock in notifyAccessibilityEvent
3808                     //   4) notifyAccessibilityEvent recycles the event that this method was about
3809                     //      to process, replaces it with a new one, and posts a second message
3810                     //   5) This method grabs the new event, processes it, and removes it from
3811                     //      mPendingEvents
3812                     //   6) The second message dispatched in (4) arrives, but the event has been
3813                     //      remvoved in (5).
3814                     event = mPendingEvents.get(eventType);
3815                     if (event == null) {
3816                         return;
3817                     }
3818                     mPendingEvents.remove(eventType);
3819                 }
3820                 if (mSecurityPolicy.canRetrieveWindowContentLocked(this)) {
3821                     event.setConnectionId(mId);
3822                 } else {
3823                     event.setSource((View) null);
3824                 }
3825                 event.setSealed(true);
3826             }
3827 
3828             try {
3829                 listener.onAccessibilityEvent(event, serviceWantsEvent);
3830                 if (DEBUG) {
3831                     Slog.i(LOG_TAG, "Event " + event + " sent to " + listener);
3832                 }
3833             } catch (RemoteException re) {
3834                 Slog.e(LOG_TAG, "Error during sending " + event + " to " + listener, re);
3835             } finally {
3836                 event.recycle();
3837             }
3838         }
3839 
notifyGesture(int gestureId)3840         public void notifyGesture(int gestureId) {
3841             mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE,
3842                     gestureId, 0).sendToTarget();
3843         }
3844 
notifyClearAccessibilityNodeInfoCache()3845         public void notifyClearAccessibilityNodeInfoCache() {
3846             mInvocationHandler.sendEmptyMessage(
3847                     InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE);
3848         }
3849 
notifyMagnificationChangedLocked(@onNull Region region, float scale, float centerX, float centerY)3850         public void notifyMagnificationChangedLocked(@NonNull Region region,
3851                 float scale, float centerX, float centerY) {
3852             mInvocationHandler
3853                     .notifyMagnificationChangedLocked(region, scale, centerX, centerY);
3854         }
3855 
notifySoftKeyboardShowModeChangedLocked(int showState)3856         public void notifySoftKeyboardShowModeChangedLocked(int showState) {
3857             mInvocationHandler.notifySoftKeyboardShowModeChangedLocked(showState);
3858         }
3859 
notifyAccessibilityButtonClickedLocked()3860         public void notifyAccessibilityButtonClickedLocked() {
3861             mInvocationHandler.notifyAccessibilityButtonClickedLocked();
3862         }
3863 
notifyAccessibilityButtonAvailabilityChangedLocked(boolean available)3864         public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) {
3865             mInvocationHandler.notifyAccessibilityButtonAvailabilityChangedLocked(available);
3866         }
3867 
3868         /**
3869          * Called by the invocation handler to notify the service that the
3870          * state of magnification has changed.
3871          */
notifyMagnificationChangedInternal(@onNull Region region, float scale, float centerX, float centerY)3872         private void notifyMagnificationChangedInternal(@NonNull Region region,
3873                 float scale, float centerX, float centerY) {
3874             final IAccessibilityServiceClient listener;
3875             synchronized (mLock) {
3876                 listener = mServiceInterface;
3877             }
3878             if (listener != null) {
3879                 try {
3880                     listener.onMagnificationChanged(region, scale, centerX, centerY);
3881                 } catch (RemoteException re) {
3882                     Slog.e(LOG_TAG, "Error sending magnification changes to " + mService, re);
3883                 }
3884             }
3885         }
3886 
3887         /**
3888          * Called by the invocation handler to notify the service that the state of the soft
3889          * keyboard show mode has changed.
3890          */
notifySoftKeyboardShowModeChangedInternal(int showState)3891         private void notifySoftKeyboardShowModeChangedInternal(int showState) {
3892             final IAccessibilityServiceClient listener;
3893             synchronized (mLock) {
3894                 listener = mServiceInterface;
3895             }
3896             if (listener != null) {
3897                 try {
3898                     listener.onSoftKeyboardShowModeChanged(showState);
3899                 } catch (RemoteException re) {
3900                     Slog.e(LOG_TAG, "Error sending soft keyboard show mode changes to " + mService,
3901                             re);
3902                 }
3903             }
3904         }
3905 
notifyAccessibilityButtonClickedInternal()3906         private void notifyAccessibilityButtonClickedInternal() {
3907             final IAccessibilityServiceClient listener;
3908             synchronized (mLock) {
3909                 listener = mServiceInterface;
3910             }
3911             if (listener != null) {
3912                 try {
3913                     listener.onAccessibilityButtonClicked();
3914                 } catch (RemoteException re) {
3915                     Slog.e(LOG_TAG, "Error sending accessibility button click to " + mService, re);
3916                 }
3917             }
3918         }
3919 
notifyAccessibilityButtonAvailabilityChangedInternal(boolean available)3920         private void notifyAccessibilityButtonAvailabilityChangedInternal(boolean available) {
3921             // Only notify the service if it's not been notified or the state has changed
3922             if (mReceivedAccessibilityButtonCallbackSinceBind
3923                     && (mLastAccessibilityButtonCallbackState == available)) {
3924                 return;
3925             }
3926             mReceivedAccessibilityButtonCallbackSinceBind = true;
3927             mLastAccessibilityButtonCallbackState = available;
3928             final IAccessibilityServiceClient listener;
3929             synchronized (mLock) {
3930                 listener = mServiceInterface;
3931             }
3932             if (listener != null) {
3933                 try {
3934                     listener.onAccessibilityButtonAvailabilityChanged(available);
3935                 } catch (RemoteException re) {
3936                     Slog.e(LOG_TAG,
3937                             "Error sending accessibility button availability change to " + mService,
3938                             re);
3939                 }
3940             }
3941         }
3942 
notifyGestureInternal(int gestureId)3943         private void notifyGestureInternal(int gestureId) {
3944             final IAccessibilityServiceClient listener;
3945             synchronized (mLock) {
3946                 listener = mServiceInterface;
3947             }
3948             if (listener != null) {
3949                 try {
3950                     listener.onGesture(gestureId);
3951                 } catch (RemoteException re) {
3952                     Slog.e(LOG_TAG, "Error during sending gesture " + gestureId
3953                             + " to " + mService, re);
3954                 }
3955             }
3956         }
3957 
notifyClearAccessibilityCacheInternal()3958         private void notifyClearAccessibilityCacheInternal() {
3959             final IAccessibilityServiceClient listener;
3960             synchronized (mLock) {
3961                 listener = mServiceInterface;
3962             }
3963             if (listener != null) {
3964                 try {
3965                     listener.clearAccessibilityCache();
3966                 } catch (RemoteException re) {
3967                     Slog.e(LOG_TAG, "Error during requesting accessibility info cache"
3968                             + " to be cleared.", re);
3969                 }
3970             }
3971         }
3972 
sendDownAndUpKeyEvents(int keyCode)3973         private void sendDownAndUpKeyEvents(int keyCode) {
3974             final long token = Binder.clearCallingIdentity();
3975 
3976             // Inject down.
3977             final long downTime = SystemClock.uptimeMillis();
3978             KeyEvent down = KeyEvent.obtain(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode, 0, 0,
3979                     KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
3980                     InputDevice.SOURCE_KEYBOARD, null);
3981             InputManager.getInstance().injectInputEvent(down,
3982                     InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
3983             down.recycle();
3984 
3985             // Inject up.
3986             final long upTime = SystemClock.uptimeMillis();
3987             KeyEvent up = KeyEvent.obtain(downTime, upTime, KeyEvent.ACTION_UP, keyCode, 0, 0,
3988                     KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
3989                     InputDevice.SOURCE_KEYBOARD, null);
3990             InputManager.getInstance().injectInputEvent(up,
3991                     InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
3992             up.recycle();
3993 
3994             Binder.restoreCallingIdentity(token);
3995         }
3996 
expandNotifications()3997         private void expandNotifications() {
3998             final long token = Binder.clearCallingIdentity();
3999 
4000             StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService(
4001                     android.app.Service.STATUS_BAR_SERVICE);
4002             statusBarManager.expandNotificationsPanel();
4003 
4004             Binder.restoreCallingIdentity(token);
4005         }
4006 
expandQuickSettings()4007         private void expandQuickSettings() {
4008             final long token = Binder.clearCallingIdentity();
4009 
4010             StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService(
4011                     android.app.Service.STATUS_BAR_SERVICE);
4012             statusBarManager.expandSettingsPanel();
4013 
4014             Binder.restoreCallingIdentity(token);
4015         }
4016 
openRecents()4017         private boolean openRecents() {
4018             final long token = Binder.clearCallingIdentity();
4019             try {
4020                 StatusBarManagerInternal statusBarService = LocalServices.getService(
4021                         StatusBarManagerInternal.class);
4022                 if (statusBarService == null) {
4023                     return false;
4024                 }
4025                 statusBarService.toggleRecentApps();
4026             } finally {
4027                 Binder.restoreCallingIdentity(token);
4028             }
4029             return true;
4030         }
4031 
showGlobalActions()4032         private void showGlobalActions() {
4033             mWindowManagerService.showGlobalActions();
4034         }
4035 
toggleSplitScreen()4036         private void toggleSplitScreen() {
4037             LocalServices.getService(StatusBarManagerInternal.class).toggleSplitScreen();
4038         }
4039 
getConnectionLocked(int windowId)4040         private IAccessibilityInteractionConnection getConnectionLocked(int windowId) {
4041             if (DEBUG) {
4042                 Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId);
4043             }
4044             AccessibilityConnectionWrapper wrapper = mGlobalInteractionConnections.get(windowId);
4045             if (wrapper == null) {
4046                 wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId);
4047             }
4048             if (wrapper != null && wrapper.mConnection != null) {
4049                 return wrapper.mConnection;
4050             }
4051             if (DEBUG) {
4052                 Slog.e(LOG_TAG, "No interaction connection to window: " + windowId);
4053             }
4054             return null;
4055         }
4056 
resolveAccessibilityWindowIdLocked(int accessibilityWindowId)4057         private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) {
4058             if (accessibilityWindowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) {
4059                 return mSecurityPolicy.getActiveWindowId();
4060             }
4061             return accessibilityWindowId;
4062         }
4063 
resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType)4064         private int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) {
4065             if (windowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) {
4066                 return mSecurityPolicy.mActiveWindowId;
4067             }
4068             if (windowId == AccessibilityWindowInfo.ANY_WINDOW_ID) {
4069                 if (focusType == AccessibilityNodeInfo.FOCUS_INPUT) {
4070                     return mSecurityPolicy.mFocusedWindowId;
4071                 } else if (focusType == AccessibilityNodeInfo.FOCUS_ACCESSIBILITY) {
4072                     return mSecurityPolicy.mAccessibilityFocusedWindowId;
4073                 }
4074             }
4075             return windowId;
4076         }
4077 
replaceCallbackIfNeeded( IAccessibilityInteractionConnectionCallback originalCallback, int resolvedWindowId, int interactionId, int interrogatingPid, long interrogatingTid)4078         private IAccessibilityInteractionConnectionCallback replaceCallbackIfNeeded(
4079                 IAccessibilityInteractionConnectionCallback originalCallback,
4080                 int resolvedWindowId, int interactionId, int interrogatingPid,
4081                 long interrogatingTid) {
4082             AccessibilityWindowInfo windowInfo = mSecurityPolicy.findWindowById(resolvedWindowId);
4083             if ((windowInfo == null) || !windowInfo.inPictureInPicture()
4084                     || (mPictureInPictureActionReplacingConnection == null)) {
4085                 return originalCallback;
4086             }
4087             return new ActionReplacingCallback(originalCallback,
4088                     mPictureInPictureActionReplacingConnection.mConnection, interactionId,
4089                     interrogatingPid, interrogatingTid);
4090         }
4091 
4092         private final class InvocationHandler extends Handler {
4093             public static final int MSG_ON_GESTURE = 1;
4094             public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 2;
4095 
4096             private static final int MSG_ON_MAGNIFICATION_CHANGED = 5;
4097             private static final int MSG_ON_SOFT_KEYBOARD_STATE_CHANGED = 6;
4098             private static final int MSG_ON_ACCESSIBILITY_BUTTON_CLICKED = 7;
4099             private static final int MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED = 8;
4100 
4101             private boolean mIsMagnificationCallbackEnabled = false;
4102             private boolean mIsSoftKeyboardCallbackEnabled = false;
4103 
InvocationHandler(Looper looper)4104             public InvocationHandler(Looper looper) {
4105                 super(looper, null, true);
4106             }
4107 
4108             @Override
handleMessage(Message message)4109             public void handleMessage(Message message) {
4110                 final int type = message.what;
4111                 switch (type) {
4112                     case MSG_ON_GESTURE: {
4113                         final int gestureId = message.arg1;
4114                         notifyGestureInternal(gestureId);
4115                     } break;
4116 
4117                     case MSG_CLEAR_ACCESSIBILITY_CACHE: {
4118                         notifyClearAccessibilityCacheInternal();
4119                     } break;
4120 
4121                     case MSG_ON_MAGNIFICATION_CHANGED: {
4122                         final SomeArgs args = (SomeArgs) message.obj;
4123                         final Region region = (Region) args.arg1;
4124                         final float scale = (float) args.arg2;
4125                         final float centerX = (float) args.arg3;
4126                         final float centerY = (float) args.arg4;
4127                         notifyMagnificationChangedInternal(region, scale, centerX, centerY);
4128                     } break;
4129 
4130                     case MSG_ON_SOFT_KEYBOARD_STATE_CHANGED: {
4131                         final int showState = (int) message.arg1;
4132                         notifySoftKeyboardShowModeChangedInternal(showState);
4133                     } break;
4134 
4135                     case MSG_ON_ACCESSIBILITY_BUTTON_CLICKED: {
4136                         notifyAccessibilityButtonClickedInternal();
4137                     } break;
4138 
4139                     case MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED: {
4140                         final boolean available = (message.arg1 != 0);
4141                         notifyAccessibilityButtonAvailabilityChangedInternal(available);
4142                     } break;
4143 
4144                     default: {
4145                         throw new IllegalArgumentException("Unknown message: " + type);
4146                     }
4147                 }
4148             }
4149 
notifyMagnificationChangedLocked(@onNull Region region, float scale, float centerX, float centerY)4150             public void notifyMagnificationChangedLocked(@NonNull Region region, float scale,
4151                     float centerX, float centerY) {
4152                 if (!mIsMagnificationCallbackEnabled) {
4153                     // Callback is disabled, don't bother packing args.
4154                     return;
4155                 }
4156 
4157                 final SomeArgs args = SomeArgs.obtain();
4158                 args.arg1 = region;
4159                 args.arg2 = scale;
4160                 args.arg3 = centerX;
4161                 args.arg4 = centerY;
4162 
4163                 final Message msg = obtainMessage(MSG_ON_MAGNIFICATION_CHANGED, args);
4164                 msg.sendToTarget();
4165             }
4166 
setMagnificationCallbackEnabled(boolean enabled)4167             public void setMagnificationCallbackEnabled(boolean enabled) {
4168                 mIsMagnificationCallbackEnabled = enabled;
4169             }
4170 
notifySoftKeyboardShowModeChangedLocked(int showState)4171             public void notifySoftKeyboardShowModeChangedLocked(int showState) {
4172                 if (!mIsSoftKeyboardCallbackEnabled) {
4173                     return;
4174                 }
4175 
4176                 final Message msg = obtainMessage(MSG_ON_SOFT_KEYBOARD_STATE_CHANGED, showState, 0);
4177                 msg.sendToTarget();
4178             }
4179 
setSoftKeyboardCallbackEnabled(boolean enabled)4180             public void setSoftKeyboardCallbackEnabled(boolean enabled) {
4181                 mIsSoftKeyboardCallbackEnabled = enabled;
4182             }
4183 
notifyAccessibilityButtonClickedLocked()4184             public void notifyAccessibilityButtonClickedLocked() {
4185                 final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_CLICKED);
4186                 msg.sendToTarget();
4187             }
4188 
notifyAccessibilityButtonAvailabilityChangedLocked(boolean available)4189             public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) {
4190                 final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED,
4191                         (available ? 1 : 0), 0);
4192                 msg.sendToTarget();
4193             }
4194         }
4195     }
4196 
4197     final class WindowsForAccessibilityCallback implements
4198             WindowManagerInternal.WindowsForAccessibilityCallback {
4199 
4200         @Override
onWindowsForAccessibilityChanged(List<WindowInfo> windows)4201         public void onWindowsForAccessibilityChanged(List<WindowInfo> windows) {
4202             synchronized (mLock) {
4203                 // Populate the windows to report.
4204                 List<AccessibilityWindowInfo> reportedWindows = new ArrayList<>();
4205                 final int receivedWindowCount = windows.size();
4206                 for (int i = 0; i < receivedWindowCount; i++) {
4207                     WindowInfo receivedWindow = windows.get(i);
4208                     AccessibilityWindowInfo reportedWindow = populateReportedWindow(
4209                             receivedWindow);
4210                     if (reportedWindow != null) {
4211                         reportedWindows.add(reportedWindow);
4212                     }
4213                 }
4214 
4215                 if (DEBUG) {
4216                     Slog.i(LOG_TAG, "Windows changed: " + reportedWindows);
4217                 }
4218 
4219                 // Let the policy update the focused and active windows.
4220                 mSecurityPolicy.updateWindowsLocked(reportedWindows);
4221 
4222                 // Someone may be waiting for the windows - advertise it.
4223                 mLock.notifyAll();
4224             }
4225         }
4226 
populateReportedWindow(WindowInfo window)4227         private AccessibilityWindowInfo populateReportedWindow(WindowInfo window) {
4228             final int windowId = findWindowIdLocked(window.token);
4229             if (windowId < 0) {
4230                 return null;
4231             }
4232 
4233             AccessibilityWindowInfo reportedWindow = AccessibilityWindowInfo.obtain();
4234 
4235             reportedWindow.setId(windowId);
4236             reportedWindow.setType(getTypeForWindowManagerWindowType(window.type));
4237             reportedWindow.setLayer(window.layer);
4238             reportedWindow.setFocused(window.focused);
4239             reportedWindow.setBoundsInScreen(window.boundsInScreen);
4240             reportedWindow.setTitle(window.title);
4241             reportedWindow.setAnchorId(window.accessibilityIdOfAnchor);
4242             reportedWindow.setPictureInPicture(window.inPictureInPicture);
4243 
4244             final int parentId = findWindowIdLocked(window.parentToken);
4245             if (parentId >= 0) {
4246                 reportedWindow.setParentId(parentId);
4247             }
4248 
4249             if (window.childTokens != null) {
4250                 final int childCount = window.childTokens.size();
4251                 for (int i = 0; i < childCount; i++) {
4252                     IBinder childToken = window.childTokens.get(i);
4253                     final int childId = findWindowIdLocked(childToken);
4254                     if (childId >= 0) {
4255                         reportedWindow.addChild(childId);
4256                     }
4257                 }
4258             }
4259 
4260             return reportedWindow;
4261         }
4262 
getTypeForWindowManagerWindowType(int windowType)4263         private int getTypeForWindowManagerWindowType(int windowType) {
4264             switch (windowType) {
4265                 case WindowManager.LayoutParams.TYPE_APPLICATION:
4266                 case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA:
4267                 case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL:
4268                 case WindowManager.LayoutParams.TYPE_APPLICATION_STARTING:
4269                 case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL:
4270                 case WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL:
4271                 case WindowManager.LayoutParams.TYPE_BASE_APPLICATION:
4272                 case WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION:
4273                 case WindowManager.LayoutParams.TYPE_PHONE:
4274                 case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE:
4275                 case WindowManager.LayoutParams.TYPE_TOAST:
4276                 case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG: {
4277                     return AccessibilityWindowInfo.TYPE_APPLICATION;
4278                 }
4279 
4280                 case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
4281                 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: {
4282                     return AccessibilityWindowInfo.TYPE_INPUT_METHOD;
4283                 }
4284 
4285                 case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG:
4286                 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
4287                 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL:
4288                 case WindowManager.LayoutParams.TYPE_SEARCH_BAR:
4289                 case WindowManager.LayoutParams.TYPE_STATUS_BAR:
4290                 case WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL:
4291                 case WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL:
4292                 case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY:
4293                 case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
4294                 case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
4295                 case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
4296                 case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
4297                 case WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY:
4298                 case WindowManager.LayoutParams.TYPE_SCREENSHOT: {
4299                     return AccessibilityWindowInfo.TYPE_SYSTEM;
4300                 }
4301 
4302                 case WindowManager.LayoutParams.TYPE_DOCK_DIVIDER: {
4303                     return AccessibilityWindowInfo.TYPE_SPLIT_SCREEN_DIVIDER;
4304                 }
4305 
4306                 case TYPE_ACCESSIBILITY_OVERLAY: {
4307                     return AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY;
4308                 }
4309 
4310                 default: {
4311                     return -1;
4312                 }
4313             }
4314         }
4315     }
4316 
4317     private final class InteractionBridge {
4318         private final Display mDefaultDisplay;
4319         private final int mConnectionId;
4320         private final AccessibilityInteractionClient mClient;
4321 
InteractionBridge()4322         public InteractionBridge() {
4323             AccessibilityServiceInfo info = new AccessibilityServiceInfo();
4324             info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
4325             info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
4326             info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
4327             Service service = new Service(UserHandle.USER_NULL,
4328                     sFakeAccessibilityServiceComponentName, info);
4329 
4330             mConnectionId = service.mId;
4331 
4332             mClient = AccessibilityInteractionClient.getInstance();
4333             mClient.addConnection(mConnectionId, service);
4334 
4335             //TODO: (multi-display) We need to support multiple displays.
4336             DisplayManager displayManager = (DisplayManager)
4337                     mContext.getSystemService(Context.DISPLAY_SERVICE);
4338             mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
4339         }
4340 
clearAccessibilityFocusNotLocked(int windowId)4341         public void clearAccessibilityFocusNotLocked(int windowId) {
4342             AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked(windowId);
4343             if (focus != null) {
4344                 focus.performAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
4345             }
4346         }
4347 
4348         /**
4349          * Perform an accessibility action on the view that currently has accessibility focus.
4350          * Has no effect if no item has accessibility focus, if the item with accessibility
4351          * focus does not expose the specified action, or if the action fails.
4352          *
4353          * @param actionId The id of the action to perform.
4354          *
4355          * @return {@code true} if the action was performed. {@code false} if it was not.
4356          */
performActionOnAccessibilityFocusedItemNotLocked( AccessibilityNodeInfo.AccessibilityAction action)4357         public boolean performActionOnAccessibilityFocusedItemNotLocked(
4358                 AccessibilityNodeInfo.AccessibilityAction action) {
4359             AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked();
4360             if ((focus == null) || !focus.getActionList().contains(action)) {
4361                 return false;
4362             }
4363             return focus.performAction(action.getId());
4364         }
4365 
getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint)4366         public boolean getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint) {
4367             AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked();
4368             if (focus == null) {
4369                 return false;
4370             }
4371 
4372             synchronized (mLock) {
4373                 Rect boundsInScreen = mTempRect;
4374                 focus.getBoundsInScreen(boundsInScreen);
4375 
4376                 // Apply magnification if needed.
4377                 MagnificationSpec spec = getCompatibleMagnificationSpecLocked(focus.getWindowId());
4378                 if (spec != null && !spec.isNop()) {
4379                     boundsInScreen.offset((int) -spec.offsetX, (int) -spec.offsetY);
4380                     boundsInScreen.scale(1 / spec.scale);
4381                 }
4382 
4383                 // Clip to the window bounds.
4384                 Rect windowBounds = mTempRect1;
4385                 getWindowBounds(focus.getWindowId(), windowBounds);
4386                 if (!boundsInScreen.intersect(windowBounds)) {
4387                     return false;
4388                 }
4389 
4390                 // Clip to the screen bounds.
4391                 Point screenSize = mTempPoint;
4392                 mDefaultDisplay.getRealSize(screenSize);
4393                 if (!boundsInScreen.intersect(0, 0, screenSize.x, screenSize.y)) {
4394                     return false;
4395                 }
4396 
4397                 outPoint.set(boundsInScreen.centerX(), boundsInScreen.centerY());
4398             }
4399 
4400             return true;
4401         }
4402 
getAccessibilityFocusNotLocked()4403         private AccessibilityNodeInfo getAccessibilityFocusNotLocked() {
4404             final int focusedWindowId;
4405             synchronized (mLock) {
4406                 focusedWindowId = mSecurityPolicy.mAccessibilityFocusedWindowId;
4407                 if (focusedWindowId == SecurityPolicy.INVALID_WINDOW_ID) {
4408                     return null;
4409                 }
4410             }
4411             return getAccessibilityFocusNotLocked(focusedWindowId);
4412         }
4413 
getAccessibilityFocusNotLocked(int windowId)4414         private AccessibilityNodeInfo getAccessibilityFocusNotLocked(int windowId) {
4415             return mClient.findFocus(mConnectionId,
4416                     windowId, AccessibilityNodeInfo.ROOT_NODE_ID,
4417                     AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
4418         }
4419     }
4420 
4421     final class SecurityPolicy {
4422         public static final int INVALID_WINDOW_ID = -1;
4423 
4424         private static final int RETRIEVAL_ALLOWING_EVENT_TYPES =
4425             AccessibilityEvent.TYPE_VIEW_CLICKED
4426             | AccessibilityEvent.TYPE_VIEW_FOCUSED
4427             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
4428             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
4429             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
4430             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
4431             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
4432             | AccessibilityEvent.TYPE_VIEW_SELECTED
4433             | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
4434             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
4435             | AccessibilityEvent.TYPE_VIEW_SCROLLED
4436             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
4437             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED
4438             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
4439 
4440         // In Z order
4441         public List<AccessibilityWindowInfo> mWindows;
4442         public SparseArray<AccessibilityWindowInfo> mWindowsById = new SparseArray<>();
4443 
4444         public int mActiveWindowId = INVALID_WINDOW_ID;
4445         public int mFocusedWindowId = INVALID_WINDOW_ID;
4446         public int mAccessibilityFocusedWindowId = INVALID_WINDOW_ID;
4447         public long mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
4448 
4449         private boolean mTouchInteractionInProgress;
4450 
canDispatchAccessibilityEventLocked(AccessibilityEvent event)4451         private boolean canDispatchAccessibilityEventLocked(AccessibilityEvent event) {
4452             final int eventType = event.getEventType();
4453             switch (eventType) {
4454                 // All events that are for changes in a global window
4455                 // state should *always* be dispatched.
4456                 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
4457                 case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
4458                 case AccessibilityEvent.TYPE_ANNOUNCEMENT:
4459                 // All events generated by the user touching the
4460                 // screen should *always* be dispatched.
4461                 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START:
4462                 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END:
4463                 case AccessibilityEvent.TYPE_GESTURE_DETECTION_START:
4464                 case AccessibilityEvent.TYPE_GESTURE_DETECTION_END:
4465                 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START:
4466                 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END:
4467                 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER:
4468                 case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT:
4469                 // Also always dispatch the event that assist is reading context.
4470                 case AccessibilityEvent.TYPE_ASSIST_READING_CONTEXT:
4471                 // Also windows changing should always be anounced.
4472                 case AccessibilityEvent.TYPE_WINDOWS_CHANGED: {
4473                     return true;
4474                 }
4475                 // All events for changes in window content should be
4476                 // dispatched *only* if this window is one of the windows
4477                 // the accessibility layer reports which are windows
4478                 // that a sighted user can touch.
4479                 default: {
4480                     return isRetrievalAllowingWindow(event.getWindowId());
4481                 }
4482             }
4483         }
4484 
clearWindowsLocked()4485         public void clearWindowsLocked() {
4486             List<AccessibilityWindowInfo> windows = Collections.emptyList();
4487             final int activeWindowId = mActiveWindowId;
4488             updateWindowsLocked(windows);
4489             mActiveWindowId = activeWindowId;
4490             mWindows = null;
4491         }
4492 
updateWindowsLocked(List<AccessibilityWindowInfo> windows)4493         public void updateWindowsLocked(List<AccessibilityWindowInfo> windows) {
4494             if (mWindows == null) {
4495                 mWindows = new ArrayList<>();
4496             }
4497 
4498             final int oldWindowCount = mWindows.size();
4499             for (int i = oldWindowCount - 1; i >= 0; i--) {
4500                 mWindows.remove(i).recycle();
4501             }
4502             mWindowsById.clear();
4503 
4504             mFocusedWindowId = INVALID_WINDOW_ID;
4505             if (!mTouchInteractionInProgress) {
4506                 mActiveWindowId = INVALID_WINDOW_ID;
4507             }
4508 
4509             // If the active window goes away while the user is touch exploring we
4510             // reset the active window id and wait for the next hover event from
4511             // under the user's finger to determine which one is the new one. It
4512             // is possible that the finger is not moving and the input system
4513             // filters out such events.
4514             boolean activeWindowGone = true;
4515 
4516             final int windowCount = windows.size();
4517             if (windowCount > 0) {
4518                 for (int i = 0; i < windowCount; i++) {
4519                     AccessibilityWindowInfo window = windows.get(i);
4520                     final int windowId = window.getId();
4521                     if (window.isFocused()) {
4522                         mFocusedWindowId = windowId;
4523                         if (!mTouchInteractionInProgress) {
4524                             mActiveWindowId = windowId;
4525                             window.setActive(true);
4526                         } else if (windowId == mActiveWindowId) {
4527                             activeWindowGone = false;
4528                         }
4529                     }
4530                     mWindows.add(window);
4531                     mWindowsById.put(windowId, window);
4532                 }
4533 
4534                 if (mTouchInteractionInProgress && activeWindowGone) {
4535                     mActiveWindowId = mFocusedWindowId;
4536                 }
4537 
4538                 // Focused window may change the active one, so set the
4539                 // active window once we decided which it is.
4540                 for (int i = 0; i < windowCount; i++) {
4541                     AccessibilityWindowInfo window = mWindows.get(i);
4542                     if (window.getId() == mActiveWindowId) {
4543                         window.setActive(true);
4544                     }
4545                     if (window.getId() == mAccessibilityFocusedWindowId) {
4546                         window.setAccessibilityFocused(true);
4547                     }
4548                 }
4549             }
4550 
4551             notifyWindowsChanged();
4552         }
4553 
computePartialInteractiveRegionForWindowLocked(int windowId, Region outRegion)4554         public boolean computePartialInteractiveRegionForWindowLocked(int windowId,
4555                 Region outRegion) {
4556             if (mWindows == null) {
4557                 return false;
4558             }
4559 
4560             // Windows are ordered in z order so start from the bottom and find
4561             // the window of interest. After that all windows that cover it should
4562             // be subtracted from the resulting region. Note that for accessibility
4563             // we are returning only interactive windows.
4564             Region windowInteractiveRegion = null;
4565             boolean windowInteractiveRegionChanged = false;
4566 
4567             final int windowCount = mWindows.size();
4568             for (int i = windowCount - 1; i >= 0; i--) {
4569                 AccessibilityWindowInfo currentWindow = mWindows.get(i);
4570                 if (windowInteractiveRegion == null) {
4571                     if (currentWindow.getId() == windowId) {
4572                         Rect currentWindowBounds = mTempRect;
4573                         currentWindow.getBoundsInScreen(currentWindowBounds);
4574                         outRegion.set(currentWindowBounds);
4575                         windowInteractiveRegion = outRegion;
4576                         continue;
4577                     }
4578                 } else if (currentWindow.getType()
4579                         != AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY) {
4580                     Rect currentWindowBounds = mTempRect;
4581                     currentWindow.getBoundsInScreen(currentWindowBounds);
4582                     if (windowInteractiveRegion.op(currentWindowBounds, Region.Op.DIFFERENCE)) {
4583                         windowInteractiveRegionChanged = true;
4584                     }
4585                 }
4586             }
4587 
4588             return windowInteractiveRegionChanged;
4589         }
4590 
updateEventSourceLocked(AccessibilityEvent event)4591         public void updateEventSourceLocked(AccessibilityEvent event) {
4592             if ((event.getEventType() & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) {
4593                 event.setSource((View) null);
4594             }
4595         }
4596 
updateActiveAndAccessibilityFocusedWindowLocked(int windowId, long nodeId, int eventType, int eventAction)4597         public void updateActiveAndAccessibilityFocusedWindowLocked(int windowId, long nodeId,
4598                 int eventType, int eventAction) {
4599             // The active window is either the window that has input focus or
4600             // the window that the user is currently touching. If the user is
4601             // touching a window that does not have input focus as soon as the
4602             // the user stops touching that window the focused window becomes
4603             // the active one. Here we detect the touched window and make it
4604             // active. In updateWindowsLocked() we update the focused window
4605             // and if the user is not touching the screen, we make the focused
4606             // window the active one.
4607             switch (eventType) {
4608                 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: {
4609                     // If no service has the capability to introspect screen,
4610                     // we do not register callback in the window manager for
4611                     // window changes, so we have to ask the window manager
4612                     // what the focused window is to update the active one.
4613                     // The active window also determined events from which
4614                     // windows are delivered.
4615                     synchronized (mLock) {
4616                         if (mWindowsForAccessibilityCallback == null) {
4617                             mFocusedWindowId = getFocusedWindowId();
4618                             if (windowId == mFocusedWindowId) {
4619                                 mActiveWindowId = windowId;
4620                             }
4621                         }
4622                     }
4623                 } break;
4624 
4625                 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: {
4626                     // Do not allow delayed hover events to confuse us
4627                     // which the active window is.
4628                     synchronized (mLock) {
4629                         if (mTouchInteractionInProgress && mActiveWindowId != windowId) {
4630                             setActiveWindowLocked(windowId);
4631                         }
4632                     }
4633                 } break;
4634 
4635                 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
4636                     synchronized (mLock) {
4637                         if (mAccessibilityFocusedWindowId != windowId) {
4638                             mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS,
4639                                     mAccessibilityFocusedWindowId, 0).sendToTarget();
4640                             mSecurityPolicy.setAccessibilityFocusedWindowLocked(windowId);
4641                             mAccessibilityFocusNodeId = nodeId;
4642                         }
4643                     }
4644                 } break;
4645 
4646                 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
4647                     synchronized (mLock) {
4648                         if (mAccessibilityFocusNodeId == nodeId) {
4649                             mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
4650                         }
4651                         // Clear the window with focus if it no longer has focus and we aren't
4652                         // just moving focus from one view to the other in the same window
4653                         if ((mAccessibilityFocusNodeId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID)
4654                                 && (mAccessibilityFocusedWindowId == windowId)
4655                                 && (eventAction != AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS)
4656                                 ) {
4657                             mAccessibilityFocusedWindowId = INVALID_WINDOW_ID;
4658                         }
4659                     }
4660                 } break;
4661             }
4662         }
4663 
onTouchInteractionStart()4664         public void onTouchInteractionStart() {
4665             synchronized (mLock) {
4666                 mTouchInteractionInProgress = true;
4667             }
4668         }
4669 
onTouchInteractionEnd()4670         public void onTouchInteractionEnd() {
4671             synchronized (mLock) {
4672                 mTouchInteractionInProgress = false;
4673                 // We want to set the active window to be current immediately
4674                 // after the user has stopped touching the screen since if the
4675                 // user types with the IME he should get a feedback for the
4676                 // letter typed in the text view which is in the input focused
4677                 // window. Note that we always deliver hover accessibility events
4678                 // (they are a result of user touching the screen) so change of
4679                 // the active window before all hover accessibility events from
4680                 // the touched window are delivered is fine.
4681                 final int oldActiveWindow = mSecurityPolicy.mActiveWindowId;
4682                 setActiveWindowLocked(mFocusedWindowId);
4683 
4684                 // If there is no service that can operate with active windows
4685                 // we keep accessibility focus behavior to constrain it only in
4686                 // the active window. Look at updateAccessibilityFocusBehaviorLocked
4687                 // for details.
4688                 if (oldActiveWindow != mSecurityPolicy.mActiveWindowId
4689                         && mAccessibilityFocusedWindowId == oldActiveWindow
4690                         && getCurrentUserStateLocked().mAccessibilityFocusOnlyInActiveWindow) {
4691                     mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS,
4692                             oldActiveWindow, 0).sendToTarget();
4693                 }
4694             }
4695         }
4696 
getActiveWindowId()4697         public int getActiveWindowId() {
4698             if (mActiveWindowId == INVALID_WINDOW_ID && !mTouchInteractionInProgress) {
4699                 mActiveWindowId = getFocusedWindowId();
4700             }
4701             return mActiveWindowId;
4702         }
4703 
setActiveWindowLocked(int windowId)4704         private void setActiveWindowLocked(int windowId) {
4705             if (mActiveWindowId != windowId) {
4706                 mActiveWindowId = windowId;
4707                 if (mWindows != null) {
4708                     final int windowCount = mWindows.size();
4709                     for (int i = 0; i < windowCount; i++) {
4710                         AccessibilityWindowInfo window = mWindows.get(i);
4711                         window.setActive(window.getId() == windowId);
4712                     }
4713                 }
4714                 notifyWindowsChanged();
4715             }
4716         }
4717 
setAccessibilityFocusedWindowLocked(int windowId)4718         private void setAccessibilityFocusedWindowLocked(int windowId) {
4719             if (mAccessibilityFocusedWindowId != windowId) {
4720                 mAccessibilityFocusedWindowId = windowId;
4721                 if (mWindows != null) {
4722                     final int windowCount = mWindows.size();
4723                     for (int i = 0; i < windowCount; i++) {
4724                         AccessibilityWindowInfo window = mWindows.get(i);
4725                         window.setAccessibilityFocused(window.getId() == windowId);
4726                     }
4727                 }
4728 
4729                 notifyWindowsChanged();
4730             }
4731         }
4732 
notifyWindowsChanged()4733         public void notifyWindowsChanged() {
4734             if (mWindowsForAccessibilityCallback == null) {
4735                 return;
4736             }
4737             final long identity = Binder.clearCallingIdentity();
4738             try {
4739                 // Let the client know the windows changed.
4740                 AccessibilityEvent event = AccessibilityEvent.obtain(
4741                         AccessibilityEvent.TYPE_WINDOWS_CHANGED);
4742                 event.setEventTime(SystemClock.uptimeMillis());
4743                 sendAccessibilityEvent(event, mCurrentUserId);
4744             } finally {
4745                 Binder.restoreCallingIdentity(identity);
4746             }
4747         }
4748 
canGetAccessibilityNodeInfoLocked(Service service, int windowId)4749         public boolean canGetAccessibilityNodeInfoLocked(Service service, int windowId) {
4750             return canRetrieveWindowContentLocked(service) && isRetrievalAllowingWindow(windowId);
4751         }
4752 
canRetrieveWindowsLocked(Service service)4753         public boolean canRetrieveWindowsLocked(Service service) {
4754             return canRetrieveWindowContentLocked(service) && service.mRetrieveInteractiveWindows;
4755         }
4756 
canRetrieveWindowContentLocked(Service service)4757         public boolean canRetrieveWindowContentLocked(Service service) {
4758             return (service.mAccessibilityServiceInfo.getCapabilities()
4759                     & AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0;
4760         }
4761 
canControlMagnification(Service service)4762         public boolean canControlMagnification(Service service) {
4763             return (service.mAccessibilityServiceInfo.getCapabilities()
4764                     & AccessibilityServiceInfo.CAPABILITY_CAN_CONTROL_MAGNIFICATION) != 0;
4765         }
4766 
canPerformGestures(Service service)4767         public boolean canPerformGestures(Service service) {
4768             return (service.mAccessibilityServiceInfo.getCapabilities()
4769                     & AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0;
4770         }
4771 
canCaptureFingerprintGestures(Service service)4772         public boolean canCaptureFingerprintGestures(Service service) {
4773             return (service.mAccessibilityServiceInfo.getCapabilities()
4774                     & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES) != 0;
4775         }
4776 
resolveProfileParentLocked(int userId)4777         private int resolveProfileParentLocked(int userId) {
4778             if (userId != mCurrentUserId) {
4779                 final long identity = Binder.clearCallingIdentity();
4780                 try {
4781                     UserInfo parent = mUserManager.getProfileParent(userId);
4782                     if (parent != null) {
4783                         return parent.getUserHandle().getIdentifier();
4784                     }
4785                 } finally {
4786                     Binder.restoreCallingIdentity(identity);
4787                 }
4788             }
4789             return userId;
4790         }
4791 
resolveCallingUserIdEnforcingPermissionsLocked(int userId)4792         public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) {
4793             final int callingUid = Binder.getCallingUid();
4794             if (callingUid == 0
4795                     || callingUid == Process.SYSTEM_UID
4796                     || callingUid == Process.SHELL_UID) {
4797                 if (userId == UserHandle.USER_CURRENT
4798                         || userId == UserHandle.USER_CURRENT_OR_SELF) {
4799                     return mCurrentUserId;
4800                 }
4801                 return resolveProfileParentLocked(userId);
4802             }
4803             final int callingUserId = UserHandle.getUserId(callingUid);
4804             if (callingUserId == userId) {
4805                 return resolveProfileParentLocked(userId);
4806             }
4807             final int callingUserParentId = resolveProfileParentLocked(callingUserId);
4808             if (callingUserParentId == mCurrentUserId &&
4809                     (userId == UserHandle.USER_CURRENT
4810                             || userId == UserHandle.USER_CURRENT_OR_SELF)) {
4811                 return mCurrentUserId;
4812             }
4813             if (!hasPermission(Manifest.permission.INTERACT_ACROSS_USERS)
4814                     && !hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) {
4815                 throw new SecurityException("Call from user " + callingUserId + " as user "
4816                         + userId + " without permission INTERACT_ACROSS_USERS or "
4817                         + "INTERACT_ACROSS_USERS_FULL not allowed.");
4818             }
4819             if (userId == UserHandle.USER_CURRENT
4820                     || userId == UserHandle.USER_CURRENT_OR_SELF) {
4821                 return mCurrentUserId;
4822             }
4823             throw new IllegalArgumentException("Calling user can be changed to only "
4824                     + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF.");
4825         }
4826 
isCallerInteractingAcrossUsers(int userId)4827         public boolean isCallerInteractingAcrossUsers(int userId) {
4828             final int callingUid = Binder.getCallingUid();
4829             return (Binder.getCallingPid() == android.os.Process.myPid()
4830                     || callingUid == Process.SHELL_UID
4831                     || userId == UserHandle.USER_CURRENT
4832                     || userId == UserHandle.USER_CURRENT_OR_SELF);
4833         }
4834 
isRetrievalAllowingWindow(int windowId)4835         private boolean isRetrievalAllowingWindow(int windowId) {
4836             // The system gets to interact with any window it wants.
4837             if (Binder.getCallingUid() == Process.SYSTEM_UID) {
4838                 return true;
4839             }
4840             if (windowId == mActiveWindowId) {
4841                 return true;
4842             }
4843             return findWindowById(windowId) != null;
4844         }
4845 
findWindowById(int windowId)4846         private AccessibilityWindowInfo findWindowById(int windowId) {
4847             return mWindowsById.get(windowId);
4848         }
4849 
getPictureInPictureWindow()4850         private AccessibilityWindowInfo getPictureInPictureWindow() {
4851             if (mWindows != null) {
4852                 final int windowCount = mWindows.size();
4853                 for (int i = 0; i < windowCount; i++) {
4854                     AccessibilityWindowInfo window = mWindows.get(i);
4855                     if (window.inPictureInPicture()) {
4856                         return window;
4857                     }
4858                 }
4859             }
4860             return null;
4861         }
4862 
enforceCallingPermission(String permission, String function)4863         private void enforceCallingPermission(String permission, String function) {
4864             if (OWN_PROCESS_ID == Binder.getCallingPid()) {
4865                 return;
4866             }
4867             if (!hasPermission(permission)) {
4868                 throw new SecurityException("You do not have " + permission
4869                         + " required to call " + function + " from pid="
4870                         + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
4871             }
4872         }
4873 
hasPermission(String permission)4874         private boolean hasPermission(String permission) {
4875             return mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED;
4876         }
4877 
getFocusedWindowId()4878         private int getFocusedWindowId() {
4879             IBinder token = mWindowManagerService.getFocusedWindowToken();
4880             synchronized (mLock) {
4881                 return findWindowIdLocked(token);
4882             }
4883         }
4884     }
4885 
4886     private class UserState {
4887         public final int mUserId;
4888 
4889         // Non-transient state.
4890 
4891         public final RemoteCallbackList<IAccessibilityManagerClient> mUserClients =
4892             new RemoteCallbackList<>();
4893 
4894         public final SparseArray<AccessibilityConnectionWrapper> mInteractionConnections =
4895                 new SparseArray<>();
4896 
4897         public final SparseArray<IBinder> mWindowTokens = new SparseArray<>();
4898 
4899         // Transient state.
4900 
4901         public final CopyOnWriteArrayList<Service> mBoundServices =
4902                 new CopyOnWriteArrayList<>();
4903 
4904         public int mLastSentRelevantEventTypes = AccessibilityEvent.TYPES_ALL_MASK;
4905 
4906         public final Map<ComponentName, Service> mComponentNameToServiceMap =
4907                 new HashMap<>();
4908 
4909         public final List<AccessibilityServiceInfo> mInstalledServices =
4910                 new ArrayList<>();
4911 
4912         public final Set<ComponentName> mBindingServices = new HashSet<>();
4913 
4914         public final Set<ComponentName> mEnabledServices = new HashSet<>();
4915 
4916         public final Set<ComponentName> mTouchExplorationGrantedServices =
4917                 new HashSet<>();
4918 
4919         public ComponentName mServiceChangingSoftKeyboardMode;
4920 
4921         public ComponentName mServiceToEnableWithShortcut;
4922 
4923         public int mLastSentClientState = -1;
4924 
4925         public int mSoftKeyboardShowMode = 0;
4926 
4927         public boolean mIsNavBarMagnificationAssignedToAccessibilityButton;
4928         public ComponentName mServiceAssignedToAccessibilityButton;
4929 
4930         public boolean mIsTouchExplorationEnabled;
4931         public boolean mIsTextHighContrastEnabled;
4932         public boolean mIsDisplayMagnificationEnabled;
4933         public boolean mIsNavBarMagnificationEnabled;
4934         public boolean mIsAutoclickEnabled;
4935         public boolean mIsPerformGesturesEnabled;
4936         public boolean mIsFilterKeyEventsEnabled;
4937         public boolean mAccessibilityFocusOnlyInActiveWindow;
4938 
4939         private Service mUiAutomationService;
4940         private int mUiAutomationFlags;
4941         private IAccessibilityServiceClient mUiAutomationServiceClient;
4942 
4943         private IBinder mUiAutomationServiceOwner;
4944         private final DeathRecipient mUiAutomationSerivceOnwerDeathRecipient =
4945                 new DeathRecipient() {
4946             @Override
4947             public void binderDied() {
4948                 mUiAutomationServiceOwner.unlinkToDeath(
4949                         mUiAutomationSerivceOnwerDeathRecipient, 0);
4950                 mUiAutomationServiceOwner = null;
4951                 if (mUiAutomationService != null) {
4952                     mUiAutomationService.binderDied();
4953                 }
4954             }
4955         };
4956 
UserState(int userId)4957         public UserState(int userId) {
4958             mUserId = userId;
4959         }
4960 
getClientState()4961         public int getClientState() {
4962             int clientState = 0;
4963             if (isHandlingAccessibilityEvents()) {
4964                 clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
4965             }
4966             // Touch exploration relies on enabled accessibility.
4967             if (isHandlingAccessibilityEvents() && mIsTouchExplorationEnabled) {
4968                 clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
4969             }
4970             if (mIsTextHighContrastEnabled) {
4971                 clientState |= AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED;
4972             }
4973             return clientState;
4974         }
4975 
isHandlingAccessibilityEvents()4976         public boolean isHandlingAccessibilityEvents() {
4977             return !mBoundServices.isEmpty() || !mBindingServices.isEmpty();
4978         }
4979 
onSwitchToAnotherUser()4980         public void onSwitchToAnotherUser() {
4981             // Clear UI test automation state.
4982             if (mUiAutomationService != null) {
4983                 mUiAutomationService.binderDied();
4984             }
4985 
4986             // Unbind all services.
4987             unbindAllServicesLocked(this);
4988 
4989             // Clear service management state.
4990             mBoundServices.clear();
4991             mBindingServices.clear();
4992 
4993             // Clear event management state.
4994             mLastSentClientState = -1;
4995 
4996             // Clear state persisted in settings.
4997             mEnabledServices.clear();
4998             mTouchExplorationGrantedServices.clear();
4999             mIsTouchExplorationEnabled = false;
5000             mIsDisplayMagnificationEnabled = false;
5001             mIsNavBarMagnificationEnabled = false;
5002             mServiceAssignedToAccessibilityButton = null;
5003             mIsNavBarMagnificationAssignedToAccessibilityButton = false;
5004             mIsAutoclickEnabled = false;
5005             mSoftKeyboardShowMode = 0;
5006         }
5007 
destroyUiAutomationService()5008         public void destroyUiAutomationService() {
5009             mUiAutomationService = null;
5010             mUiAutomationFlags = 0;
5011             mUiAutomationServiceClient = null;
5012             if (mUiAutomationServiceOwner != null) {
5013                 mUiAutomationServiceOwner.unlinkToDeath(
5014                         mUiAutomationSerivceOnwerDeathRecipient, 0);
5015                 mUiAutomationServiceOwner = null;
5016             }
5017         }
5018 
isUiAutomationSuppressingOtherServices()5019         boolean isUiAutomationSuppressingOtherServices() {
5020             return ((mUiAutomationService != null) && (mUiAutomationFlags
5021                     & UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) == 0);
5022         }
5023     }
5024 
5025     private final class AccessibilityContentObserver extends ContentObserver {
5026 
5027         private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor(
5028                 Settings.Secure.TOUCH_EXPLORATION_ENABLED);
5029 
5030         private final Uri mDisplayMagnificationEnabledUri = Settings.Secure.getUriFor(
5031                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
5032 
5033         private final Uri mNavBarMagnificationEnabledUri = Settings.Secure.getUriFor(
5034                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED);
5035 
5036         private final Uri mAutoclickEnabledUri = Settings.Secure.getUriFor(
5037                 Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED);
5038 
5039         private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor(
5040                 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
5041 
5042         private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure
5043                 .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
5044 
5045         private final Uri mDisplayInversionEnabledUri = Settings.Secure.getUriFor(
5046                 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
5047 
5048         private final Uri mDisplayDaltonizerEnabledUri = Settings.Secure.getUriFor(
5049                 Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED);
5050 
5051         private final Uri mDisplayDaltonizerUri = Settings.Secure.getUriFor(
5052                 Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER);
5053 
5054         private final Uri mHighTextContrastUri = Settings.Secure.getUriFor(
5055                 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED);
5056 
5057         private final Uri mAccessibilitySoftKeyboardModeUri = Settings.Secure.getUriFor(
5058                 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE);
5059 
5060         private final Uri mAccessibilityShortcutServiceIdUri = Settings.Secure.getUriFor(
5061                 Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
5062 
5063         private final Uri mAccessibilityButtonComponentIdUri = Settings.Secure.getUriFor(
5064                 Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT);
5065 
AccessibilityContentObserver(Handler handler)5066         public AccessibilityContentObserver(Handler handler) {
5067             super(handler);
5068         }
5069 
register(ContentResolver contentResolver)5070         public void register(ContentResolver contentResolver) {
5071             contentResolver.registerContentObserver(mTouchExplorationEnabledUri,
5072                     false, this, UserHandle.USER_ALL);
5073             contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri,
5074                     false, this, UserHandle.USER_ALL);
5075             contentResolver.registerContentObserver(mNavBarMagnificationEnabledUri,
5076                     false, this, UserHandle.USER_ALL);
5077             contentResolver.registerContentObserver(mAutoclickEnabledUri,
5078                     false, this, UserHandle.USER_ALL);
5079             contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri,
5080                     false, this, UserHandle.USER_ALL);
5081             contentResolver.registerContentObserver(
5082                     mTouchExplorationGrantedAccessibilityServicesUri,
5083                     false, this, UserHandle.USER_ALL);
5084             contentResolver.registerContentObserver(
5085                     mDisplayInversionEnabledUri, false, this, UserHandle.USER_ALL);
5086             contentResolver.registerContentObserver(
5087                     mDisplayDaltonizerEnabledUri, false, this, UserHandle.USER_ALL);
5088             contentResolver.registerContentObserver(
5089                     mDisplayDaltonizerUri, false, this, UserHandle.USER_ALL);
5090             contentResolver.registerContentObserver(
5091                     mHighTextContrastUri, false, this, UserHandle.USER_ALL);
5092             contentResolver.registerContentObserver(
5093                     mAccessibilitySoftKeyboardModeUri, false, this, UserHandle.USER_ALL);
5094             contentResolver.registerContentObserver(
5095                     mAccessibilityShortcutServiceIdUri, false, this, UserHandle.USER_ALL);
5096             contentResolver.registerContentObserver(
5097                     mAccessibilityButtonComponentIdUri, false, this, UserHandle.USER_ALL);
5098         }
5099 
5100         @Override
onChange(boolean selfChange, Uri uri)5101         public void onChange(boolean selfChange, Uri uri) {
5102             synchronized (mLock) {
5103                 // Profiles share the accessibility state of the parent. Therefore,
5104                 // we are checking for changes only the parent settings.
5105                 UserState userState = getCurrentUserStateLocked();
5106 
5107                 // If the automation service is suppressing, we will update when it dies.
5108                 if (userState.isUiAutomationSuppressingOtherServices()) {
5109                     return;
5110                 }
5111 
5112                 if (mTouchExplorationEnabledUri.equals(uri)) {
5113                     if (readTouchExplorationEnabledSettingLocked(userState)) {
5114                         onUserStateChangedLocked(userState);
5115                     }
5116                 } else if (mDisplayMagnificationEnabledUri.equals(uri)
5117                         || mNavBarMagnificationEnabledUri.equals(uri)) {
5118                     if (readMagnificationEnabledSettingsLocked(userState)) {
5119                         onUserStateChangedLocked(userState);
5120                     }
5121                 } else if (mAutoclickEnabledUri.equals(uri)) {
5122                     if (readAutoclickEnabledSettingLocked(userState)) {
5123                         onUserStateChangedLocked(userState);
5124                     }
5125                 } else if (mEnabledAccessibilityServicesUri.equals(uri)) {
5126                     if (readEnabledAccessibilityServicesLocked(userState)) {
5127                         onUserStateChangedLocked(userState);
5128                     }
5129                 } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) {
5130                     if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) {
5131                         onUserStateChangedLocked(userState);
5132                     }
5133                 } else if (mDisplayDaltonizerEnabledUri.equals(uri)
5134                         || mDisplayDaltonizerUri.equals(uri)) {
5135                     updateDisplayDaltonizerLocked(userState);
5136                 } else if (mDisplayInversionEnabledUri.equals(uri)) {
5137                     updateDisplayInversionLocked(userState);
5138                 } else if (mHighTextContrastUri.equals(uri)) {
5139                     if (readHighTextContrastEnabledSettingLocked(userState)) {
5140                         onUserStateChangedLocked(userState);
5141                     }
5142                 } else if (mAccessibilitySoftKeyboardModeUri.equals(uri)) {
5143                     if (readSoftKeyboardShowModeChangedLocked(userState)) {
5144                         notifySoftKeyboardShowModeChangedLocked(userState.mSoftKeyboardShowMode);
5145                         onUserStateChangedLocked(userState);
5146                     }
5147                 } else if (mAccessibilityShortcutServiceIdUri.equals(uri)) {
5148                     if (readAccessibilityShortcutSettingLocked(userState)) {
5149                         onUserStateChangedLocked(userState);
5150                     }
5151                 } else if (mAccessibilityButtonComponentIdUri.equals(uri)) {
5152                     if (readAccessibilityButtonSettingsLocked(userState)) {
5153                         onUserStateChangedLocked(userState);
5154                     }
5155                 }
5156             }
5157         }
5158     }
5159 }
5160