• 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.provider.Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED;
20 import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_BUTTON;
21 import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_SHORTCUT_KEY;
22 import static android.view.accessibility.AccessibilityManager.ShortcutType;
23 
24 import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_COMPONENT_NAME;
25 import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
26 import static com.android.internal.accessibility.common.ShortcutConstants.CHOOSER_PACKAGE_NAME;
27 import static com.android.internal.accessibility.util.AccessibilityStatsLogUtils.logAccessibilityShortcutActivated;
28 import static com.android.internal.util.FunctionalUtils.ignoreRemoteException;
29 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
30 import static com.android.server.accessibility.AccessibilityUserState.doesShortcutTargetsStringContain;
31 
32 import android.Manifest;
33 import android.accessibilityservice.AccessibilityGestureEvent;
34 import android.accessibilityservice.AccessibilityService;
35 import android.accessibilityservice.AccessibilityServiceInfo;
36 import android.accessibilityservice.AccessibilityShortcutInfo;
37 import android.accessibilityservice.IAccessibilityServiceClient;
38 import android.annotation.NonNull;
39 import android.annotation.Nullable;
40 import android.app.ActivityOptions;
41 import android.app.AlertDialog;
42 import android.app.PendingIntent;
43 import android.app.RemoteAction;
44 import android.appwidget.AppWidgetManagerInternal;
45 import android.content.ActivityNotFoundException;
46 import android.content.BroadcastReceiver;
47 import android.content.ComponentName;
48 import android.content.ContentResolver;
49 import android.content.Context;
50 import android.content.DialogInterface;
51 import android.content.DialogInterface.OnClickListener;
52 import android.content.Intent;
53 import android.content.IntentFilter;
54 import android.content.pm.PackageManager;
55 import android.content.pm.PackageManagerInternal;
56 import android.content.pm.ResolveInfo;
57 import android.content.pm.ServiceInfo;
58 import android.database.ContentObserver;
59 import android.graphics.Point;
60 import android.graphics.Rect;
61 import android.graphics.Region;
62 import android.hardware.display.DisplayManager;
63 import android.hardware.fingerprint.IFingerprintService;
64 import android.media.AudioManagerInternal;
65 import android.net.Uri;
66 import android.os.Binder;
67 import android.os.Build;
68 import android.os.Bundle;
69 import android.os.Handler;
70 import android.os.IBinder;
71 import android.os.Looper;
72 import android.os.Message;
73 import android.os.PowerManager;
74 import android.os.Process;
75 import android.os.RemoteCallbackList;
76 import android.os.RemoteException;
77 import android.os.ResultReceiver;
78 import android.os.ServiceManager;
79 import android.os.ShellCallback;
80 import android.os.SystemClock;
81 import android.os.UserHandle;
82 import android.os.UserManager;
83 import android.os.UserManagerInternal;
84 import android.provider.Settings;
85 import android.provider.SettingsStringUtil.SettingStringHelper;
86 import android.text.TextUtils;
87 import android.text.TextUtils.SimpleStringSplitter;
88 import android.util.ArraySet;
89 import android.util.IntArray;
90 import android.util.Slog;
91 import android.util.SparseArray;
92 import android.view.Display;
93 import android.view.IWindow;
94 import android.view.KeyEvent;
95 import android.view.MagnificationSpec;
96 import android.view.WindowManager;
97 import android.view.accessibility.AccessibilityEvent;
98 import android.view.accessibility.AccessibilityInteractionClient;
99 import android.view.accessibility.AccessibilityManager;
100 import android.view.accessibility.AccessibilityNodeInfo;
101 import android.view.accessibility.AccessibilityWindowInfo;
102 import android.view.accessibility.IAccessibilityInteractionConnection;
103 import android.view.accessibility.IAccessibilityManager;
104 import android.view.accessibility.IAccessibilityManagerClient;
105 import android.view.accessibility.IWindowMagnificationConnection;
106 
107 import com.android.internal.R;
108 import com.android.internal.accessibility.AccessibilityShortcutController;
109 import com.android.internal.accessibility.AccessibilityShortcutController.ToggleableFrameworkFeatureInfo;
110 import com.android.internal.accessibility.dialog.AccessibilityButtonChooserActivity;
111 import com.android.internal.accessibility.dialog.AccessibilityShortcutChooserActivity;
112 import com.android.internal.annotations.GuardedBy;
113 import com.android.internal.annotations.VisibleForTesting;
114 import com.android.internal.content.PackageMonitor;
115 import com.android.internal.util.ArrayUtils;
116 import com.android.internal.util.DumpUtils;
117 import com.android.internal.util.IntPair;
118 import com.android.server.LocalServices;
119 import com.android.server.SystemService;
120 import com.android.server.accessibility.magnification.WindowMagnificationManager;
121 import com.android.server.wm.ActivityTaskManagerInternal;
122 import com.android.server.wm.WindowManagerInternal;
123 
124 import org.xmlpull.v1.XmlPullParserException;
125 
126 import java.io.FileDescriptor;
127 import java.io.IOException;
128 import java.io.PrintWriter;
129 import java.util.ArrayList;
130 import java.util.Arrays;
131 import java.util.Collections;
132 import java.util.HashSet;
133 import java.util.Iterator;
134 import java.util.List;
135 import java.util.Map;
136 import java.util.Set;
137 import java.util.function.Consumer;
138 import java.util.function.Function;
139 import java.util.function.Predicate;
140 
141 /**
142  * This class is instantiated by the system as a system level service and can be
143  * accessed only by the system. The task of this service is to be a centralized
144  * event dispatch for {@link AccessibilityEvent}s generated across all processes
145  * on the device. Events are dispatched to {@link AccessibilityService}s.
146  */
147 public class AccessibilityManagerService extends IAccessibilityManager.Stub
148         implements AbstractAccessibilityServiceConnection.SystemSupport,
149         AccessibilityUserState.ServiceInfoChangeListener,
150         AccessibilityWindowManager.AccessibilityEventSender,
151         AccessibilitySecurityPolicy.AccessibilityUserManager,
152         SystemActionPerformer.SystemActionsChangedListener {
153 
154     private static final boolean DEBUG = false;
155 
156     private static final String LOG_TAG = "AccessibilityManagerService";
157 
158     // TODO: This is arbitrary. When there is time implement this by watching
159     //       when that accessibility services are bound.
160     private static final int WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS = 3000;
161 
162     // TODO: Restructure service initialization so services aren't connected before all of
163     //       their capabilities are ready.
164     private static final int WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS = 1000;
165 
166     static final String FUNCTION_REGISTER_SYSTEM_ACTION = "registerSystemAction";
167     static final String FUNCTION_UNREGISTER_SYSTEM_ACTION = "unregisterSystemAction";
168     private static final String FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE =
169         "registerUiTestAutomationService";
170 
171     private static final String TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED =
172             "temporaryEnableAccessibilityStateUntilKeyguardRemoved";
173 
174     private static final String GET_WINDOW_TOKEN = "getWindowToken";
175 
176     private static final String SET_PIP_ACTION_REPLACEMENT =
177             "setPictureInPictureActionReplacingConnection";
178 
179     private static final char COMPONENT_NAME_SEPARATOR = ':';
180 
181     private static final int OWN_PROCESS_ID = android.os.Process.myPid();
182 
183     // Each service has an ID. Also provide one for magnification gesture handling
184     public static final int MAGNIFICATION_GESTURE_HANDLER_ID = 0;
185 
186     private static int sIdCounter = MAGNIFICATION_GESTURE_HANDLER_ID + 1;
187 
188     private final Context mContext;
189 
190     private final Object mLock = new Object();
191 
192     private final SimpleStringSplitter mStringColonSplitter =
193             new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
194 
195     private final Rect mTempRect = new Rect();
196     private final Rect mTempRect1 = new Rect();
197 
198     private final PackageManager mPackageManager;
199 
200     private final PowerManager mPowerManager;
201 
202     private final WindowManagerInternal mWindowManagerService;
203 
204     private final AccessibilitySecurityPolicy mSecurityPolicy;
205 
206     private final AccessibilityWindowManager mA11yWindowManager;
207 
208     private final AccessibilityDisplayListener mA11yDisplayListener;
209 
210     private final ActivityTaskManagerInternal mActivityTaskManagerService;
211 
212     private final MainHandler mMainHandler;
213 
214     // Lazily initialized - access through getSystemActionPerfomer()
215     private SystemActionPerformer mSystemActionPerformer;
216 
217     private MagnificationController mMagnificationController;
218 
219     private InteractionBridge mInteractionBridge;
220 
221     private AlertDialog mEnableTouchExplorationDialog;
222 
223     private AccessibilityInputFilter mInputFilter;
224 
225     private WindowMagnificationManager mWindowMagnificationMgr;
226 
227     private boolean mHasInputFilter;
228 
229     private KeyEventDispatcher mKeyEventDispatcher;
230 
231     private SparseArray<MotionEventInjector> mMotionEventInjectors;
232 
233     private FingerprintGestureDispatcher mFingerprintGestureDispatcher;
234 
235     private final Set<ComponentName> mTempComponentNameSet = new HashSet<>();
236 
237     private final List<AccessibilityServiceInfo> mTempAccessibilityServiceInfoList =
238             new ArrayList<>();
239 
240     private final IntArray mTempIntArray = new IntArray(0);
241 
242     private final RemoteCallbackList<IAccessibilityManagerClient> mGlobalClients =
243             new RemoteCallbackList<>();
244 
245     private final SparseArray<AccessibilityUserState> mUserStates = new SparseArray<>();
246 
247     private final UiAutomationManager mUiAutomationManager = new UiAutomationManager(mLock);
248 
249     private int mCurrentUserId = UserHandle.USER_SYSTEM;
250 
251     //TODO: Remove this hack
252     private boolean mInitialized;
253 
254     private Point mTempPoint = new Point();
255     private boolean mIsAccessibilityButtonShown;
256 
getCurrentUserStateLocked()257     private AccessibilityUserState getCurrentUserStateLocked() {
258         return getUserStateLocked(mCurrentUserId);
259     }
260 
261     public static final class Lifecycle extends SystemService {
262         private final AccessibilityManagerService mService;
263 
Lifecycle(Context context)264         public Lifecycle(Context context) {
265             super(context);
266             mService = new AccessibilityManagerService(context);
267         }
268 
269         @Override
onStart()270         public void onStart() {
271             publishBinderService(Context.ACCESSIBILITY_SERVICE, mService);
272         }
273 
274         @Override
onBootPhase(int phase)275         public void onBootPhase(int phase) {
276             mService.onBootPhase(phase);
277         }
278     }
279 
280     @VisibleForTesting
AccessibilityManagerService( Context context, PackageManager packageManager, AccessibilitySecurityPolicy securityPolicy, SystemActionPerformer systemActionPerformer, AccessibilityWindowManager a11yWindowManager, AccessibilityDisplayListener a11yDisplayListener)281     AccessibilityManagerService(
282             Context context,
283             PackageManager packageManager,
284             AccessibilitySecurityPolicy securityPolicy,
285             SystemActionPerformer systemActionPerformer,
286             AccessibilityWindowManager a11yWindowManager,
287             AccessibilityDisplayListener a11yDisplayListener) {
288         mContext = context;
289         mPowerManager =  (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
290         mWindowManagerService = LocalServices.getService(WindowManagerInternal.class);
291         mMainHandler = new MainHandler(mContext.getMainLooper());
292         mActivityTaskManagerService = LocalServices.getService(ActivityTaskManagerInternal.class);
293         mPackageManager = packageManager;
294         mSecurityPolicy = securityPolicy;
295         mSystemActionPerformer = systemActionPerformer;
296         mA11yWindowManager = a11yWindowManager;
297         mA11yDisplayListener = a11yDisplayListener;
298         init();
299     }
300 
301     /**
302      * Creates a new instance.
303      *
304      * @param context A {@link Context} instance.
305      */
AccessibilityManagerService(Context context)306     public AccessibilityManagerService(Context context) {
307         mContext = context;
308         mPowerManager =  (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
309         mWindowManagerService = LocalServices.getService(WindowManagerInternal.class);
310         mMainHandler = new MainHandler(mContext.getMainLooper());
311         mActivityTaskManagerService = LocalServices.getService(ActivityTaskManagerInternal.class);
312         mPackageManager = mContext.getPackageManager();
313         mSecurityPolicy = new AccessibilitySecurityPolicy(mContext, this);
314         mA11yWindowManager = new AccessibilityWindowManager(mLock, mMainHandler,
315                 mWindowManagerService, this, mSecurityPolicy, this);
316         mA11yDisplayListener = new AccessibilityDisplayListener(mContext, mMainHandler);
317         init();
318     }
319 
init()320     private void init() {
321         mSecurityPolicy.setAccessibilityWindowManager(mA11yWindowManager);
322         registerBroadcastReceivers();
323         new AccessibilityContentObserver(mMainHandler).register(
324                 mContext.getContentResolver());
325     }
326 
327     @Override
getCurrentUserIdLocked()328     public int getCurrentUserIdLocked() {
329         return mCurrentUserId;
330     }
331 
332     @Override
isAccessibilityButtonShown()333     public boolean isAccessibilityButtonShown() {
334         return mIsAccessibilityButtonShown;
335     }
336 
337     @Override
onServiceInfoChangedLocked(AccessibilityUserState userState)338     public void onServiceInfoChangedLocked(AccessibilityUserState userState) {
339         scheduleNotifyClientsOfServicesStateChangeLocked(userState);
340     }
341 
342     @Nullable
getFingerprintGestureDispatcher()343     public FingerprintGestureDispatcher getFingerprintGestureDispatcher() {
344         return mFingerprintGestureDispatcher;
345     }
346 
onBootPhase(int phase)347     private void onBootPhase(int phase) {
348         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
349             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)) {
350                 mSecurityPolicy.setAppWidgetManager(
351                         LocalServices.getService(AppWidgetManagerInternal.class));
352             }
353         }
354     }
355 
getUserState(int userId)356     private AccessibilityUserState getUserState(int userId) {
357         synchronized (mLock) {
358             return getUserStateLocked(userId);
359         }
360     }
361 
362     @NonNull
getUserStateLocked(int userId)363     private AccessibilityUserState getUserStateLocked(int userId) {
364         AccessibilityUserState state = mUserStates.get(userId);
365         if (state == null) {
366             state = new AccessibilityUserState(userId, mContext, this);
367             mUserStates.put(userId, state);
368         }
369         return state;
370     }
371 
getBindInstantServiceAllowed(int userId)372     boolean getBindInstantServiceAllowed(int userId) {
373         synchronized (mLock) {
374             final AccessibilityUserState userState = getUserStateLocked(userId);
375             return userState.getBindInstantServiceAllowedLocked();
376         }
377     }
378 
setBindInstantServiceAllowed(int userId, boolean allowed)379     void setBindInstantServiceAllowed(int userId, boolean allowed) {
380         mContext.enforceCallingOrSelfPermission(
381                 Manifest.permission.MANAGE_BIND_INSTANT_SERVICE,
382                 "setBindInstantServiceAllowed");
383         synchronized (mLock) {
384             final AccessibilityUserState userState = getUserStateLocked(userId);
385             if (allowed != userState.getBindInstantServiceAllowedLocked()) {
386                 userState.setBindInstantServiceAllowedLocked(allowed);
387                 onUserStateChangedLocked(userState);
388             }
389         }
390     }
391 
registerBroadcastReceivers()392     private void registerBroadcastReceivers() {
393         PackageMonitor monitor = new PackageMonitor() {
394             @Override
395             public void onSomePackagesChanged() {
396                 synchronized (mLock) {
397                     // Only the profile parent can install accessibility services.
398                     // Therefore we ignore packages from linked profiles.
399                     if (getChangingUserId() != mCurrentUserId) {
400                         return;
401                     }
402                     // We will update when the automation service dies.
403                     final AccessibilityUserState userState = getCurrentUserStateLocked();
404                     // We have to reload the installed services since some services may
405                     // have different attributes, resolve info (does not support equals),
406                     // etc. Remove them then to force reload.
407                     userState.mInstalledServices.clear();
408                     if (readConfigurationForUserStateLocked(userState)) {
409                         onUserStateChangedLocked(userState);
410                     }
411                 }
412             }
413 
414             @Override
415             public void onPackageUpdateFinished(String packageName, int uid) {
416                 // The package should already be removed from mBoundServices, and added into
417                 // mBindingServices in binderDied() during updating. Remove services from  this
418                 // package from mBindingServices, and then update the user state to re-bind new
419                 // versions of them.
420                 synchronized (mLock) {
421                     final int userId = getChangingUserId();
422                     if (userId != mCurrentUserId) {
423                         return;
424                     }
425                     final AccessibilityUserState userState = getUserStateLocked(userId);
426                     final boolean reboundAService = userState.getBindingServicesLocked().removeIf(
427                             component -> component != null
428                                     && component.getPackageName().equals(packageName))
429                             || userState.mCrashedServices.removeIf(component -> component != null
430                                     && component.getPackageName().equals(packageName));
431                     // Reloads the installed services info to make sure the rebound service could
432                     // get a new one.
433                     userState.mInstalledServices.clear();
434                     final boolean configurationChanged =
435                             readConfigurationForUserStateLocked(userState);
436                     if (reboundAService || configurationChanged) {
437                         onUserStateChangedLocked(userState);
438                     }
439                     migrateAccessibilityButtonSettingsIfNecessaryLocked(userState, packageName);
440                 }
441             }
442 
443             @Override
444             public void onPackageRemoved(String packageName, int uid) {
445                 synchronized (mLock) {
446                     final int userId = getChangingUserId();
447                     // Only the profile parent can install accessibility services.
448                     // Therefore we ignore packages from linked profiles.
449                     if (userId != mCurrentUserId) {
450                         return;
451                     }
452                     final AccessibilityUserState userState = getUserStateLocked(userId);
453                     final Predicate<ComponentName> filter =
454                             component -> component != null && component.getPackageName().equals(
455                                     packageName);
456                     userState.mBindingServices.removeIf(filter);
457                     userState.mCrashedServices.removeIf(filter);
458                     final Iterator<ComponentName> it = userState.mEnabledServices.iterator();
459                     while (it.hasNext()) {
460                         final ComponentName comp = it.next();
461                         final String compPkg = comp.getPackageName();
462                         if (compPkg.equals(packageName)) {
463                             it.remove();
464                             // Update the enabled services setting.
465                             persistComponentNamesToSettingLocked(
466                                     Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
467                                     userState.mEnabledServices, userId);
468                             // Update the touch exploration granted services setting.
469                             userState.mTouchExplorationGrantedServices.remove(comp);
470                             persistComponentNamesToSettingLocked(
471                                     Settings.Secure.
472                                     TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
473                                     userState.mTouchExplorationGrantedServices, userId);
474                             onUserStateChangedLocked(userState);
475                             return;
476                         }
477                     }
478                 }
479             }
480 
481             @Override
482             public boolean onHandleForceStop(Intent intent, String[] packages,
483                     int uid, boolean doit) {
484                 synchronized (mLock) {
485                     final int userId = getChangingUserId();
486                     // Only the profile parent can install accessibility services.
487                     // Therefore we ignore packages from linked profiles.
488                     if (userId != mCurrentUserId) {
489                         return false;
490                     }
491                     final AccessibilityUserState userState = getUserStateLocked(userId);
492                     final Iterator<ComponentName> it = userState.mEnabledServices.iterator();
493                     while (it.hasNext()) {
494                         final ComponentName comp = it.next();
495                         final String compPkg = comp.getPackageName();
496                         for (String pkg : packages) {
497                             if (compPkg.equals(pkg)) {
498                                 if (!doit) {
499                                     return true;
500                                 }
501                                 it.remove();
502                                 userState.getBindingServicesLocked().remove(comp);
503                                 persistComponentNamesToSettingLocked(
504                                         Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
505                                         userState.mEnabledServices, userId);
506                                 onUserStateChangedLocked(userState);
507                             }
508                         }
509                     }
510                     return false;
511                 }
512             }
513         };
514 
515         // package changes
516         monitor.register(mContext, null,  UserHandle.ALL, true);
517 
518         // user change and unlock
519         IntentFilter intentFilter = new IntentFilter();
520         intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
521         intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
522         intentFilter.addAction(Intent.ACTION_USER_REMOVED);
523         intentFilter.addAction(Intent.ACTION_USER_PRESENT);
524         intentFilter.addAction(Intent.ACTION_SETTING_RESTORED);
525 
526         mContext.registerReceiverAsUser(new BroadcastReceiver() {
527             @Override
528             public void onReceive(Context context, Intent intent) {
529                 String action = intent.getAction();
530                 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
531                     switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
532                 } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
533                     unlockUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
534                 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
535                     removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
536                 } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
537                     // We will update when the automation service dies.
538                     synchronized (mLock) {
539                         AccessibilityUserState userState = getCurrentUserStateLocked();
540                         if (readConfigurationForUserStateLocked(userState)) {
541                             onUserStateChangedLocked(userState);
542                         }
543                     }
544                 } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
545                     final String which = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
546                     if (Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(which)) {
547                         synchronized (mLock) {
548                             restoreEnabledAccessibilityServicesLocked(
549                                     intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
550                                     intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
551                         }
552                     } else if (ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED.equals(which)) {
553                         synchronized (mLock) {
554                             restoreLegacyDisplayMagnificationNavBarIfNeededLocked(
555                                     intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE),
556                                     intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT,
557                                             0));
558                         }
559                     }
560                 }
561             }
562         }, UserHandle.ALL, intentFilter, null, null);
563     }
564 
565     // Called only during settings restore; currently supports only the owner user
566     // TODO: b/22388012
restoreLegacyDisplayMagnificationNavBarIfNeededLocked(String newSetting, int restoreFromSdkInt)567     private void restoreLegacyDisplayMagnificationNavBarIfNeededLocked(String newSetting,
568             int restoreFromSdkInt) {
569         if (restoreFromSdkInt >= Build.VERSION_CODES.R) {
570             return;
571         }
572 
573         boolean displayMagnificationNavBarEnabled;
574         try {
575             displayMagnificationNavBarEnabled = Integer.parseInt(newSetting) == 1;
576         } catch (NumberFormatException e) {
577             Slog.w(LOG_TAG, "number format is incorrect" + e);
578             return;
579         }
580 
581         final AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM);
582         final Set<String> targetsFromSetting = new ArraySet<>();
583         readColonDelimitedSettingToSet(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
584                 userState.mUserId, targetsFromSetting, str -> str);
585         final boolean targetsContainMagnification = targetsFromSetting.contains(
586                 MAGNIFICATION_CONTROLLER_NAME);
587         if (targetsContainMagnification == displayMagnificationNavBarEnabled) {
588             return;
589         }
590 
591         if (displayMagnificationNavBarEnabled) {
592             targetsFromSetting.add(MAGNIFICATION_CONTROLLER_NAME);
593         } else {
594             targetsFromSetting.remove(MAGNIFICATION_CONTROLLER_NAME);
595         }
596         persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
597                 userState.mUserId, targetsFromSetting, str -> str);
598         readAccessibilityButtonTargetsLocked(userState);
599         onUserStateChangedLocked(userState);
600     }
601 
602     @Override
addClient(IAccessibilityManagerClient callback, int userId)603     public long addClient(IAccessibilityManagerClient callback, int userId) {
604         synchronized (mLock) {
605             // We treat calls from a profile as if made by its parent as profiles
606             // share the accessibility state of the parent. The call below
607             // performs the current profile parent resolution.
608             final int resolvedUserId = mSecurityPolicy
609                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
610 
611             // If the client is from a process that runs across users such as
612             // the system UI or the system we add it to the global state that
613             // is shared across users.
614             AccessibilityUserState userState = getUserStateLocked(resolvedUserId);
615             Client client = new Client(callback, Binder.getCallingUid(), userState);
616             if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
617                 mGlobalClients.register(callback, client);
618                 if (DEBUG) {
619                     Slog.i(LOG_TAG, "Added global client for pid:" + Binder.getCallingPid());
620                 }
621                 return IntPair.of(
622                         getClientStateLocked(userState),
623                         client.mLastSentRelevantEventTypes);
624             } else {
625                 userState.mUserClients.register(callback, client);
626                 // If this client is not for the current user we do not
627                 // return a state since it is not for the foreground user.
628                 // We will send the state to the client on a user switch.
629                 if (DEBUG) {
630                     Slog.i(LOG_TAG, "Added user client for pid:" + Binder.getCallingPid()
631                             + " and userId:" + mCurrentUserId);
632                 }
633                 return IntPair.of(
634                         (resolvedUserId == mCurrentUserId) ? getClientStateLocked(userState) : 0,
635                         client.mLastSentRelevantEventTypes);
636             }
637         }
638     }
639 
640     @Override
sendAccessibilityEvent(AccessibilityEvent event, int userId)641     public void sendAccessibilityEvent(AccessibilityEvent event, int userId) {
642         boolean dispatchEvent = false;
643 
644         synchronized (mLock) {
645             if (event.getWindowId() ==
646                 AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID) {
647                 // The replacer window isn't shown to services. Move its events into the pip.
648                 AccessibilityWindowInfo pip = mA11yWindowManager.getPictureInPictureWindowLocked();
649                 if (pip != null) {
650                     int pipId = pip.getId();
651                     event.setWindowId(pipId);
652                 }
653             }
654 
655             // We treat calls from a profile as if made by its parent as profiles
656             // share the accessibility state of the parent. The call below
657             // performs the current profile parent resolution.
658             final int resolvedUserId = mSecurityPolicy
659                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
660 
661             // Make sure the reported package is one the caller has access to.
662             event.setPackageName(mSecurityPolicy.resolveValidReportedPackageLocked(
663                     event.getPackageName(), UserHandle.getCallingAppId(), resolvedUserId,
664                     getCallingPid()));
665 
666             // This method does nothing for a background user.
667             if (resolvedUserId == mCurrentUserId) {
668                 if (mSecurityPolicy.canDispatchAccessibilityEventLocked(mCurrentUserId, event)) {
669                     mA11yWindowManager.updateActiveAndAccessibilityFocusedWindowLocked(
670                             mCurrentUserId, event.getWindowId(), event.getSourceNodeId(),
671                             event.getEventType(), event.getAction());
672                     mSecurityPolicy.updateEventSourceLocked(event);
673                     dispatchEvent = true;
674                 }
675                 if (mHasInputFilter && mInputFilter != null) {
676                     mMainHandler.sendMessage(obtainMessage(
677                             AccessibilityManagerService::sendAccessibilityEventToInputFilter,
678                             this, AccessibilityEvent.obtain(event)));
679                 }
680             }
681         }
682 
683         if (dispatchEvent) {
684             // Make sure clients receiving this event will be able to get the
685             // current state of the windows as the window manager may be delaying
686             // the computation for performance reasons.
687             boolean shouldComputeWindows = false;
688             int displayId = Display.INVALID_DISPLAY;
689             synchronized (mLock) {
690                 final int windowId = event.getWindowId();
691                 if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
692                         && windowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) {
693                     displayId = mA11yWindowManager.getDisplayIdByUserIdAndWindowIdLocked(
694                             mCurrentUserId, windowId);
695                 }
696                 if (displayId != Display.INVALID_DISPLAY
697                         && mA11yWindowManager.isTrackingWindowsLocked(displayId)) {
698                     shouldComputeWindows = true;
699                 }
700             }
701             if (shouldComputeWindows) {
702                 final WindowManagerInternal wm = LocalServices.getService(
703                         WindowManagerInternal.class);
704                 wm.computeWindowsForAccessibility(displayId);
705             }
706             synchronized (mLock) {
707                 notifyAccessibilityServicesDelayedLocked(event, false);
708                 notifyAccessibilityServicesDelayedLocked(event, true);
709                 mUiAutomationManager.sendAccessibilityEventLocked(event);
710             }
711         }
712 
713         if (OWN_PROCESS_ID != Binder.getCallingPid()) {
714             event.recycle();
715         }
716     }
717 
sendAccessibilityEventToInputFilter(AccessibilityEvent event)718     private void sendAccessibilityEventToInputFilter(AccessibilityEvent event) {
719         synchronized (mLock) {
720             if (mHasInputFilter && mInputFilter != null) {
721                 mInputFilter.notifyAccessibilityEvent(event);
722             }
723         }
724         event.recycle();
725     }
726 
727     /**
728      * This is the implementation of AccessibilityManager system API.
729      * System UI calls into this method through AccessibilityManager system API to register a
730      * system action.
731      */
732     @Override
registerSystemAction(RemoteAction action, int actionId)733     public void registerSystemAction(RemoteAction action, int actionId) {
734         mSecurityPolicy.enforceCallerIsRecentsOrHasPermission(
735                 Manifest.permission.MANAGE_ACCESSIBILITY,
736                 FUNCTION_REGISTER_SYSTEM_ACTION);
737         getSystemActionPerformer().registerSystemAction(actionId, action);
738     }
739 
740     /**
741      * This is the implementation of AccessibilityManager system API.
742      * System UI calls into this method through AccessibilityManager system API to unregister a
743      * system action.
744      */
745     @Override
unregisterSystemAction(int actionId)746     public void unregisterSystemAction(int actionId) {
747         mSecurityPolicy.enforceCallerIsRecentsOrHasPermission(
748                 Manifest.permission.MANAGE_ACCESSIBILITY,
749                 FUNCTION_UNREGISTER_SYSTEM_ACTION);
750         getSystemActionPerformer().unregisterSystemAction(actionId);
751     }
752 
getSystemActionPerformer()753     private SystemActionPerformer getSystemActionPerformer() {
754         if (mSystemActionPerformer == null) {
755             mSystemActionPerformer =
756                     new SystemActionPerformer(mContext, mWindowManagerService, null, this);
757         }
758         return mSystemActionPerformer;
759     }
760 
761     @Override
getInstalledAccessibilityServiceList(int userId)762     public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) {
763         synchronized (mLock) {
764             // We treat calls from a profile as if made by its parent as profiles
765             // share the accessibility state of the parent. The call below
766             // performs the current profile parent resolution.
767             final int resolvedUserId = mSecurityPolicy
768                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
769             return getUserStateLocked(resolvedUserId).mInstalledServices;
770         }
771     }
772 
773     @Override
getEnabledAccessibilityServiceList(int feedbackType, int userId)774     public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType,
775             int userId) {
776         synchronized (mLock) {
777             // We treat calls from a profile as if made by its parent as profiles
778             // share the accessibility state of the parent. The call below
779             // performs the current profile parent resolution.
780             final int resolvedUserId = mSecurityPolicy
781                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
782 
783             // The automation service can suppress other services.
784             final AccessibilityUserState userState = getUserStateLocked(resolvedUserId);
785             if (mUiAutomationManager.suppressingAccessibilityServicesLocked()) {
786                 return Collections.emptyList();
787             }
788 
789             final List<AccessibilityServiceConnection> services = userState.mBoundServices;
790             final int serviceCount = services.size();
791             final List<AccessibilityServiceInfo> result = new ArrayList<>(serviceCount);
792             for (int i = 0; i < serviceCount; ++i) {
793                 final AccessibilityServiceConnection service = services.get(i);
794                 if ((service.mFeedbackType & feedbackType) != 0) {
795                     result.add(service.getServiceInfo());
796                 }
797             }
798             return result;
799         }
800     }
801 
802     @Override
interrupt(int userId)803     public void interrupt(int userId) {
804         List<IAccessibilityServiceClient> interfacesToInterrupt;
805         synchronized (mLock) {
806             // We treat calls from a profile as if made by its parent as profiles
807             // share the accessibility state of the parent. The call below
808             // performs the current profile parent resolution.
809             final int resolvedUserId = mSecurityPolicy
810                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
811             // This method does nothing for a background user.
812             if (resolvedUserId != mCurrentUserId) {
813                 return;
814             }
815             List<AccessibilityServiceConnection> services =
816                     getUserStateLocked(resolvedUserId).mBoundServices;
817             int numServices = services.size();
818             interfacesToInterrupt = new ArrayList<>(numServices);
819             for (int i = 0; i < numServices; i++) {
820                 AccessibilityServiceConnection service = services.get(i);
821                 IBinder a11yServiceBinder = service.mService;
822                 IAccessibilityServiceClient a11yServiceInterface = service.mServiceInterface;
823                 if ((a11yServiceBinder != null) && (a11yServiceInterface != null)) {
824                     interfacesToInterrupt.add(a11yServiceInterface);
825                 }
826             }
827         }
828         for (int i = 0, count = interfacesToInterrupt.size(); i < count; i++) {
829             try {
830                 interfacesToInterrupt.get(i).onInterrupt();
831             } catch (RemoteException re) {
832                 Slog.e(LOG_TAG, "Error sending interrupt request to "
833                         + interfacesToInterrupt.get(i), re);
834             }
835         }
836     }
837 
838     @Override
addAccessibilityInteractionConnection(IWindow windowToken, IBinder leashToken, IAccessibilityInteractionConnection connection, String packageName, int userId)839     public int addAccessibilityInteractionConnection(IWindow windowToken, IBinder leashToken,
840             IAccessibilityInteractionConnection connection, String packageName,
841             int userId) throws RemoteException {
842         return mA11yWindowManager.addAccessibilityInteractionConnection(
843                 windowToken, leashToken, connection, packageName, userId);
844     }
845 
846     @Override
removeAccessibilityInteractionConnection(IWindow window)847     public void removeAccessibilityInteractionConnection(IWindow window) {
848         mA11yWindowManager.removeAccessibilityInteractionConnection(window);
849     }
850 
851     @Override
setPictureInPictureActionReplacingConnection( IAccessibilityInteractionConnection connection)852     public void setPictureInPictureActionReplacingConnection(
853             IAccessibilityInteractionConnection connection) throws RemoteException {
854         mSecurityPolicy.enforceCallingPermission(Manifest.permission.MODIFY_ACCESSIBILITY_DATA,
855                 SET_PIP_ACTION_REPLACEMENT);
856         mA11yWindowManager.setPictureInPictureActionReplacingConnection(connection);
857     }
858 
859     @Override
registerUiTestAutomationService(IBinder owner, IAccessibilityServiceClient serviceClient, AccessibilityServiceInfo accessibilityServiceInfo, int flags)860     public void registerUiTestAutomationService(IBinder owner,
861             IAccessibilityServiceClient serviceClient,
862             AccessibilityServiceInfo accessibilityServiceInfo,
863             int flags) {
864         mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT,
865                 FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE);
866 
867         synchronized (mLock) {
868             mUiAutomationManager.registerUiTestAutomationServiceLocked(owner, serviceClient,
869                     mContext, accessibilityServiceInfo, sIdCounter++, mMainHandler,
870                     mSecurityPolicy, this, mWindowManagerService, getSystemActionPerformer(),
871                     mA11yWindowManager, flags);
872             onUserStateChangedLocked(getCurrentUserStateLocked());
873         }
874     }
875 
876     @Override
unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient)877     public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) {
878         synchronized (mLock) {
879             mUiAutomationManager.unregisterUiTestAutomationServiceLocked(serviceClient);
880         }
881     }
882 
883     @Override
temporaryEnableAccessibilityStateUntilKeyguardRemoved( ComponentName service, boolean touchExplorationEnabled)884     public void temporaryEnableAccessibilityStateUntilKeyguardRemoved(
885             ComponentName service, boolean touchExplorationEnabled) {
886         mSecurityPolicy.enforceCallingPermission(
887                 Manifest.permission.TEMPORARY_ENABLE_ACCESSIBILITY,
888                 TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED);
889         if (!mWindowManagerService.isKeyguardLocked()) {
890             return;
891         }
892         synchronized (mLock) {
893             // Set the temporary state.
894             AccessibilityUserState userState = getCurrentUserStateLocked();
895 
896             userState.setTouchExplorationEnabledLocked(touchExplorationEnabled);
897             userState.setDisplayMagnificationEnabledLocked(false);
898             userState.disableShortcutMagnificationLocked();
899             userState.setAutoclickEnabledLocked(false);
900             userState.mEnabledServices.clear();
901             userState.mEnabledServices.add(service);
902             userState.getBindingServicesLocked().clear();
903             userState.getCrashedServicesLocked().clear();
904             userState.mTouchExplorationGrantedServices.clear();
905             userState.mTouchExplorationGrantedServices.add(service);
906 
907             // User the current state instead settings.
908             onUserStateChangedLocked(userState);
909         }
910     }
911 
912     @Override
getWindowToken(int windowId, int userId)913     public IBinder getWindowToken(int windowId, int userId) {
914         mSecurityPolicy.enforceCallingPermission(
915                 Manifest.permission.RETRIEVE_WINDOW_TOKEN,
916                 GET_WINDOW_TOKEN);
917         synchronized (mLock) {
918             // We treat calls from a profile as if made by its parent as profiles
919             // share the accessibility state of the parent. The call below
920             // performs the current profile parent resolution.
921             final int resolvedUserId = mSecurityPolicy
922                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
923             if (resolvedUserId != mCurrentUserId) {
924                 return null;
925             }
926             if (mA11yWindowManager.findA11yWindowInfoByIdLocked(windowId) == null) {
927                 return null;
928             }
929             return mA11yWindowManager.getWindowTokenForUserAndWindowIdLocked(userId, windowId);
930         }
931     }
932 
933     /**
934      * Invoked remotely over AIDL by SysUi when the accessibility button within the system's
935      * navigation area has been clicked.
936      *
937      * @param displayId The logical display id.
938      * @param targetName The flattened {@link ComponentName} string or the class name of a system
939      *        class implementing a supported accessibility feature, or {@code null} if there's no
940      *        specified target.
941      */
942     @Override
notifyAccessibilityButtonClicked(int displayId, String targetName)943     public void notifyAccessibilityButtonClicked(int displayId, String targetName) {
944         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE)
945                 != PackageManager.PERMISSION_GRANTED) {
946             throw new SecurityException("Caller does not hold permission "
947                     + android.Manifest.permission.STATUS_BAR_SERVICE);
948         }
949         if (targetName == null) {
950             synchronized (mLock) {
951                 final AccessibilityUserState userState = getCurrentUserStateLocked();
952                 targetName = userState.getTargetAssignedToAccessibilityButton();
953             }
954         }
955         mMainHandler.sendMessage(obtainMessage(
956                 AccessibilityManagerService::performAccessibilityShortcutInternal, this,
957                 displayId, ACCESSIBILITY_BUTTON, targetName));
958     }
959 
960     /**
961      * Invoked remotely over AIDL by SysUi when the visibility of the accessibility
962      * button within the system's navigation area has changed.
963      *
964      * @param shown {@code true} if the accessibility button is shown to the
965      *                  user, {@code false} otherwise
966      */
967     @Override
notifyAccessibilityButtonVisibilityChanged(boolean shown)968     public void notifyAccessibilityButtonVisibilityChanged(boolean shown) {
969         mSecurityPolicy.enforceCallingOrSelfPermission(
970                 android.Manifest.permission.STATUS_BAR_SERVICE);
971         synchronized (mLock) {
972             notifyAccessibilityButtonVisibilityChangedLocked(shown);
973         }
974     }
975 
976     /**
977      * Called when a gesture is detected on a display.
978      *
979      * @param gestureEvent the detail of the gesture.
980      * @return true if the event is handled.
981      */
onGesture(AccessibilityGestureEvent gestureEvent)982     public boolean onGesture(AccessibilityGestureEvent gestureEvent) {
983         synchronized (mLock) {
984             boolean handled = notifyGestureLocked(gestureEvent, false);
985             if (!handled) {
986                 handled = notifyGestureLocked(gestureEvent, true);
987             }
988             return handled;
989         }
990     }
991 
992     /**
993      * Called when the system action list is changed.
994      */
995     @Override
onSystemActionsChanged()996     public void onSystemActionsChanged() {
997         synchronized (mLock) {
998             AccessibilityUserState state = getCurrentUserStateLocked();
999             notifySystemActionsChangedLocked(state);
1000         }
1001     }
1002 
1003     @VisibleForTesting
notifySystemActionsChangedLocked(AccessibilityUserState userState)1004     void notifySystemActionsChangedLocked(AccessibilityUserState userState) {
1005         for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
1006             AccessibilityServiceConnection service = userState.mBoundServices.get(i);
1007             service.notifySystemActionsChangedLocked();
1008         }
1009     }
1010 
1011     @VisibleForTesting
notifyKeyEvent(KeyEvent event, int policyFlags)1012     public boolean notifyKeyEvent(KeyEvent event, int policyFlags) {
1013         synchronized (mLock) {
1014             List<AccessibilityServiceConnection> boundServices =
1015                     getCurrentUserStateLocked().mBoundServices;
1016             if (boundServices.isEmpty()) {
1017                 return false;
1018             }
1019             return getKeyEventDispatcher().notifyKeyEventLocked(event, policyFlags, boundServices);
1020         }
1021     }
1022 
1023     /**
1024      * Called by the MagnificationController when the state of display
1025      * magnification changes.
1026      *
1027      * @param displayId The logical display id.
1028      * @param region the new magnified region, may be empty if
1029      *               magnification is not enabled (e.g. scale is 1)
1030      * @param scale the new scale
1031      * @param centerX the new screen-relative center X coordinate
1032      * @param centerY the new screen-relative center Y coordinate
1033      */
notifyMagnificationChanged(int displayId, @NonNull Region region, float scale, float centerX, float centerY)1034     public void notifyMagnificationChanged(int displayId, @NonNull Region region,
1035             float scale, float centerX, float centerY) {
1036         synchronized (mLock) {
1037             notifyClearAccessibilityCacheLocked();
1038             notifyMagnificationChangedLocked(displayId, region, scale, centerX, centerY);
1039         }
1040     }
1041 
1042     /**
1043      * Called by AccessibilityInputFilter when it creates or destroys the motionEventInjector.
1044      * Not using a getter because the AccessibilityInputFilter isn't thread-safe
1045      *
1046      * @param motionEventInjectors The array of motionEventInjectors. May be null.
1047      *
1048      */
setMotionEventInjectors(SparseArray<MotionEventInjector> motionEventInjectors)1049     void setMotionEventInjectors(SparseArray<MotionEventInjector> motionEventInjectors) {
1050         synchronized (mLock) {
1051             mMotionEventInjectors = motionEventInjectors;
1052             // We may be waiting on this object being set
1053             mLock.notifyAll();
1054         }
1055     }
1056 
1057     @Override
getMotionEventInjectorForDisplayLocked(int displayId)1058     public @Nullable MotionEventInjector getMotionEventInjectorForDisplayLocked(int displayId) {
1059         final long endMillis = SystemClock.uptimeMillis() + WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS;
1060         MotionEventInjector motionEventInjector = null;
1061         while ((mMotionEventInjectors == null) && (SystemClock.uptimeMillis() < endMillis)) {
1062             try {
1063                 mLock.wait(endMillis - SystemClock.uptimeMillis());
1064             } catch (InterruptedException ie) {
1065                 /* ignore */
1066             }
1067         }
1068         if (mMotionEventInjectors == null) {
1069             Slog.e(LOG_TAG, "MotionEventInjector installation timed out");
1070         } else {
1071             motionEventInjector = mMotionEventInjectors.get(displayId);
1072         }
1073         return motionEventInjector;
1074     }
1075 
1076     /**
1077      * Gets a point within the accessibility focused node where we can send down
1078      * and up events to perform a click.
1079      *
1080      * @param outPoint The click point to populate.
1081      * @return Whether accessibility a click point was found and set.
1082      */
1083     // TODO: (multi-display) Make sure this works for multiple displays.
getAccessibilityFocusClickPointInScreen(Point outPoint)1084     public boolean getAccessibilityFocusClickPointInScreen(Point outPoint) {
1085         return getInteractionBridge().getAccessibilityFocusClickPointInScreenNotLocked(outPoint);
1086     }
1087 
1088     /**
1089      * Perform an accessibility action on the view that currently has accessibility focus.
1090      * Has no effect if no item has accessibility focus, if the item with accessibility
1091      * focus does not expose the specified action, or if the action fails.
1092      *
1093      * @param action The action to perform.
1094      *
1095      * @return {@code true} if the action was performed. {@code false} if it was not.
1096      */
performActionOnAccessibilityFocusedItem( AccessibilityNodeInfo.AccessibilityAction action)1097     public boolean performActionOnAccessibilityFocusedItem(
1098             AccessibilityNodeInfo.AccessibilityAction action) {
1099         return getInteractionBridge().performActionOnAccessibilityFocusedItemNotLocked(action);
1100     }
1101 
1102     /**
1103      * Returns true if accessibility focus is confined to the active window.
1104      */
accessibilityFocusOnlyInActiveWindow()1105     public boolean accessibilityFocusOnlyInActiveWindow() {
1106         synchronized (mLock) {
1107             return mA11yWindowManager.isTrackingWindowsLocked();
1108         }
1109     }
1110 
1111     /**
1112      * Gets the bounds of a window.
1113      *
1114      * @param outBounds The output to which to write the bounds.
1115      */
getWindowBounds(int windowId, Rect outBounds)1116     boolean getWindowBounds(int windowId, Rect outBounds) {
1117         IBinder token;
1118         synchronized (mLock) {
1119             token = getWindowToken(windowId, mCurrentUserId);
1120         }
1121         mWindowManagerService.getWindowFrame(token, outBounds);
1122         if (!outBounds.isEmpty()) {
1123             return true;
1124         }
1125         return false;
1126     }
1127 
getActiveWindowId()1128     public int getActiveWindowId() {
1129         return mA11yWindowManager.getActiveWindowId(mCurrentUserId);
1130     }
1131 
onTouchInteractionStart()1132     public void onTouchInteractionStart() {
1133         mA11yWindowManager.onTouchInteractionStart();
1134     }
1135 
onTouchInteractionEnd()1136     public void onTouchInteractionEnd() {
1137         mA11yWindowManager.onTouchInteractionEnd();
1138     }
1139 
switchUser(int userId)1140     private void switchUser(int userId) {
1141         synchronized (mLock) {
1142             if (mCurrentUserId == userId && mInitialized) {
1143                 return;
1144             }
1145 
1146             // Disconnect from services for the old user.
1147             AccessibilityUserState oldUserState = getCurrentUserStateLocked();
1148             oldUserState.onSwitchToAnotherUserLocked();
1149 
1150             // Disable the local managers for the old user.
1151             if (oldUserState.mUserClients.getRegisteredCallbackCount() > 0) {
1152                 mMainHandler.sendMessage(obtainMessage(
1153                         AccessibilityManagerService::sendStateToClients,
1154                         this, 0, oldUserState.mUserId));
1155             }
1156 
1157             // Announce user changes only if more that one exist.
1158             UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1159             final boolean announceNewUser = userManager.getUsers().size() > 1;
1160 
1161             // The user changed.
1162             mCurrentUserId = userId;
1163 
1164             AccessibilityUserState userState = getCurrentUserStateLocked();
1165 
1166             readConfigurationForUserStateLocked(userState);
1167             // Even if reading did not yield change, we have to update
1168             // the state since the context in which the current user
1169             // state was used has changed since it was inactive.
1170             onUserStateChangedLocked(userState);
1171             migrateAccessibilityButtonSettingsIfNecessaryLocked(userState, null);
1172 
1173             if (announceNewUser) {
1174                 // Schedule announcement of the current user if needed.
1175                 mMainHandler.sendMessageDelayed(
1176                         obtainMessage(AccessibilityManagerService::announceNewUserIfNeeded, this),
1177                         WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS);
1178             }
1179         }
1180     }
1181 
announceNewUserIfNeeded()1182     private void announceNewUserIfNeeded() {
1183         synchronized (mLock) {
1184             AccessibilityUserState userState = getCurrentUserStateLocked();
1185             if (userState.isHandlingAccessibilityEventsLocked()) {
1186                 UserManager userManager = (UserManager) mContext.getSystemService(
1187                         Context.USER_SERVICE);
1188                 String message = mContext.getString(R.string.user_switched,
1189                         userManager.getUserInfo(mCurrentUserId).name);
1190                 AccessibilityEvent event = AccessibilityEvent.obtain(
1191                         AccessibilityEvent.TYPE_ANNOUNCEMENT);
1192                 event.getText().add(message);
1193                 sendAccessibilityEventLocked(event, mCurrentUserId);
1194             }
1195         }
1196     }
1197 
unlockUser(int userId)1198     private void unlockUser(int userId) {
1199         synchronized (mLock) {
1200             int parentUserId = mSecurityPolicy.resolveProfileParentLocked(userId);
1201             if (parentUserId == mCurrentUserId) {
1202                 AccessibilityUserState userState = getUserStateLocked(mCurrentUserId);
1203                 onUserStateChangedLocked(userState);
1204             }
1205         }
1206     }
1207 
removeUser(int userId)1208     private void removeUser(int userId) {
1209         synchronized (mLock) {
1210             mUserStates.remove(userId);
1211         }
1212     }
1213 
1214     // Called only during settings restore; currently supports only the owner user
1215     // TODO: http://b/22388012
restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting)1216     void restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting) {
1217         readComponentNamesFromStringLocked(oldSetting, mTempComponentNameSet, false);
1218         readComponentNamesFromStringLocked(newSetting, mTempComponentNameSet, true);
1219 
1220         AccessibilityUserState userState = getUserStateLocked(UserHandle.USER_SYSTEM);
1221         userState.mEnabledServices.clear();
1222         userState.mEnabledServices.addAll(mTempComponentNameSet);
1223         persistComponentNamesToSettingLocked(
1224                 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
1225                 userState.mEnabledServices,
1226                 UserHandle.USER_SYSTEM);
1227         onUserStateChangedLocked(userState);
1228         migrateAccessibilityButtonSettingsIfNecessaryLocked(userState, null);
1229     }
1230 
getClientStateLocked(AccessibilityUserState userState)1231     private int getClientStateLocked(AccessibilityUserState userState) {
1232         return userState.getClientStateLocked(mUiAutomationManager.isUiAutomationRunningLocked());
1233     }
1234 
getInteractionBridge()1235     private InteractionBridge getInteractionBridge() {
1236         synchronized (mLock) {
1237             if (mInteractionBridge == null) {
1238                 mInteractionBridge = new InteractionBridge();
1239             }
1240             return mInteractionBridge;
1241         }
1242     }
1243 
notifyGestureLocked(AccessibilityGestureEvent gestureEvent, boolean isDefault)1244     private boolean notifyGestureLocked(AccessibilityGestureEvent gestureEvent, boolean isDefault) {
1245         // TODO: Now we are giving the gestures to the last enabled
1246         //       service that can handle them which is the last one
1247         //       in our list since we write the last enabled as the
1248         //       last record in the enabled services setting. Ideally,
1249         //       the user should make the call which service handles
1250         //       gestures. However, only one service should handle
1251         //       gestures to avoid user frustration when different
1252         //       behavior is observed from different combinations of
1253         //       enabled accessibility services.
1254         AccessibilityUserState state = getCurrentUserStateLocked();
1255         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1256             AccessibilityServiceConnection service = state.mBoundServices.get(i);
1257             if (service.mRequestTouchExplorationMode && service.mIsDefault == isDefault) {
1258                 service.notifyGesture(gestureEvent);
1259                 return true;
1260             }
1261         }
1262         return false;
1263     }
1264 
notifyClearAccessibilityCacheLocked()1265     private void notifyClearAccessibilityCacheLocked() {
1266         AccessibilityUserState state = getCurrentUserStateLocked();
1267         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1268             AccessibilityServiceConnection service = state.mBoundServices.get(i);
1269             service.notifyClearAccessibilityNodeInfoCache();
1270         }
1271     }
1272 
notifyMagnificationChangedLocked(int displayId, @NonNull Region region, float scale, float centerX, float centerY)1273     private void notifyMagnificationChangedLocked(int displayId, @NonNull Region region,
1274             float scale, float centerX, float centerY) {
1275         final AccessibilityUserState state = getCurrentUserStateLocked();
1276         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1277             final AccessibilityServiceConnection service = state.mBoundServices.get(i);
1278             service.notifyMagnificationChangedLocked(displayId, region, scale, centerX, centerY);
1279         }
1280     }
1281 
sendAccessibilityButtonToInputFilter(int displayId)1282     private void sendAccessibilityButtonToInputFilter(int displayId) {
1283         synchronized (mLock) {
1284             if (mHasInputFilter && mInputFilter != null) {
1285                 mInputFilter.notifyAccessibilityButtonClicked(displayId);
1286             }
1287         }
1288     }
1289 
showAccessibilityTargetsSelection(int displayId, @ShortcutType int shortcutType)1290     private void showAccessibilityTargetsSelection(int displayId,
1291             @ShortcutType int shortcutType) {
1292         final Intent intent = new Intent(AccessibilityManager.ACTION_CHOOSE_ACCESSIBILITY_BUTTON);
1293         final String chooserClassName = (shortcutType == ACCESSIBILITY_SHORTCUT_KEY)
1294                 ? AccessibilityShortcutChooserActivity.class.getName()
1295                 : AccessibilityButtonChooserActivity.class.getName();
1296         intent.setClassName(CHOOSER_PACKAGE_NAME, chooserClassName);
1297         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1298         final Bundle bundle = ActivityOptions.makeBasic().setLaunchDisplayId(displayId).toBundle();
1299         mContext.startActivityAsUser(intent, bundle, UserHandle.of(mCurrentUserId));
1300     }
1301 
launchShortcutTargetActivity(int displayId, ComponentName name)1302     private void launchShortcutTargetActivity(int displayId, ComponentName name) {
1303         final Intent intent = new Intent();
1304         final Bundle bundle = ActivityOptions.makeBasic().setLaunchDisplayId(displayId).toBundle();
1305         intent.setComponent(name);
1306         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1307         try {
1308             mContext.startActivityAsUser(intent, bundle, UserHandle.of(mCurrentUserId));
1309         } catch (ActivityNotFoundException ignore) {
1310             // ignore the exception
1311         }
1312     }
1313 
notifyAccessibilityButtonVisibilityChangedLocked(boolean available)1314     private void notifyAccessibilityButtonVisibilityChangedLocked(boolean available) {
1315         final AccessibilityUserState state = getCurrentUserStateLocked();
1316         mIsAccessibilityButtonShown = available;
1317         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1318             final AccessibilityServiceConnection clientConnection = state.mBoundServices.get(i);
1319             if (clientConnection.mRequestAccessibilityButton) {
1320                 clientConnection.notifyAccessibilityButtonAvailabilityChangedLocked(
1321                         clientConnection.isAccessibilityButtonAvailableLocked(state));
1322             }
1323         }
1324     }
1325 
readInstalledAccessibilityServiceLocked(AccessibilityUserState userState)1326     private boolean readInstalledAccessibilityServiceLocked(AccessibilityUserState userState) {
1327         mTempAccessibilityServiceInfoList.clear();
1328 
1329         int flags = PackageManager.GET_SERVICES
1330                 | PackageManager.GET_META_DATA
1331                 | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
1332                 | PackageManager.MATCH_DIRECT_BOOT_AWARE
1333                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
1334 
1335         if (userState.getBindInstantServiceAllowedLocked()) {
1336             flags |= PackageManager.MATCH_INSTANT;
1337         }
1338 
1339         List<ResolveInfo> installedServices = mPackageManager.queryIntentServicesAsUser(
1340                 new Intent(AccessibilityService.SERVICE_INTERFACE), flags, mCurrentUserId);
1341 
1342         for (int i = 0, count = installedServices.size(); i < count; i++) {
1343             ResolveInfo resolveInfo = installedServices.get(i);
1344             ServiceInfo serviceInfo = resolveInfo.serviceInfo;
1345 
1346             if (!mSecurityPolicy.canRegisterService(serviceInfo)) {
1347                 continue;
1348             }
1349 
1350             AccessibilityServiceInfo accessibilityServiceInfo;
1351             try {
1352                 accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext);
1353                 if (userState.mCrashedServices.contains(serviceInfo.getComponentName())) {
1354                     // Restore the crashed attribute.
1355                     accessibilityServiceInfo.crashed = true;
1356                 }
1357                 mTempAccessibilityServiceInfoList.add(accessibilityServiceInfo);
1358             } catch (XmlPullParserException | IOException xppe) {
1359                 Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", xppe);
1360             }
1361         }
1362 
1363         if (!mTempAccessibilityServiceInfoList.equals(userState.mInstalledServices)) {
1364             userState.mInstalledServices.clear();
1365             userState.mInstalledServices.addAll(mTempAccessibilityServiceInfoList);
1366             mTempAccessibilityServiceInfoList.clear();
1367             return true;
1368         }
1369 
1370         mTempAccessibilityServiceInfoList.clear();
1371         return false;
1372     }
1373 
readInstalledAccessibilityShortcutLocked(AccessibilityUserState userState)1374     private boolean readInstalledAccessibilityShortcutLocked(AccessibilityUserState userState) {
1375         final List<AccessibilityShortcutInfo> shortcutInfos = AccessibilityManager
1376                 .getInstance(mContext).getInstalledAccessibilityShortcutListAsUser(
1377                         mContext, mCurrentUserId);
1378         if (!shortcutInfos.equals(userState.mInstalledShortcuts)) {
1379             userState.mInstalledShortcuts.clear();
1380             userState.mInstalledShortcuts.addAll(shortcutInfos);
1381             return true;
1382         }
1383         return false;
1384     }
1385 
readEnabledAccessibilityServicesLocked(AccessibilityUserState userState)1386     private boolean readEnabledAccessibilityServicesLocked(AccessibilityUserState userState) {
1387         mTempComponentNameSet.clear();
1388         readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
1389                 userState.mUserId, mTempComponentNameSet);
1390         if (!mTempComponentNameSet.equals(userState.mEnabledServices)) {
1391             userState.mEnabledServices.clear();
1392             userState.mEnabledServices.addAll(mTempComponentNameSet);
1393             mTempComponentNameSet.clear();
1394             return true;
1395         }
1396         mTempComponentNameSet.clear();
1397         return false;
1398     }
1399 
readTouchExplorationGrantedAccessibilityServicesLocked( AccessibilityUserState userState)1400     private boolean readTouchExplorationGrantedAccessibilityServicesLocked(
1401             AccessibilityUserState userState) {
1402         mTempComponentNameSet.clear();
1403         readComponentNamesFromSettingLocked(
1404                 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
1405                 userState.mUserId, mTempComponentNameSet);
1406         if (!mTempComponentNameSet.equals(userState.mTouchExplorationGrantedServices)) {
1407             userState.mTouchExplorationGrantedServices.clear();
1408             userState.mTouchExplorationGrantedServices.addAll(mTempComponentNameSet);
1409             mTempComponentNameSet.clear();
1410             return true;
1411         }
1412         mTempComponentNameSet.clear();
1413         return false;
1414     }
1415 
1416     /**
1417      * Performs {@link AccessibilityService}s delayed notification. The delay is configurable
1418      * and denotes the period after the last event before notifying the service.
1419      *
1420      * @param event The event.
1421      * @param isDefault True to notify default listeners, not default services.
1422      */
notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event, boolean isDefault)1423     private void notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event,
1424             boolean isDefault) {
1425         try {
1426             AccessibilityUserState state = getCurrentUserStateLocked();
1427             for (int i = 0, count = state.mBoundServices.size(); i < count; i++) {
1428                 AccessibilityServiceConnection service = state.mBoundServices.get(i);
1429 
1430                 if (service.mIsDefault == isDefault) {
1431                     service.notifyAccessibilityEvent(event);
1432                 }
1433             }
1434         } catch (IndexOutOfBoundsException oobe) {
1435             // An out of bounds exception can happen if services are going away
1436             // as the for loop is running. If that happens, just bail because
1437             // there are no more services to notify.
1438         }
1439     }
1440 
updateRelevantEventsLocked(AccessibilityUserState userState)1441     private void updateRelevantEventsLocked(AccessibilityUserState userState) {
1442         mMainHandler.post(() -> {
1443             broadcastToClients(userState, ignoreRemoteException(client -> {
1444                 int relevantEventTypes;
1445                 boolean changed = false;
1446                 synchronized (mLock) {
1447                     relevantEventTypes = computeRelevantEventTypesLocked(userState, client);
1448 
1449                     if (client.mLastSentRelevantEventTypes != relevantEventTypes) {
1450                         client.mLastSentRelevantEventTypes = relevantEventTypes;
1451                         changed = true;
1452                     }
1453                 }
1454                 if (changed) {
1455                     client.mCallback.setRelevantEventTypes(relevantEventTypes);
1456                 }
1457             }));
1458         });
1459     }
1460 
computeRelevantEventTypesLocked(AccessibilityUserState userState, Client client)1461     private int computeRelevantEventTypesLocked(AccessibilityUserState userState, Client client) {
1462         int relevantEventTypes = 0;
1463 
1464         int serviceCount = userState.mBoundServices.size();
1465         for (int i = 0; i < serviceCount; i++) {
1466             AccessibilityServiceConnection service = userState.mBoundServices.get(i);
1467             relevantEventTypes |= isClientInPackageWhitelist(service.getServiceInfo(), client)
1468                     ? service.getRelevantEventTypes()
1469                     : 0;
1470         }
1471 
1472         relevantEventTypes |= isClientInPackageWhitelist(
1473                 mUiAutomationManager.getServiceInfo(), client)
1474                 ? mUiAutomationManager.getRelevantEventTypes()
1475                 : 0;
1476         return relevantEventTypes;
1477     }
1478 
isClientInPackageWhitelist( @ullable AccessibilityServiceInfo serviceInfo, Client client)1479     private static boolean isClientInPackageWhitelist(
1480             @Nullable AccessibilityServiceInfo serviceInfo, Client client) {
1481         if (serviceInfo == null) return false;
1482 
1483         String[] clientPackages = client.mPackageNames;
1484         boolean result = ArrayUtils.isEmpty(serviceInfo.packageNames);
1485         if (!result && clientPackages != null) {
1486             for (String packageName : clientPackages) {
1487                 if (ArrayUtils.contains(serviceInfo.packageNames, packageName)) {
1488                     result = true;
1489                     break;
1490                 }
1491             }
1492         }
1493         if (!result) {
1494             if (DEBUG) {
1495                 Slog.d(LOG_TAG, "Dropping events: "
1496                         + Arrays.toString(clientPackages) + " -> "
1497                         + serviceInfo.getComponentName().flattenToShortString()
1498                         + " due to not being in package whitelist "
1499                         + Arrays.toString(serviceInfo.packageNames));
1500             }
1501         }
1502 
1503         return result;
1504     }
1505 
broadcastToClients( AccessibilityUserState userState, Consumer<Client> clientAction)1506     private void broadcastToClients(
1507             AccessibilityUserState userState, Consumer<Client> clientAction) {
1508         mGlobalClients.broadcastForEachCookie(clientAction);
1509         userState.mUserClients.broadcastForEachCookie(clientAction);
1510     }
1511 
1512     /**
1513      * Populates a set with the {@link ComponentName}s stored in a colon
1514      * separated value setting for a given user.
1515      *
1516      * @param settingName The setting to parse.
1517      * @param userId The user id.
1518      * @param outComponentNames The output component names.
1519      */
readComponentNamesFromSettingLocked(String settingName, int userId, Set<ComponentName> outComponentNames)1520     private void readComponentNamesFromSettingLocked(String settingName, int userId,
1521             Set<ComponentName> outComponentNames) {
1522         readColonDelimitedSettingToSet(settingName, userId, outComponentNames,
1523                 str -> ComponentName.unflattenFromString(str));
1524     }
1525 
1526     /**
1527      * Populates a set with the {@link ComponentName}s contained in a colon-delimited string.
1528      *
1529      * @param names The colon-delimited string to parse.
1530      * @param outComponentNames The set of component names to be populated based on
1531      *    the contents of the <code>names</code> string.
1532      * @param doMerge If true, the parsed component names will be merged into the output
1533      *    set, rather than replacing the set's existing contents entirely.
1534      */
readComponentNamesFromStringLocked(String names, Set<ComponentName> outComponentNames, boolean doMerge)1535     private void readComponentNamesFromStringLocked(String names,
1536             Set<ComponentName> outComponentNames,
1537             boolean doMerge) {
1538         readColonDelimitedStringToSet(names, outComponentNames, doMerge,
1539                 str -> ComponentName.unflattenFromString(str));
1540     }
1541 
1542     @Override
persistComponentNamesToSettingLocked(String settingName, Set<ComponentName> componentNames, int userId)1543     public void persistComponentNamesToSettingLocked(String settingName,
1544             Set<ComponentName> componentNames, int userId) {
1545         persistColonDelimitedSetToSettingLocked(settingName, userId, componentNames,
1546                 componentName -> componentName.flattenToShortString());
1547     }
1548 
readColonDelimitedSettingToSet(String settingName, int userId, Set<T> outSet, Function<String, T> toItem)1549     private <T> void readColonDelimitedSettingToSet(String settingName, int userId, Set<T> outSet,
1550             Function<String, T> toItem) {
1551         final String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(),
1552                 settingName, userId);
1553         readColonDelimitedStringToSet(settingValue, outSet, false, toItem);
1554     }
1555 
readColonDelimitedStringToSet(String names, Set<T> outSet, boolean doMerge, Function<String, T> toItem)1556     private <T> void readColonDelimitedStringToSet(String names, Set<T> outSet, boolean doMerge,
1557             Function<String, T> toItem) {
1558         if (!doMerge) {
1559             outSet.clear();
1560         }
1561         if (!TextUtils.isEmpty(names)) {
1562             final TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
1563             splitter.setString(names);
1564             while (splitter.hasNext()) {
1565                 final String str = splitter.next();
1566                 if (TextUtils.isEmpty(str)) {
1567                     continue;
1568                 }
1569                 final T item = toItem.apply(str);
1570                 if (item != null) {
1571                     outSet.add(item);
1572                 }
1573             }
1574         }
1575     }
1576 
persistColonDelimitedSetToSettingLocked(String settingName, int userId, Set<T> set, Function<T, String> toString)1577     private <T> void persistColonDelimitedSetToSettingLocked(String settingName, int userId,
1578             Set<T> set, Function<T, String> toString) {
1579         final StringBuilder builder = new StringBuilder();
1580         for (T item : set) {
1581             final String str = (item != null ? toString.apply(item) : null);
1582             if (TextUtils.isEmpty(str)) {
1583                 continue;
1584             }
1585             if (builder.length() > 0) {
1586                 builder.append(COMPONENT_NAME_SEPARATOR);
1587             }
1588             builder.append(str);
1589         }
1590         final long identity = Binder.clearCallingIdentity();
1591         try {
1592             final String settingValue = builder.toString();
1593             Settings.Secure.putStringForUser(mContext.getContentResolver(),
1594                     settingName, TextUtils.isEmpty(settingValue) ? null : settingValue, userId);
1595         } finally {
1596             Binder.restoreCallingIdentity(identity);
1597         }
1598     }
1599 
updateServicesLocked(AccessibilityUserState userState)1600     private void updateServicesLocked(AccessibilityUserState userState) {
1601         Map<ComponentName, AccessibilityServiceConnection> componentNameToServiceMap =
1602                 userState.mComponentNameToServiceMap;
1603         boolean isUnlockingOrUnlocked = LocalServices.getService(UserManagerInternal.class)
1604                     .isUserUnlockingOrUnlocked(userState.mUserId);
1605 
1606         for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) {
1607             AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i);
1608             ComponentName componentName = ComponentName.unflattenFromString(
1609                     installedService.getId());
1610 
1611             AccessibilityServiceConnection service = componentNameToServiceMap.get(componentName);
1612 
1613             // Ignore non-encryption-aware services until user is unlocked
1614             if (!isUnlockingOrUnlocked && !installedService.isDirectBootAware()) {
1615                 Slog.d(LOG_TAG, "Ignoring non-encryption-aware service " + componentName);
1616                 continue;
1617             }
1618 
1619             // Skip the component since it may be in process or crashed.
1620             if (userState.getBindingServicesLocked().contains(componentName)
1621                     || userState.getCrashedServicesLocked().contains(componentName)) {
1622                 continue;
1623             }
1624             if (userState.mEnabledServices.contains(componentName)
1625                     && !mUiAutomationManager.suppressingAccessibilityServicesLocked()) {
1626                 if (service == null) {
1627                     service = new AccessibilityServiceConnection(userState, mContext, componentName,
1628                             installedService, sIdCounter++, mMainHandler, mLock, mSecurityPolicy,
1629                             this, mWindowManagerService, getSystemActionPerformer(),
1630                             mA11yWindowManager, mActivityTaskManagerService);
1631                 } else if (userState.mBoundServices.contains(service)) {
1632                     continue;
1633                 }
1634                 service.bindLocked();
1635             } else {
1636                 if (service != null) {
1637                     service.unbindLocked();
1638                     removeShortcutTargetForUnboundServiceLocked(userState, service);
1639                 }
1640             }
1641         }
1642 
1643         final int count = userState.mBoundServices.size();
1644         mTempIntArray.clear();
1645         for (int i = 0; i < count; i++) {
1646             final ResolveInfo resolveInfo =
1647                     userState.mBoundServices.get(i).mAccessibilityServiceInfo.getResolveInfo();
1648             if (resolveInfo != null) {
1649                 mTempIntArray.add(resolveInfo.serviceInfo.applicationInfo.uid);
1650             }
1651         }
1652         // Calling out with lock held, but to a lower-level service
1653         final AudioManagerInternal audioManager =
1654                 LocalServices.getService(AudioManagerInternal.class);
1655         if (audioManager != null) {
1656             audioManager.setAccessibilityServiceUids(mTempIntArray);
1657         }
1658         updateAccessibilityEnabledSettingLocked(userState);
1659     }
1660 
scheduleUpdateClientsIfNeededLocked(AccessibilityUserState userState)1661     private void scheduleUpdateClientsIfNeededLocked(AccessibilityUserState userState) {
1662         final int clientState = getClientStateLocked(userState);
1663         if (userState.getLastSentClientStateLocked() != clientState
1664                 && (mGlobalClients.getRegisteredCallbackCount() > 0
1665                         || userState.mUserClients.getRegisteredCallbackCount() > 0)) {
1666             userState.setLastSentClientStateLocked(clientState);
1667             mMainHandler.sendMessage(obtainMessage(
1668                     AccessibilityManagerService::sendStateToAllClients,
1669                     this, clientState, userState.mUserId));
1670         }
1671     }
1672 
sendStateToAllClients(int clientState, int userId)1673     private void sendStateToAllClients(int clientState, int userId) {
1674         sendStateToClients(clientState, mGlobalClients);
1675         sendStateToClients(clientState, userId);
1676     }
1677 
sendStateToClients(int clientState, int userId)1678     private void sendStateToClients(int clientState, int userId) {
1679         sendStateToClients(clientState, getUserState(userId).mUserClients);
1680     }
1681 
sendStateToClients(int clientState, RemoteCallbackList<IAccessibilityManagerClient> clients)1682     private void sendStateToClients(int clientState,
1683             RemoteCallbackList<IAccessibilityManagerClient> clients) {
1684         clients.broadcast(ignoreRemoteException(
1685                 client -> client.setState(clientState)));
1686     }
1687 
scheduleNotifyClientsOfServicesStateChangeLocked( AccessibilityUserState userState)1688     private void scheduleNotifyClientsOfServicesStateChangeLocked(
1689             AccessibilityUserState userState) {
1690         updateRecommendedUiTimeoutLocked(userState);
1691         mMainHandler.sendMessage(obtainMessage(
1692                 AccessibilityManagerService::sendServicesStateChanged,
1693                 this, userState.mUserClients, getRecommendedTimeoutMillisLocked(userState)));
1694     }
1695 
sendServicesStateChanged( RemoteCallbackList<IAccessibilityManagerClient> userClients, long uiTimeout)1696     private void sendServicesStateChanged(
1697             RemoteCallbackList<IAccessibilityManagerClient> userClients, long uiTimeout) {
1698         notifyClientsOfServicesStateChange(mGlobalClients, uiTimeout);
1699         notifyClientsOfServicesStateChange(userClients, uiTimeout);
1700     }
1701 
notifyClientsOfServicesStateChange( RemoteCallbackList<IAccessibilityManagerClient> clients, long uiTimeout)1702     private void notifyClientsOfServicesStateChange(
1703             RemoteCallbackList<IAccessibilityManagerClient> clients, long uiTimeout) {
1704         clients.broadcast(ignoreRemoteException(
1705                 client -> client.notifyServicesStateChanged(uiTimeout)));
1706     }
1707 
scheduleUpdateInputFilter(AccessibilityUserState userState)1708     private void scheduleUpdateInputFilter(AccessibilityUserState userState) {
1709         mMainHandler.sendMessage(obtainMessage(
1710                 AccessibilityManagerService::updateInputFilter, this, userState));
1711     }
1712 
scheduleUpdateFingerprintGestureHandling(AccessibilityUserState userState)1713     private void scheduleUpdateFingerprintGestureHandling(AccessibilityUserState userState) {
1714         mMainHandler.sendMessage(obtainMessage(
1715                 AccessibilityManagerService::updateFingerprintGestureHandling,
1716                 this, userState));
1717     }
1718 
updateInputFilter(AccessibilityUserState userState)1719     private void updateInputFilter(AccessibilityUserState userState) {
1720         if (mUiAutomationManager.suppressingAccessibilityServicesLocked()) return;
1721 
1722         boolean setInputFilter = false;
1723         AccessibilityInputFilter inputFilter = null;
1724         synchronized (mLock) {
1725             int flags = 0;
1726             if (userState.isDisplayMagnificationEnabledLocked()) {
1727                 flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER;
1728             }
1729             if (userState.isShortcutMagnificationEnabledLocked()) {
1730                 flags |= AccessibilityInputFilter.FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER;
1731             }
1732             if (userHasMagnificationServicesLocked(userState)) {
1733                 flags |= AccessibilityInputFilter.FLAG_FEATURE_CONTROL_SCREEN_MAGNIFIER;
1734             }
1735             // Touch exploration without accessibility makes no sense.
1736             if (userState.isHandlingAccessibilityEventsLocked()
1737                     && userState.isTouchExplorationEnabledLocked()) {
1738                 flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION;
1739                 if (userState.isServiceHandlesDoubleTapEnabledLocked()) {
1740                     flags |= AccessibilityInputFilter.FLAG_SERVICE_HANDLES_DOUBLE_TAP;
1741                 }
1742                 if (userState.isMultiFingerGesturesEnabledLocked()) {
1743                     flags |= AccessibilityInputFilter.FLAG_REQUEST_MULTI_FINGER_GESTURES;
1744                 }
1745                 if (userState.isTwoFingerPassthroughEnabledLocked()) {
1746                     flags |= AccessibilityInputFilter.FLAG_REQUEST_2_FINGER_PASSTHROUGH;
1747                 }
1748             }
1749             if (userState.isFilterKeyEventsEnabledLocked()) {
1750                 flags |= AccessibilityInputFilter.FLAG_FEATURE_FILTER_KEY_EVENTS;
1751             }
1752             if (userState.isAutoclickEnabledLocked()) {
1753                 flags |= AccessibilityInputFilter.FLAG_FEATURE_AUTOCLICK;
1754             }
1755             if (userState.isPerformGesturesEnabledLocked()) {
1756                 flags |= AccessibilityInputFilter.FLAG_FEATURE_INJECT_MOTION_EVENTS;
1757             }
1758             if (flags != 0) {
1759                 if (!mHasInputFilter) {
1760                     mHasInputFilter = true;
1761                     if (mInputFilter == null) {
1762                         mInputFilter = new AccessibilityInputFilter(mContext,
1763                                 AccessibilityManagerService.this);
1764                     }
1765                     inputFilter = mInputFilter;
1766                     setInputFilter = true;
1767                 }
1768                 mInputFilter.setUserAndEnabledFeatures(userState.mUserId, flags);
1769             } else {
1770                 if (mHasInputFilter) {
1771                     mHasInputFilter = false;
1772                     mInputFilter.setUserAndEnabledFeatures(userState.mUserId, 0);
1773                     inputFilter = null;
1774                     setInputFilter = true;
1775                 }
1776             }
1777         }
1778         if (setInputFilter) {
1779             mWindowManagerService.setInputFilter(inputFilter);
1780         }
1781     }
1782 
showEnableTouchExplorationDialog(final AccessibilityServiceConnection service)1783     private void showEnableTouchExplorationDialog(final AccessibilityServiceConnection service) {
1784         synchronized (mLock) {
1785             String label = service.getServiceInfo().getResolveInfo()
1786                     .loadLabel(mContext.getPackageManager()).toString();
1787 
1788             final AccessibilityUserState userState = getCurrentUserStateLocked();
1789             if (userState.isTouchExplorationEnabledLocked()) {
1790                 return;
1791             }
1792             if (mEnableTouchExplorationDialog != null
1793                     && mEnableTouchExplorationDialog.isShowing()) {
1794                 return;
1795             }
1796             mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext)
1797                 .setIconAttribute(android.R.attr.alertDialogIcon)
1798                 .setPositiveButton(android.R.string.ok, new OnClickListener() {
1799                     @Override
1800                     public void onClick(DialogInterface dialog, int which) {
1801                         // The user allowed the service to toggle touch exploration.
1802                         userState.mTouchExplorationGrantedServices.add(service.mComponentName);
1803                         persistComponentNamesToSettingLocked(
1804                                 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
1805                                 userState.mTouchExplorationGrantedServices, userState.mUserId);
1806                         // Enable touch exploration.
1807                         userState.setTouchExplorationEnabledLocked(true);
1808                         final long identity = Binder.clearCallingIdentity();
1809                         try {
1810                             Settings.Secure.putIntForUser(mContext.getContentResolver(),
1811                                     Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1,
1812                                     userState.mUserId);
1813                         } finally {
1814                             Binder.restoreCallingIdentity(identity);
1815                         }
1816                         onUserStateChangedLocked(userState);
1817                     }
1818                 })
1819                 .setNegativeButton(android.R.string.cancel, new OnClickListener() {
1820                     @Override
1821                     public void onClick(DialogInterface dialog, int which) {
1822                         dialog.dismiss();
1823                     }
1824                 })
1825                 .setTitle(R.string.enable_explore_by_touch_warning_title)
1826                 .setMessage(mContext.getString(
1827                         R.string.enable_explore_by_touch_warning_message, label))
1828                 .create();
1829              mEnableTouchExplorationDialog.getWindow().setType(
1830                      WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
1831              mEnableTouchExplorationDialog.getWindow().getAttributes().privateFlags
1832                      |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
1833              mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true);
1834              mEnableTouchExplorationDialog.show();
1835         }
1836     }
1837 
1838     /**
1839      * Called when any property of the user state has changed.
1840      *
1841      * @param userState the new user state
1842      */
onUserStateChangedLocked(AccessibilityUserState userState)1843     private void onUserStateChangedLocked(AccessibilityUserState userState) {
1844         // TODO: Remove this hack
1845         mInitialized = true;
1846         updateLegacyCapabilitiesLocked(userState);
1847         updateServicesLocked(userState);
1848         updateWindowsForAccessibilityCallbackLocked(userState);
1849         updateFilterKeyEventsLocked(userState);
1850         updateTouchExplorationLocked(userState);
1851         updatePerformGesturesLocked(userState);
1852         updateMagnificationLocked(userState);
1853         scheduleUpdateFingerprintGestureHandling(userState);
1854         scheduleUpdateInputFilter(userState);
1855         updateRelevantEventsLocked(userState);
1856         scheduleUpdateClientsIfNeededLocked(userState);
1857         updateAccessibilityShortcutKeyTargetsLocked(userState);
1858         updateAccessibilityButtonTargetsLocked(userState);
1859     }
1860 
updateWindowsForAccessibilityCallbackLocked(AccessibilityUserState userState)1861     private void updateWindowsForAccessibilityCallbackLocked(AccessibilityUserState userState) {
1862         // We observe windows for accessibility only if there is at least
1863         // one bound service that can retrieve window content that specified
1864         // it is interested in accessing such windows. For services that are
1865         // binding we do an update pass after each bind event, so we run this
1866         // code and register the callback if needed.
1867 
1868         boolean observingWindows = mUiAutomationManager.canRetrieveInteractiveWindowsLocked();
1869         List<AccessibilityServiceConnection> boundServices = userState.mBoundServices;
1870         final int boundServiceCount = boundServices.size();
1871         for (int i = 0; !observingWindows && (i < boundServiceCount); i++) {
1872             AccessibilityServiceConnection boundService = boundServices.get(i);
1873             if (boundService.canRetrieveInteractiveWindowsLocked()) {
1874                 userState.setAccessibilityFocusOnlyInActiveWindow(false);
1875                 observingWindows = true;
1876             }
1877         }
1878         userState.setAccessibilityFocusOnlyInActiveWindow(true);
1879 
1880         // Gets all valid displays and start tracking windows of each display if there is at least
1881         // one bound service that can retrieve window content.
1882         final ArrayList<Display> displays = getValidDisplayList();
1883         for (int i = 0; i < displays.size(); i++) {
1884             final Display display = displays.get(i);
1885             if (display != null) {
1886                 if (observingWindows) {
1887                     mA11yWindowManager.startTrackingWindows(display.getDisplayId());
1888                 } else {
1889                     mA11yWindowManager.stopTrackingWindows(display.getDisplayId());
1890                 }
1891             }
1892         }
1893     }
1894 
updateLegacyCapabilitiesLocked(AccessibilityUserState userState)1895     private void updateLegacyCapabilitiesLocked(AccessibilityUserState userState) {
1896         // Up to JB-MR1 we had a white list with services that can enable touch
1897         // exploration. When a service is first started we show a dialog to the
1898         // use to get a permission to white list the service.
1899         final int installedServiceCount = userState.mInstalledServices.size();
1900         for (int i = 0; i < installedServiceCount; i++) {
1901             AccessibilityServiceInfo serviceInfo = userState.mInstalledServices.get(i);
1902             ResolveInfo resolveInfo = serviceInfo.getResolveInfo();
1903             if ((serviceInfo.getCapabilities()
1904                         & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) == 0
1905                     && resolveInfo.serviceInfo.applicationInfo.targetSdkVersion
1906                         <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
1907                 ComponentName componentName = new ComponentName(
1908                         resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
1909                 if (userState.mTouchExplorationGrantedServices.contains(componentName)) {
1910                     serviceInfo.setCapabilities(serviceInfo.getCapabilities()
1911                             | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION);
1912                 }
1913             }
1914         }
1915     }
1916 
updatePerformGesturesLocked(AccessibilityUserState userState)1917     private void updatePerformGesturesLocked(AccessibilityUserState userState) {
1918         final int serviceCount = userState.mBoundServices.size();
1919         for (int i = 0; i < serviceCount; i++) {
1920             AccessibilityServiceConnection service = userState.mBoundServices.get(i);
1921             if ((service.getCapabilities()
1922                     & AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0) {
1923                 userState.setPerformGesturesEnabledLocked(true);
1924                 return;
1925             }
1926         }
1927         userState.setPerformGesturesEnabledLocked(false);
1928     }
1929 
updateFilterKeyEventsLocked(AccessibilityUserState userState)1930     private void updateFilterKeyEventsLocked(AccessibilityUserState userState) {
1931         final int serviceCount = userState.mBoundServices.size();
1932         for (int i = 0; i < serviceCount; i++) {
1933             AccessibilityServiceConnection service = userState.mBoundServices.get(i);
1934             if (service.mRequestFilterKeyEvents
1935                     && (service.getCapabilities()
1936                             & AccessibilityServiceInfo
1937                             .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) != 0) {
1938                 userState.setFilterKeyEventsEnabledLocked(true);
1939                 return;
1940             }
1941         }
1942         userState.setFilterKeyEventsEnabledLocked(false);
1943     }
1944 
readConfigurationForUserStateLocked(AccessibilityUserState userState)1945     private boolean readConfigurationForUserStateLocked(AccessibilityUserState userState) {
1946         boolean somethingChanged = readInstalledAccessibilityServiceLocked(userState);
1947         somethingChanged |= readInstalledAccessibilityShortcutLocked(userState);
1948         somethingChanged |= readEnabledAccessibilityServicesLocked(userState);
1949         somethingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState);
1950         somethingChanged |= readTouchExplorationEnabledSettingLocked(userState);
1951         somethingChanged |= readHighTextContrastEnabledSettingLocked(userState);
1952         somethingChanged |= readMagnificationEnabledSettingsLocked(userState);
1953         somethingChanged |= readAutoclickEnabledSettingLocked(userState);
1954         somethingChanged |= readAccessibilityShortcutKeySettingLocked(userState);
1955         somethingChanged |= readAccessibilityButtonTargetsLocked(userState);
1956         somethingChanged |= readAccessibilityButtonTargetComponentLocked(userState);
1957         somethingChanged |= readUserRecommendedUiTimeoutSettingsLocked(userState);
1958         return somethingChanged;
1959     }
1960 
updateAccessibilityEnabledSettingLocked(AccessibilityUserState userState)1961     private void updateAccessibilityEnabledSettingLocked(AccessibilityUserState userState) {
1962         final long identity = Binder.clearCallingIdentity();
1963         final boolean isA11yEnabled = mUiAutomationManager.isUiAutomationRunningLocked()
1964                 || userState.isHandlingAccessibilityEventsLocked();
1965         try {
1966             Settings.Secure.putIntForUser(mContext.getContentResolver(),
1967                     Settings.Secure.ACCESSIBILITY_ENABLED,
1968                     (isA11yEnabled) ? 1 : 0,
1969                     userState.mUserId);
1970         } finally {
1971             Binder.restoreCallingIdentity(identity);
1972         }
1973     }
1974 
readTouchExplorationEnabledSettingLocked(AccessibilityUserState userState)1975     private boolean readTouchExplorationEnabledSettingLocked(AccessibilityUserState userState) {
1976         final boolean touchExplorationEnabled = Settings.Secure.getIntForUser(
1977                 mContext.getContentResolver(),
1978                 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId) == 1;
1979         if (touchExplorationEnabled != userState.isTouchExplorationEnabledLocked()) {
1980             userState.setTouchExplorationEnabledLocked(touchExplorationEnabled);
1981             return true;
1982         }
1983         return false;
1984     }
1985 
readMagnificationEnabledSettingsLocked(AccessibilityUserState userState)1986     private boolean readMagnificationEnabledSettingsLocked(AccessibilityUserState userState) {
1987         final boolean displayMagnificationEnabled = Settings.Secure.getIntForUser(
1988                 mContext.getContentResolver(),
1989                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
1990                 0, userState.mUserId) == 1;
1991         if ((displayMagnificationEnabled != userState.isDisplayMagnificationEnabledLocked())) {
1992             userState.setDisplayMagnificationEnabledLocked(displayMagnificationEnabled);
1993             return true;
1994         }
1995         return false;
1996     }
1997 
readAutoclickEnabledSettingLocked(AccessibilityUserState userState)1998     private boolean readAutoclickEnabledSettingLocked(AccessibilityUserState userState) {
1999         final boolean autoclickEnabled = Settings.Secure.getIntForUser(
2000                 mContext.getContentResolver(),
2001                 Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED,
2002                 0, userState.mUserId) == 1;
2003         if (autoclickEnabled != userState.isAutoclickEnabledLocked()) {
2004             userState.setAutoclickEnabledLocked(autoclickEnabled);
2005             return true;
2006         }
2007         return false;
2008     }
2009 
readHighTextContrastEnabledSettingLocked(AccessibilityUserState userState)2010     private boolean readHighTextContrastEnabledSettingLocked(AccessibilityUserState userState) {
2011         final boolean highTextContrastEnabled = Settings.Secure.getIntForUser(
2012                 mContext.getContentResolver(),
2013                 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 0,
2014                 userState.mUserId) == 1;
2015         if (highTextContrastEnabled != userState.isTextHighContrastEnabledLocked()) {
2016             userState.setTextHighContrastEnabledLocked(highTextContrastEnabled);
2017             return true;
2018         }
2019         return false;
2020     }
2021 
updateTouchExplorationLocked(AccessibilityUserState userState)2022     private void updateTouchExplorationLocked(AccessibilityUserState userState) {
2023         boolean touchExplorationEnabled = mUiAutomationManager.isTouchExplorationEnabledLocked();
2024         boolean serviceHandlesDoubleTapEnabled = false;
2025         boolean requestMultiFingerGestures = false;
2026         boolean requestTwoFingerPassthrough = false;
2027         final int serviceCount = userState.mBoundServices.size();
2028         for (int i = 0; i < serviceCount; i++) {
2029             AccessibilityServiceConnection service = userState.mBoundServices.get(i);
2030             if (canRequestAndRequestsTouchExplorationLocked(service, userState)) {
2031                 touchExplorationEnabled = true;
2032                 serviceHandlesDoubleTapEnabled = service.isServiceHandlesDoubleTapEnabled();
2033                 requestMultiFingerGestures = service.isMultiFingerGesturesEnabled();
2034                 requestTwoFingerPassthrough = service.isTwoFingerPassthroughEnabled();
2035                 break;
2036             }
2037         }
2038         if (touchExplorationEnabled != userState.isTouchExplorationEnabledLocked()) {
2039             userState.setTouchExplorationEnabledLocked(touchExplorationEnabled);
2040             final long identity = Binder.clearCallingIdentity();
2041             try {
2042                 Settings.Secure.putIntForUser(mContext.getContentResolver(),
2043                         Settings.Secure.TOUCH_EXPLORATION_ENABLED, touchExplorationEnabled ? 1 : 0,
2044                         userState.mUserId);
2045             } finally {
2046                 Binder.restoreCallingIdentity(identity);
2047             }
2048         }
2049         userState.setServiceHandlesDoubleTapLocked(serviceHandlesDoubleTapEnabled);
2050         userState.setMultiFingerGesturesLocked(requestMultiFingerGestures);
2051         userState.setTwoFingerPassthroughLocked(requestTwoFingerPassthrough);
2052     }
2053 
readAccessibilityShortcutKeySettingLocked(AccessibilityUserState userState)2054     private boolean readAccessibilityShortcutKeySettingLocked(AccessibilityUserState userState) {
2055         final String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(),
2056                 Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, userState.mUserId);
2057         final Set<String> targetsFromSetting = new ArraySet<>();
2058         readColonDelimitedStringToSet(settingValue, targetsFromSetting, false, str -> str);
2059         // Fall back to device's default a11y service, only when setting is never updated.
2060         if (settingValue == null) {
2061             final String defaultService = mContext.getString(
2062                     R.string.config_defaultAccessibilityService);
2063             if (!TextUtils.isEmpty(defaultService)) {
2064                 targetsFromSetting.add(defaultService);
2065             }
2066         }
2067 
2068         final Set<String> currentTargets =
2069                 userState.getShortcutTargetsLocked(ACCESSIBILITY_SHORTCUT_KEY);
2070         if (targetsFromSetting.equals(currentTargets)) {
2071             return false;
2072         }
2073         currentTargets.clear();
2074         currentTargets.addAll(targetsFromSetting);
2075         scheduleNotifyClientsOfServicesStateChangeLocked(userState);
2076         return true;
2077     }
2078 
readAccessibilityButtonTargetsLocked(AccessibilityUserState userState)2079     private boolean readAccessibilityButtonTargetsLocked(AccessibilityUserState userState) {
2080         final Set<String> targetsFromSetting = new ArraySet<>();
2081         readColonDelimitedSettingToSet(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
2082                 userState.mUserId, targetsFromSetting, str -> str);
2083 
2084         final Set<String> currentTargets =
2085                 userState.getShortcutTargetsLocked(ACCESSIBILITY_BUTTON);
2086         if (targetsFromSetting.equals(currentTargets)) {
2087             return false;
2088         }
2089         currentTargets.clear();
2090         currentTargets.addAll(targetsFromSetting);
2091         scheduleNotifyClientsOfServicesStateChangeLocked(userState);
2092         return true;
2093     }
2094 
readAccessibilityButtonTargetComponentLocked(AccessibilityUserState userState)2095     private boolean readAccessibilityButtonTargetComponentLocked(AccessibilityUserState userState) {
2096         final String componentId = Settings.Secure.getStringForUser(mContext.getContentResolver(),
2097                 Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, userState.mUserId);
2098         if (TextUtils.isEmpty(componentId)) {
2099             if (userState.getTargetAssignedToAccessibilityButton() == null) {
2100                 return false;
2101             }
2102             userState.setTargetAssignedToAccessibilityButton(null);
2103             return true;
2104         }
2105         if (componentId.equals(userState.getTargetAssignedToAccessibilityButton())) {
2106             return false;
2107         }
2108         userState.setTargetAssignedToAccessibilityButton(componentId);
2109         return true;
2110     }
2111 
readUserRecommendedUiTimeoutSettingsLocked(AccessibilityUserState userState)2112     private boolean readUserRecommendedUiTimeoutSettingsLocked(AccessibilityUserState userState) {
2113         final int nonInteractiveUiTimeout = Settings.Secure.getIntForUser(
2114                 mContext.getContentResolver(),
2115                 Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, 0,
2116                 userState.mUserId);
2117         final int interactiveUiTimeout = Settings.Secure.getIntForUser(
2118                 mContext.getContentResolver(),
2119                 Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, 0,
2120                 userState.mUserId);
2121         if (nonInteractiveUiTimeout != userState.getUserNonInteractiveUiTimeoutLocked()
2122                 || interactiveUiTimeout != userState.getUserInteractiveUiTimeoutLocked()) {
2123             userState.setUserNonInteractiveUiTimeoutLocked(nonInteractiveUiTimeout);
2124             userState.setUserInteractiveUiTimeoutLocked(interactiveUiTimeout);
2125             scheduleNotifyClientsOfServicesStateChangeLocked(userState);
2126             return true;
2127         }
2128         return false;
2129     }
2130 
2131     /**
2132      * Check if the target that will be enabled by the accessibility shortcut key is installed.
2133      * If it isn't, remove it from the list and associated setting so a side loaded service can't
2134      * spoof the package name of the default service.
2135      */
updateAccessibilityShortcutKeyTargetsLocked(AccessibilityUserState userState)2136     private void updateAccessibilityShortcutKeyTargetsLocked(AccessibilityUserState userState) {
2137         final Set<String> currentTargets =
2138                 userState.getShortcutTargetsLocked(ACCESSIBILITY_SHORTCUT_KEY);
2139         final int lastSize = currentTargets.size();
2140         if (lastSize == 0) {
2141             return;
2142         }
2143         currentTargets.removeIf(
2144                 name -> !userState.isShortcutTargetInstalledLocked(name));
2145         if (lastSize == currentTargets.size()) {
2146             return;
2147         }
2148 
2149         // Update setting key with new value.
2150         persistColonDelimitedSetToSettingLocked(
2151                 Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
2152                 userState.mUserId, currentTargets, str -> str);
2153         scheduleNotifyClientsOfServicesStateChangeLocked(userState);
2154     }
2155 
canRequestAndRequestsTouchExplorationLocked( AccessibilityServiceConnection service, AccessibilityUserState userState)2156     private boolean canRequestAndRequestsTouchExplorationLocked(
2157             AccessibilityServiceConnection service, AccessibilityUserState userState) {
2158         // Service not ready or cannot request the feature - well nothing to do.
2159         if (!service.canReceiveEventsLocked() || !service.mRequestTouchExplorationMode) {
2160             return false;
2161         }
2162         if (service.getServiceInfo().getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion
2163                 <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
2164             // Up to JB-MR1 we had a white list with services that can enable touch
2165             // exploration. When a service is first started we show a dialog to the
2166             // use to get a permission to white list the service.
2167             if (userState.mTouchExplorationGrantedServices.contains(service.mComponentName)) {
2168                 return true;
2169             } else if (mEnableTouchExplorationDialog == null
2170                     || !mEnableTouchExplorationDialog.isShowing()) {
2171                 mMainHandler.sendMessage(obtainMessage(
2172                         AccessibilityManagerService::showEnableTouchExplorationDialog,
2173                         this, service));
2174             }
2175         } else {
2176             // Starting in JB-MR2 we request an accessibility service to declare
2177             // certain capabilities in its meta-data to allow it to enable the
2178             // corresponding features.
2179             if ((service.getCapabilities()
2180                     & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) != 0) {
2181                 return true;
2182             }
2183         }
2184         return false;
2185     }
2186 
updateMagnificationLocked(AccessibilityUserState userState)2187     private void updateMagnificationLocked(AccessibilityUserState userState) {
2188         if (userState.mUserId != mCurrentUserId) {
2189             return;
2190         }
2191 
2192         if (mMagnificationController != null) {
2193             mMagnificationController.setUserId(userState.mUserId);
2194         }
2195 
2196         if (mUiAutomationManager.suppressingAccessibilityServicesLocked()
2197                 && mMagnificationController != null) {
2198             mMagnificationController.unregisterAll();
2199             return;
2200         }
2201 
2202         // Get all valid displays and register them if global magnification is enabled.
2203         // We would skip overlay display because it uses overlay window to simulate secondary
2204         // displays in one display. It's not a real display and there's no input events for it.
2205         final ArrayList<Display> displays = getValidDisplayList();
2206         if (userState.isDisplayMagnificationEnabledLocked()
2207                 || userState.isShortcutMagnificationEnabledLocked()) {
2208             for (int i = 0; i < displays.size(); i++) {
2209                 final Display display = displays.get(i);
2210                 getMagnificationController().register(display.getDisplayId());
2211             }
2212             return;
2213         }
2214 
2215         // Register if display has listening magnification services.
2216         for (int i = 0; i < displays.size(); i++) {
2217             final Display display = displays.get(i);
2218             final int displayId = display.getDisplayId();
2219             if (userHasListeningMagnificationServicesLocked(userState, displayId)) {
2220                 getMagnificationController().register(displayId);
2221             } else if (mMagnificationController != null) {
2222                 mMagnificationController.unregister(displayId);
2223             }
2224         }
2225     }
2226 
2227     /**
2228      * Returns whether the specified user has any services that are capable of
2229      * controlling magnification.
2230      */
userHasMagnificationServicesLocked(AccessibilityUserState userState)2231     private boolean userHasMagnificationServicesLocked(AccessibilityUserState userState) {
2232         final List<AccessibilityServiceConnection> services = userState.mBoundServices;
2233         for (int i = 0, count = services.size(); i < count; i++) {
2234             final AccessibilityServiceConnection service = services.get(i);
2235             if (mSecurityPolicy.canControlMagnification(service)) {
2236                 return true;
2237             }
2238         }
2239         return false;
2240     }
2241 
2242     /**
2243      * Returns whether the specified user has any services that are capable of
2244      * controlling magnification and are actively listening for magnification updates.
2245      */
userHasListeningMagnificationServicesLocked(AccessibilityUserState userState, int displayId)2246     private boolean userHasListeningMagnificationServicesLocked(AccessibilityUserState userState,
2247             int displayId) {
2248         final List<AccessibilityServiceConnection> services = userState.mBoundServices;
2249         for (int i = 0, count = services.size(); i < count; i++) {
2250             final AccessibilityServiceConnection service = services.get(i);
2251             if (mSecurityPolicy.canControlMagnification(service)
2252                     && service.isMagnificationCallbackEnabled(displayId)) {
2253                 return true;
2254             }
2255         }
2256         return false;
2257     }
2258 
updateFingerprintGestureHandling(AccessibilityUserState userState)2259     private void updateFingerprintGestureHandling(AccessibilityUserState userState) {
2260         final List<AccessibilityServiceConnection> services;
2261         synchronized (mLock) {
2262             services = userState.mBoundServices;
2263             if ((mFingerprintGestureDispatcher == null)
2264                     &&  mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
2265                 // Only create the controller when a service wants to use the feature
2266                 int numServices = services.size();
2267                 for (int i = 0; i < numServices; i++) {
2268                     if (services.get(i).isCapturingFingerprintGestures()) {
2269                         final long identity = Binder.clearCallingIdentity();
2270                         IFingerprintService service = null;
2271                         try {
2272                             service = IFingerprintService.Stub.asInterface(
2273                                     ServiceManager.getService(Context.FINGERPRINT_SERVICE));
2274                         } finally {
2275                             Binder.restoreCallingIdentity(identity);
2276                         }
2277                         if (service != null) {
2278                             mFingerprintGestureDispatcher = new FingerprintGestureDispatcher(
2279                                     service, mContext.getResources(), mLock);
2280                             break;
2281                         }
2282                     }
2283                 }
2284             }
2285         }
2286         if (mFingerprintGestureDispatcher != null) {
2287             mFingerprintGestureDispatcher.updateClientList(services);
2288         }
2289     }
2290 
2291     /**
2292      * 1) Update accessibility button availability to accessibility services.
2293      * 2) Check if the target that will be enabled by the accessibility button is installed.
2294      *    If it isn't, remove it from the list and associated setting so a side loaded service can't
2295      *    spoof the package name of the default service.
2296      */
updateAccessibilityButtonTargetsLocked(AccessibilityUserState userState)2297     private void updateAccessibilityButtonTargetsLocked(AccessibilityUserState userState) {
2298         // Update accessibility button availability.
2299         for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
2300             final AccessibilityServiceConnection service = userState.mBoundServices.get(i);
2301             if (service.mRequestAccessibilityButton) {
2302                 service.notifyAccessibilityButtonAvailabilityChangedLocked(
2303                         service.isAccessibilityButtonAvailableLocked(userState));
2304             }
2305         }
2306 
2307         final Set<String> currentTargets =
2308                 userState.getShortcutTargetsLocked(ACCESSIBILITY_BUTTON);
2309         final int lastSize = currentTargets.size();
2310         if (lastSize == 0) {
2311             return;
2312         }
2313         currentTargets.removeIf(
2314                 name -> !userState.isShortcutTargetInstalledLocked(name));
2315         if (lastSize == currentTargets.size()) {
2316             return;
2317         }
2318 
2319         // Update setting key with new value.
2320         persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
2321                 userState.mUserId, currentTargets, str -> str);
2322         scheduleNotifyClientsOfServicesStateChangeLocked(userState);
2323     }
2324 
2325     /**
2326      * 1) Check if the service assigned to accessibility button target sdk version > Q.
2327      *    If it isn't, remove it from the list and associated setting.
2328      *    (It happens when an accessibility service package is downgraded.)
2329      * 2) For a service targeting sdk version > Q and requesting a11y button, it should be in the
2330      *    enabled list if's assigned to a11y button.
2331      *    (It happens when an accessibility service package is same graded, and updated requesting
2332      *     a11y button flag)
2333      * 3) Check if an enabled service targeting sdk version > Q and requesting a11y button is
2334      *    assigned to a shortcut. If it isn't, assigns it to the accessibility button.
2335      *    (It happens when an enabled accessibility service package is upgraded.)
2336      *
2337      * @param packageName The package name to check, or {@code null} to check all services.
2338      */
migrateAccessibilityButtonSettingsIfNecessaryLocked( AccessibilityUserState userState, @Nullable String packageName)2339     private void migrateAccessibilityButtonSettingsIfNecessaryLocked(
2340             AccessibilityUserState userState, @Nullable String packageName) {
2341         final Set<String> buttonTargets =
2342                 userState.getShortcutTargetsLocked(ACCESSIBILITY_BUTTON);
2343         int lastSize = buttonTargets.size();
2344         buttonTargets.removeIf(name -> {
2345             if (packageName != null && name != null && !name.contains(packageName)) {
2346                 return false;
2347             }
2348             final ComponentName componentName = ComponentName.unflattenFromString(name);
2349             if (componentName == null) {
2350                 return false;
2351             }
2352             final AccessibilityServiceInfo serviceInfo =
2353                     userState.getInstalledServiceInfoLocked(componentName);
2354             if (serviceInfo == null) {
2355                 return false;
2356             }
2357             if (serviceInfo.getResolveInfo().serviceInfo.applicationInfo
2358                     .targetSdkVersion <= Build.VERSION_CODES.Q) {
2359                 // A11y services targeting sdk version <= Q should not be in the list.
2360                 Slog.v(LOG_TAG, "Legacy service " + componentName
2361                         + " should not in the button");
2362                 return true;
2363             }
2364             final boolean requestA11yButton = (serviceInfo.flags
2365                     & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
2366             if (requestA11yButton && !userState.mEnabledServices.contains(componentName)) {
2367                 // An a11y service targeting sdk version > Q and request A11y button and is assigned
2368                 // to a11y btn should be in the enabled list.
2369                 Slog.v(LOG_TAG, "Service requesting a11y button and be assigned to the button"
2370                         + componentName + " should be enabled state");
2371                 return true;
2372             }
2373             return false;
2374         });
2375         boolean changed = (lastSize != buttonTargets.size());
2376         lastSize = buttonTargets.size();
2377 
2378         final Set<String> shortcutKeyTargets =
2379                 userState.getShortcutTargetsLocked(ACCESSIBILITY_SHORTCUT_KEY);
2380         userState.mEnabledServices.forEach(componentName -> {
2381             if (packageName != null && componentName != null
2382                     && !packageName.equals(componentName.getPackageName())) {
2383                 return;
2384             }
2385             final AccessibilityServiceInfo serviceInfo =
2386                     userState.getInstalledServiceInfoLocked(componentName);
2387             if (serviceInfo == null) {
2388                 return;
2389             }
2390             final boolean requestA11yButton = (serviceInfo.flags
2391                     & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
2392             if (!(serviceInfo.getResolveInfo().serviceInfo.applicationInfo
2393                     .targetSdkVersion > Build.VERSION_CODES.Q && requestA11yButton)) {
2394                 return;
2395             }
2396             final String serviceName = componentName.flattenToString();
2397             if (TextUtils.isEmpty(serviceName)) {
2398                 return;
2399             }
2400             if (doesShortcutTargetsStringContain(buttonTargets, serviceName)
2401                     || doesShortcutTargetsStringContain(shortcutKeyTargets, serviceName)) {
2402                 return;
2403             }
2404             // For enabled a11y services targeting sdk version > Q and requesting a11y button should
2405             // be assigned to a shortcut.
2406             Slog.v(LOG_TAG, "A enabled service requesting a11y button " + componentName
2407                     + " should be assign to the button or shortcut.");
2408             buttonTargets.add(serviceName);
2409         });
2410         changed |= (lastSize != buttonTargets.size());
2411         if (!changed) {
2412             return;
2413         }
2414 
2415         // Update setting key with new value.
2416         persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
2417                 userState.mUserId, buttonTargets, str -> str);
2418         scheduleNotifyClientsOfServicesStateChangeLocked(userState);
2419     }
2420 
2421     /**
2422      * Remove the shortcut target for the unbound service which is requesting accessibility button
2423      * and targeting sdk > Q from the accessibility button and shortcut.
2424      *
2425      * @param userState The accessibility user state.
2426      * @param service The unbound service.
2427      */
removeShortcutTargetForUnboundServiceLocked(AccessibilityUserState userState, AccessibilityServiceConnection service)2428     private void removeShortcutTargetForUnboundServiceLocked(AccessibilityUserState userState,
2429             AccessibilityServiceConnection service) {
2430         if (!service.mRequestAccessibilityButton
2431                 || service.getServiceInfo().getResolveInfo().serviceInfo.applicationInfo
2432                 .targetSdkVersion <= Build.VERSION_CODES.Q) {
2433             return;
2434         }
2435         final ComponentName serviceName = service.getComponentName();
2436         if (userState.removeShortcutTargetLocked(ACCESSIBILITY_SHORTCUT_KEY, serviceName)) {
2437             final Set<String> currentTargets = userState.getShortcutTargetsLocked(
2438                     ACCESSIBILITY_SHORTCUT_KEY);
2439             persistColonDelimitedSetToSettingLocked(
2440                     Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
2441                     userState.mUserId, currentTargets, str -> str);
2442         }
2443         if (userState.removeShortcutTargetLocked(ACCESSIBILITY_BUTTON, serviceName)) {
2444             final Set<String> currentTargets = userState.getShortcutTargetsLocked(
2445                     ACCESSIBILITY_BUTTON);
2446             persistColonDelimitedSetToSettingLocked(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
2447                     userState.mUserId, currentTargets, str -> str);
2448         }
2449     }
2450 
updateRecommendedUiTimeoutLocked(AccessibilityUserState userState)2451     private void updateRecommendedUiTimeoutLocked(AccessibilityUserState userState) {
2452         int newNonInteractiveUiTimeout = userState.getUserNonInteractiveUiTimeoutLocked();
2453         int newInteractiveUiTimeout = userState.getUserInteractiveUiTimeoutLocked();
2454         // read from a11y services if user does not specify value
2455         if (newNonInteractiveUiTimeout == 0 || newInteractiveUiTimeout == 0) {
2456             int serviceNonInteractiveUiTimeout = 0;
2457             int serviceInteractiveUiTimeout = 0;
2458             final List<AccessibilityServiceConnection> services = userState.mBoundServices;
2459             for (int i = 0; i < services.size(); i++) {
2460                 int timeout = services.get(i).getServiceInfo().getInteractiveUiTimeoutMillis();
2461                 if (serviceInteractiveUiTimeout < timeout) {
2462                     serviceInteractiveUiTimeout = timeout;
2463                 }
2464                 timeout = services.get(i).getServiceInfo().getNonInteractiveUiTimeoutMillis();
2465                 if (serviceNonInteractiveUiTimeout < timeout) {
2466                     serviceNonInteractiveUiTimeout = timeout;
2467                 }
2468             }
2469             if (newNonInteractiveUiTimeout == 0) {
2470                 newNonInteractiveUiTimeout = serviceNonInteractiveUiTimeout;
2471             }
2472             if (newInteractiveUiTimeout == 0) {
2473                 newInteractiveUiTimeout = serviceInteractiveUiTimeout;
2474             }
2475         }
2476         userState.setNonInteractiveUiTimeoutLocked(newNonInteractiveUiTimeout);
2477         userState.setInteractiveUiTimeoutLocked(newInteractiveUiTimeout);
2478     }
2479 
2480     @GuardedBy("mLock")
2481     @Override
getCompatibleMagnificationSpecLocked(int windowId)2482     public MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId) {
2483         IBinder windowToken = mA11yWindowManager.getWindowTokenForUserAndWindowIdLocked(
2484                 mCurrentUserId, windowId);
2485         if (windowToken != null) {
2486             return mWindowManagerService.getCompatibleMagnificationSpecForWindow(
2487                     windowToken);
2488         }
2489         return null;
2490     }
2491 
2492     @Override
getKeyEventDispatcher()2493     public KeyEventDispatcher getKeyEventDispatcher() {
2494         if (mKeyEventDispatcher == null) {
2495             mKeyEventDispatcher = new KeyEventDispatcher(
2496                     mMainHandler, MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER, mLock,
2497                     mPowerManager);
2498         }
2499         return mKeyEventDispatcher;
2500     }
2501 
2502     @Override
getPendingIntentActivity(Context context, int requestCode, Intent intent, int flags)2503     public PendingIntent getPendingIntentActivity(Context context, int requestCode, Intent intent,
2504             int flags) {
2505         return PendingIntent.getActivity(context, requestCode, intent, flags);
2506     }
2507 
2508     /**
2509      * AIDL-exposed method to be called when the accessibility shortcut key is enabled. Requires
2510      * permission to write secure settings, since someone with that permission can enable
2511      * accessibility services themselves.
2512      *
2513      * @param targetName The flattened {@link ComponentName} string or the class name of a system
2514      *        class implementing a supported accessibility feature, or {@code null} if there's no
2515      *        specified target.
2516      */
2517     @Override
performAccessibilityShortcut(String targetName)2518     public void performAccessibilityShortcut(String targetName) {
2519         if ((UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID)
2520                 && (mContext.checkCallingPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
2521                 != PackageManager.PERMISSION_GRANTED)) {
2522             throw new SecurityException(
2523                     "performAccessibilityShortcut requires the MANAGE_ACCESSIBILITY permission");
2524         }
2525         mMainHandler.sendMessage(obtainMessage(
2526                 AccessibilityManagerService::performAccessibilityShortcutInternal, this,
2527                 Display.DEFAULT_DISPLAY, ACCESSIBILITY_SHORTCUT_KEY, targetName));
2528     }
2529 
2530     /**
2531      * Perform the accessibility shortcut action.
2532      *
2533      * @param shortcutType The shortcut type.
2534      * @param displayId The display id of the accessibility button.
2535      * @param targetName The flattened {@link ComponentName} string or the class name of a system
2536      *        class implementing a supported accessibility feature, or {@code null} if there's no
2537      *        specified target.
2538      */
performAccessibilityShortcutInternal(int displayId, @ShortcutType int shortcutType, @Nullable String targetName)2539     private void performAccessibilityShortcutInternal(int displayId,
2540             @ShortcutType int shortcutType, @Nullable String targetName) {
2541         final List<String> shortcutTargets = getAccessibilityShortcutTargetsInternal(shortcutType);
2542         if (shortcutTargets.isEmpty()) {
2543             Slog.d(LOG_TAG, "No target to perform shortcut, shortcutType=" + shortcutType);
2544             return;
2545         }
2546         // In case the caller specified a target name
2547         if (targetName != null && !doesShortcutTargetsStringContain(shortcutTargets, targetName)) {
2548             Slog.v(LOG_TAG, "Perform shortcut failed, invalid target name:" + targetName);
2549             targetName = null;
2550         }
2551         if (targetName == null) {
2552             // In case there are many targets assigned to the given shortcut.
2553             if (shortcutTargets.size() > 1) {
2554                 showAccessibilityTargetsSelection(displayId, shortcutType);
2555                 return;
2556             }
2557             targetName = shortcutTargets.get(0);
2558         }
2559         // In case user assigned magnification to the given shortcut.
2560         if (targetName.equals(MAGNIFICATION_CONTROLLER_NAME)) {
2561             final boolean enabled = !getMagnificationController().isMagnifying(displayId);
2562             logAccessibilityShortcutActivated(MAGNIFICATION_COMPONENT_NAME, shortcutType, enabled);
2563             sendAccessibilityButtonToInputFilter(displayId);
2564             return;
2565         }
2566         final ComponentName targetComponentName = ComponentName.unflattenFromString(targetName);
2567         if (targetComponentName == null) {
2568             Slog.d(LOG_TAG, "Perform shortcut failed, invalid target name:" + targetName);
2569             return;
2570         }
2571         // In case user assigned an accessibility framework feature to the given shortcut.
2572         if (performAccessibilityFrameworkFeature(targetComponentName, shortcutType)) {
2573             return;
2574         }
2575         // In case user assigned an accessibility shortcut target to the given shortcut.
2576         if (performAccessibilityShortcutTargetActivity(displayId, targetComponentName)) {
2577             logAccessibilityShortcutActivated(targetComponentName, shortcutType);
2578             return;
2579         }
2580         // in case user assigned an accessibility service to the given shortcut.
2581         if (performAccessibilityShortcutTargetService(
2582                 displayId, shortcutType, targetComponentName)) {
2583             return;
2584         }
2585     }
2586 
performAccessibilityFrameworkFeature(ComponentName assignedTarget, @ShortcutType int shortcutType)2587     private boolean performAccessibilityFrameworkFeature(ComponentName assignedTarget,
2588             @ShortcutType int shortcutType) {
2589         final Map<ComponentName, ToggleableFrameworkFeatureInfo> frameworkFeatureMap =
2590                 AccessibilityShortcutController.getFrameworkShortcutFeaturesMap();
2591         if (!frameworkFeatureMap.containsKey(assignedTarget)) {
2592             return false;
2593         }
2594         // Toggle the requested framework feature
2595         final ToggleableFrameworkFeatureInfo featureInfo = frameworkFeatureMap.get(assignedTarget);
2596         final SettingStringHelper setting = new SettingStringHelper(mContext.getContentResolver(),
2597                 featureInfo.getSettingKey(), mCurrentUserId);
2598         // Assuming that the default state will be to have the feature off
2599         if (!TextUtils.equals(featureInfo.getSettingOnValue(), setting.read())) {
2600             logAccessibilityShortcutActivated(assignedTarget, shortcutType, /* serviceEnabled= */
2601                     true);
2602             setting.write(featureInfo.getSettingOnValue());
2603         } else {
2604             logAccessibilityShortcutActivated(assignedTarget, shortcutType, /* serviceEnabled= */
2605                     false);
2606             setting.write(featureInfo.getSettingOffValue());
2607         }
2608         return true;
2609     }
2610 
performAccessibilityShortcutTargetActivity(int displayId, ComponentName assignedTarget)2611     private boolean performAccessibilityShortcutTargetActivity(int displayId,
2612             ComponentName assignedTarget) {
2613         synchronized (mLock) {
2614             final AccessibilityUserState userState = getCurrentUserStateLocked();
2615             for (int i = 0; i < userState.mInstalledShortcuts.size(); i++) {
2616                 final AccessibilityShortcutInfo shortcutInfo = userState.mInstalledShortcuts.get(i);
2617                 if (!shortcutInfo.getComponentName().equals(assignedTarget)) {
2618                     continue;
2619                 }
2620                 launchShortcutTargetActivity(displayId, assignedTarget);
2621                 return true;
2622             }
2623         }
2624         return false;
2625     }
2626 
2627     /**
2628      * Perform accessibility service shortcut action.
2629      *
2630      * 1) For {@link AccessibilityManager#ACCESSIBILITY_BUTTON} type and services targeting sdk
2631      *    version <= Q: callbacks to accessibility service if service is bounded and requests
2632      *    accessibility button.
2633      * 2) For {@link AccessibilityManager#ACCESSIBILITY_SHORTCUT_KEY} type and service targeting sdk
2634      *    version <= Q: turns on / off the accessibility service.
2635      * 3) For {@link AccessibilityManager#ACCESSIBILITY_SHORTCUT_KEY} type and service targeting sdk
2636      *    version > Q and request accessibility button: turn on the accessibility service if it's
2637      *    not in the enabled state.
2638      *    (It'll happen when a service is disabled and assigned to shortcut then upgraded.)
2639      * 4) For services targeting sdk version > Q:
2640      *    a) Turns on / off the accessibility service, if service does not request accessibility
2641      *       button.
2642      *    b) Callbacks to accessibility service if service is bounded and requests accessibility
2643      *       button.
2644      */
performAccessibilityShortcutTargetService(int displayId, @ShortcutType int shortcutType, ComponentName assignedTarget)2645     private boolean performAccessibilityShortcutTargetService(int displayId,
2646             @ShortcutType int shortcutType, ComponentName assignedTarget) {
2647         synchronized (mLock) {
2648             final AccessibilityUserState userState = getCurrentUserStateLocked();
2649             final AccessibilityServiceInfo installedServiceInfo =
2650                     userState.getInstalledServiceInfoLocked(assignedTarget);
2651             if (installedServiceInfo == null) {
2652                 Slog.d(LOG_TAG, "Perform shortcut failed, invalid component name:"
2653                         + assignedTarget);
2654                 return false;
2655             }
2656 
2657             final AccessibilityServiceConnection serviceConnection =
2658                     userState.getServiceConnectionLocked(assignedTarget);
2659             final int targetSdk = installedServiceInfo.getResolveInfo()
2660                     .serviceInfo.applicationInfo.targetSdkVersion;
2661             final boolean requestA11yButton = (installedServiceInfo.flags
2662                     & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
2663             // Turns on / off the accessibility service
2664             if ((targetSdk <= Build.VERSION_CODES.Q && shortcutType == ACCESSIBILITY_SHORTCUT_KEY)
2665                     || (targetSdk > Build.VERSION_CODES.Q && !requestA11yButton)) {
2666                 if (serviceConnection == null) {
2667                     logAccessibilityShortcutActivated(assignedTarget,
2668                             shortcutType, /* serviceEnabled= */ true);
2669                     enableAccessibilityServiceLocked(assignedTarget, mCurrentUserId);
2670 
2671                 } else {
2672                     logAccessibilityShortcutActivated(assignedTarget,
2673                             shortcutType, /* serviceEnabled= */ false);
2674                     disableAccessibilityServiceLocked(assignedTarget, mCurrentUserId);
2675                 }
2676                 return true;
2677             }
2678             if (shortcutType == ACCESSIBILITY_SHORTCUT_KEY && targetSdk > Build.VERSION_CODES.Q
2679                     && requestA11yButton) {
2680                 if (!userState.getEnabledServicesLocked().contains(assignedTarget)) {
2681                     enableAccessibilityServiceLocked(assignedTarget, mCurrentUserId);
2682                     return true;
2683                 }
2684             }
2685             // Callbacks to a11y service if it's bounded and requests a11y button.
2686             if (serviceConnection == null
2687                     || !userState.mBoundServices.contains(serviceConnection)
2688                     || !serviceConnection.mRequestAccessibilityButton) {
2689                 Slog.d(LOG_TAG, "Perform shortcut failed, service is not ready:"
2690                         + assignedTarget);
2691                 return false;
2692             }
2693             // ServiceConnection means service enabled.
2694             logAccessibilityShortcutActivated(assignedTarget, shortcutType, /* serviceEnabled= */
2695                     true);
2696             serviceConnection.notifyAccessibilityButtonClickedLocked(displayId);
2697             return true;
2698         }
2699     }
2700 
2701     @Override
getAccessibilityShortcutTargets(@hortcutType int shortcutType)2702     public List<String> getAccessibilityShortcutTargets(@ShortcutType int shortcutType) {
2703         if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
2704                 != PackageManager.PERMISSION_GRANTED) {
2705             throw new SecurityException(
2706                     "getAccessibilityShortcutService requires the MANAGE_ACCESSIBILITY permission");
2707         }
2708         return getAccessibilityShortcutTargetsInternal(shortcutType);
2709     }
2710 
getAccessibilityShortcutTargetsInternal(@hortcutType int shortcutType)2711     private List<String> getAccessibilityShortcutTargetsInternal(@ShortcutType int shortcutType) {
2712         synchronized (mLock) {
2713             final AccessibilityUserState userState = getCurrentUserStateLocked();
2714             final ArrayList<String> shortcutTargets = new ArrayList<>(
2715                     userState.getShortcutTargetsLocked(shortcutType));
2716             if (shortcutType != ACCESSIBILITY_BUTTON) {
2717                 return shortcutTargets;
2718             }
2719             // Adds legacy a11y services requesting a11y button into the list.
2720             for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
2721                 final AccessibilityServiceConnection service = userState.mBoundServices.get(i);
2722                 if (!service.mRequestAccessibilityButton
2723                         || service.getServiceInfo().getResolveInfo().serviceInfo.applicationInfo
2724                         .targetSdkVersion > Build.VERSION_CODES.Q) {
2725                     continue;
2726                 }
2727                 final String serviceName = service.getComponentName().flattenToString();
2728                 if (!TextUtils.isEmpty(serviceName)) {
2729                     shortcutTargets.add(serviceName);
2730                 }
2731             }
2732             return shortcutTargets;
2733         }
2734     }
2735 
2736     /**
2737      * Enables accessibility service specified by {@param componentName} for the {@param userId}.
2738      */
enableAccessibilityServiceLocked(ComponentName componentName, int userId)2739     private void enableAccessibilityServiceLocked(ComponentName componentName, int userId) {
2740         mTempComponentNameSet.clear();
2741         readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
2742                 userId, mTempComponentNameSet);
2743         mTempComponentNameSet.add(componentName);
2744         persistComponentNamesToSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
2745                 mTempComponentNameSet, userId);
2746 
2747         AccessibilityUserState userState = getUserStateLocked(userId);
2748         if (userState.mEnabledServices.add(componentName)) {
2749             onUserStateChangedLocked(userState);
2750         }
2751     }
2752 
2753     /**
2754      * Disables accessibility service specified by {@param componentName} for the {@param userId}.
2755      */
disableAccessibilityServiceLocked(ComponentName componentName, int userId)2756     private void disableAccessibilityServiceLocked(ComponentName componentName, int userId) {
2757         mTempComponentNameSet.clear();
2758         readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
2759                 userId, mTempComponentNameSet);
2760         mTempComponentNameSet.remove(componentName);
2761         persistComponentNamesToSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
2762                 mTempComponentNameSet, userId);
2763 
2764         AccessibilityUserState userState = getUserStateLocked(userId);
2765         if (userState.mEnabledServices.remove(componentName)) {
2766             onUserStateChangedLocked(userState);
2767         }
2768     }
2769 
2770     @Override
sendAccessibilityEventForCurrentUserLocked(AccessibilityEvent event)2771     public void sendAccessibilityEventForCurrentUserLocked(AccessibilityEvent event) {
2772         sendAccessibilityEventLocked(event, mCurrentUserId);
2773     }
2774 
sendAccessibilityEventLocked(AccessibilityEvent event, int userId)2775     private void sendAccessibilityEventLocked(AccessibilityEvent event, int userId) {
2776         // Resync to avoid calling out with the lock held
2777         event.setEventTime(SystemClock.uptimeMillis());
2778         mMainHandler.sendMessage(obtainMessage(
2779                 AccessibilityManagerService::sendAccessibilityEvent,
2780                 this, event, userId));
2781     }
2782 
2783     /**
2784      * AIDL-exposed method. System only.
2785      * Inform accessibility that a fingerprint gesture was performed
2786      *
2787      * @param gestureKeyCode The key code corresponding to the fingerprint gesture.
2788      * @return {@code true} if accessibility consumes the fingerprint gesture, {@code false} if it
2789      * doesn't.
2790      */
2791     @Override
sendFingerprintGesture(int gestureKeyCode)2792     public boolean sendFingerprintGesture(int gestureKeyCode) {
2793         synchronized(mLock) {
2794             if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) {
2795                 throw new SecurityException("Only SYSTEM can call sendFingerprintGesture");
2796             }
2797         }
2798         if (mFingerprintGestureDispatcher == null) {
2799             return false;
2800         }
2801         return mFingerprintGestureDispatcher.onFingerprintGesture(gestureKeyCode);
2802     }
2803 
2804     /**
2805      * AIDL-exposed method. System only.
2806      * Gets accessibility window id from window token.
2807      *
2808      * @param windowToken Window token to get accessibility window id.
2809      * @return Accessibility window id for the window token. Returns -1 if no such token is
2810      *   registered.
2811      */
2812     @Override
getAccessibilityWindowId(@ullable IBinder windowToken)2813     public int getAccessibilityWindowId(@Nullable IBinder windowToken) {
2814         synchronized (mLock) {
2815             if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) {
2816                 throw new SecurityException("Only SYSTEM can call getAccessibilityWindowId");
2817             }
2818 
2819             return mA11yWindowManager.findWindowIdLocked(mCurrentUserId, windowToken);
2820         }
2821     }
2822 
2823     /**
2824      * Get the recommended timeout of interactive controls and non-interactive controls.
2825      *
2826      * @return A long for pair of {@code int}s. First integer for interactive one, and second
2827      * integer for non-interactive one.
2828      */
2829     @Override
getRecommendedTimeoutMillis()2830     public long getRecommendedTimeoutMillis() {
2831         synchronized(mLock) {
2832             final AccessibilityUserState userState = getCurrentUserStateLocked();
2833             return getRecommendedTimeoutMillisLocked(userState);
2834         }
2835     }
2836 
getRecommendedTimeoutMillisLocked(AccessibilityUserState userState)2837     private long getRecommendedTimeoutMillisLocked(AccessibilityUserState userState) {
2838         return IntPair.of(userState.getInteractiveUiTimeoutLocked(),
2839                 userState.getNonInteractiveUiTimeoutLocked());
2840     }
2841 
2842     @Override
setWindowMagnificationConnection( IWindowMagnificationConnection connection)2843     public void setWindowMagnificationConnection(
2844             IWindowMagnificationConnection connection) throws RemoteException {
2845         mSecurityPolicy.enforceCallingOrSelfPermission(
2846                 android.Manifest.permission.STATUS_BAR_SERVICE);
2847 
2848         getWindowMagnificationMgr().setConnection(connection);
2849     }
2850 
getWindowMagnificationMgr()2851     WindowMagnificationManager getWindowMagnificationMgr() {
2852         synchronized (mLock) {
2853             if (mWindowMagnificationMgr == null) {
2854                 mWindowMagnificationMgr = new WindowMagnificationManager();
2855             }
2856             return mWindowMagnificationMgr;
2857         }
2858     }
2859 
2860     @Override
associateEmbeddedHierarchy(@onNull IBinder host, @NonNull IBinder embedded)2861     public void associateEmbeddedHierarchy(@NonNull IBinder host, @NonNull IBinder embedded) {
2862         synchronized (mLock) {
2863             mA11yWindowManager.associateEmbeddedHierarchyLocked(host, embedded);
2864         }
2865     }
2866 
2867     @Override
disassociateEmbeddedHierarchy(@onNull IBinder token)2868     public void disassociateEmbeddedHierarchy(@NonNull IBinder token) {
2869         synchronized (mLock) {
2870             mA11yWindowManager.disassociateEmbeddedHierarchyLocked(token);
2871         }
2872     }
2873 
2874     @Override
dump(FileDescriptor fd, final PrintWriter pw, String[] args)2875     public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
2876         if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
2877         synchronized (mLock) {
2878             pw.println("ACCESSIBILITY MANAGER (dumpsys accessibility)");
2879             pw.println();
2880             pw.append("currentUserId=").append(String.valueOf(mCurrentUserId));
2881             pw.println();
2882             final int userCount = mUserStates.size();
2883             for (int i = 0; i < userCount; i++) {
2884                 mUserStates.valueAt(i).dump(fd, pw, args);
2885             }
2886             if (mUiAutomationManager.isUiAutomationRunningLocked()) {
2887                 mUiAutomationManager.dumpUiAutomationService(fd, pw, args);
2888                 pw.println();
2889             }
2890             mA11yWindowManager.dump(fd, pw, args);
2891         }
2892     }
2893 
2894     //TODO remove after refactoring KeyEventDispatcherTest
2895     final class MainHandler extends Handler {
2896         public static final int MSG_SEND_KEY_EVENT_TO_INPUT_FILTER = 8;
2897 
MainHandler(Looper looper)2898         public MainHandler(Looper looper) {
2899             super(looper);
2900         }
2901 
2902         @Override
handleMessage(Message msg)2903         public void handleMessage(Message msg) {
2904             if (msg.what == MSG_SEND_KEY_EVENT_TO_INPUT_FILTER) {
2905                 KeyEvent event = (KeyEvent) msg.obj;
2906                 final int policyFlags = msg.arg1;
2907                 synchronized (mLock) {
2908                     if (mHasInputFilter && mInputFilter != null) {
2909                         mInputFilter.sendInputEvent(event, policyFlags);
2910                     }
2911                 }
2912                 event.recycle();
2913             }
2914         }
2915     }
2916 
2917     @Override
getMagnificationController()2918     public MagnificationController getMagnificationController() {
2919         synchronized (mLock) {
2920             if (mMagnificationController == null) {
2921                 mMagnificationController = new MagnificationController(mContext, this, mLock);
2922                 mMagnificationController.setUserId(mCurrentUserId);
2923             }
2924             return mMagnificationController;
2925         }
2926     }
2927 
2928     @Override
onClientChangeLocked(boolean serviceInfoChanged)2929     public void onClientChangeLocked(boolean serviceInfoChanged) {
2930         AccessibilityUserState userState = getUserStateLocked(mCurrentUserId);
2931         onUserStateChangedLocked(userState);
2932         if (serviceInfoChanged) {
2933             scheduleNotifyClientsOfServicesStateChangeLocked(userState);
2934         }
2935     }
2936 
2937     @Override
onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)2938     public void onShellCommand(FileDescriptor in, FileDescriptor out,
2939             FileDescriptor err, String[] args, ShellCallback callback,
2940             ResultReceiver resultReceiver) {
2941         new AccessibilityShellCommand(this, mSystemActionPerformer).exec(this, in, out, err, args,
2942                 callback, resultReceiver);
2943     }
2944 
2945     private final class InteractionBridge {
2946         private final ComponentName COMPONENT_NAME =
2947                 new ComponentName("com.android.server.accessibility", "InteractionBridge");
2948 
2949         private final Display mDefaultDisplay;
2950         private final int mConnectionId;
2951         private final AccessibilityInteractionClient mClient;
2952 
InteractionBridge()2953         public InteractionBridge() {
2954             final AccessibilityServiceInfo info = new AccessibilityServiceInfo();
2955             info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
2956             info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
2957             info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
2958             final AccessibilityUserState userState;
2959             synchronized (mLock) {
2960                 userState = getCurrentUserStateLocked();
2961             }
2962             AccessibilityServiceConnection service = new AccessibilityServiceConnection(
2963                     userState, mContext,
2964                     COMPONENT_NAME, info, sIdCounter++, mMainHandler, mLock, mSecurityPolicy,
2965                     AccessibilityManagerService.this, mWindowManagerService,
2966                     getSystemActionPerformer(), mA11yWindowManager, mActivityTaskManagerService) {
2967                 @Override
2968                 public boolean supportsFlagForNotImportantViews(AccessibilityServiceInfo info) {
2969                     return true;
2970                 }
2971             };
2972 
2973             mConnectionId = service.mId;
2974 
2975             mClient = AccessibilityInteractionClient.getInstance();
2976             mClient.addConnection(mConnectionId, service);
2977 
2978             //TODO: (multi-display) We need to support multiple displays.
2979             DisplayManager displayManager = (DisplayManager)
2980                     mContext.getSystemService(Context.DISPLAY_SERVICE);
2981             mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
2982         }
2983 
2984         /**
2985          * Gets a point within the accessibility focused node where we can send down and up events
2986          * to perform a click.
2987          *
2988          * @param outPoint The click point to populate.
2989          * @return Whether accessibility a click point was found and set.
2990          */
2991         // TODO: (multi-display) Make sure this works for multiple displays.
getAccessibilityFocusClickPointInScreen(Point outPoint)2992         boolean getAccessibilityFocusClickPointInScreen(Point outPoint) {
2993             return getInteractionBridge()
2994                     .getAccessibilityFocusClickPointInScreenNotLocked(outPoint);
2995         }
2996 
2997     /**
2998          * Perform an accessibility action on the view that currently has accessibility focus.
2999          * Has no effect if no item has accessibility focus, if the item with accessibility
3000          * focus does not expose the specified action, or if the action fails.
3001          *
3002          * @param action The action to perform.
3003          *
3004          * @return {@code true} if the action was performed. {@code false} if it was not.
3005          */
performActionOnAccessibilityFocusedItemNotLocked( AccessibilityNodeInfo.AccessibilityAction action)3006         public boolean performActionOnAccessibilityFocusedItemNotLocked(
3007                 AccessibilityNodeInfo.AccessibilityAction action) {
3008             AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked();
3009             if ((focus == null) || !focus.getActionList().contains(action)) {
3010                 return false;
3011             }
3012             return focus.performAction(action.getId());
3013         }
3014 
getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint)3015         public boolean getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint) {
3016             AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked();
3017             if (focus == null) {
3018                 return false;
3019             }
3020 
3021             synchronized (mLock) {
3022                 Rect boundsInScreen = mTempRect;
3023                 focus.getBoundsInScreen(boundsInScreen);
3024 
3025                 // Apply magnification if needed.
3026                 MagnificationSpec spec = getCompatibleMagnificationSpecLocked(focus.getWindowId());
3027                 if (spec != null && !spec.isNop()) {
3028                     boundsInScreen.offset((int) -spec.offsetX, (int) -spec.offsetY);
3029                     boundsInScreen.scale(1 / spec.scale);
3030                 }
3031 
3032                 // Clip to the window bounds.
3033                 Rect windowBounds = mTempRect1;
3034                 getWindowBounds(focus.getWindowId(), windowBounds);
3035                 if (!boundsInScreen.intersect(windowBounds)) {
3036                     return false;
3037                 }
3038 
3039                 // Clip to the screen bounds.
3040                 Point screenSize = mTempPoint;
3041                 mDefaultDisplay.getRealSize(screenSize);
3042                 if (!boundsInScreen.intersect(0, 0, screenSize.x, screenSize.y)) {
3043                     return false;
3044                 }
3045 
3046                 outPoint.set(boundsInScreen.centerX(), boundsInScreen.centerY());
3047             }
3048 
3049             return true;
3050         }
3051 
getAccessibilityFocusNotLocked()3052         private AccessibilityNodeInfo getAccessibilityFocusNotLocked() {
3053             final int focusedWindowId;
3054             synchronized (mLock) {
3055                 focusedWindowId = mA11yWindowManager.getFocusedWindowId(
3056                         AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
3057                 if (focusedWindowId == AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) {
3058                     return null;
3059                 }
3060             }
3061             return getAccessibilityFocusNotLocked(focusedWindowId);
3062         }
3063 
getAccessibilityFocusNotLocked(int windowId)3064         private AccessibilityNodeInfo getAccessibilityFocusNotLocked(int windowId) {
3065             return mClient.findFocus(mConnectionId,
3066                     windowId, AccessibilityNodeInfo.ROOT_NODE_ID,
3067                     AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
3068         }
3069     }
3070 
3071     /**
3072      * Gets all currently valid logical displays.
3073      *
3074      * @return An array list containing all valid logical displays.
3075      */
getValidDisplayList()3076     public ArrayList<Display> getValidDisplayList() {
3077         return mA11yDisplayListener.getValidDisplayList();
3078     }
3079 
3080     /**
3081      * A Utility class to handle display state.
3082      */
3083     public class AccessibilityDisplayListener implements DisplayManager.DisplayListener {
3084         private final DisplayManager mDisplayManager;
3085         private final ArrayList<Display> mDisplaysList = new ArrayList<>();
3086         private int mSystemUiUid = 0;
3087 
AccessibilityDisplayListener(Context context, MainHandler handler)3088         AccessibilityDisplayListener(Context context, MainHandler handler) {
3089             mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
3090             mDisplayManager.registerDisplayListener(this, handler);
3091             initializeDisplayList();
3092 
3093             final PackageManagerInternal pm =
3094                     LocalServices.getService(PackageManagerInternal.class);
3095             if (pm != null) {
3096                 mSystemUiUid = pm.getPackageUid(pm.getSystemUiServiceComponent().getPackageName(),
3097                         PackageManager.MATCH_SYSTEM_ONLY, mCurrentUserId);
3098             }
3099         }
3100 
getValidDisplayList()3101         ArrayList<Display> getValidDisplayList() {
3102             synchronized (mLock) {
3103                 return mDisplaysList;
3104             }
3105         }
3106 
initializeDisplayList()3107         private void initializeDisplayList() {
3108             final Display[] displays = mDisplayManager.getDisplays();
3109             synchronized (mLock) {
3110                 mDisplaysList.clear();
3111                 for (int i = 0; i < displays.length; i++) {
3112                     // Exclude overlay virtual displays. The display list is for A11yInputFilter
3113                     // to create event handler per display. The events should be handled by the
3114                     // display which is overlaid by it.
3115                     final Display display = displays[i];
3116                     if (isValidDisplay(display)) {
3117                         mDisplaysList.add(display);
3118                     }
3119                 }
3120             }
3121         }
3122 
3123         @Override
onDisplayAdded(int displayId)3124         public void onDisplayAdded(int displayId) {
3125             final Display display = mDisplayManager.getDisplay(displayId);
3126             if (!isValidDisplay(display)) {
3127                 return;
3128             }
3129 
3130             synchronized (mLock) {
3131                 mDisplaysList.add(display);
3132                 if (mInputFilter != null) {
3133                     mInputFilter.onDisplayChanged();
3134                 }
3135                 AccessibilityUserState userState = getCurrentUserStateLocked();
3136                 if (displayId != Display.DEFAULT_DISPLAY) {
3137                     final List<AccessibilityServiceConnection> services = userState.mBoundServices;
3138                     for (int i = 0; i < services.size(); i++) {
3139                         AccessibilityServiceConnection boundClient = services.get(i);
3140                         boundClient.onDisplayAdded(displayId);
3141                     }
3142                 }
3143                 updateMagnificationLocked(userState);
3144                 updateWindowsForAccessibilityCallbackLocked(userState);
3145             }
3146         }
3147 
3148         @Override
onDisplayRemoved(int displayId)3149         public void onDisplayRemoved(int displayId) {
3150             synchronized (mLock) {
3151                 if (!removeDisplayFromList(displayId)) {
3152                     return;
3153                 }
3154                 if (mInputFilter != null) {
3155                     mInputFilter.onDisplayChanged();
3156                 }
3157                 AccessibilityUserState userState = getCurrentUserStateLocked();
3158                 if (displayId != Display.DEFAULT_DISPLAY) {
3159                     final List<AccessibilityServiceConnection> services = userState.mBoundServices;
3160                     for (int i = 0; i < services.size(); i++) {
3161                         AccessibilityServiceConnection boundClient = services.get(i);
3162                         boundClient.onDisplayRemoved(displayId);
3163                     }
3164                 }
3165             }
3166             if (mMagnificationController != null) {
3167                 mMagnificationController.onDisplayRemoved(displayId);
3168             }
3169             mA11yWindowManager.stopTrackingWindows(displayId);
3170         }
3171 
3172         @GuardedBy("mLock")
removeDisplayFromList(int displayId)3173         private boolean removeDisplayFromList(int displayId) {
3174             for (int i = 0; i < mDisplaysList.size(); i++) {
3175                 if (mDisplaysList.get(i).getDisplayId() == displayId) {
3176                     mDisplaysList.remove(i);
3177                     return true;
3178                 }
3179             }
3180             return false;
3181         }
3182 
3183         @Override
onDisplayChanged(int displayId)3184         public void onDisplayChanged(int displayId) {
3185             /* do nothing */
3186         }
3187 
isValidDisplay(@ullable Display display)3188         private boolean isValidDisplay(@Nullable Display display) {
3189             if (display == null || display.getType() == Display.TYPE_OVERLAY) {
3190                 return false;
3191             }
3192             // Private virtual displays are created by the ap and is not allowed to access by other
3193             // aps. We assume we could ignore them.
3194             // The exceptional case is for bubbles. Because the bubbles use the activityView, and
3195             // the virtual display of the activityView is private, so if the owner UID of the
3196             // private virtual display is the one of system ui which creates the virtual display of
3197             // bubbles, then this private virtual display should track the windows.
3198             if (display.getType() == Display.TYPE_VIRTUAL
3199                     && (display.getFlags() & Display.FLAG_PRIVATE) != 0
3200                     && display.getOwnerUid() != mSystemUiUid) {
3201                 return false;
3202             }
3203             return true;
3204         }
3205     }
3206 
3207     /** Represents an {@link AccessibilityManager} */
3208     class Client {
3209         final IAccessibilityManagerClient mCallback;
3210         final String[] mPackageNames;
3211         int mLastSentRelevantEventTypes;
3212 
Client(IAccessibilityManagerClient callback, int clientUid, AccessibilityUserState userState)3213         private Client(IAccessibilityManagerClient callback, int clientUid,
3214                 AccessibilityUserState userState) {
3215             mCallback = callback;
3216             mPackageNames = mPackageManager.getPackagesForUid(clientUid);
3217             synchronized (mLock) {
3218                 mLastSentRelevantEventTypes = computeRelevantEventTypesLocked(userState, this);
3219             }
3220         }
3221     }
3222 
3223     private final class AccessibilityContentObserver extends ContentObserver {
3224 
3225         private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor(
3226                 Settings.Secure.TOUCH_EXPLORATION_ENABLED);
3227 
3228         private final Uri mDisplayMagnificationEnabledUri = Settings.Secure.getUriFor(
3229                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
3230 
3231         private final Uri mAutoclickEnabledUri = Settings.Secure.getUriFor(
3232                 Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED);
3233 
3234         private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor(
3235                 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
3236 
3237         private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure
3238                 .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
3239 
3240         private final Uri mHighTextContrastUri = Settings.Secure.getUriFor(
3241                 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED);
3242 
3243         private final Uri mAccessibilitySoftKeyboardModeUri = Settings.Secure.getUriFor(
3244                 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE);
3245 
3246         private final Uri mShowImeWithHardKeyboardUri = Settings.Secure.getUriFor(
3247                 Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
3248 
3249         private final Uri mAccessibilityShortcutServiceIdUri = Settings.Secure.getUriFor(
3250                 Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
3251 
3252         private final Uri mAccessibilityButtonComponentIdUri = Settings.Secure.getUriFor(
3253                 Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT);
3254 
3255         private final Uri mAccessibilityButtonTargetsUri = Settings.Secure.getUriFor(
3256                 Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS);
3257 
3258         private final Uri mUserNonInteractiveUiTimeoutUri = Settings.Secure.getUriFor(
3259                 Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS);
3260 
3261         private final Uri mUserInteractiveUiTimeoutUri = Settings.Secure.getUriFor(
3262                 Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS);
3263 
AccessibilityContentObserver(Handler handler)3264         public AccessibilityContentObserver(Handler handler) {
3265             super(handler);
3266         }
3267 
register(ContentResolver contentResolver)3268         public void register(ContentResolver contentResolver) {
3269             contentResolver.registerContentObserver(mTouchExplorationEnabledUri,
3270                     false, this, UserHandle.USER_ALL);
3271             contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri,
3272                     false, this, UserHandle.USER_ALL);
3273             contentResolver.registerContentObserver(mAutoclickEnabledUri,
3274                     false, this, UserHandle.USER_ALL);
3275             contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri,
3276                     false, this, UserHandle.USER_ALL);
3277             contentResolver.registerContentObserver(
3278                     mTouchExplorationGrantedAccessibilityServicesUri,
3279                     false, this, UserHandle.USER_ALL);
3280             contentResolver.registerContentObserver(
3281                     mHighTextContrastUri, false, this, UserHandle.USER_ALL);
3282             contentResolver.registerContentObserver(
3283                     mAccessibilitySoftKeyboardModeUri, false, this, UserHandle.USER_ALL);
3284             contentResolver.registerContentObserver(
3285                     mShowImeWithHardKeyboardUri, false, this, UserHandle.USER_ALL);
3286             contentResolver.registerContentObserver(
3287                     mAccessibilityShortcutServiceIdUri, false, this, UserHandle.USER_ALL);
3288             contentResolver.registerContentObserver(
3289                     mAccessibilityButtonComponentIdUri, false, this, UserHandle.USER_ALL);
3290             contentResolver.registerContentObserver(
3291                     mAccessibilityButtonTargetsUri, false, this, UserHandle.USER_ALL);
3292             contentResolver.registerContentObserver(
3293                     mUserNonInteractiveUiTimeoutUri, false, this, UserHandle.USER_ALL);
3294             contentResolver.registerContentObserver(
3295                     mUserInteractiveUiTimeoutUri, false, this, UserHandle.USER_ALL);
3296         }
3297 
3298         @Override
onChange(boolean selfChange, Uri uri)3299         public void onChange(boolean selfChange, Uri uri) {
3300             synchronized (mLock) {
3301                 // Profiles share the accessibility state of the parent. Therefore,
3302                 // we are checking for changes only the parent settings.
3303                 AccessibilityUserState userState = getCurrentUserStateLocked();
3304 
3305                 if (mTouchExplorationEnabledUri.equals(uri)) {
3306                     if (readTouchExplorationEnabledSettingLocked(userState)) {
3307                         onUserStateChangedLocked(userState);
3308                     }
3309                 } else if (mDisplayMagnificationEnabledUri.equals(uri)) {
3310                     if (readMagnificationEnabledSettingsLocked(userState)) {
3311                         onUserStateChangedLocked(userState);
3312                     }
3313                 } else if (mAutoclickEnabledUri.equals(uri)) {
3314                     if (readAutoclickEnabledSettingLocked(userState)) {
3315                         onUserStateChangedLocked(userState);
3316                     }
3317                 } else if (mEnabledAccessibilityServicesUri.equals(uri)) {
3318                     if (readEnabledAccessibilityServicesLocked(userState)) {
3319                         userState.updateCrashedServicesIfNeededLocked();
3320                         onUserStateChangedLocked(userState);
3321                     }
3322                 } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) {
3323                     if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) {
3324                         onUserStateChangedLocked(userState);
3325                     }
3326                 } else if (mHighTextContrastUri.equals(uri)) {
3327                     if (readHighTextContrastEnabledSettingLocked(userState)) {
3328                         onUserStateChangedLocked(userState);
3329                     }
3330                 } else if (mAccessibilitySoftKeyboardModeUri.equals(uri)
3331                         || mShowImeWithHardKeyboardUri.equals(uri)) {
3332                     userState.reconcileSoftKeyboardModeWithSettingsLocked();
3333                 } else if (mAccessibilityShortcutServiceIdUri.equals(uri)) {
3334                     if (readAccessibilityShortcutKeySettingLocked(userState)) {
3335                         onUserStateChangedLocked(userState);
3336                     }
3337                 } else if (mAccessibilityButtonComponentIdUri.equals(uri)) {
3338                     if (readAccessibilityButtonTargetComponentLocked(userState)) {
3339                         onUserStateChangedLocked(userState);
3340                     }
3341                 } else if (mAccessibilityButtonTargetsUri.equals(uri)) {
3342                     if (readAccessibilityButtonTargetsLocked(userState)) {
3343                         onUserStateChangedLocked(userState);
3344                     }
3345                 } else if (mUserNonInteractiveUiTimeoutUri.equals(uri)
3346                         || mUserInteractiveUiTimeoutUri.equals(uri)) {
3347                     readUserRecommendedUiTimeoutSettingsLocked(userState);
3348                 }
3349             }
3350         }
3351     }
3352 
3353     @Override
setGestureDetectionPassthroughRegion(int displayId, Region region)3354     public void setGestureDetectionPassthroughRegion(int displayId, Region region) {
3355         mMainHandler.sendMessage(
3356                 obtainMessage(
3357                         AccessibilityManagerService::setGestureDetectionPassthroughRegionInternal,
3358                         this,
3359                         displayId,
3360                         region));
3361     }
3362 
3363     @Override
setTouchExplorationPassthroughRegion(int displayId, Region region)3364     public void setTouchExplorationPassthroughRegion(int displayId, Region region) {
3365         mMainHandler.sendMessage(
3366                 obtainMessage(
3367                         AccessibilityManagerService::setTouchExplorationPassthroughRegionInternal,
3368                         this,
3369                         displayId,
3370                         region));
3371     }
3372 
setTouchExplorationPassthroughRegionInternal(int displayId, Region region)3373     private void setTouchExplorationPassthroughRegionInternal(int displayId, Region region) {
3374         synchronized (mLock) {
3375             if (mHasInputFilter && mInputFilter != null) {
3376                 mInputFilter.setTouchExplorationPassthroughRegion(displayId, region);
3377             }
3378         }
3379     }
3380 
setGestureDetectionPassthroughRegionInternal(int displayId, Region region)3381     private void setGestureDetectionPassthroughRegionInternal(int displayId, Region region) {
3382         synchronized (mLock) {
3383             if (mHasInputFilter && mInputFilter != null) {
3384                 mInputFilter.setGestureDetectionPassthroughRegion(displayId, region);
3385             }
3386         }
3387     }
3388 }
3389