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