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