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