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