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.AccessibilityService.SHOW_MODE_AUTO;
20 import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE;
21 import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN;
22 import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HIDDEN;
23 import static android.accessibilityservice.AccessibilityService.SHOW_MODE_IGNORE_HARD_KEYBOARD;
24 import static android.accessibilityservice.AccessibilityService.SHOW_MODE_MASK;
25 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
26 import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED;
27 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS;
28 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS;
29 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
30 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
31 
32 import static com.android.internal.util.FunctionalUtils.ignoreRemoteException;
33 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
34 
35 import android.Manifest;
36 import android.accessibilityservice.AccessibilityService;
37 import android.accessibilityservice.AccessibilityServiceInfo;
38 import android.accessibilityservice.IAccessibilityServiceClient;
39 import android.annotation.NonNull;
40 import android.annotation.Nullable;
41 import android.app.ActivityOptions;
42 import android.app.AlertDialog;
43 import android.app.AppOpsManager;
44 import android.app.PendingIntent;
45 import android.appwidget.AppWidgetManagerInternal;
46 import android.content.BroadcastReceiver;
47 import android.content.ComponentName;
48 import android.content.ContentResolver;
49 import android.content.Context;
50 import android.content.DialogInterface;
51 import android.content.DialogInterface.OnClickListener;
52 import android.content.Intent;
53 import android.content.IntentFilter;
54 import android.content.pm.PackageManager;
55 import android.content.pm.ResolveInfo;
56 import android.content.pm.ServiceInfo;
57 import android.content.pm.UserInfo;
58 import android.database.ContentObserver;
59 import android.graphics.Point;
60 import android.graphics.Rect;
61 import android.graphics.Region;
62 import android.hardware.display.DisplayManager;
63 import android.hardware.fingerprint.IFingerprintService;
64 import android.media.AudioManagerInternal;
65 import android.net.Uri;
66 import android.os.Binder;
67 import android.os.Build;
68 import android.os.Bundle;
69 import android.os.Handler;
70 import android.os.IBinder;
71 import android.os.Looper;
72 import android.os.Message;
73 import android.os.PowerManager;
74 import android.os.Process;
75 import android.os.RemoteCallbackList;
76 import android.os.RemoteException;
77 import android.os.ResultReceiver;
78 import android.os.ServiceManager;
79 import android.os.ShellCallback;
80 import android.os.SystemClock;
81 import android.os.UserHandle;
82 import android.os.UserManager;
83 import android.os.UserManagerInternal;
84 import android.provider.Settings;
85 import android.provider.SettingsStringUtil.SettingStringHelper;
86 import android.text.TextUtils;
87 import android.text.TextUtils.SimpleStringSplitter;
88 import android.util.ArraySet;
89 import android.util.IntArray;
90 import android.util.Slog;
91 import android.util.SparseArray;
92 import android.view.Display;
93 import android.view.IWindow;
94 import android.view.KeyEvent;
95 import android.view.MagnificationSpec;
96 import android.view.View;
97 import android.view.WindowInfo;
98 import android.view.WindowManager;
99 import android.view.accessibility.AccessibilityEvent;
100 import android.view.accessibility.AccessibilityInteractionClient;
101 import android.view.accessibility.AccessibilityManager;
102 import android.view.accessibility.AccessibilityNodeInfo;
103 import android.view.accessibility.AccessibilityWindowInfo;
104 import android.view.accessibility.IAccessibilityInteractionConnection;
105 import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
106 import android.view.accessibility.IAccessibilityManager;
107 import android.view.accessibility.IAccessibilityManagerClient;
108 
109 import com.android.internal.R;
110 import com.android.internal.accessibility.AccessibilityShortcutController;
111 import com.android.internal.accessibility.AccessibilityShortcutController.ToggleableFrameworkFeatureInfo;
112 import com.android.internal.annotations.GuardedBy;
113 import com.android.internal.annotations.VisibleForTesting;
114 import com.android.internal.content.PackageMonitor;
115 import com.android.internal.util.ArrayUtils;
116 import com.android.internal.util.DumpUtils;
117 import com.android.internal.util.IntPair;
118 import com.android.internal.util.function.pooled.PooledLambda;
119 import com.android.server.LocalServices;
120 import com.android.server.SystemService;
121 import com.android.server.wm.ActivityTaskManagerInternal;
122 import com.android.server.wm.WindowManagerInternal;
123 
124 import libcore.util.EmptyArray;
125 
126 import org.xmlpull.v1.XmlPullParserException;
127 
128 import java.io.FileDescriptor;
129 import java.io.IOException;
130 import java.io.PrintWriter;
131 import java.util.ArrayList;
132 import java.util.Arrays;
133 import java.util.Collections;
134 import java.util.HashMap;
135 import java.util.HashSet;
136 import java.util.Iterator;
137 import java.util.List;
138 import java.util.Map;
139 import java.util.Objects;
140 import java.util.Set;
141 import java.util.function.Consumer;
142 import java.util.function.IntSupplier;
143 
144 /**
145  * This class is instantiated by the system as a system level service and can be
146  * accessed only by the system. The task of this service is to be a centralized
147  * event dispatch for {@link AccessibilityEvent}s generated across all processes
148  * on the device. Events are dispatched to {@link AccessibilityService}s.
149  */
150 public class AccessibilityManagerService extends IAccessibilityManager.Stub
151         implements AbstractAccessibilityServiceConnection.SystemSupport {
152 
153     private static final boolean DEBUG = false;
154 
155     private static final String LOG_TAG = "AccessibilityManagerService";
156 
157     // TODO: This is arbitrary. When there is time implement this by watching
158     //       when that accessibility services are bound.
159     private static final int WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS = 3000;
160 
161     private static final int WAIT_WINDOWS_TIMEOUT_MILLIS = 5000;
162 
163     // TODO: Restructure service initialization so services aren't connected before all of
164     //       their capabilities are ready.
165     private static final int WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS = 1000;
166 
167     private static final String FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE =
168         "registerUiTestAutomationService";
169 
170     private static final String TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED =
171             "temporaryEnableAccessibilityStateUntilKeyguardRemoved";
172 
173     private static final String GET_WINDOW_TOKEN = "getWindowToken";
174 
175     private static final String SET_PIP_ACTION_REPLACEMENT =
176             "setPictureInPictureActionReplacingConnection";
177 
178     private static final String FUNCTION_DUMP = "dump";
179 
180     private static final char COMPONENT_NAME_SEPARATOR = ':';
181 
182     private static final int OWN_PROCESS_ID = android.os.Process.myPid();
183 
184     // Each service has an ID. Also provide one for magnification gesture handling
185     public static final int MAGNIFICATION_GESTURE_HANDLER_ID = 0;
186 
187     private static int sIdCounter = MAGNIFICATION_GESTURE_HANDLER_ID + 1;
188 
189     private static int sNextWindowId;
190 
191     private final Context mContext;
192 
193     private final Object mLock = new Object();
194 
195     private final SimpleStringSplitter mStringColonSplitter =
196             new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
197 
198     private final Rect mTempRect = new Rect();
199 
200     private final Rect mTempRect1 = new Rect();
201 
202     private final Point mTempPoint = new Point();
203 
204     private final PackageManager mPackageManager;
205 
206     private final PowerManager mPowerManager;
207 
208     private final WindowManagerInternal mWindowManagerService;
209 
210     private AppWidgetManagerInternal mAppWidgetService;
211 
212     private final SecurityPolicy mSecurityPolicy;
213 
214     private final AccessibilityDisplayListener mA11yDisplayListener;
215 
216     private final AppOpsManager mAppOpsManager;
217 
218     private final ActivityTaskManagerInternal mActivityTaskManagerService;
219 
220     private final MainHandler mMainHandler;
221 
222     private final GlobalActionPerformer mGlobalActionPerformer;
223 
224     private MagnificationController mMagnificationController;
225 
226     private InteractionBridge mInteractionBridge;
227 
228     private AlertDialog mEnableTouchExplorationDialog;
229 
230     private AccessibilityInputFilter mInputFilter;
231 
232     private boolean mHasInputFilter;
233 
234     private KeyEventDispatcher mKeyEventDispatcher;
235 
236     private MotionEventInjector mMotionEventInjector;
237 
238     private FingerprintGestureDispatcher mFingerprintGestureDispatcher;
239 
240     private final Set<ComponentName> mTempComponentNameSet = new HashSet<>();
241 
242     private final List<AccessibilityServiceInfo> mTempAccessibilityServiceInfoList =
243             new ArrayList<>();
244 
245     private final IntArray mTempIntArray = new IntArray(0);
246 
247     private final RemoteCallbackList<IAccessibilityManagerClient> mGlobalClients =
248             new RemoteCallbackList<>();
249 
250     private final SparseArray<RemoteAccessibilityConnection> mGlobalInteractionConnections =
251             new SparseArray<>();
252 
253     private RemoteAccessibilityConnection mPictureInPictureActionReplacingConnection;
254 
255     private final SparseArray<IBinder> mGlobalWindowTokens = new SparseArray<>();
256 
257     private final SparseArray<UserState> mUserStates = new SparseArray<>();
258 
259     private final UserManager mUserManager;
260 
261     private final UiAutomationManager mUiAutomationManager = new UiAutomationManager(mLock);
262 
263     private int mCurrentUserId = UserHandle.USER_SYSTEM;
264 
265     //TODO: Remove this hack
266     private boolean mInitialized;
267 
268     private WindowsForAccessibilityCallback mWindowsForAccessibilityCallback;
269 
270     private boolean mIsAccessibilityButtonShown;
271 
getCurrentUserStateLocked()272     private UserState getCurrentUserStateLocked() {
273         return getUserStateLocked(mCurrentUserId);
274     }
275 
276     public static final class Lifecycle extends SystemService {
277         private final AccessibilityManagerService mService;
278 
Lifecycle(Context context)279         public Lifecycle(Context context) {
280             super(context);
281             mService = new AccessibilityManagerService(context);
282         }
283 
284         @Override
onStart()285         public void onStart() {
286             publishBinderService(Context.ACCESSIBILITY_SERVICE, mService);
287         }
288 
289         @Override
onBootPhase(int phase)290         public void onBootPhase(int phase) {
291             mService.onBootPhase(phase);
292         }
293     }
294 
295     /**
296      * Creates a new instance.
297      *
298      * @param context A {@link Context} instance.
299      */
AccessibilityManagerService(Context context)300     public AccessibilityManagerService(Context context) {
301         mContext = context;
302         mPackageManager = mContext.getPackageManager();
303         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
304         mWindowManagerService = LocalServices.getService(WindowManagerInternal.class);
305         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
306         mSecurityPolicy = new SecurityPolicy();
307         mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
308         mMainHandler = new MainHandler(mContext.getMainLooper());
309         mGlobalActionPerformer = new GlobalActionPerformer(mContext, mWindowManagerService);
310         mA11yDisplayListener = new AccessibilityDisplayListener(mContext, mMainHandler);
311         mActivityTaskManagerService = LocalServices.getService(ActivityTaskManagerInternal.class);
312 
313         registerBroadcastReceivers();
314         new AccessibilityContentObserver(mMainHandler).register(
315                 context.getContentResolver());
316     }
317 
318     @Override
getCurrentUserIdLocked()319     public int getCurrentUserIdLocked() {
320         return mCurrentUserId;
321     }
322 
323     @Override
isAccessibilityButtonShown()324     public boolean isAccessibilityButtonShown() {
325         return mIsAccessibilityButtonShown;
326     }
327 
328     @Nullable
getFingerprintGestureDispatcher()329     public FingerprintGestureDispatcher getFingerprintGestureDispatcher() {
330         return mFingerprintGestureDispatcher;
331     }
332 
onBootPhase(int phase)333     private void onBootPhase(int phase) {
334         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
335             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)) {
336                 mAppWidgetService = LocalServices.getService(AppWidgetManagerInternal.class);
337             }
338         }
339     }
340 
getUserState(int userId)341     private UserState getUserState(int userId) {
342         synchronized (mLock) {
343             return getUserStateLocked(userId);
344         }
345     }
346 
getUserStateLocked(int userId)347     private UserState getUserStateLocked(int userId) {
348         UserState state = mUserStates.get(userId);
349         if (state == null) {
350             state = new UserState(userId);
351             mUserStates.put(userId, state);
352         }
353         return state;
354     }
355 
getBindInstantServiceAllowed(int userId)356     boolean getBindInstantServiceAllowed(int userId) {
357         final UserState userState = getUserState(userId);
358         if (userState == null) return false;
359         return userState.getBindInstantServiceAllowed();
360     }
361 
setBindInstantServiceAllowed(int userId, boolean allowed)362     void setBindInstantServiceAllowed(int userId, boolean allowed) {
363         UserState userState;
364         synchronized (mLock) {
365             userState = getUserState(userId);
366             if (userState == null) {
367                 if (!allowed) {
368                     return;
369                 }
370                 userState = new UserState(userId);
371                 mUserStates.put(userId, userState);
372             }
373         }
374         userState.setBindInstantServiceAllowed(allowed);
375     }
376 
registerBroadcastReceivers()377     private void registerBroadcastReceivers() {
378         PackageMonitor monitor = new PackageMonitor() {
379             @Override
380             public void onSomePackagesChanged() {
381                 synchronized (mLock) {
382                     // Only the profile parent can install accessibility services.
383                     // Therefore we ignore packages from linked profiles.
384                     if (getChangingUserId() != mCurrentUserId) {
385                         return;
386                     }
387                     // We will update when the automation service dies.
388                     UserState userState = getCurrentUserStateLocked();
389                     // We have to reload the installed services since some services may
390                     // have different attributes, resolve info (does not support equals),
391                     // etc. Remove them then to force reload.
392                     userState.mInstalledServices.clear();
393                     if (readConfigurationForUserStateLocked(userState)) {
394                         onUserStateChangedLocked(userState);
395                     }
396                 }
397             }
398 
399             @Override
400             public void onPackageUpdateFinished(String packageName, int uid) {
401                 // The package should already be removed from mBoundServices, and added into
402                 // mBindingServices in binderDied() during updating. Remove services from  this
403                 // package from mBindingServices, and then update the user state to re-bind new
404                 // versions of them.
405                 synchronized (mLock) {
406                     final int userId = getChangingUserId();
407                     if (userId != mCurrentUserId) {
408                         return;
409                     }
410                     UserState userState = getUserStateLocked(userId);
411                     boolean reboundAService = userState.mBindingServices.removeIf(
412                             component -> component != null
413                                     && component.getPackageName().equals(packageName));
414                     if (reboundAService) {
415                         onUserStateChangedLocked(userState);
416                     }
417                 }
418             }
419 
420             @Override
421             public void onPackageRemoved(String packageName, int uid) {
422                 synchronized (mLock) {
423                     final int userId = getChangingUserId();
424                     // Only the profile parent can install accessibility services.
425                     // Therefore we ignore packages from linked profiles.
426                     if (userId != mCurrentUserId) {
427                         return;
428                     }
429                     UserState userState = getUserStateLocked(userId);
430                     Iterator<ComponentName> it = userState.mEnabledServices.iterator();
431                     while (it.hasNext()) {
432                         ComponentName comp = it.next();
433                         String compPkg = comp.getPackageName();
434                         if (compPkg.equals(packageName)) {
435                             it.remove();
436                             userState.mBindingServices.remove(comp);
437                             // Update the enabled services setting.
438                             persistComponentNamesToSettingLocked(
439                                     Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
440                                     userState.mEnabledServices, userId);
441                             // Update the touch exploration granted services setting.
442                             userState.mTouchExplorationGrantedServices.remove(comp);
443                             persistComponentNamesToSettingLocked(
444                                     Settings.Secure.
445                                     TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
446                                     userState.mTouchExplorationGrantedServices, userId);
447                             onUserStateChangedLocked(userState);
448                             return;
449                         }
450                     }
451                 }
452             }
453 
454             @Override
455             public boolean onHandleForceStop(Intent intent, String[] packages,
456                     int uid, boolean doit) {
457                 synchronized (mLock) {
458                     final int userId = getChangingUserId();
459                     // Only the profile parent can install accessibility services.
460                     // Therefore we ignore packages from linked profiles.
461                     if (userId != mCurrentUserId) {
462                         return false;
463                     }
464                     UserState userState = getUserStateLocked(userId);
465                     Iterator<ComponentName> it = userState.mEnabledServices.iterator();
466                     while (it.hasNext()) {
467                         ComponentName comp = it.next();
468                         String compPkg = comp.getPackageName();
469                         for (String pkg : packages) {
470                             if (compPkg.equals(pkg)) {
471                                 if (!doit) {
472                                     return true;
473                                 }
474                                 it.remove();
475                                 userState.mBindingServices.remove(comp);
476                                 persistComponentNamesToSettingLocked(
477                                         Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
478                                         userState.mEnabledServices, userId);
479                                 onUserStateChangedLocked(userState);
480                             }
481                         }
482                     }
483                     return false;
484                 }
485             }
486         };
487 
488         // package changes
489         monitor.register(mContext, null,  UserHandle.ALL, true);
490 
491         // user change and unlock
492         IntentFilter intentFilter = new IntentFilter();
493         intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
494         intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
495         intentFilter.addAction(Intent.ACTION_USER_REMOVED);
496         intentFilter.addAction(Intent.ACTION_USER_PRESENT);
497         intentFilter.addAction(Intent.ACTION_SETTING_RESTORED);
498 
499         mContext.registerReceiverAsUser(new BroadcastReceiver() {
500             @Override
501             public void onReceive(Context context, Intent intent) {
502                 String action = intent.getAction();
503                 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
504                     switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
505                 } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
506                     unlockUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
507                 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
508                     removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
509                 } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
510                     // We will update when the automation service dies.
511                     synchronized (mLock) {
512                         UserState userState = getCurrentUserStateLocked();
513                         if (readConfigurationForUserStateLocked(userState)) {
514                             onUserStateChangedLocked(userState);
515                         }
516                     }
517                 } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
518                     final String which = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
519                     if (Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(which)) {
520                         synchronized (mLock) {
521                             restoreEnabledAccessibilityServicesLocked(
522                                     intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
523                                     intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
524                         }
525                     }
526                 }
527             }
528         }, UserHandle.ALL, intentFilter, null, null);
529     }
530 
531     @Override
addClient(IAccessibilityManagerClient callback, int userId)532     public long addClient(IAccessibilityManagerClient callback, int userId) {
533         synchronized (mLock) {
534             // We treat calls from a profile as if made by its parent as profiles
535             // share the accessibility state of the parent. The call below
536             // performs the current profile parent resolution.
537             final int resolvedUserId = mSecurityPolicy
538                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
539 
540             // If the client is from a process that runs across users such as
541             // the system UI or the system we add it to the global state that
542             // is shared across users.
543             UserState userState = getUserStateLocked(resolvedUserId);
544             Client client = new Client(callback, Binder.getCallingUid(), userState);
545             if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
546                 mGlobalClients.register(callback, client);
547                 if (DEBUG) {
548                     Slog.i(LOG_TAG, "Added global client for pid:" + Binder.getCallingPid());
549                 }
550                 return IntPair.of(
551                         userState.getClientState(),
552                         client.mLastSentRelevantEventTypes);
553             } else {
554                 userState.mUserClients.register(callback, client);
555                 // If this client is not for the current user we do not
556                 // return a state since it is not for the foreground user.
557                 // We will send the state to the client on a user switch.
558                 if (DEBUG) {
559                     Slog.i(LOG_TAG, "Added user client for pid:" + Binder.getCallingPid()
560                             + " and userId:" + mCurrentUserId);
561                 }
562                 return IntPair.of(
563                         (resolvedUserId == mCurrentUserId) ? userState.getClientState() : 0,
564                         client.mLastSentRelevantEventTypes);
565             }
566         }
567     }
568 
569     @Override
sendAccessibilityEvent(AccessibilityEvent event, int userId)570     public void sendAccessibilityEvent(AccessibilityEvent event, int userId) {
571         boolean dispatchEvent = false;
572 
573         synchronized (mLock) {
574             if (event.getWindowId() ==
575                 AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID) {
576                 // The replacer window isn't shown to services. Move its events into the pip.
577                 AccessibilityWindowInfo pip = mSecurityPolicy.getPictureInPictureWindow();
578                 if (pip != null) {
579                     int pipId = pip.getId();
580                     event.setWindowId(pipId);
581                 }
582             }
583 
584             // We treat calls from a profile as if made by its parent as profiles
585             // share the accessibility state of the parent. The call below
586             // performs the current profile parent resolution.
587             final int resolvedUserId = mSecurityPolicy
588                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
589 
590             // Make sure the reported package is one the caller has access to.
591             event.setPackageName(mSecurityPolicy.resolveValidReportedPackageLocked(
592                     event.getPackageName(), UserHandle.getCallingAppId(), resolvedUserId));
593 
594             // This method does nothing for a background user.
595             if (resolvedUserId == mCurrentUserId) {
596                 if (mSecurityPolicy.canDispatchAccessibilityEventLocked(event)) {
597                     mSecurityPolicy.updateActiveAndAccessibilityFocusedWindowLocked(
598                             event.getWindowId(), event.getSourceNodeId(),
599                             event.getEventType(), event.getAction());
600                     mSecurityPolicy.updateEventSourceLocked(event);
601                     dispatchEvent = true;
602                 }
603                 if (mHasInputFilter && mInputFilter != null) {
604                     mMainHandler.sendMessage(obtainMessage(
605                             AccessibilityManagerService::sendAccessibilityEventToInputFilter,
606                             this, AccessibilityEvent.obtain(event)));
607                 }
608             }
609         }
610 
611         if (dispatchEvent) {
612             // Make sure clients receiving this event will be able to get the
613             // current state of the windows as the window manager may be delaying
614             // the computation for performance reasons.
615             if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
616                     && mWindowsForAccessibilityCallback != null) {
617                 WindowManagerInternal wm = LocalServices.getService(WindowManagerInternal.class);
618                 wm.computeWindowsForAccessibility();
619             }
620             synchronized (mLock) {
621                 notifyAccessibilityServicesDelayedLocked(event, false);
622                 notifyAccessibilityServicesDelayedLocked(event, true);
623                 mUiAutomationManager.sendAccessibilityEventLocked(event);
624             }
625         }
626 
627         if (OWN_PROCESS_ID != Binder.getCallingPid()) {
628             event.recycle();
629         }
630     }
631 
sendAccessibilityEventToInputFilter(AccessibilityEvent event)632     private void sendAccessibilityEventToInputFilter(AccessibilityEvent event) {
633         synchronized (mLock) {
634             if (mHasInputFilter && mInputFilter != null) {
635                 mInputFilter.notifyAccessibilityEvent(event);
636             }
637         }
638         event.recycle();
639     }
640 
641     @Override
getInstalledAccessibilityServiceList(int userId)642     public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) {
643         synchronized (mLock) {
644             // We treat calls from a profile as if made by its parent as profiles
645             // share the accessibility state of the parent. The call below
646             // performs the current profile parent resolution.
647             final int resolvedUserId = mSecurityPolicy
648                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
649             return getUserStateLocked(resolvedUserId).mInstalledServices;
650         }
651     }
652 
653     @Override
getEnabledAccessibilityServiceList(int feedbackType, int userId)654     public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType,
655             int userId) {
656         synchronized (mLock) {
657             // We treat calls from a profile as if made by its parent as profiles
658             // share the accessibility state of the parent. The call below
659             // performs the current profile parent resolution.
660             final int resolvedUserId = mSecurityPolicy
661                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
662 
663             // The automation service can suppress other services.
664             final UserState userState = getUserStateLocked(resolvedUserId);
665             if (mUiAutomationManager.suppressingAccessibilityServicesLocked()) {
666                 return Collections.emptyList();
667             }
668 
669             final List<AccessibilityServiceConnection> services = userState.mBoundServices;
670             final int serviceCount = services.size();
671             final List<AccessibilityServiceInfo> result = new ArrayList<>(serviceCount);
672             for (int i = 0; i < serviceCount; ++i) {
673                 final AccessibilityServiceConnection service = services.get(i);
674                 if ((service.mFeedbackType & feedbackType) != 0) {
675                     result.add(service.getServiceInfo());
676                 }
677             }
678             return result;
679         }
680     }
681 
682     @Override
interrupt(int userId)683     public void interrupt(int userId) {
684         List<IAccessibilityServiceClient> interfacesToInterrupt;
685         synchronized (mLock) {
686             // We treat calls from a profile as if made by its parent as profiles
687             // share the accessibility state of the parent. The call below
688             // performs the current profile parent resolution.
689             final int resolvedUserId = mSecurityPolicy
690                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
691             // This method does nothing for a background user.
692             if (resolvedUserId != mCurrentUserId) {
693                 return;
694             }
695             List<AccessibilityServiceConnection> services =
696                     getUserStateLocked(resolvedUserId).mBoundServices;
697             int numServices = services.size();
698             interfacesToInterrupt = new ArrayList<>(numServices);
699             for (int i = 0; i < numServices; i++) {
700                 AccessibilityServiceConnection service = services.get(i);
701                 IBinder a11yServiceBinder = service.mService;
702                 IAccessibilityServiceClient a11yServiceInterface = service.mServiceInterface;
703                 if ((a11yServiceBinder != null) && (a11yServiceInterface != null)) {
704                     interfacesToInterrupt.add(a11yServiceInterface);
705                 }
706             }
707         }
708         for (int i = 0, count = interfacesToInterrupt.size(); i < count; i++) {
709             try {
710                 interfacesToInterrupt.get(i).onInterrupt();
711             } catch (RemoteException re) {
712                 Slog.e(LOG_TAG, "Error sending interrupt request to "
713                         + interfacesToInterrupt.get(i), re);
714             }
715         }
716     }
717 
718     @Override
addAccessibilityInteractionConnection(IWindow windowToken, IAccessibilityInteractionConnection connection, String packageName, int userId)719     public int addAccessibilityInteractionConnection(IWindow windowToken,
720             IAccessibilityInteractionConnection connection, String packageName,
721             int userId) throws RemoteException {
722         final int windowId;
723         synchronized (mLock) {
724             // We treat calls from a profile as if made by its parent as profiles
725             // share the accessibility state of the parent. The call below
726             // performs the current profile parent resolution.
727             final int resolvedUserId = mSecurityPolicy
728                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
729             final int resolvedUid = UserHandle.getUid(resolvedUserId, UserHandle.getCallingAppId());
730 
731             // Make sure the reported package is one the caller has access to.
732             packageName = mSecurityPolicy.resolveValidReportedPackageLocked(
733                     packageName, UserHandle.getCallingAppId(), resolvedUserId);
734 
735             windowId = sNextWindowId++;
736             // If the window is from a process that runs across users such as
737             // the system UI or the system we add it to the global state that
738             // is shared across users.
739             if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
740                 RemoteAccessibilityConnection wrapper = new RemoteAccessibilityConnection(
741                         windowId, connection, packageName, resolvedUid, UserHandle.USER_ALL);
742                 wrapper.linkToDeath();
743                 mGlobalInteractionConnections.put(windowId, wrapper);
744                 mGlobalWindowTokens.put(windowId, windowToken.asBinder());
745                 if (DEBUG) {
746                     Slog.i(LOG_TAG, "Added global connection for pid:" + Binder.getCallingPid()
747                             + " with windowId: " + windowId + " and  token: "
748                             + windowToken.asBinder());
749                 }
750             } else {
751                 RemoteAccessibilityConnection wrapper = new RemoteAccessibilityConnection(
752                         windowId, connection, packageName, resolvedUid, resolvedUserId);
753                 wrapper.linkToDeath();
754                 UserState userState = getUserStateLocked(resolvedUserId);
755                 userState.mInteractionConnections.put(windowId, wrapper);
756                 userState.mWindowTokens.put(windowId, windowToken.asBinder());
757                 if (DEBUG) {
758                     Slog.i(LOG_TAG, "Added user connection for pid:" + Binder.getCallingPid()
759                             + " with windowId: " + windowId + " and userId:" + mCurrentUserId
760                             + " and  token: " + windowToken.asBinder());
761                 }
762             }
763         }
764         WindowManagerInternal wm = LocalServices.getService(WindowManagerInternal.class);
765         wm.computeWindowsForAccessibility();
766         return windowId;
767     }
768 
769     @Override
removeAccessibilityInteractionConnection(IWindow window)770     public void removeAccessibilityInteractionConnection(IWindow window) {
771         synchronized (mLock) {
772             // We treat calls from a profile as if made by its parent as profiles
773             // share the accessibility state of the parent. The call below
774             // performs the current profile parent resolution.
775             mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(
776                     UserHandle.getCallingUserId());
777             IBinder token = window.asBinder();
778             final int removedWindowId = removeAccessibilityInteractionConnectionInternalLocked(
779                     token, mGlobalWindowTokens, mGlobalInteractionConnections);
780             if (removedWindowId >= 0) {
781                 mSecurityPolicy.onAccessibilityClientRemovedLocked(removedWindowId);
782                 if (DEBUG) {
783                     Slog.i(LOG_TAG, "Removed global connection for pid:" + Binder.getCallingPid()
784                             + " with windowId: " + removedWindowId + " and token: " + window.asBinder());
785                 }
786                 return;
787             }
788             final int userCount = mUserStates.size();
789             for (int i = 0; i < userCount; i++) {
790                 UserState userState = mUserStates.valueAt(i);
791                 final int removedWindowIdForUser =
792                         removeAccessibilityInteractionConnectionInternalLocked(
793                         token, userState.mWindowTokens, userState.mInteractionConnections);
794                 if (removedWindowIdForUser >= 0) {
795                     mSecurityPolicy.onAccessibilityClientRemovedLocked(removedWindowIdForUser);
796                     if (DEBUG) {
797                         Slog.i(LOG_TAG, "Removed user connection for pid:" + Binder.getCallingPid()
798                                 + " with windowId: " + removedWindowIdForUser + " and userId:"
799                                 + mUserStates.keyAt(i) + " and token: " + window.asBinder());
800                     }
801                     return;
802                 }
803             }
804         }
805     }
806 
removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken, SparseArray<IBinder> windowTokens, SparseArray<RemoteAccessibilityConnection> interactionConnections)807     private int removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken,
808             SparseArray<IBinder> windowTokens,
809             SparseArray<RemoteAccessibilityConnection> interactionConnections) {
810         final int count = windowTokens.size();
811         for (int i = 0; i < count; i++) {
812             if (windowTokens.valueAt(i) == windowToken) {
813                 final int windowId = windowTokens.keyAt(i);
814                 windowTokens.removeAt(i);
815                 RemoteAccessibilityConnection wrapper = interactionConnections.get(windowId);
816                 wrapper.unlinkToDeath();
817                 interactionConnections.remove(windowId);
818                 return windowId;
819             }
820         }
821         return -1;
822     }
823 
824     @Override
setPictureInPictureActionReplacingConnection( IAccessibilityInteractionConnection connection)825     public void setPictureInPictureActionReplacingConnection(
826             IAccessibilityInteractionConnection connection) throws RemoteException {
827         mSecurityPolicy.enforceCallingPermission(Manifest.permission.MODIFY_ACCESSIBILITY_DATA,
828                 SET_PIP_ACTION_REPLACEMENT);
829         synchronized (mLock) {
830             if (mPictureInPictureActionReplacingConnection != null) {
831                 mPictureInPictureActionReplacingConnection.unlinkToDeath();
832                 mPictureInPictureActionReplacingConnection = null;
833             }
834             if (connection != null) {
835                 RemoteAccessibilityConnection wrapper = new RemoteAccessibilityConnection(
836                         AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID,
837                         connection, "foo.bar.baz", Process.SYSTEM_UID, UserHandle.USER_ALL);
838                 mPictureInPictureActionReplacingConnection = wrapper;
839                 wrapper.linkToDeath();
840             }
841         }
842     }
843 
844     @Override
registerUiTestAutomationService(IBinder owner, IAccessibilityServiceClient serviceClient, AccessibilityServiceInfo accessibilityServiceInfo, int flags)845     public void registerUiTestAutomationService(IBinder owner,
846             IAccessibilityServiceClient serviceClient,
847             AccessibilityServiceInfo accessibilityServiceInfo,
848             int flags) {
849         mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT,
850                 FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE);
851 
852         synchronized (mLock) {
853             mUiAutomationManager.registerUiTestAutomationServiceLocked(owner, serviceClient,
854                     mContext, accessibilityServiceInfo, sIdCounter++, mMainHandler,
855                     mSecurityPolicy, this, mWindowManagerService, mGlobalActionPerformer, flags);
856             onUserStateChangedLocked(getCurrentUserStateLocked());
857         }
858     }
859 
860     @Override
unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient)861     public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) {
862         synchronized (mLock) {
863             mUiAutomationManager.unregisterUiTestAutomationServiceLocked(serviceClient);
864         }
865     }
866 
867     @Override
temporaryEnableAccessibilityStateUntilKeyguardRemoved( ComponentName service, boolean touchExplorationEnabled)868     public void temporaryEnableAccessibilityStateUntilKeyguardRemoved(
869             ComponentName service, boolean touchExplorationEnabled) {
870         mSecurityPolicy.enforceCallingPermission(
871                 Manifest.permission.TEMPORARY_ENABLE_ACCESSIBILITY,
872                 TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED);
873         if (!mWindowManagerService.isKeyguardLocked()) {
874             return;
875         }
876         synchronized (mLock) {
877             // Set the temporary state.
878             UserState userState = getCurrentUserStateLocked();
879 
880             userState.mIsTouchExplorationEnabled = touchExplorationEnabled;
881             userState.mIsDisplayMagnificationEnabled = false;
882             userState.mIsNavBarMagnificationEnabled = false;
883             userState.mIsAutoclickEnabled = false;
884             userState.mEnabledServices.clear();
885             userState.mEnabledServices.add(service);
886             userState.mBindingServices.clear();
887             userState.mTouchExplorationGrantedServices.clear();
888             userState.mTouchExplorationGrantedServices.add(service);
889 
890             // User the current state instead settings.
891             onUserStateChangedLocked(userState);
892         }
893     }
894 
895     @Override
getWindowToken(int windowId, int userId)896     public IBinder getWindowToken(int windowId, int userId) {
897         mSecurityPolicy.enforceCallingPermission(
898                 Manifest.permission.RETRIEVE_WINDOW_TOKEN,
899                 GET_WINDOW_TOKEN);
900         synchronized (mLock) {
901             // We treat calls from a profile as if made by its parent as profiles
902             // share the accessibility state of the parent. The call below
903             // performs the current profile parent resolution.
904             final int resolvedUserId = mSecurityPolicy
905                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
906             if (resolvedUserId != mCurrentUserId) {
907                 return null;
908             }
909             if (mSecurityPolicy.findA11yWindowInfoById(windowId) == null) {
910                 return null;
911             }
912             return findWindowTokenLocked(windowId);
913         }
914     }
915 
916     /**
917      * Invoked remotely over AIDL by SysUi when the accessibility button within the system's
918      * navigation area has been clicked.
919      *
920      * @param displayId The logical display id.
921      */
922     @Override
notifyAccessibilityButtonClicked(int displayId)923     public void notifyAccessibilityButtonClicked(int displayId) {
924         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE)
925                 != PackageManager.PERMISSION_GRANTED) {
926             throw new SecurityException("Caller does not hold permission "
927                     + android.Manifest.permission.STATUS_BAR_SERVICE);
928         }
929         synchronized (mLock) {
930             notifyAccessibilityButtonClickedLocked(displayId);
931         }
932     }
933 
934     /**
935      * Invoked remotely over AIDL by SysUi when the visibility of the accessibility
936      * button within the system's navigation area has changed.
937      *
938      * @param shown {@code true} if the accessibility button is shown to the
939      *                  user, {@code false} otherwise
940      */
941     @Override
notifyAccessibilityButtonVisibilityChanged(boolean shown)942     public void notifyAccessibilityButtonVisibilityChanged(boolean shown) {
943         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE)
944                 != PackageManager.PERMISSION_GRANTED) {
945             throw new SecurityException("Caller does not hold permission "
946                     + android.Manifest.permission.STATUS_BAR_SERVICE);
947         }
948         synchronized (mLock) {
949             notifyAccessibilityButtonVisibilityChangedLocked(shown);
950         }
951     }
952 
953 
onGesture(int gestureId)954     boolean onGesture(int gestureId) {
955         synchronized (mLock) {
956             boolean handled = notifyGestureLocked(gestureId, false);
957             if (!handled) {
958                 handled = notifyGestureLocked(gestureId, true);
959             }
960             return handled;
961         }
962     }
963 
964     @VisibleForTesting
notifyKeyEvent(KeyEvent event, int policyFlags)965     public boolean notifyKeyEvent(KeyEvent event, int policyFlags) {
966         synchronized (mLock) {
967             List<AccessibilityServiceConnection> boundServices =
968                     getCurrentUserStateLocked().mBoundServices;
969             if (boundServices.isEmpty()) {
970                 return false;
971             }
972             return getKeyEventDispatcher().notifyKeyEventLocked(event, policyFlags, boundServices);
973         }
974     }
975 
976     /**
977      * Called by the MagnificationController when the state of display
978      * magnification changes.
979      *
980      * @param displayId The logical display id.
981      * @param region the new magnified region, may be empty if
982      *               magnification is not enabled (e.g. scale is 1)
983      * @param scale the new scale
984      * @param centerX the new screen-relative center X coordinate
985      * @param centerY the new screen-relative center Y coordinate
986      */
notifyMagnificationChanged(int displayId, @NonNull Region region, float scale, float centerX, float centerY)987     public void notifyMagnificationChanged(int displayId, @NonNull Region region,
988             float scale, float centerX, float centerY) {
989         synchronized (mLock) {
990             notifyClearAccessibilityCacheLocked();
991             notifyMagnificationChangedLocked(displayId, region, scale, centerX, centerY);
992         }
993     }
994 
995     /**
996      * Called by AccessibilityInputFilter when it creates or destroys the motionEventInjector.
997      * Not using a getter because the AccessibilityInputFilter isn't thread-safe
998      *
999      * @param motionEventInjector The new value of the motionEventInjector. May be null.
1000      */
setMotionEventInjector(MotionEventInjector motionEventInjector)1001     void setMotionEventInjector(MotionEventInjector motionEventInjector) {
1002         synchronized (mLock) {
1003             mMotionEventInjector = motionEventInjector;
1004             // We may be waiting on this object being set
1005             mLock.notifyAll();
1006         }
1007     }
1008 
1009     @Override
getMotionEventInjectorLocked()1010     public MotionEventInjector getMotionEventInjectorLocked() {
1011         final long endMillis = SystemClock.uptimeMillis() + WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS;
1012         while ((mMotionEventInjector == null) && (SystemClock.uptimeMillis() < endMillis)) {
1013             try {
1014                 mLock.wait(endMillis - SystemClock.uptimeMillis());
1015             } catch (InterruptedException ie) {
1016                 /* ignore */
1017             }
1018         }
1019         if (mMotionEventInjector == null) {
1020             Slog.e(LOG_TAG, "MotionEventInjector installation timed out");
1021         }
1022         return mMotionEventInjector;
1023     }
1024 
1025     /**
1026      * Gets a point within the accessibility focused node where we can send down
1027      * and up events to perform a click.
1028      *
1029      * @param outPoint The click point to populate.
1030      * @return Whether accessibility a click point was found and set.
1031      */
1032     // TODO: (multi-display) Make sure this works for multiple displays.
getAccessibilityFocusClickPointInScreen(Point outPoint)1033     boolean getAccessibilityFocusClickPointInScreen(Point outPoint) {
1034         return getInteractionBridge().getAccessibilityFocusClickPointInScreenNotLocked(outPoint);
1035     }
1036 
1037     /**
1038      * Perform an accessibility action on the view that currently has accessibility focus.
1039      * Has no effect if no item has accessibility focus, if the item with accessibility
1040      * focus does not expose the specified action, or if the action fails.
1041      *
1042      * @param action The action to perform.
1043      *
1044      * @return {@code true} if the action was performed. {@code false} if it was not.
1045      */
performActionOnAccessibilityFocusedItem( AccessibilityNodeInfo.AccessibilityAction action)1046     public boolean performActionOnAccessibilityFocusedItem(
1047             AccessibilityNodeInfo.AccessibilityAction action) {
1048         return getInteractionBridge().performActionOnAccessibilityFocusedItemNotLocked(action);
1049     }
1050 
1051     /**
1052      * Gets the bounds of a window.
1053      *
1054      * @param outBounds The output to which to write the bounds.
1055      */
getWindowBounds(int windowId, Rect outBounds)1056     boolean getWindowBounds(int windowId, Rect outBounds) {
1057         IBinder token;
1058         synchronized (mLock) {
1059             token = mGlobalWindowTokens.get(windowId);
1060             if (token == null) {
1061                 token = getCurrentUserStateLocked().mWindowTokens.get(windowId);
1062             }
1063         }
1064         mWindowManagerService.getWindowFrame(token, outBounds);
1065         if (!outBounds.isEmpty()) {
1066             return true;
1067         }
1068         return false;
1069     }
1070 
accessibilityFocusOnlyInActiveWindow()1071     boolean accessibilityFocusOnlyInActiveWindow() {
1072         synchronized (mLock) {
1073             return mWindowsForAccessibilityCallback == null;
1074         }
1075     }
1076 
getActiveWindowId()1077     int getActiveWindowId() {
1078         return mSecurityPolicy.getActiveWindowId();
1079     }
1080 
onTouchInteractionStart()1081     void onTouchInteractionStart() {
1082         mSecurityPolicy.onTouchInteractionStart();
1083     }
1084 
onTouchInteractionEnd()1085     void onTouchInteractionEnd() {
1086         mSecurityPolicy.onTouchInteractionEnd();
1087     }
1088 
switchUser(int userId)1089     private void switchUser(int userId) {
1090         synchronized (mLock) {
1091             if (mCurrentUserId == userId && mInitialized) {
1092                 return;
1093             }
1094 
1095             // Disconnect from services for the old user.
1096             UserState oldUserState = getCurrentUserStateLocked();
1097             oldUserState.onSwitchToAnotherUserLocked();
1098 
1099             // Disable the local managers for the old user.
1100             if (oldUserState.mUserClients.getRegisteredCallbackCount() > 0) {
1101                 mMainHandler.sendMessage(obtainMessage(
1102                         AccessibilityManagerService::sendStateToClients,
1103                         this, 0, oldUserState.mUserId));
1104             }
1105 
1106             // Announce user changes only if more that one exist.
1107             UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1108             final boolean announceNewUser = userManager.getUsers().size() > 1;
1109 
1110             // The user changed.
1111             mCurrentUserId = userId;
1112 
1113             UserState userState = getCurrentUserStateLocked();
1114 
1115             readConfigurationForUserStateLocked(userState);
1116             // Even if reading did not yield change, we have to update
1117             // the state since the context in which the current user
1118             // state was used has changed since it was inactive.
1119             onUserStateChangedLocked(userState);
1120 
1121             if (announceNewUser) {
1122                 // Schedule announcement of the current user if needed.
1123                 mMainHandler.sendMessageDelayed(
1124                         obtainMessage(AccessibilityManagerService::announceNewUserIfNeeded, this),
1125                         WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS);
1126             }
1127         }
1128     }
1129 
announceNewUserIfNeeded()1130     private void announceNewUserIfNeeded() {
1131         synchronized (mLock) {
1132             UserState userState = getCurrentUserStateLocked();
1133             if (userState.isHandlingAccessibilityEvents()) {
1134                 UserManager userManager = (UserManager) mContext.getSystemService(
1135                         Context.USER_SERVICE);
1136                 String message = mContext.getString(R.string.user_switched,
1137                         userManager.getUserInfo(mCurrentUserId).name);
1138                 AccessibilityEvent event = AccessibilityEvent.obtain(
1139                         AccessibilityEvent.TYPE_ANNOUNCEMENT);
1140                 event.getText().add(message);
1141                 sendAccessibilityEventLocked(event, mCurrentUserId);
1142             }
1143         }
1144     }
1145 
unlockUser(int userId)1146     private void unlockUser(int userId) {
1147         synchronized (mLock) {
1148             int parentUserId = mSecurityPolicy.resolveProfileParentLocked(userId);
1149             if (parentUserId == mCurrentUserId) {
1150                 UserState userState = getUserStateLocked(mCurrentUserId);
1151                 onUserStateChangedLocked(userState);
1152             }
1153         }
1154     }
1155 
removeUser(int userId)1156     private void removeUser(int userId) {
1157         synchronized (mLock) {
1158             mUserStates.remove(userId);
1159         }
1160     }
1161 
1162     // Called only during settings restore; currently supports only the owner user
1163     // TODO: http://b/22388012
restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting)1164     void restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting) {
1165         readComponentNamesFromStringLocked(oldSetting, mTempComponentNameSet, false);
1166         readComponentNamesFromStringLocked(newSetting, mTempComponentNameSet, true);
1167 
1168         UserState userState = getUserStateLocked(UserHandle.USER_SYSTEM);
1169         userState.mEnabledServices.clear();
1170         userState.mEnabledServices.addAll(mTempComponentNameSet);
1171         persistComponentNamesToSettingLocked(
1172                 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
1173                 userState.mEnabledServices,
1174                 UserHandle.USER_SYSTEM);
1175         onUserStateChangedLocked(userState);
1176     }
1177 
getInteractionBridge()1178     private InteractionBridge getInteractionBridge() {
1179         synchronized (mLock) {
1180             if (mInteractionBridge == null) {
1181                 mInteractionBridge = new InteractionBridge();
1182             }
1183             return mInteractionBridge;
1184         }
1185     }
1186 
notifyGestureLocked(int gestureId, boolean isDefault)1187     private boolean notifyGestureLocked(int gestureId, boolean isDefault) {
1188         // TODO: Now we are giving the gestures to the last enabled
1189         //       service that can handle them which is the last one
1190         //       in our list since we write the last enabled as the
1191         //       last record in the enabled services setting. Ideally,
1192         //       the user should make the call which service handles
1193         //       gestures. However, only one service should handle
1194         //       gestures to avoid user frustration when different
1195         //       behavior is observed from different combinations of
1196         //       enabled accessibility services.
1197         UserState state = getCurrentUserStateLocked();
1198         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1199             AccessibilityServiceConnection service = state.mBoundServices.get(i);
1200             if (service.mRequestTouchExplorationMode && service.mIsDefault == isDefault) {
1201                 service.notifyGesture(gestureId);
1202                 return true;
1203             }
1204         }
1205         return false;
1206     }
1207 
notifyClearAccessibilityCacheLocked()1208     private void notifyClearAccessibilityCacheLocked() {
1209         UserState state = getCurrentUserStateLocked();
1210         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1211             AccessibilityServiceConnection service = state.mBoundServices.get(i);
1212             service.notifyClearAccessibilityNodeInfoCache();
1213         }
1214     }
1215 
notifyMagnificationChangedLocked(int displayId, @NonNull Region region, float scale, float centerX, float centerY)1216     private void notifyMagnificationChangedLocked(int displayId, @NonNull Region region,
1217             float scale, float centerX, float centerY) {
1218         final UserState state = getCurrentUserStateLocked();
1219         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1220             final AccessibilityServiceConnection service = state.mBoundServices.get(i);
1221             service.notifyMagnificationChangedLocked(displayId, region, scale, centerX, centerY);
1222         }
1223     }
1224 
notifySoftKeyboardShowModeChangedLocked(int showMode)1225     private void notifySoftKeyboardShowModeChangedLocked(int showMode) {
1226         final UserState state = getCurrentUserStateLocked();
1227         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1228             final AccessibilityServiceConnection service = state.mBoundServices.get(i);
1229             service.notifySoftKeyboardShowModeChangedLocked(showMode);
1230         }
1231     }
1232 
notifyAccessibilityButtonClickedLocked(int displayId)1233     private void notifyAccessibilityButtonClickedLocked(int displayId) {
1234         final UserState state = getCurrentUserStateLocked();
1235 
1236         int potentialTargets = state.mIsNavBarMagnificationEnabled ? 1 : 0;
1237         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1238             final AccessibilityServiceConnection service = state.mBoundServices.get(i);
1239             if (service.mRequestAccessibilityButton) {
1240                 potentialTargets++;
1241             }
1242         }
1243 
1244         if (potentialTargets == 0) {
1245             return;
1246         }
1247         if (potentialTargets == 1) {
1248             if (state.mIsNavBarMagnificationEnabled) {
1249                 mMainHandler.sendMessage(obtainMessage(
1250                         AccessibilityManagerService::sendAccessibilityButtonToInputFilter, this,
1251                         displayId));
1252                 return;
1253             } else {
1254                 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1255                     final AccessibilityServiceConnection service = state.mBoundServices.get(i);
1256                     if (service.mRequestAccessibilityButton) {
1257                         // TODO(b/120762691): Need to notify each accessibility service if
1258                         // accessibility button is clicked per display.
1259                         service.notifyAccessibilityButtonClickedLocked();
1260                         return;
1261                     }
1262                 }
1263             }
1264         } else {
1265             if (state.mServiceAssignedToAccessibilityButton == null
1266                     && !state.mIsNavBarMagnificationAssignedToAccessibilityButton) {
1267                 mMainHandler.sendMessage(obtainMessage(
1268                         AccessibilityManagerService::showAccessibilityButtonTargetSelection, this,
1269                         displayId));
1270             } else if (state.mIsNavBarMagnificationEnabled
1271                     && state.mIsNavBarMagnificationAssignedToAccessibilityButton) {
1272                 mMainHandler.sendMessage(obtainMessage(
1273                         AccessibilityManagerService::sendAccessibilityButtonToInputFilter, this,
1274                         displayId));
1275                 return;
1276             } else {
1277                 for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1278                     final AccessibilityServiceConnection service = state.mBoundServices.get(i);
1279                     if (service.mRequestAccessibilityButton && (service.mComponentName.equals(
1280                             state.mServiceAssignedToAccessibilityButton))) {
1281                         // TODO(b/120762691): Need to notify each accessibility service if
1282                         // accessibility button is clicked per display.
1283                         service.notifyAccessibilityButtonClickedLocked();
1284                         return;
1285                     }
1286                 }
1287             }
1288             // The user may have turned off the assigned service or feature
1289             mMainHandler.sendMessage(obtainMessage(
1290                     AccessibilityManagerService::showAccessibilityButtonTargetSelection, this,
1291                     displayId));
1292         }
1293     }
1294 
sendAccessibilityButtonToInputFilter(int displayId)1295     private void sendAccessibilityButtonToInputFilter(int displayId) {
1296         synchronized (mLock) {
1297             if (mHasInputFilter && mInputFilter != null) {
1298                 mInputFilter.notifyAccessibilityButtonClicked(displayId);
1299             }
1300         }
1301     }
1302 
showAccessibilityButtonTargetSelection(int displayId)1303     private void showAccessibilityButtonTargetSelection(int displayId) {
1304         Intent intent = new Intent(AccessibilityManager.ACTION_CHOOSE_ACCESSIBILITY_BUTTON);
1305         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1306         final Bundle bundle = ActivityOptions.makeBasic().setLaunchDisplayId(displayId).toBundle();
1307         mContext.startActivityAsUser(intent, bundle, UserHandle.of(mCurrentUserId));
1308     }
1309 
notifyAccessibilityButtonVisibilityChangedLocked(boolean available)1310     private void notifyAccessibilityButtonVisibilityChangedLocked(boolean available) {
1311         final UserState state = getCurrentUserStateLocked();
1312         mIsAccessibilityButtonShown = available;
1313         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
1314             final AccessibilityServiceConnection clientConnection = state.mBoundServices.get(i);
1315             if (clientConnection.mRequestAccessibilityButton) {
1316                 clientConnection.notifyAccessibilityButtonAvailabilityChangedLocked(
1317                         clientConnection.isAccessibilityButtonAvailableLocked(state));
1318             }
1319         }
1320     }
1321 
1322     /**
1323      * Removes an AccessibilityInteractionConnection.
1324      *
1325      * @param windowId The id of the window to which the connection is targeted.
1326      * @param userId The id of the user owning the connection. UserHandle.USER_ALL
1327      *     if global.
1328      */
removeAccessibilityInteractionConnectionLocked(int windowId, int userId)1329     private void removeAccessibilityInteractionConnectionLocked(int windowId, int userId) {
1330         if (userId == UserHandle.USER_ALL) {
1331             mGlobalWindowTokens.remove(windowId);
1332             mGlobalInteractionConnections.remove(windowId);
1333         } else {
1334             UserState userState = getCurrentUserStateLocked();
1335             userState.mWindowTokens.remove(windowId);
1336             userState.mInteractionConnections.remove(windowId);
1337         }
1338         mSecurityPolicy.onAccessibilityClientRemovedLocked(windowId);
1339         if (DEBUG) {
1340             Slog.i(LOG_TAG, "Removing interaction connection to windowId: " + windowId);
1341         }
1342     }
1343 
readInstalledAccessibilityServiceLocked(UserState userState)1344     private boolean readInstalledAccessibilityServiceLocked(UserState userState) {
1345         mTempAccessibilityServiceInfoList.clear();
1346 
1347         int flags = PackageManager.GET_SERVICES
1348                 | PackageManager.GET_META_DATA
1349                 | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
1350                 | PackageManager.MATCH_DIRECT_BOOT_AWARE
1351                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
1352 
1353         if (userState.getBindInstantServiceAllowed()) {
1354             flags |= PackageManager.MATCH_INSTANT;
1355         }
1356 
1357         List<ResolveInfo> installedServices = mPackageManager.queryIntentServicesAsUser(
1358                 new Intent(AccessibilityService.SERVICE_INTERFACE), flags, mCurrentUserId);
1359 
1360         for (int i = 0, count = installedServices.size(); i < count; i++) {
1361             ResolveInfo resolveInfo = installedServices.get(i);
1362             ServiceInfo serviceInfo = resolveInfo.serviceInfo;
1363 
1364             if (!canRegisterService(serviceInfo)) {
1365                 continue;
1366             }
1367 
1368             AccessibilityServiceInfo accessibilityServiceInfo;
1369             try {
1370                 accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext);
1371                 mTempAccessibilityServiceInfoList.add(accessibilityServiceInfo);
1372             } catch (XmlPullParserException | IOException xppe) {
1373                 Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", xppe);
1374             }
1375         }
1376 
1377         if (!mTempAccessibilityServiceInfoList.equals(userState.mInstalledServices)) {
1378             userState.mInstalledServices.clear();
1379             userState.mInstalledServices.addAll(mTempAccessibilityServiceInfoList);
1380             mTempAccessibilityServiceInfoList.clear();
1381             return true;
1382         }
1383 
1384         mTempAccessibilityServiceInfoList.clear();
1385         return false;
1386     }
1387 
canRegisterService(ServiceInfo serviceInfo)1388     private boolean canRegisterService(ServiceInfo serviceInfo) {
1389         if (!android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE.equals(
1390                 serviceInfo.permission)) {
1391             Slog.w(LOG_TAG, "Skipping accessibility service " + new ComponentName(
1392                     serviceInfo.packageName, serviceInfo.name).flattenToShortString()
1393                     + ": it does not require the permission "
1394                     + android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE);
1395             return false;
1396         }
1397 
1398         int servicePackageUid = serviceInfo.applicationInfo.uid;
1399         if (mAppOpsManager.noteOpNoThrow(AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE,
1400                 servicePackageUid, serviceInfo.packageName) != AppOpsManager.MODE_ALLOWED) {
1401             Slog.w(LOG_TAG, "Skipping accessibility service " + new ComponentName(
1402                     serviceInfo.packageName, serviceInfo.name).flattenToShortString()
1403                     + ": disallowed by AppOps");
1404             return false;
1405         }
1406 
1407         return true;
1408     }
1409 
readEnabledAccessibilityServicesLocked(UserState userState)1410     private boolean readEnabledAccessibilityServicesLocked(UserState userState) {
1411         mTempComponentNameSet.clear();
1412         readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
1413                 userState.mUserId, mTempComponentNameSet);
1414         if (!mTempComponentNameSet.equals(userState.mEnabledServices)) {
1415             userState.mEnabledServices.clear();
1416             userState.mEnabledServices.addAll(mTempComponentNameSet);
1417             mTempComponentNameSet.clear();
1418             return true;
1419         }
1420         mTempComponentNameSet.clear();
1421         return false;
1422     }
1423 
readTouchExplorationGrantedAccessibilityServicesLocked( UserState userState)1424     private boolean readTouchExplorationGrantedAccessibilityServicesLocked(
1425             UserState userState) {
1426         mTempComponentNameSet.clear();
1427         readComponentNamesFromSettingLocked(
1428                 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
1429                 userState.mUserId, mTempComponentNameSet);
1430         if (!mTempComponentNameSet.equals(userState.mTouchExplorationGrantedServices)) {
1431             userState.mTouchExplorationGrantedServices.clear();
1432             userState.mTouchExplorationGrantedServices.addAll(mTempComponentNameSet);
1433             mTempComponentNameSet.clear();
1434             return true;
1435         }
1436         mTempComponentNameSet.clear();
1437         return false;
1438     }
1439 
1440     /**
1441      * Performs {@link AccessibilityService}s delayed notification. The delay is configurable
1442      * and denotes the period after the last event before notifying the service.
1443      *
1444      * @param event The event.
1445      * @param isDefault True to notify default listeners, not default services.
1446      */
notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event, boolean isDefault)1447     private void notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event,
1448             boolean isDefault) {
1449         try {
1450             UserState state = getCurrentUserStateLocked();
1451             for (int i = 0, count = state.mBoundServices.size(); i < count; i++) {
1452                 AccessibilityServiceConnection service = state.mBoundServices.get(i);
1453 
1454                 if (service.mIsDefault == isDefault) {
1455                     service.notifyAccessibilityEvent(event);
1456                 }
1457             }
1458         } catch (IndexOutOfBoundsException oobe) {
1459             // An out of bounds exception can happen if services are going away
1460             // as the for loop is running. If that happens, just bail because
1461             // there are no more services to notify.
1462         }
1463     }
1464 
updateRelevantEventsLocked(UserState userState)1465     private void updateRelevantEventsLocked(UserState userState) {
1466         mMainHandler.post(() -> {
1467             broadcastToClients(userState, ignoreRemoteException(client -> {
1468                 int relevantEventTypes;
1469                 boolean changed = false;
1470                 synchronized (mLock) {
1471                     relevantEventTypes = computeRelevantEventTypesLocked(userState, client);
1472 
1473                     if (client.mLastSentRelevantEventTypes != relevantEventTypes) {
1474                         client.mLastSentRelevantEventTypes = relevantEventTypes;
1475                         changed = true;
1476                     }
1477                 }
1478                 if (changed) {
1479                     client.mCallback.setRelevantEventTypes(relevantEventTypes);
1480                 }
1481             }));
1482         });
1483     }
1484 
computeRelevantEventTypesLocked(UserState userState, Client client)1485     private int computeRelevantEventTypesLocked(UserState userState, Client client) {
1486         int relevantEventTypes = 0;
1487 
1488         int serviceCount = userState.mBoundServices.size();
1489         for (int i = 0; i < serviceCount; i++) {
1490             AccessibilityServiceConnection service = userState.mBoundServices.get(i);
1491             relevantEventTypes |= isClientInPackageWhitelist(service.getServiceInfo(), client)
1492                     ? service.getRelevantEventTypes()
1493                     : 0;
1494         }
1495 
1496         relevantEventTypes |= isClientInPackageWhitelist(
1497                 mUiAutomationManager.getServiceInfo(), client)
1498                 ? mUiAutomationManager.getRelevantEventTypes()
1499                 : 0;
1500         return relevantEventTypes;
1501     }
1502 
isClientInPackageWhitelist( @ullable AccessibilityServiceInfo serviceInfo, Client client)1503     private static boolean isClientInPackageWhitelist(
1504             @Nullable AccessibilityServiceInfo serviceInfo, Client client) {
1505         if (serviceInfo == null) return false;
1506 
1507         String[] clientPackages = client.mPackageNames;
1508         boolean result = ArrayUtils.isEmpty(serviceInfo.packageNames);
1509         if (!result && clientPackages != null) {
1510             for (String packageName : clientPackages) {
1511                 if (ArrayUtils.contains(serviceInfo.packageNames, packageName)) {
1512                     result = true;
1513                     break;
1514                 }
1515             }
1516         }
1517         if (!result) {
1518             if (DEBUG) {
1519                 Slog.d(LOG_TAG, "Dropping events: "
1520                         + Arrays.toString(clientPackages) + " -> "
1521                         + serviceInfo.getComponentName().flattenToShortString()
1522                         + " due to not being in package whitelist "
1523                         + Arrays.toString(serviceInfo.packageNames));
1524             }
1525         }
1526 
1527         return result;
1528     }
1529 
broadcastToClients( UserState userState, Consumer<Client> clientAction)1530     private void broadcastToClients(
1531             UserState userState, Consumer<Client> clientAction) {
1532         mGlobalClients.broadcastForEachCookie(clientAction);
1533         userState.mUserClients.broadcastForEachCookie(clientAction);
1534     }
1535 
unbindAllServicesLocked(UserState userState)1536     private void unbindAllServicesLocked(UserState userState) {
1537         List<AccessibilityServiceConnection> services = userState.mBoundServices;
1538         for (int count = services.size(); count > 0; count--) {
1539             // When the service is unbound, it disappears from the list, so there's no need to
1540             // keep track of the index
1541             services.get(0).unbindLocked();
1542         }
1543     }
1544 
1545     /**
1546      * Populates a set with the {@link ComponentName}s stored in a colon
1547      * separated value setting for a given user.
1548      *
1549      * @param settingName The setting to parse.
1550      * @param userId The user id.
1551      * @param outComponentNames The output component names.
1552      */
readComponentNamesFromSettingLocked(String settingName, int userId, Set<ComponentName> outComponentNames)1553     private void readComponentNamesFromSettingLocked(String settingName, int userId,
1554             Set<ComponentName> outComponentNames) {
1555         String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(),
1556                 settingName, userId);
1557         readComponentNamesFromStringLocked(settingValue, outComponentNames, false);
1558     }
1559 
1560     /**
1561      * Populates a set with the {@link ComponentName}s contained in a colon-delimited string.
1562      *
1563      * @param names The colon-delimited string to parse.
1564      * @param outComponentNames The set of component names to be populated based on
1565      *    the contents of the <code>names</code> string.
1566      * @param doMerge If true, the parsed component names will be merged into the output
1567      *    set, rather than replacing the set's existing contents entirely.
1568      */
readComponentNamesFromStringLocked(String names, Set<ComponentName> outComponentNames, boolean doMerge)1569     private void readComponentNamesFromStringLocked(String names,
1570             Set<ComponentName> outComponentNames,
1571             boolean doMerge) {
1572         if (!doMerge) {
1573             outComponentNames.clear();
1574         }
1575         if (names != null) {
1576             TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
1577             splitter.setString(names);
1578             while (splitter.hasNext()) {
1579                 String str = splitter.next();
1580                 if (str == null || str.length() <= 0) {
1581                     continue;
1582                 }
1583                 ComponentName enabledService = ComponentName.unflattenFromString(str);
1584                 if (enabledService != null) {
1585                     outComponentNames.add(enabledService);
1586                 }
1587             }
1588         }
1589     }
1590 
1591     @Override
persistComponentNamesToSettingLocked(String settingName, Set<ComponentName> componentNames, int userId)1592     public void persistComponentNamesToSettingLocked(String settingName,
1593             Set<ComponentName> componentNames, int userId) {
1594         StringBuilder builder = new StringBuilder();
1595         for (ComponentName componentName : componentNames) {
1596             if (builder.length() > 0) {
1597                 builder.append(COMPONENT_NAME_SEPARATOR);
1598             }
1599             builder.append(componentName.flattenToShortString());
1600         }
1601         final long identity = Binder.clearCallingIdentity();
1602         try {
1603             final String settingValue = builder.toString();
1604             Settings.Secure.putStringForUser(mContext.getContentResolver(),
1605                     settingName, TextUtils.isEmpty(settingValue) ? null : settingValue, userId);
1606         } finally {
1607             Binder.restoreCallingIdentity(identity);
1608         }
1609     }
1610 
updateServicesLocked(UserState userState)1611     private void updateServicesLocked(UserState userState) {
1612         Map<ComponentName, AccessibilityServiceConnection> componentNameToServiceMap =
1613                 userState.mComponentNameToServiceMap;
1614         boolean isUnlockingOrUnlocked = LocalServices.getService(UserManagerInternal.class)
1615                     .isUserUnlockingOrUnlocked(userState.mUserId);
1616 
1617         for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) {
1618             AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i);
1619             ComponentName componentName = ComponentName.unflattenFromString(
1620                     installedService.getId());
1621 
1622             AccessibilityServiceConnection service = componentNameToServiceMap.get(componentName);
1623 
1624             // Ignore non-encryption-aware services until user is unlocked
1625             if (!isUnlockingOrUnlocked && !installedService.isDirectBootAware()) {
1626                 Slog.d(LOG_TAG, "Ignoring non-encryption-aware service " + componentName);
1627                 continue;
1628             }
1629 
1630             // Wait for the binding if it is in process.
1631             if (userState.mBindingServices.contains(componentName)) {
1632                 continue;
1633             }
1634             if (userState.mEnabledServices.contains(componentName)
1635                     && !mUiAutomationManager.suppressingAccessibilityServicesLocked()) {
1636                 if (service == null) {
1637                     service = new AccessibilityServiceConnection(userState, mContext, componentName,
1638                             installedService, sIdCounter++, mMainHandler, mLock, mSecurityPolicy,
1639                             this, mWindowManagerService, mGlobalActionPerformer,
1640                             mActivityTaskManagerService);
1641                 } else if (userState.mBoundServices.contains(service)) {
1642                     continue;
1643                 }
1644                 service.bindLocked();
1645             } else {
1646                 if (service != null) {
1647                     service.unbindLocked();
1648                 }
1649             }
1650         }
1651 
1652         final int count = userState.mBoundServices.size();
1653         mTempIntArray.clear();
1654         for (int i = 0; i < count; i++) {
1655             final ResolveInfo resolveInfo =
1656                     userState.mBoundServices.get(i).mAccessibilityServiceInfo.getResolveInfo();
1657             if (resolveInfo != null) {
1658                 mTempIntArray.add(resolveInfo.serviceInfo.applicationInfo.uid);
1659             }
1660         }
1661         // Calling out with lock held, but to a lower-level service
1662         final AudioManagerInternal audioManager =
1663                 LocalServices.getService(AudioManagerInternal.class);
1664         if (audioManager != null) {
1665             audioManager.setAccessibilityServiceUids(mTempIntArray);
1666         }
1667         updateAccessibilityEnabledSetting(userState);
1668     }
1669 
scheduleUpdateClientsIfNeededLocked(UserState userState)1670     private void scheduleUpdateClientsIfNeededLocked(UserState userState) {
1671         final int clientState = userState.getClientState();
1672         if (userState.mLastSentClientState != clientState
1673                 && (mGlobalClients.getRegisteredCallbackCount() > 0
1674                         || userState.mUserClients.getRegisteredCallbackCount() > 0)) {
1675             userState.mLastSentClientState = clientState;
1676             mMainHandler.sendMessage(obtainMessage(
1677                     AccessibilityManagerService::sendStateToAllClients,
1678                     this, clientState, userState.mUserId));
1679         }
1680     }
1681 
sendStateToAllClients(int clientState, int userId)1682     private void sendStateToAllClients(int clientState, int userId) {
1683         sendStateToClients(clientState, mGlobalClients);
1684         sendStateToClients(clientState, userId);
1685     }
1686 
sendStateToClients(int clientState, int userId)1687     private void sendStateToClients(int clientState, int userId) {
1688         sendStateToClients(clientState, getUserState(userId).mUserClients);
1689     }
1690 
sendStateToClients(int clientState, RemoteCallbackList<IAccessibilityManagerClient> clients)1691     private void sendStateToClients(int clientState,
1692             RemoteCallbackList<IAccessibilityManagerClient> clients) {
1693         clients.broadcast(ignoreRemoteException(
1694                 client -> client.setState(clientState)));
1695     }
1696 
scheduleNotifyClientsOfServicesStateChangeLocked(UserState userState)1697     private void scheduleNotifyClientsOfServicesStateChangeLocked(UserState userState) {
1698         updateRecommendedUiTimeoutLocked(userState);
1699         mMainHandler.sendMessage(obtainMessage(
1700                 AccessibilityManagerService::sendServicesStateChanged,
1701                 this, userState.mUserClients, getRecommendedTimeoutMillisLocked(userState)));
1702     }
1703 
sendServicesStateChanged( RemoteCallbackList<IAccessibilityManagerClient> userClients, long uiTimeout)1704     private void sendServicesStateChanged(
1705             RemoteCallbackList<IAccessibilityManagerClient> userClients, long uiTimeout) {
1706         notifyClientsOfServicesStateChange(mGlobalClients, uiTimeout);
1707         notifyClientsOfServicesStateChange(userClients, uiTimeout);
1708     }
1709 
notifyClientsOfServicesStateChange( RemoteCallbackList<IAccessibilityManagerClient> clients, long uiTimeout)1710     private void notifyClientsOfServicesStateChange(
1711             RemoteCallbackList<IAccessibilityManagerClient> clients, long uiTimeout) {
1712         clients.broadcast(ignoreRemoteException(
1713                 client -> client.notifyServicesStateChanged(uiTimeout)));
1714     }
1715 
scheduleUpdateInputFilter(UserState userState)1716     private void scheduleUpdateInputFilter(UserState userState) {
1717         mMainHandler.sendMessage(obtainMessage(
1718                 AccessibilityManagerService::updateInputFilter, this, userState));
1719     }
1720 
scheduleUpdateFingerprintGestureHandling(UserState userState)1721     private void scheduleUpdateFingerprintGestureHandling(UserState userState) {
1722         mMainHandler.sendMessage(obtainMessage(
1723                 AccessibilityManagerService::updateFingerprintGestureHandling,
1724                 this, userState));
1725     }
1726 
updateInputFilter(UserState userState)1727     private void updateInputFilter(UserState userState) {
1728         if (mUiAutomationManager.suppressingAccessibilityServicesLocked()) return;
1729 
1730         boolean setInputFilter = false;
1731         AccessibilityInputFilter inputFilter = null;
1732         synchronized (mLock) {
1733             int flags = 0;
1734             if (userState.mIsDisplayMagnificationEnabled) {
1735                 flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER;
1736             }
1737             if (userState.mIsNavBarMagnificationEnabled) {
1738                 flags |= AccessibilityInputFilter.FLAG_FEATURE_TRIGGERED_SCREEN_MAGNIFIER;
1739             }
1740             if (userHasMagnificationServicesLocked(userState)) {
1741                 flags |= AccessibilityInputFilter.FLAG_FEATURE_CONTROL_SCREEN_MAGNIFIER;
1742             }
1743             // Touch exploration without accessibility makes no sense.
1744             if (userState.isHandlingAccessibilityEvents() && userState.mIsTouchExplorationEnabled) {
1745                 flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION;
1746             }
1747             if (userState.mIsFilterKeyEventsEnabled) {
1748                 flags |= AccessibilityInputFilter.FLAG_FEATURE_FILTER_KEY_EVENTS;
1749             }
1750             if (userState.mIsAutoclickEnabled) {
1751                 flags |= AccessibilityInputFilter.FLAG_FEATURE_AUTOCLICK;
1752             }
1753             if (userState.mIsPerformGesturesEnabled) {
1754                 flags |= AccessibilityInputFilter.FLAG_FEATURE_INJECT_MOTION_EVENTS;
1755             }
1756             if (flags != 0) {
1757                 if (!mHasInputFilter) {
1758                     mHasInputFilter = true;
1759                     if (mInputFilter == null) {
1760                         mInputFilter = new AccessibilityInputFilter(mContext,
1761                                 AccessibilityManagerService.this);
1762                     }
1763                     inputFilter = mInputFilter;
1764                     setInputFilter = true;
1765                 }
1766                 mInputFilter.setUserAndEnabledFeatures(userState.mUserId, flags);
1767             } else {
1768                 if (mHasInputFilter) {
1769                     mHasInputFilter = false;
1770                     mInputFilter.setUserAndEnabledFeatures(userState.mUserId, 0);
1771                     inputFilter = null;
1772                     setInputFilter = true;
1773                 }
1774             }
1775         }
1776         if (setInputFilter) {
1777             mWindowManagerService.setInputFilter(inputFilter);
1778         }
1779     }
1780 
showEnableTouchExplorationDialog(final AccessibilityServiceConnection service)1781     private void showEnableTouchExplorationDialog(final AccessibilityServiceConnection service) {
1782         synchronized (mLock) {
1783             String label = service.getServiceInfo().getResolveInfo()
1784                     .loadLabel(mContext.getPackageManager()).toString();
1785 
1786             final UserState userState = getCurrentUserStateLocked();
1787             if (userState.mIsTouchExplorationEnabled) {
1788                 return;
1789             }
1790             if (mEnableTouchExplorationDialog != null
1791                     && mEnableTouchExplorationDialog.isShowing()) {
1792                 return;
1793             }
1794             mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext)
1795                 .setIconAttribute(android.R.attr.alertDialogIcon)
1796                 .setPositiveButton(android.R.string.ok, new OnClickListener() {
1797                      @Override
1798                      public void onClick(DialogInterface dialog, int which) {
1799                          // The user allowed the service to toggle touch exploration.
1800                          userState.mTouchExplorationGrantedServices.add(service.mComponentName);
1801                          persistComponentNamesToSettingLocked(
1802                                  Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
1803                                  userState.mTouchExplorationGrantedServices, userState.mUserId);
1804                          // Enable touch exploration.
1805                          userState.mIsTouchExplorationEnabled = true;
1806                          final long identity = Binder.clearCallingIdentity();
1807                          try {
1808                              Settings.Secure.putIntForUser(mContext.getContentResolver(),
1809                                      Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1,
1810                                      userState.mUserId);
1811                          } finally {
1812                              Binder.restoreCallingIdentity(identity);
1813                          }
1814                          onUserStateChangedLocked(userState);
1815                      }
1816                  })
1817                  .setNegativeButton(android.R.string.cancel, new OnClickListener() {
1818                      @Override
1819                      public void onClick(DialogInterface dialog, int which) {
1820                          dialog.dismiss();
1821                      }
1822                  })
1823                  .setTitle(R.string.enable_explore_by_touch_warning_title)
1824                  .setMessage(mContext.getString(
1825                          R.string.enable_explore_by_touch_warning_message, label))
1826                  .create();
1827              mEnableTouchExplorationDialog.getWindow().setType(
1828                      WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
1829              mEnableTouchExplorationDialog.getWindow().getAttributes().privateFlags
1830                      |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
1831              mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true);
1832              mEnableTouchExplorationDialog.show();
1833         }
1834     }
1835 
1836     /**
1837      * Called when any property of the user state has changed.
1838      *
1839      * @param userState the new user state
1840      */
onUserStateChangedLocked(UserState userState)1841     private void onUserStateChangedLocked(UserState userState) {
1842         // TODO: Remove this hack
1843         mInitialized = true;
1844         updateLegacyCapabilitiesLocked(userState);
1845         updateServicesLocked(userState);
1846         updateAccessibilityShortcutLocked(userState);
1847         updateWindowsForAccessibilityCallbackLocked(userState);
1848         updateAccessibilityFocusBehaviorLocked(userState);
1849         updateFilterKeyEventsLocked(userState);
1850         updateTouchExplorationLocked(userState);
1851         updatePerformGesturesLocked(userState);
1852         updateMagnificationLocked(userState);
1853         scheduleUpdateFingerprintGestureHandling(userState);
1854         scheduleUpdateInputFilter(userState);
1855         updateRelevantEventsLocked(userState);
1856         scheduleUpdateClientsIfNeededLocked(userState);
1857         updateAccessibilityButtonTargetsLocked(userState);
1858     }
1859 
updateAccessibilityFocusBehaviorLocked(UserState userState)1860     private void updateAccessibilityFocusBehaviorLocked(UserState userState) {
1861         // If there is no service that can operate with interactive windows
1862         // then we keep the old behavior where a window loses accessibility
1863         // focus if it is no longer active. This still changes the behavior
1864         // for services that do not operate with interactive windows and run
1865         // at the same time as the one(s) which does. In practice however,
1866         // there is only one service that uses accessibility focus and it
1867         // is typically the one that operates with interactive windows, So,
1868         // this is fine. Note that to allow a service to work across windows
1869         // we have to allow accessibility focus stay in any of them. Sigh...
1870         List<AccessibilityServiceConnection> boundServices = userState.mBoundServices;
1871         final int boundServiceCount = boundServices.size();
1872         for (int i = 0; i < boundServiceCount; i++) {
1873             AccessibilityServiceConnection boundService = boundServices.get(i);
1874             if (boundService.canRetrieveInteractiveWindowsLocked()) {
1875                 userState.mAccessibilityFocusOnlyInActiveWindow = false;
1876                 return;
1877             }
1878         }
1879         userState.mAccessibilityFocusOnlyInActiveWindow = true;
1880     }
1881 
updateWindowsForAccessibilityCallbackLocked(UserState userState)1882     private void updateWindowsForAccessibilityCallbackLocked(UserState userState) {
1883         // We observe windows for accessibility only if there is at least
1884         // one bound service that can retrieve window content that specified
1885         // it is interested in accessing such windows. For services that are
1886         // binding we do an update pass after each bind event, so we run this
1887         // code and register the callback if needed.
1888 
1889         boolean observingWindows = mUiAutomationManager.canRetrieveInteractiveWindowsLocked();
1890         List<AccessibilityServiceConnection> boundServices = userState.mBoundServices;
1891         final int boundServiceCount = boundServices.size();
1892         for (int i = 0; !observingWindows && (i < boundServiceCount); i++) {
1893             AccessibilityServiceConnection boundService = boundServices.get(i);
1894             if (boundService.canRetrieveInteractiveWindowsLocked()) {
1895                 observingWindows = true;
1896             }
1897         }
1898 
1899         if (observingWindows) {
1900             if (mWindowsForAccessibilityCallback == null) {
1901                 mWindowsForAccessibilityCallback = new WindowsForAccessibilityCallback();
1902                 mWindowManagerService.setWindowsForAccessibilityCallback(
1903                         mWindowsForAccessibilityCallback);
1904             }
1905             return;
1906         }
1907 
1908         if (mWindowsForAccessibilityCallback != null) {
1909             mWindowsForAccessibilityCallback = null;
1910             mWindowManagerService.setWindowsForAccessibilityCallback(null);
1911             // Drop all windows we know about.
1912             mSecurityPolicy.clearWindowsLocked();
1913         }
1914     }
1915 
updateLegacyCapabilitiesLocked(UserState userState)1916     private void updateLegacyCapabilitiesLocked(UserState userState) {
1917         // Up to JB-MR1 we had a white list with services that can enable touch
1918         // exploration. When a service is first started we show a dialog to the
1919         // use to get a permission to white list the service.
1920         final int installedServiceCount = userState.mInstalledServices.size();
1921         for (int i = 0; i < installedServiceCount; i++) {
1922             AccessibilityServiceInfo serviceInfo = userState.mInstalledServices.get(i);
1923             ResolveInfo resolveInfo = serviceInfo.getResolveInfo();
1924             if ((serviceInfo.getCapabilities()
1925                         & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) == 0
1926                     && resolveInfo.serviceInfo.applicationInfo.targetSdkVersion
1927                         <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
1928                 ComponentName componentName = new ComponentName(
1929                         resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
1930                 if (userState.mTouchExplorationGrantedServices.contains(componentName)) {
1931                     serviceInfo.setCapabilities(serviceInfo.getCapabilities()
1932                             | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION);
1933                 }
1934             }
1935         }
1936     }
1937 
updatePerformGesturesLocked(UserState userState)1938     private void updatePerformGesturesLocked(UserState userState) {
1939         final int serviceCount = userState.mBoundServices.size();
1940         for (int i = 0; i < serviceCount; i++) {
1941             AccessibilityServiceConnection service = userState.mBoundServices.get(i);
1942             if ((service.getCapabilities()
1943                     & AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0) {
1944                 userState.mIsPerformGesturesEnabled = true;
1945                 return;
1946             }
1947         }
1948         userState.mIsPerformGesturesEnabled = false;
1949     }
1950 
updateFilterKeyEventsLocked(UserState userState)1951     private void updateFilterKeyEventsLocked(UserState userState) {
1952         final int serviceCount = userState.mBoundServices.size();
1953         for (int i = 0; i < serviceCount; i++) {
1954             AccessibilityServiceConnection service = userState.mBoundServices.get(i);
1955             if (service.mRequestFilterKeyEvents
1956                     && (service.getCapabilities()
1957                             & AccessibilityServiceInfo
1958                             .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) != 0) {
1959                 userState.mIsFilterKeyEventsEnabled = true;
1960                 return;
1961             }
1962         }
1963         userState.mIsFilterKeyEventsEnabled = false;
1964     }
1965 
readConfigurationForUserStateLocked(UserState userState)1966     private boolean readConfigurationForUserStateLocked(UserState userState) {
1967         boolean somethingChanged = readInstalledAccessibilityServiceLocked(userState);
1968         somethingChanged |= readEnabledAccessibilityServicesLocked(userState);
1969         somethingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState);
1970         somethingChanged |= readTouchExplorationEnabledSettingLocked(userState);
1971         somethingChanged |= readHighTextContrastEnabledSettingLocked(userState);
1972         somethingChanged |= readMagnificationEnabledSettingsLocked(userState);
1973         somethingChanged |= readAutoclickEnabledSettingLocked(userState);
1974         somethingChanged |= readAccessibilityShortcutSettingLocked(userState);
1975         somethingChanged |= readAccessibilityButtonSettingsLocked(userState);
1976         somethingChanged |= readUserRecommendedUiTimeoutSettingsLocked(userState);
1977         return somethingChanged;
1978     }
1979 
updateAccessibilityEnabledSetting(UserState userState)1980     private void updateAccessibilityEnabledSetting(UserState userState) {
1981         final long identity = Binder.clearCallingIdentity();
1982         final boolean isA11yEnabled = mUiAutomationManager.isUiAutomationRunningLocked()
1983                 || userState.isHandlingAccessibilityEvents();
1984         try {
1985             Settings.Secure.putIntForUser(mContext.getContentResolver(),
1986                     Settings.Secure.ACCESSIBILITY_ENABLED,
1987                     (isA11yEnabled) ? 1 : 0,
1988                     userState.mUserId);
1989         } finally {
1990             Binder.restoreCallingIdentity(identity);
1991         }
1992     }
1993 
readTouchExplorationEnabledSettingLocked(UserState userState)1994     private boolean readTouchExplorationEnabledSettingLocked(UserState userState) {
1995         final boolean touchExplorationEnabled = Settings.Secure.getIntForUser(
1996                 mContext.getContentResolver(),
1997                 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId) == 1;
1998         if (touchExplorationEnabled != userState.mIsTouchExplorationEnabled) {
1999             userState.mIsTouchExplorationEnabled = touchExplorationEnabled;
2000             return true;
2001         }
2002         return false;
2003     }
2004 
readMagnificationEnabledSettingsLocked(UserState userState)2005     private boolean readMagnificationEnabledSettingsLocked(UserState userState) {
2006         final boolean displayMagnificationEnabled = Settings.Secure.getIntForUser(
2007                 mContext.getContentResolver(),
2008                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
2009                 0, userState.mUserId) == 1;
2010         final boolean navBarMagnificationEnabled = Settings.Secure.getIntForUser(
2011                 mContext.getContentResolver(),
2012                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED,
2013                 0, userState.mUserId) == 1;
2014         if ((displayMagnificationEnabled != userState.mIsDisplayMagnificationEnabled)
2015                 || (navBarMagnificationEnabled != userState.mIsNavBarMagnificationEnabled)) {
2016             userState.mIsDisplayMagnificationEnabled = displayMagnificationEnabled;
2017             userState.mIsNavBarMagnificationEnabled = navBarMagnificationEnabled;
2018             return true;
2019         }
2020         return false;
2021     }
2022 
readAutoclickEnabledSettingLocked(UserState userState)2023     private boolean readAutoclickEnabledSettingLocked(UserState userState) {
2024         final boolean autoclickEnabled = Settings.Secure.getIntForUser(
2025                 mContext.getContentResolver(),
2026                 Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED,
2027                 0, userState.mUserId) == 1;
2028         if (autoclickEnabled != userState.mIsAutoclickEnabled) {
2029             userState.mIsAutoclickEnabled = autoclickEnabled;
2030             return true;
2031         }
2032         return false;
2033     }
2034 
readHighTextContrastEnabledSettingLocked(UserState userState)2035     private boolean readHighTextContrastEnabledSettingLocked(UserState userState) {
2036         final boolean highTextContrastEnabled = Settings.Secure.getIntForUser(
2037                 mContext.getContentResolver(),
2038                 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 0,
2039                 userState.mUserId) == 1;
2040         if (highTextContrastEnabled != userState.mIsTextHighContrastEnabled) {
2041             userState.mIsTextHighContrastEnabled = highTextContrastEnabled;
2042             return true;
2043         }
2044         return false;
2045     }
2046 
updateTouchExplorationLocked(UserState userState)2047     private void updateTouchExplorationLocked(UserState userState) {
2048         boolean enabled = mUiAutomationManager.isTouchExplorationEnabledLocked();
2049         final int serviceCount = userState.mBoundServices.size();
2050         for (int i = 0; i < serviceCount; i++) {
2051             AccessibilityServiceConnection service = userState.mBoundServices.get(i);
2052             if (canRequestAndRequestsTouchExplorationLocked(service, userState)) {
2053                 enabled = true;
2054                 break;
2055             }
2056         }
2057         if (enabled != userState.mIsTouchExplorationEnabled) {
2058             userState.mIsTouchExplorationEnabled = enabled;
2059             final long identity = Binder.clearCallingIdentity();
2060             try {
2061                 Settings.Secure.putIntForUser(mContext.getContentResolver(),
2062                         Settings.Secure.TOUCH_EXPLORATION_ENABLED, enabled ? 1 : 0,
2063                         userState.mUserId);
2064             } finally {
2065                 Binder.restoreCallingIdentity(identity);
2066             }
2067         }
2068     }
2069 
readAccessibilityShortcutSettingLocked(UserState userState)2070     private boolean readAccessibilityShortcutSettingLocked(UserState userState) {
2071         String componentNameToEnableString = AccessibilityShortcutController
2072                 .getTargetServiceComponentNameString(mContext, userState.mUserId);
2073         if ((componentNameToEnableString == null) || componentNameToEnableString.isEmpty()) {
2074             if (userState.mServiceToEnableWithShortcut == null) {
2075                 return false;
2076             }
2077             userState.mServiceToEnableWithShortcut = null;
2078             return true;
2079         }
2080         ComponentName componentNameToEnable =
2081             ComponentName.unflattenFromString(componentNameToEnableString);
2082         if ((componentNameToEnable != null)
2083                 && componentNameToEnable.equals(userState.mServiceToEnableWithShortcut)) {
2084             return false;
2085         }
2086 
2087         userState.mServiceToEnableWithShortcut = componentNameToEnable;
2088         scheduleNotifyClientsOfServicesStateChangeLocked(userState);
2089         return true;
2090     }
2091 
readAccessibilityButtonSettingsLocked(UserState userState)2092     private boolean readAccessibilityButtonSettingsLocked(UserState userState) {
2093         String componentId = Settings.Secure.getStringForUser(mContext.getContentResolver(),
2094                 Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT, userState.mUserId);
2095         if (TextUtils.isEmpty(componentId)) {
2096             if ((userState.mServiceAssignedToAccessibilityButton == null)
2097                     && !userState.mIsNavBarMagnificationAssignedToAccessibilityButton) {
2098                 return false;
2099             }
2100             userState.mServiceAssignedToAccessibilityButton = null;
2101             userState.mIsNavBarMagnificationAssignedToAccessibilityButton = false;
2102             return true;
2103         }
2104 
2105         if (componentId.equals(MagnificationController.class.getName())) {
2106             if (userState.mIsNavBarMagnificationAssignedToAccessibilityButton) {
2107                 return false;
2108             }
2109             userState.mServiceAssignedToAccessibilityButton = null;
2110             userState.mIsNavBarMagnificationAssignedToAccessibilityButton = true;
2111             return true;
2112         }
2113 
2114         ComponentName componentName = ComponentName.unflattenFromString(componentId);
2115         if (Objects.equals(componentName, userState.mServiceAssignedToAccessibilityButton)) {
2116             return false;
2117         }
2118         userState.mServiceAssignedToAccessibilityButton = componentName;
2119         userState.mIsNavBarMagnificationAssignedToAccessibilityButton = false;
2120         return true;
2121     }
2122 
readUserRecommendedUiTimeoutSettingsLocked(UserState userState)2123     private boolean readUserRecommendedUiTimeoutSettingsLocked(UserState userState) {
2124         final int nonInteractiveUiTimeout = Settings.Secure.getIntForUser(
2125                 mContext.getContentResolver(),
2126                 Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, 0,
2127                 userState.mUserId);
2128         final int interactiveUiTimeout = Settings.Secure.getIntForUser(
2129                 mContext.getContentResolver(),
2130                 Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, 0,
2131                 userState.mUserId);
2132         if (nonInteractiveUiTimeout != userState.mUserNonInteractiveUiTimeout
2133                 || interactiveUiTimeout != userState.mUserInteractiveUiTimeout) {
2134             userState.mUserNonInteractiveUiTimeout = nonInteractiveUiTimeout;
2135             userState.mUserInteractiveUiTimeout = interactiveUiTimeout;
2136             scheduleNotifyClientsOfServicesStateChangeLocked(userState);
2137             return true;
2138         }
2139         return false;
2140     }
2141 
2142     /**
2143      * Check if the service that will be enabled by the shortcut is installed. If it isn't,
2144      * clear the value and the associated setting so a sideloaded service can't spoof the
2145      * package name of the default service.
2146      *
2147      * @param userState
2148      */
updateAccessibilityShortcutLocked(UserState userState)2149     private void updateAccessibilityShortcutLocked(UserState userState) {
2150         if (userState.mServiceToEnableWithShortcut == null) {
2151             return;
2152         }
2153         boolean shortcutServiceIsInstalled =
2154                 AccessibilityShortcutController.getFrameworkShortcutFeaturesMap()
2155                         .containsKey(userState.mServiceToEnableWithShortcut);
2156         for (int i = 0; !shortcutServiceIsInstalled && (i < userState.mInstalledServices.size());
2157                 i++) {
2158             if (userState.mInstalledServices.get(i).getComponentName()
2159                     .equals(userState.mServiceToEnableWithShortcut)) {
2160                 shortcutServiceIsInstalled = true;
2161             }
2162         }
2163         if (!shortcutServiceIsInstalled) {
2164             userState.mServiceToEnableWithShortcut = null;
2165             final long identity = Binder.clearCallingIdentity();
2166             try {
2167                 Settings.Secure.putStringForUser(mContext.getContentResolver(),
2168                         Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, null,
2169                         userState.mUserId);
2170 
2171                 Settings.Secure.putIntForUser(mContext.getContentResolver(),
2172                         Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 0, userState.mUserId);
2173             } finally {
2174                 Binder.restoreCallingIdentity(identity);
2175             }
2176         }
2177     }
2178 
canRequestAndRequestsTouchExplorationLocked( AccessibilityServiceConnection service, UserState userState)2179     private boolean canRequestAndRequestsTouchExplorationLocked(
2180             AccessibilityServiceConnection service, UserState userState) {
2181         // Service not ready or cannot request the feature - well nothing to do.
2182         if (!service.canReceiveEventsLocked() || !service.mRequestTouchExplorationMode) {
2183             return false;
2184         }
2185         if (service.getServiceInfo().getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion
2186                 <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
2187             // Up to JB-MR1 we had a white list with services that can enable touch
2188             // exploration. When a service is first started we show a dialog to the
2189             // use to get a permission to white list the service.
2190             if (userState.mTouchExplorationGrantedServices.contains(service.mComponentName)) {
2191                 return true;
2192             } else if (mEnableTouchExplorationDialog == null
2193                     || !mEnableTouchExplorationDialog.isShowing()) {
2194                 mMainHandler.sendMessage(obtainMessage(
2195                         AccessibilityManagerService::showEnableTouchExplorationDialog,
2196                         this, service));
2197             }
2198         } else {
2199             // Starting in JB-MR2 we request an accessibility service to declare
2200             // certain capabilities in its meta-data to allow it to enable the
2201             // corresponding features.
2202             if ((service.getCapabilities()
2203                     & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) != 0) {
2204                 return true;
2205             }
2206         }
2207         return false;
2208     }
2209 
updateMagnificationLocked(UserState userState)2210     private void updateMagnificationLocked(UserState userState) {
2211         if (userState.mUserId != mCurrentUserId) {
2212             return;
2213         }
2214 
2215         if (mUiAutomationManager.suppressingAccessibilityServicesLocked()
2216                 && mMagnificationController != null) {
2217             mMagnificationController.unregisterAll();
2218             return;
2219         }
2220 
2221         // Get all valid displays and register them if global magnification is enabled.
2222         // We would skip overlay display because it uses overlay window to simulate secondary
2223         // displays in one display. It's not a real display and there's no input events for it.
2224         final ArrayList<Display> displays = getValidDisplayList();
2225         if (userState.mIsDisplayMagnificationEnabled
2226                 || userState.mIsNavBarMagnificationEnabled) {
2227             for (int i = 0; i < displays.size(); i++) {
2228                 final Display display = displays.get(i);
2229                 getMagnificationController().register(display.getDisplayId());
2230             }
2231             return;
2232         }
2233 
2234         // Register if display has listening magnification services.
2235         for (int i = 0; i < displays.size(); i++) {
2236             final Display display = displays.get(i);
2237             final int displayId = display.getDisplayId();
2238             if (userHasListeningMagnificationServicesLocked(userState, displayId)) {
2239                 getMagnificationController().register(displayId);
2240             } else if (mMagnificationController != null) {
2241                 mMagnificationController.unregister(displayId);
2242             }
2243         }
2244     }
2245 
2246     /**
2247      * Returns whether the specified user has any services that are capable of
2248      * controlling magnification.
2249      */
userHasMagnificationServicesLocked(UserState userState)2250     private boolean userHasMagnificationServicesLocked(UserState userState) {
2251         final List<AccessibilityServiceConnection> services = userState.mBoundServices;
2252         for (int i = 0, count = services.size(); i < count; i++) {
2253             final AccessibilityServiceConnection service = services.get(i);
2254             if (mSecurityPolicy.canControlMagnification(service)) {
2255                 return true;
2256             }
2257         }
2258         return false;
2259     }
2260 
2261     /**
2262      * Returns whether the specified user has any services that are capable of
2263      * controlling magnification and are actively listening for magnification updates.
2264      */
userHasListeningMagnificationServicesLocked(UserState userState, int displayId)2265     private boolean userHasListeningMagnificationServicesLocked(UserState userState,
2266             int displayId) {
2267         final List<AccessibilityServiceConnection> services = userState.mBoundServices;
2268         for (int i = 0, count = services.size(); i < count; i++) {
2269             final AccessibilityServiceConnection service = services.get(i);
2270             if (mSecurityPolicy.canControlMagnification(service)
2271                     && service.isMagnificationCallbackEnabled(displayId)) {
2272                 return true;
2273             }
2274         }
2275         return false;
2276     }
2277 
updateFingerprintGestureHandling(UserState userState)2278     private void updateFingerprintGestureHandling(UserState userState) {
2279         final List<AccessibilityServiceConnection> services;
2280         synchronized (mLock) {
2281             services = userState.mBoundServices;
2282             if ((mFingerprintGestureDispatcher == null)
2283                     &&  mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
2284                 // Only create the controller when a service wants to use the feature
2285                 int numServices = services.size();
2286                 for (int i = 0; i < numServices; i++) {
2287                     if (services.get(i).isCapturingFingerprintGestures()) {
2288                         final long identity = Binder.clearCallingIdentity();
2289                         IFingerprintService service = null;
2290                         try {
2291                             service = IFingerprintService.Stub.asInterface(
2292                                     ServiceManager.getService(Context.FINGERPRINT_SERVICE));
2293                         } finally {
2294                             Binder.restoreCallingIdentity(identity);
2295                         }
2296                         if (service != null) {
2297                             mFingerprintGestureDispatcher = new FingerprintGestureDispatcher(
2298                                     service, mContext.getResources(), mLock);
2299                             break;
2300                         }
2301                     }
2302                 }
2303             }
2304         }
2305         if (mFingerprintGestureDispatcher != null) {
2306             mFingerprintGestureDispatcher.updateClientList(services);
2307         }
2308     }
2309 
updateAccessibilityButtonTargetsLocked(UserState userState)2310     private void updateAccessibilityButtonTargetsLocked(UserState userState) {
2311         for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
2312             final AccessibilityServiceConnection service = userState.mBoundServices.get(i);
2313             if (service.mRequestAccessibilityButton) {
2314                 service.notifyAccessibilityButtonAvailabilityChangedLocked(
2315                         service.isAccessibilityButtonAvailableLocked(userState));
2316             }
2317         }
2318     }
2319 
updateRecommendedUiTimeoutLocked(UserState userState)2320     private void updateRecommendedUiTimeoutLocked(UserState userState) {
2321         int newNonInteractiveUiTimeout = userState.mUserNonInteractiveUiTimeout;
2322         int newInteractiveUiTimeout = userState.mUserInteractiveUiTimeout;
2323         // read from a11y services if user does not specify value
2324         if (newNonInteractiveUiTimeout == 0 || newInteractiveUiTimeout == 0) {
2325             int serviceNonInteractiveUiTimeout = 0;
2326             int serviceInteractiveUiTimeout = 0;
2327             final List<AccessibilityServiceConnection> services = userState.mBoundServices;
2328             for (int i = 0; i < services.size(); i++) {
2329                 int timeout = services.get(i).getServiceInfo().getInteractiveUiTimeoutMillis();
2330                 if (serviceInteractiveUiTimeout < timeout) {
2331                     serviceInteractiveUiTimeout = timeout;
2332                 }
2333                 timeout = services.get(i).getServiceInfo().getNonInteractiveUiTimeoutMillis();
2334                 if (serviceNonInteractiveUiTimeout < timeout) {
2335                     serviceNonInteractiveUiTimeout = timeout;
2336                 }
2337             }
2338             if (newNonInteractiveUiTimeout == 0) {
2339                 newNonInteractiveUiTimeout = serviceNonInteractiveUiTimeout;
2340             }
2341             if (newInteractiveUiTimeout == 0) {
2342                 newInteractiveUiTimeout = serviceInteractiveUiTimeout;
2343             }
2344         }
2345         userState.mNonInteractiveUiTimeout = newNonInteractiveUiTimeout;
2346         userState.mInteractiveUiTimeout = newInteractiveUiTimeout;
2347     }
2348 
2349     @GuardedBy("mLock")
2350     @Override
getCompatibleMagnificationSpecLocked(int windowId)2351     public MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId) {
2352         IBinder windowToken = mGlobalWindowTokens.get(windowId);
2353         if (windowToken == null) {
2354             windowToken = getCurrentUserStateLocked().mWindowTokens.get(windowId);
2355         }
2356         if (windowToken != null) {
2357             return mWindowManagerService.getCompatibleMagnificationSpecForWindow(
2358                     windowToken);
2359         }
2360         return null;
2361     }
2362 
2363     @Override
getKeyEventDispatcher()2364     public KeyEventDispatcher getKeyEventDispatcher() {
2365         if (mKeyEventDispatcher == null) {
2366             mKeyEventDispatcher = new KeyEventDispatcher(
2367                     mMainHandler, MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER, mLock,
2368                     mPowerManager);
2369         }
2370         return mKeyEventDispatcher;
2371     }
2372 
2373     @Override
getPendingIntentActivity(Context context, int requestCode, Intent intent, int flags)2374     public PendingIntent getPendingIntentActivity(Context context, int requestCode, Intent intent,
2375             int flags) {
2376         return PendingIntent.getActivity(context, requestCode, intent, flags);
2377     }
2378     /**
2379      * AIDL-exposed method to be called when the accessibility shortcut is enabled. Requires
2380      * permission to write secure settings, since someone with that permission can enable
2381      * accessibility services themselves.
2382      */
2383     @Override
performAccessibilityShortcut()2384     public void performAccessibilityShortcut() {
2385         if ((UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID)
2386                 && (mContext.checkCallingPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
2387                 != PackageManager.PERMISSION_GRANTED)) {
2388             throw new SecurityException(
2389                     "performAccessibilityShortcut requires the MANAGE_ACCESSIBILITY permission");
2390         }
2391         final Map<ComponentName, ToggleableFrameworkFeatureInfo> frameworkFeatureMap =
2392                 AccessibilityShortcutController.getFrameworkShortcutFeaturesMap();
2393         synchronized(mLock) {
2394             final UserState userState = getUserStateLocked(mCurrentUserId);
2395             final ComponentName serviceName = userState.mServiceToEnableWithShortcut;
2396             if (serviceName == null) {
2397                 return;
2398             }
2399             if (frameworkFeatureMap.containsKey(serviceName)) {
2400                 // Toggle the requested framework feature
2401                 ToggleableFrameworkFeatureInfo featureInfo = frameworkFeatureMap.get(serviceName);
2402                 SettingStringHelper setting = new SettingStringHelper(mContext.getContentResolver(),
2403                         featureInfo.getSettingKey(), mCurrentUserId);
2404                 // Assuming that the default state will be to have the feature off
2405                 if (!TextUtils.equals(featureInfo.getSettingOnValue(), setting.read())) {
2406                     setting.write(featureInfo.getSettingOnValue());
2407                 } else {
2408                     setting.write(featureInfo.getSettingOffValue());
2409                 }
2410             }
2411             final long identity = Binder.clearCallingIdentity();
2412             try {
2413                 if (userState.mComponentNameToServiceMap.get(serviceName) == null) {
2414                     enableAccessibilityServiceLocked(serviceName, mCurrentUserId);
2415                 } else {
2416                     disableAccessibilityServiceLocked(serviceName, mCurrentUserId);
2417                 }
2418             } finally {
2419                 Binder.restoreCallingIdentity(identity);
2420             }
2421         }
2422     };
2423 
2424     @Override
getAccessibilityShortcutService()2425     public String getAccessibilityShortcutService() {
2426         if (mContext.checkCallingPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
2427                 != PackageManager.PERMISSION_GRANTED) {
2428             throw new SecurityException(
2429                     "getAccessibilityShortcutService requires the MANAGE_ACCESSIBILITY permission");
2430         }
2431         synchronized(mLock) {
2432             final UserState userState = getUserStateLocked(mCurrentUserId);
2433             return userState.mServiceToEnableWithShortcut.flattenToString();
2434         }
2435     }
2436 
2437     /**
2438      * Enables accessibility service specified by {@param componentName} for the {@param userId}.
2439      */
enableAccessibilityServiceLocked(ComponentName componentName, int userId)2440     private void enableAccessibilityServiceLocked(ComponentName componentName, int userId) {
2441         mTempComponentNameSet.clear();
2442         readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
2443                 userId, mTempComponentNameSet);
2444         mTempComponentNameSet.add(componentName);
2445         persistComponentNamesToSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
2446                 mTempComponentNameSet, userId);
2447 
2448         UserState userState = getUserStateLocked(userId);
2449         if (userState.mEnabledServices.add(componentName)) {
2450             onUserStateChangedLocked(userState);
2451         }
2452     }
2453 
2454     /**
2455      * Disables accessibility service specified by {@param componentName} for the {@param userId}.
2456      */
disableAccessibilityServiceLocked(ComponentName componentName, int userId)2457     private void disableAccessibilityServiceLocked(ComponentName componentName, int userId) {
2458         mTempComponentNameSet.clear();
2459         readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
2460                 userId, mTempComponentNameSet);
2461         mTempComponentNameSet.remove(componentName);
2462         persistComponentNamesToSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
2463                 mTempComponentNameSet, userId);
2464 
2465         UserState userState = getUserStateLocked(userId);
2466         if (userState.mEnabledServices.remove(componentName)) {
2467             onUserStateChangedLocked(userState);
2468         }
2469     }
2470 
sendAccessibilityEventLocked(AccessibilityEvent event, int userId)2471     private void sendAccessibilityEventLocked(AccessibilityEvent event, int userId) {
2472         // Resync to avoid calling out with the lock held
2473         event.setEventTime(SystemClock.uptimeMillis());
2474         mMainHandler.sendMessage(obtainMessage(
2475                 AccessibilityManagerService::sendAccessibilityEvent,
2476                 this, event, userId));
2477     }
2478 
2479     /**
2480      * AIDL-exposed method. System only.
2481      * Inform accessibility that a fingerprint gesture was performed
2482      *
2483      * @param gestureKeyCode The key code corresponding to the fingerprint gesture.
2484      * @return {@code true} if accessibility consumes the fingerprint gesture, {@code false} if it
2485      * doesn't.
2486      */
2487     @Override
sendFingerprintGesture(int gestureKeyCode)2488     public boolean sendFingerprintGesture(int gestureKeyCode) {
2489         synchronized(mLock) {
2490             if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) {
2491                 throw new SecurityException("Only SYSTEM can call sendFingerprintGesture");
2492             }
2493         }
2494         if (mFingerprintGestureDispatcher == null) {
2495             return false;
2496         }
2497         return mFingerprintGestureDispatcher.onFingerprintGesture(gestureKeyCode);
2498     }
2499 
2500     /**
2501      * AIDL-exposed method. System only.
2502      * Gets accessibility window id from window token.
2503      *
2504      * @param windowToken Window token to get accessibility window id.
2505      * @return Accessibility window id for the window token. Returns -1 if no such token is
2506      *   registered.
2507      */
2508     @Override
getAccessibilityWindowId(@ullable IBinder windowToken)2509     public int getAccessibilityWindowId(@Nullable IBinder windowToken) {
2510         synchronized (mLock) {
2511             if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) {
2512                 throw new SecurityException("Only SYSTEM can call getAccessibilityWindowId");
2513             }
2514 
2515             return findWindowIdLocked(windowToken);
2516         }
2517     }
2518 
2519     /**
2520      * Get the recommended timeout of interactive controls and non-interactive controls.
2521      *
2522      * @return A long for pair of {@code int}s. First integer for interactive one, and second
2523      * integer for non-interactive one.
2524      */
2525     @Override
getRecommendedTimeoutMillis()2526     public long getRecommendedTimeoutMillis() {
2527         synchronized(mLock) {
2528             final UserState userState = getCurrentUserStateLocked();
2529             return getRecommendedTimeoutMillisLocked(userState);
2530         }
2531     }
2532 
getRecommendedTimeoutMillisLocked(UserState userState)2533     private long getRecommendedTimeoutMillisLocked(UserState userState) {
2534         return IntPair.of(userState.mInteractiveUiTimeout,
2535                 userState.mNonInteractiveUiTimeout);
2536     }
2537 
2538     @Override
dump(FileDescriptor fd, final PrintWriter pw, String[] args)2539     public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
2540         if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
2541         synchronized (mLock) {
2542             pw.println("ACCESSIBILITY MANAGER (dumpsys accessibility)");
2543             pw.println();
2544             final int userCount = mUserStates.size();
2545             for (int i = 0; i < userCount; i++) {
2546                 UserState userState = mUserStates.valueAt(i);
2547                 pw.append("User state[attributes:{id=" + userState.mUserId);
2548                 pw.append(", currentUser=" + (userState.mUserId == mCurrentUserId));
2549                 pw.append(", touchExplorationEnabled=" + userState.mIsTouchExplorationEnabled);
2550                 pw.append(", displayMagnificationEnabled="
2551                         + userState.mIsDisplayMagnificationEnabled);
2552                 pw.append(", navBarMagnificationEnabled="
2553                         + userState.mIsNavBarMagnificationEnabled);
2554                 pw.append(", autoclickEnabled=" + userState.mIsAutoclickEnabled);
2555                 pw.append(", nonInteractiveUiTimeout=" + userState.mNonInteractiveUiTimeout);
2556                 pw.append(", interactiveUiTimeout=" + userState.mInteractiveUiTimeout);
2557                 pw.append(", installedServiceCount=" + userState.mInstalledServices.size());
2558                 if (mUiAutomationManager.isUiAutomationRunningLocked()) {
2559                     pw.append(", ");
2560                     mUiAutomationManager.dumpUiAutomationService(fd, pw, args);
2561                     pw.println();
2562                 }
2563                 pw.append("}");
2564                 pw.println();
2565                 pw.append("     Bound services:{");
2566                 final int serviceCount = userState.mBoundServices.size();
2567                 for (int j = 0; j < serviceCount; j++) {
2568                     if (j > 0) {
2569                         pw.append(", ");
2570                         pw.println();
2571                         pw.append("                     ");
2572                     }
2573                     AccessibilityServiceConnection service = userState.mBoundServices.get(j);
2574                     service.dump(fd, pw, args);
2575                 }
2576                 pw.println("}");
2577                 pw.append("     Enabled services:{");
2578                 Iterator<ComponentName> it = userState.mEnabledServices.iterator();
2579                 if (it.hasNext()) {
2580                     ComponentName componentName = it.next();
2581                     pw.append(componentName.toShortString());
2582                     while (it.hasNext()) {
2583                         componentName = it.next();
2584                         pw.append(", ");
2585                         pw.append(componentName.toShortString());
2586                     }
2587                 }
2588                 pw.println("}");
2589                 pw.append("     Binding services:{");
2590                 it = userState.mBindingServices.iterator();
2591                 if (it.hasNext()) {
2592                     ComponentName componentName = it.next();
2593                     pw.append(componentName.toShortString());
2594                     while (it.hasNext()) {
2595                         componentName = it.next();
2596                         pw.append(", ");
2597                         pw.append(componentName.toShortString());
2598                     }
2599                 }
2600                 pw.println("}]");
2601                 pw.println();
2602             }
2603             if (mSecurityPolicy.mWindows != null) {
2604                 final int windowCount = mSecurityPolicy.mWindows.size();
2605                 for (int j = 0; j < windowCount; j++) {
2606                     if (j > 0) {
2607                         pw.append(',');
2608                         pw.println();
2609                     }
2610                     pw.append("Window[");
2611                     AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(j);
2612                     pw.append(window.toString());
2613                     pw.append(']');
2614                 }
2615                 pw.println();
2616             }
2617         }
2618     }
2619 
putSecureIntForUser(String key, int value, int userid)2620     private void putSecureIntForUser(String key, int value, int userid) {
2621         final long identity = Binder.clearCallingIdentity();
2622         try {
2623             Settings.Secure.putIntForUser(mContext.getContentResolver(), key, value, userid);
2624         } finally {
2625             Binder.restoreCallingIdentity(identity);
2626         }
2627     }
2628 
2629     class RemoteAccessibilityConnection implements DeathRecipient {
2630         private final int mUid;
2631         private final String mPackageName;
2632         private final int mWindowId;
2633         private final int mUserId;
2634         private final IAccessibilityInteractionConnection mConnection;
2635 
RemoteAccessibilityConnection(int windowId, IAccessibilityInteractionConnection connection, String packageName, int uid, int userId)2636         RemoteAccessibilityConnection(int windowId,
2637                 IAccessibilityInteractionConnection connection,
2638                 String packageName, int uid, int userId) {
2639             mWindowId = windowId;
2640             mPackageName = packageName;
2641             mUid = uid;
2642             mUserId = userId;
2643             mConnection = connection;
2644         }
2645 
getUid()2646         public int getUid() {
2647             return  mUid;
2648         }
2649 
getPackageName()2650         public String getPackageName() {
2651             return mPackageName;
2652         }
2653 
getRemote()2654         public IAccessibilityInteractionConnection getRemote() {
2655             return mConnection;
2656         }
2657 
linkToDeath()2658         public void linkToDeath() throws RemoteException {
2659             mConnection.asBinder().linkToDeath(this, 0);
2660         }
2661 
unlinkToDeath()2662         public void unlinkToDeath() {
2663             mConnection.asBinder().unlinkToDeath(this, 0);
2664         }
2665 
2666         @Override
binderDied()2667         public void binderDied() {
2668             unlinkToDeath();
2669             synchronized (mLock) {
2670                 removeAccessibilityInteractionConnectionLocked(mWindowId, mUserId);
2671             }
2672         }
2673     }
2674 
2675     //TODO remove after refactoring KeyEventDispatcherTest
2676     final class MainHandler extends Handler {
2677         public static final int MSG_SEND_KEY_EVENT_TO_INPUT_FILTER = 8;
2678 
MainHandler(Looper looper)2679         public MainHandler(Looper looper) {
2680             super(looper);
2681         }
2682 
2683         @Override
handleMessage(Message msg)2684         public void handleMessage(Message msg) {
2685             if (msg.what == MSG_SEND_KEY_EVENT_TO_INPUT_FILTER) {
2686                 KeyEvent event = (KeyEvent) msg.obj;
2687                 final int policyFlags = msg.arg1;
2688                 synchronized (mLock) {
2689                     if (mHasInputFilter && mInputFilter != null) {
2690                         mInputFilter.sendInputEvent(event, policyFlags);
2691                     }
2692                 }
2693                 event.recycle();
2694             }
2695         }
2696     }
2697 
clearAccessibilityFocus(IntSupplier windowId)2698     void clearAccessibilityFocus(IntSupplier windowId) {
2699         clearAccessibilityFocus(windowId.getAsInt());
2700     }
2701 
clearAccessibilityFocus(int windowId)2702     void clearAccessibilityFocus(int windowId) {
2703         getInteractionBridge().clearAccessibilityFocusNotLocked(windowId);
2704     }
2705 
findWindowTokenLocked(int windowId)2706     private IBinder findWindowTokenLocked(int windowId) {
2707         IBinder token = mGlobalWindowTokens.get(windowId);
2708         if (token != null) {
2709             return token;
2710         }
2711         return getCurrentUserStateLocked().mWindowTokens.get(windowId);
2712     }
2713 
findWindowIdLocked(IBinder token)2714     private int findWindowIdLocked(IBinder token) {
2715         final int globalIndex = mGlobalWindowTokens.indexOfValue(token);
2716         if (globalIndex >= 0) {
2717             return mGlobalWindowTokens.keyAt(globalIndex);
2718         }
2719         UserState userState = getCurrentUserStateLocked();
2720         final int userIndex = userState.mWindowTokens.indexOfValue(token);
2721         if (userIndex >= 0) {
2722             return userState.mWindowTokens.keyAt(userIndex);
2723         }
2724         return -1;
2725     }
2726 
notifyOutsideTouchIfNeeded(int targetWindowId, int action)2727     private void notifyOutsideTouchIfNeeded(int targetWindowId, int action) {
2728         if (action != ACTION_CLICK && action != ACTION_LONG_CLICK) {
2729             return;
2730         }
2731 
2732         final List<Integer> outsideWindowsIds;
2733         final List<RemoteAccessibilityConnection> connectionList = new ArrayList<>();
2734         synchronized (mLock) {
2735             outsideWindowsIds = mSecurityPolicy.getWatchOutsideTouchWindowIdLocked(targetWindowId);
2736             for (int i = 0; i < outsideWindowsIds.size(); i++) {
2737                 connectionList.add(getConnectionLocked(outsideWindowsIds.get(i)));
2738             }
2739         }
2740         for (int i = 0; i < connectionList.size(); i++) {
2741             final RemoteAccessibilityConnection connection = connectionList.get(i);
2742             if (connection != null) {
2743                 try {
2744                     connection.getRemote().notifyOutsideTouch();
2745                 } catch (RemoteException re) {
2746                     if (DEBUG) {
2747                         Slog.e(LOG_TAG, "Error calling notifyOutsideTouch()");
2748                     }
2749                 }
2750             }
2751         }
2752     }
2753 
2754     @Override
ensureWindowsAvailableTimed()2755     public void ensureWindowsAvailableTimed() {
2756         synchronized (mLock) {
2757             if (mSecurityPolicy.mWindows != null) {
2758                 return;
2759             }
2760             // If we have no registered callback, update the state we
2761             // we may have to register one but it didn't happen yet.
2762             if (mWindowsForAccessibilityCallback == null) {
2763                 UserState userState = getCurrentUserStateLocked();
2764                 onUserStateChangedLocked(userState);
2765             }
2766             // We have no windows but do not care about them, done.
2767             if (mWindowsForAccessibilityCallback == null) {
2768                 return;
2769             }
2770 
2771             // Wait for the windows with a timeout.
2772             final long startMillis = SystemClock.uptimeMillis();
2773             while (mSecurityPolicy.mWindows == null) {
2774                 final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
2775                 final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis;
2776                 if (remainMillis <= 0) {
2777                     return;
2778                 }
2779                 try {
2780                     mLock.wait(remainMillis);
2781                 } catch (InterruptedException ie) {
2782                     /* ignore */
2783                 }
2784             }
2785         }
2786     }
2787 
2788     @Override
getMagnificationController()2789     public MagnificationController getMagnificationController() {
2790         synchronized (mLock) {
2791             if (mMagnificationController == null) {
2792                 mMagnificationController = new MagnificationController(mContext, this, mLock);
2793                 mMagnificationController.setUserId(mCurrentUserId);
2794             }
2795             return mMagnificationController;
2796         }
2797     }
2798 
2799     @Override
performAccessibilityAction(int resolvedWindowId, long accessibilityNodeId, int action, Bundle arguments, int interactionId, IAccessibilityInteractionConnectionCallback callback, int fetchFlags, long interrogatingTid)2800     public boolean performAccessibilityAction(int resolvedWindowId,
2801             long accessibilityNodeId, int action, Bundle arguments, int interactionId,
2802             IAccessibilityInteractionConnectionCallback callback, int fetchFlags,
2803             long interrogatingTid) {
2804         RemoteAccessibilityConnection connection;
2805         IBinder activityToken = null;
2806         synchronized (mLock) {
2807             connection = getConnectionLocked(resolvedWindowId);
2808             if (connection == null)  {
2809                 return false;
2810             }
2811             final boolean isA11yFocusAction = (action == ACTION_ACCESSIBILITY_FOCUS)
2812                     || (action == ACTION_CLEAR_ACCESSIBILITY_FOCUS);
2813             final AccessibilityWindowInfo a11yWindowInfo =
2814                     mSecurityPolicy.findA11yWindowInfoById(resolvedWindowId);
2815             if (!isA11yFocusAction) {
2816                 final WindowInfo windowInfo =
2817                         mSecurityPolicy.findWindowInfoById(resolvedWindowId);
2818                 if (windowInfo != null) activityToken = windowInfo.activityToken;
2819             }
2820             if ((a11yWindowInfo != null) && a11yWindowInfo.isInPictureInPictureMode()
2821                     && (mPictureInPictureActionReplacingConnection != null) && !isA11yFocusAction) {
2822                 connection = mPictureInPictureActionReplacingConnection;
2823             }
2824         }
2825         final int interrogatingPid = Binder.getCallingPid();
2826         final long identityToken = Binder.clearCallingIdentity();
2827         try {
2828             // Regardless of whether or not the action succeeds, it was generated by an
2829             // accessibility service that is driven by user actions, so note user activity.
2830             mPowerManager.userActivity(SystemClock.uptimeMillis(),
2831                     PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);
2832 
2833             notifyOutsideTouchIfNeeded(resolvedWindowId, action);
2834             if (activityToken != null) {
2835                 LocalServices.getService(ActivityTaskManagerInternal.class)
2836                         .setFocusedActivity(activityToken);
2837             }
2838             connection.mConnection.performAccessibilityAction(accessibilityNodeId, action,
2839                     arguments, interactionId, callback, fetchFlags, interrogatingPid,
2840                     interrogatingTid);
2841         } catch (RemoteException re) {
2842             if (DEBUG) {
2843                 Slog.e(LOG_TAG, "Error calling performAccessibilityAction: " + re);
2844             }
2845             return false;
2846         } finally {
2847             Binder.restoreCallingIdentity(identityToken);
2848         }
2849         return true;
2850     }
2851 
2852     @Override
getConnectionLocked(int windowId)2853     public RemoteAccessibilityConnection getConnectionLocked(int windowId) {
2854         if (DEBUG) {
2855             Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId);
2856         }
2857         RemoteAccessibilityConnection connection =
2858                 mGlobalInteractionConnections.get(windowId);
2859         if (connection == null) {
2860             connection = getCurrentUserStateLocked().mInteractionConnections.get(windowId);
2861         }
2862         if (connection != null && connection.mConnection != null) {
2863             return connection;
2864         }
2865         if (DEBUG) {
2866             Slog.e(LOG_TAG, "No interaction connection to window: " + windowId);
2867         }
2868         return null;
2869     }
2870 
2871     @Override
replaceCallbackIfNeeded( IAccessibilityInteractionConnectionCallback originalCallback, int resolvedWindowId, int interactionId, int interrogatingPid, long interrogatingTid)2872     public IAccessibilityInteractionConnectionCallback replaceCallbackIfNeeded(
2873             IAccessibilityInteractionConnectionCallback originalCallback,
2874             int resolvedWindowId, int interactionId, int interrogatingPid,
2875             long interrogatingTid) {
2876         AccessibilityWindowInfo windowInfo =
2877                 mSecurityPolicy.findA11yWindowInfoById(resolvedWindowId);
2878         if ((windowInfo == null) || !windowInfo.isInPictureInPictureMode()
2879                 || (mPictureInPictureActionReplacingConnection == null)) {
2880             return originalCallback;
2881         }
2882         return new ActionReplacingCallback(originalCallback,
2883                 mPictureInPictureActionReplacingConnection.mConnection, interactionId,
2884                 interrogatingPid, interrogatingTid);
2885     }
2886 
2887     @Override
onClientChangeLocked(boolean serviceInfoChanged)2888     public void onClientChangeLocked(boolean serviceInfoChanged) {
2889         AccessibilityManagerService.UserState userState = getUserStateLocked(mCurrentUserId);
2890         onUserStateChangedLocked(userState);
2891         if (serviceInfoChanged) {
2892             scheduleNotifyClientsOfServicesStateChangeLocked(userState);
2893         }
2894     }
2895 
2896     @Override
onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)2897     public void onShellCommand(FileDescriptor in, FileDescriptor out,
2898             FileDescriptor err, String[] args, ShellCallback callback,
2899             ResultReceiver resultReceiver) {
2900         new AccessibilityShellCommand(this).exec(this, in, out, err, args,
2901                 callback, resultReceiver);
2902     }
2903 
2904     final class WindowsForAccessibilityCallback implements
2905             WindowManagerInternal.WindowsForAccessibilityCallback {
2906 
2907         @Override
onWindowsForAccessibilityChanged(List<WindowInfo> windows)2908         public void onWindowsForAccessibilityChanged(List<WindowInfo> windows) {
2909             synchronized (mLock) {
2910                 if (DEBUG) {
2911                     Slog.i(LOG_TAG, "Windows changed: " + windows);
2912                 }
2913 
2914                 // Let the policy update the focused and active windows.
2915                 mSecurityPolicy.updateWindowsLocked(windows);
2916 
2917                 // Someone may be waiting for the windows - advertise it.
2918                 mLock.notifyAll();
2919             }
2920         }
2921 
populateReportedWindowLocked(WindowInfo window)2922         private AccessibilityWindowInfo populateReportedWindowLocked(WindowInfo window) {
2923             final int windowId = findWindowIdLocked(window.token);
2924             if (windowId < 0) {
2925                 return null;
2926             }
2927 
2928             AccessibilityWindowInfo reportedWindow = AccessibilityWindowInfo.obtain();
2929 
2930             reportedWindow.setId(windowId);
2931             reportedWindow.setType(getTypeForWindowManagerWindowType(window.type));
2932             reportedWindow.setLayer(window.layer);
2933             reportedWindow.setFocused(window.focused);
2934             reportedWindow.setBoundsInScreen(window.boundsInScreen);
2935             reportedWindow.setTitle(window.title);
2936             reportedWindow.setAnchorId(window.accessibilityIdOfAnchor);
2937             reportedWindow.setPictureInPicture(window.inPictureInPicture);
2938 
2939             final int parentId = findWindowIdLocked(window.parentToken);
2940             if (parentId >= 0) {
2941                 reportedWindow.setParentId(parentId);
2942             }
2943 
2944             if (window.childTokens != null) {
2945                 final int childCount = window.childTokens.size();
2946                 for (int i = 0; i < childCount; i++) {
2947                     IBinder childToken = window.childTokens.get(i);
2948                     final int childId = findWindowIdLocked(childToken);
2949                     if (childId >= 0) {
2950                         reportedWindow.addChild(childId);
2951                     }
2952                 }
2953             }
2954 
2955             return reportedWindow;
2956         }
2957 
getTypeForWindowManagerWindowType(int windowType)2958         private int getTypeForWindowManagerWindowType(int windowType) {
2959             switch (windowType) {
2960                 case WindowManager.LayoutParams.TYPE_APPLICATION:
2961                 case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA:
2962                 case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL:
2963                 case WindowManager.LayoutParams.TYPE_APPLICATION_STARTING:
2964                 case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL:
2965                 case WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL:
2966                 case WindowManager.LayoutParams.TYPE_BASE_APPLICATION:
2967                 case WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION:
2968                 case WindowManager.LayoutParams.TYPE_PHONE:
2969                 case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE:
2970                 case WindowManager.LayoutParams.TYPE_TOAST:
2971                 case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG: {
2972                     return AccessibilityWindowInfo.TYPE_APPLICATION;
2973                 }
2974 
2975                 case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
2976                 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: {
2977                     return AccessibilityWindowInfo.TYPE_INPUT_METHOD;
2978                 }
2979 
2980                 case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG:
2981                 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
2982                 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL:
2983                 case WindowManager.LayoutParams.TYPE_SEARCH_BAR:
2984                 case WindowManager.LayoutParams.TYPE_STATUS_BAR:
2985                 case WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL:
2986                 case WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL:
2987                 case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY:
2988                 case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
2989                 case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
2990                 case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
2991                 case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
2992                 case WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY:
2993                 case WindowManager.LayoutParams.TYPE_SCREENSHOT: {
2994                     return AccessibilityWindowInfo.TYPE_SYSTEM;
2995                 }
2996 
2997                 case WindowManager.LayoutParams.TYPE_DOCK_DIVIDER: {
2998                     return AccessibilityWindowInfo.TYPE_SPLIT_SCREEN_DIVIDER;
2999                 }
3000 
3001                 case TYPE_ACCESSIBILITY_OVERLAY: {
3002                     return AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY;
3003                 }
3004 
3005                 default: {
3006                     return -1;
3007                 }
3008             }
3009         }
3010     }
3011 
3012     private final class InteractionBridge {
3013         private final ComponentName COMPONENT_NAME =
3014                 new ComponentName("com.android.server.accessibility", "InteractionBridge");
3015 
3016         private final Display mDefaultDisplay;
3017         private final int mConnectionId;
3018         private final AccessibilityInteractionClient mClient;
3019 
InteractionBridge()3020         public InteractionBridge() {
3021             final AccessibilityServiceInfo info = new AccessibilityServiceInfo();
3022             info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
3023             info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
3024             info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
3025             final UserState userState;
3026             synchronized (mLock) {
3027                 userState = getCurrentUserStateLocked();
3028             }
3029             AccessibilityServiceConnection service = new AccessibilityServiceConnection(
3030                     userState, mContext,
3031                     COMPONENT_NAME, info, sIdCounter++, mMainHandler, mLock, mSecurityPolicy,
3032                     AccessibilityManagerService.this, mWindowManagerService,
3033                     mGlobalActionPerformer, mActivityTaskManagerService) {
3034                 @Override
3035                 public boolean supportsFlagForNotImportantViews(AccessibilityServiceInfo info) {
3036                     return true;
3037                 }
3038             };
3039 
3040             mConnectionId = service.mId;
3041 
3042             mClient = AccessibilityInteractionClient.getInstance();
3043             mClient.addConnection(mConnectionId, service);
3044 
3045             //TODO: (multi-display) We need to support multiple displays.
3046             DisplayManager displayManager = (DisplayManager)
3047                     mContext.getSystemService(Context.DISPLAY_SERVICE);
3048             mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
3049         }
3050 
clearAccessibilityFocusNotLocked(int windowId)3051         public void clearAccessibilityFocusNotLocked(int windowId) {
3052             RemoteAccessibilityConnection connection;
3053             synchronized (mLock) {
3054                 connection = getConnectionLocked(windowId);
3055                 if (connection == null) {
3056                     return;
3057                 }
3058             }
3059             try {
3060                 connection.getRemote().clearAccessibilityFocus();
3061             } catch (RemoteException re) {
3062                 if (DEBUG) {
3063                     Slog.e(LOG_TAG, "Error calling clearAccessibilityFocus()");
3064                 }
3065             }
3066         }
3067 
3068         /**
3069          * Perform an accessibility action on the view that currently has accessibility focus.
3070          * Has no effect if no item has accessibility focus, if the item with accessibility
3071          * focus does not expose the specified action, or if the action fails.
3072          *
3073          * @param action The action to perform.
3074          *
3075          * @return {@code true} if the action was performed. {@code false} if it was not.
3076          */
performActionOnAccessibilityFocusedItemNotLocked( AccessibilityNodeInfo.AccessibilityAction action)3077         public boolean performActionOnAccessibilityFocusedItemNotLocked(
3078                 AccessibilityNodeInfo.AccessibilityAction action) {
3079             AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked();
3080             if ((focus == null) || !focus.getActionList().contains(action)) {
3081                 return false;
3082             }
3083             return focus.performAction(action.getId());
3084         }
3085 
getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint)3086         public boolean getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint) {
3087             AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked();
3088             if (focus == null) {
3089                 return false;
3090             }
3091 
3092             synchronized (mLock) {
3093                 Rect boundsInScreen = mTempRect;
3094                 focus.getBoundsInScreen(boundsInScreen);
3095 
3096                 // Apply magnification if needed.
3097                 MagnificationSpec spec = getCompatibleMagnificationSpecLocked(focus.getWindowId());
3098                 if (spec != null && !spec.isNop()) {
3099                     boundsInScreen.offset((int) -spec.offsetX, (int) -spec.offsetY);
3100                     boundsInScreen.scale(1 / spec.scale);
3101                 }
3102 
3103                 // Clip to the window bounds.
3104                 Rect windowBounds = mTempRect1;
3105                 getWindowBounds(focus.getWindowId(), windowBounds);
3106                 if (!boundsInScreen.intersect(windowBounds)) {
3107                     return false;
3108                 }
3109 
3110                 // Clip to the screen bounds.
3111                 Point screenSize = mTempPoint;
3112                 mDefaultDisplay.getRealSize(screenSize);
3113                 if (!boundsInScreen.intersect(0, 0, screenSize.x, screenSize.y)) {
3114                     return false;
3115                 }
3116 
3117                 outPoint.set(boundsInScreen.centerX(), boundsInScreen.centerY());
3118             }
3119 
3120             return true;
3121         }
3122 
getAccessibilityFocusNotLocked()3123         private AccessibilityNodeInfo getAccessibilityFocusNotLocked() {
3124             final int focusedWindowId;
3125             synchronized (mLock) {
3126                 focusedWindowId = mSecurityPolicy.mAccessibilityFocusedWindowId;
3127                 if (focusedWindowId == SecurityPolicy.INVALID_WINDOW_ID) {
3128                     return null;
3129                 }
3130             }
3131             return getAccessibilityFocusNotLocked(focusedWindowId);
3132         }
3133 
getAccessibilityFocusNotLocked(int windowId)3134         private AccessibilityNodeInfo getAccessibilityFocusNotLocked(int windowId) {
3135             return mClient.findFocus(mConnectionId,
3136                     windowId, AccessibilityNodeInfo.ROOT_NODE_ID,
3137                     AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
3138         }
3139     }
3140 
3141     public class SecurityPolicy {
3142         public static final int INVALID_WINDOW_ID = -1;
3143 
3144         private static final int KEEP_SOURCE_EVENT_TYPES = AccessibilityEvent.TYPE_VIEW_CLICKED
3145                 | AccessibilityEvent.TYPE_VIEW_FOCUSED
3146                 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
3147                 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
3148                 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
3149                 | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
3150                 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
3151                 | AccessibilityEvent.TYPE_WINDOWS_CHANGED
3152                 | AccessibilityEvent.TYPE_VIEW_SELECTED
3153                 | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
3154                 | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
3155                 | AccessibilityEvent.TYPE_VIEW_SCROLLED
3156                 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
3157                 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED
3158                 | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
3159 
3160         // In Z order top to bottom
3161         public List<AccessibilityWindowInfo> mWindows;
3162         public SparseArray<AccessibilityWindowInfo> mA11yWindowInfoById = new SparseArray<>();
3163         public SparseArray<WindowInfo> mWindowInfoById = new SparseArray<>();
3164 
3165         public int mActiveWindowId = INVALID_WINDOW_ID;
3166         public int mFocusedWindowId = INVALID_WINDOW_ID;
3167         public int mAccessibilityFocusedWindowId = INVALID_WINDOW_ID;
3168         public long mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
3169 
3170         private boolean mTouchInteractionInProgress;
3171         private boolean mHasWatchOutsideTouchWindow;
3172 
canDispatchAccessibilityEventLocked(AccessibilityEvent event)3173         private boolean canDispatchAccessibilityEventLocked(AccessibilityEvent event) {
3174             final int eventType = event.getEventType();
3175             switch (eventType) {
3176                 // All events that are for changes in a global window
3177                 // state should *always* be dispatched.
3178                 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
3179                 case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
3180                 case AccessibilityEvent.TYPE_ANNOUNCEMENT:
3181                 // All events generated by the user touching the
3182                 // screen should *always* be dispatched.
3183                 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START:
3184                 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END:
3185                 case AccessibilityEvent.TYPE_GESTURE_DETECTION_START:
3186                 case AccessibilityEvent.TYPE_GESTURE_DETECTION_END:
3187                 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START:
3188                 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END:
3189                 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER:
3190                 case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT:
3191                 // Also always dispatch the event that assist is reading context.
3192                 case AccessibilityEvent.TYPE_ASSIST_READING_CONTEXT:
3193                 // Also windows changing should always be anounced.
3194                 case AccessibilityEvent.TYPE_WINDOWS_CHANGED: {
3195                     return true;
3196                 }
3197                 // All events for changes in window content should be
3198                 // dispatched *only* if this window is one of the windows
3199                 // the accessibility layer reports which are windows
3200                 // that a sighted user can touch.
3201                 default: {
3202                     return isRetrievalAllowingWindowLocked(event.getWindowId());
3203                 }
3204             }
3205         }
3206 
isValidPackageForUid(String packageName, int uid)3207         private boolean isValidPackageForUid(String packageName, int uid) {
3208             final long token = Binder.clearCallingIdentity();
3209             try {
3210                 return uid == mPackageManager.getPackageUidAsUser(
3211                         packageName, UserHandle.getUserId(uid));
3212             } catch (PackageManager.NameNotFoundException e) {
3213                 return false;
3214             } finally {
3215                 Binder.restoreCallingIdentity(token);
3216             }
3217         }
3218 
resolveValidReportedPackageLocked(CharSequence packageName, int appId, int userId)3219         String resolveValidReportedPackageLocked(CharSequence packageName, int appId, int userId) {
3220             // Okay to pass no package
3221             if (packageName == null) {
3222                 return null;
3223             }
3224             // The system gets to pass any package
3225             if (appId == Process.SYSTEM_UID) {
3226                 return packageName.toString();
3227             }
3228             // Passing a package in your UID is fine
3229             final String packageNameStr = packageName.toString();
3230             final int resolvedUid = UserHandle.getUid(userId, appId);
3231             if (isValidPackageForUid(packageNameStr, resolvedUid)) {
3232                 return packageName.toString();
3233             }
3234             // Appwidget hosts get to pass packages for widgets they host
3235             if (mAppWidgetService != null && ArrayUtils.contains(mAppWidgetService
3236                             .getHostedWidgetPackages(resolvedUid), packageNameStr)) {
3237                 return packageName.toString();
3238             }
3239             // Otherwise, set the package to the first one in the UID
3240             final String[] packageNames = mPackageManager.getPackagesForUid(resolvedUid);
3241             if (ArrayUtils.isEmpty(packageNames)) {
3242                 return null;
3243             }
3244             // Okay, the caller reported a package it does not have access to.
3245             // Instead of crashing the caller for better backwards compatibility
3246             // we report the first package in the UID. Since most of the time apps
3247             // don't use shared user id, this will yield correct results and for
3248             // the edge case of using a shared user id we may report the wrong
3249             // package but this is fine since first, this is a cheating app and
3250             // second there is no way to get the correct package anyway.
3251             return packageNames[0];
3252         }
3253 
3254         /**
3255          * Get a list of package names an app may report, including any widget packages it owns.
3256          *
3257          * @param targetPackage The known valid target package
3258          * @param targetUid The uid of the target app
3259          * @return
3260          */
computeValidReportedPackages(String targetPackage, int targetUid)3261         String[] computeValidReportedPackages(String targetPackage, int targetUid) {
3262             if (UserHandle.getAppId(targetUid) == Process.SYSTEM_UID) {
3263                 // Empty array means any package is Okay
3264                 return EmptyArray.STRING;
3265             }
3266             // IMPORTANT: The target package is already vetted to be in the target UID
3267             String[] uidPackages = new String[]{targetPackage};
3268             // Appwidget hosts get to pass packages for widgets they host
3269             if (mAppWidgetService != null) {
3270                 final ArraySet<String> widgetPackages = mAppWidgetService
3271                         .getHostedWidgetPackages(targetUid);
3272                 if (widgetPackages != null && !widgetPackages.isEmpty()) {
3273                     final String[] validPackages = new String[uidPackages.length
3274                             + widgetPackages.size()];
3275                     System.arraycopy(uidPackages, 0, validPackages, 0, uidPackages.length);
3276                     final int widgetPackageCount = widgetPackages.size();
3277                     for (int i = 0; i < widgetPackageCount; i++) {
3278                         validPackages[uidPackages.length + i] = widgetPackages.valueAt(i);
3279                     }
3280                     return validPackages;
3281                 }
3282             }
3283             return uidPackages;
3284         }
3285 
clearWindowsLocked()3286         public void clearWindowsLocked() {
3287             List<WindowInfo> windows = Collections.emptyList();
3288             final int activeWindowId = mActiveWindowId;
3289             updateWindowsLocked(windows);
3290             mActiveWindowId = activeWindowId;
3291             mWindows = null;
3292         }
3293 
3294         /**
3295          * A callback when accessibility interaction client is removed.
3296          */
onAccessibilityClientRemovedLocked(int windowId)3297         public void onAccessibilityClientRemovedLocked(int windowId) {
3298             // Active window cannot update immediately, if windows callback is unregistered.
3299             // Update active window to invalid, when its a11y interaction client is removed.
3300             if (mWindowsForAccessibilityCallback == null && windowId >= 0
3301                     && mActiveWindowId == windowId) {
3302                 mActiveWindowId = INVALID_WINDOW_ID;
3303             }
3304         }
3305 
updateWindowsLocked(List<WindowInfo> windows)3306         public void updateWindowsLocked(List<WindowInfo> windows) {
3307             if (mWindows == null) {
3308                 mWindows = new ArrayList<>();
3309             }
3310 
3311             List<AccessibilityWindowInfo> oldWindowList = new ArrayList<>(mWindows);
3312             SparseArray<AccessibilityWindowInfo> oldWindowsById = mA11yWindowInfoById.clone();
3313 
3314             mWindows.clear();
3315             mA11yWindowInfoById.clear();
3316 
3317             for (int i = 0; i < mWindowInfoById.size(); i++) {
3318                 mWindowInfoById.valueAt(i).recycle();
3319             }
3320             mWindowInfoById.clear();
3321             mHasWatchOutsideTouchWindow = false;
3322 
3323             mFocusedWindowId = INVALID_WINDOW_ID;
3324             if (!mTouchInteractionInProgress) {
3325                 mActiveWindowId = INVALID_WINDOW_ID;
3326             }
3327 
3328             // If the active window goes away while the user is touch exploring we
3329             // reset the active window id and wait for the next hover event from
3330             // under the user's finger to determine which one is the new one. It
3331             // is possible that the finger is not moving and the input system
3332             // filters out such events.
3333             boolean activeWindowGone = true;
3334 
3335             final int windowCount = windows.size();
3336 
3337             // We'll clear accessibility focus if the window with focus is no longer visible to
3338             // accessibility services
3339             boolean shouldClearAccessibilityFocus =
3340                     mAccessibilityFocusedWindowId != INVALID_WINDOW_ID;
3341             if (windowCount > 0) {
3342                 for (int i = 0; i < windowCount; i++) {
3343                     final WindowInfo windowInfo = windows.get(i);
3344                     final AccessibilityWindowInfo window;
3345                     if (mWindowsForAccessibilityCallback != null) {
3346                         window = mWindowsForAccessibilityCallback
3347                                 .populateReportedWindowLocked(windowInfo);
3348                     } else {
3349                         window = null;
3350                     }
3351                     if (window != null) {
3352 
3353                         // Flip layers in list to be consistent with AccessibilityService#getWindows
3354                         window.setLayer(windowCount - 1 - window.getLayer());
3355 
3356                         final int windowId = window.getId();
3357                         if (window.isFocused()) {
3358                             mFocusedWindowId = windowId;
3359                             if (!mTouchInteractionInProgress) {
3360                                 mActiveWindowId = windowId;
3361                                 window.setActive(true);
3362                             } else if (windowId == mActiveWindowId) {
3363                                 activeWindowGone = false;
3364                             }
3365                         }
3366                         if (!mHasWatchOutsideTouchWindow && windowInfo.hasFlagWatchOutsideTouch) {
3367                             mHasWatchOutsideTouchWindow = true;
3368                         }
3369                         mWindows.add(window);
3370                         mA11yWindowInfoById.put(windowId, window);
3371                         mWindowInfoById.put(windowId, WindowInfo.obtain(windowInfo));
3372                     }
3373                 }
3374 
3375                 if (mTouchInteractionInProgress && activeWindowGone) {
3376                     mActiveWindowId = mFocusedWindowId;
3377                 }
3378 
3379                 // Focused window may change the active one, so set the
3380                 // active window once we decided which it is.
3381                 final int accessibilityWindowCount = mWindows.size();
3382                 for (int i = 0; i < accessibilityWindowCount; i++) {
3383                     final AccessibilityWindowInfo window = mWindows.get(i);
3384                     if (window.getId() == mActiveWindowId) {
3385                         window.setActive(true);
3386                     }
3387                     if (window.getId() == mAccessibilityFocusedWindowId) {
3388                         window.setAccessibilityFocused(true);
3389                         shouldClearAccessibilityFocus = false;
3390                     }
3391                 }
3392             }
3393 
3394             sendEventsForChangedWindowsLocked(oldWindowList, oldWindowsById);
3395 
3396             final int oldWindowCount = oldWindowList.size();
3397             for (int i = oldWindowCount - 1; i >= 0; i--) {
3398                 oldWindowList.remove(i).recycle();
3399             }
3400 
3401             if (shouldClearAccessibilityFocus) {
3402                 mMainHandler.sendMessage(obtainMessage(
3403                         AccessibilityManagerService::clearAccessibilityFocus,
3404                         AccessibilityManagerService.this,
3405                         box(mAccessibilityFocusedWindowId)));
3406             }
3407         }
3408 
sendEventsForChangedWindowsLocked(List<AccessibilityWindowInfo> oldWindows, SparseArray<AccessibilityWindowInfo> oldWindowsById)3409         private void sendEventsForChangedWindowsLocked(List<AccessibilityWindowInfo> oldWindows,
3410                 SparseArray<AccessibilityWindowInfo> oldWindowsById) {
3411             List<AccessibilityEvent> events = new ArrayList<>();
3412             // Send events for all removed windows
3413             final int oldWindowsCount = oldWindows.size();
3414             for (int i = 0; i < oldWindowsCount; i++) {
3415                 final AccessibilityWindowInfo window = oldWindows.get(i);
3416                 if (mA11yWindowInfoById.get(window.getId()) == null) {
3417                     events.add(AccessibilityEvent.obtainWindowsChangedEvent(
3418                             window.getId(), AccessibilityEvent.WINDOWS_CHANGE_REMOVED));
3419                 }
3420             }
3421 
3422             // Look for other changes
3423             int oldWindowIndex = 0;
3424             final int newWindowCount = mWindows.size();
3425             for (int i = 0; i < newWindowCount; i++) {
3426                 final AccessibilityWindowInfo newWindow = mWindows.get(i);
3427                 final AccessibilityWindowInfo oldWindow = oldWindowsById.get(newWindow.getId());
3428                 if (oldWindow == null) {
3429                     events.add(AccessibilityEvent.obtainWindowsChangedEvent(
3430                             newWindow.getId(), AccessibilityEvent.WINDOWS_CHANGE_ADDED));
3431                 } else {
3432                     int changes = newWindow.differenceFrom(oldWindow);
3433                     if (changes !=  0) {
3434                         events.add(AccessibilityEvent.obtainWindowsChangedEvent(
3435                                 newWindow.getId(), changes));
3436                     }
3437                 }
3438             }
3439 
3440             final int numEvents = events.size();
3441             for (int i = 0; i < numEvents; i++) {
3442                 sendAccessibilityEventLocked(events.get(i), mCurrentUserId);
3443             }
3444         }
3445 
computePartialInteractiveRegionForWindowLocked(int windowId, Region outRegion)3446         public boolean computePartialInteractiveRegionForWindowLocked(int windowId,
3447                 Region outRegion) {
3448             if (mWindows == null) {
3449                 return false;
3450             }
3451 
3452             // Windows are ordered in z order so start from the bottom and find
3453             // the window of interest. After that all windows that cover it should
3454             // be subtracted from the resulting region. Note that for accessibility
3455             // we are returning only interactive windows.
3456             Region windowInteractiveRegion = null;
3457             boolean windowInteractiveRegionChanged = false;
3458 
3459             final int windowCount = mWindows.size();
3460             for (int i = windowCount - 1; i >= 0; i--) {
3461                 AccessibilityWindowInfo currentWindow = mWindows.get(i);
3462                 if (windowInteractiveRegion == null) {
3463                     if (currentWindow.getId() == windowId) {
3464                         Rect currentWindowBounds = mTempRect;
3465                         currentWindow.getBoundsInScreen(currentWindowBounds);
3466                         outRegion.set(currentWindowBounds);
3467                         windowInteractiveRegion = outRegion;
3468                         continue;
3469                     }
3470                 } else if (currentWindow.getType()
3471                         != AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY) {
3472                     Rect currentWindowBounds = mTempRect;
3473                     currentWindow.getBoundsInScreen(currentWindowBounds);
3474                     if (windowInteractiveRegion.op(currentWindowBounds, Region.Op.DIFFERENCE)) {
3475                         windowInteractiveRegionChanged = true;
3476                     }
3477                 }
3478             }
3479 
3480             return windowInteractiveRegionChanged;
3481         }
3482 
updateEventSourceLocked(AccessibilityEvent event)3483         public void updateEventSourceLocked(AccessibilityEvent event) {
3484             if ((event.getEventType() & KEEP_SOURCE_EVENT_TYPES) == 0) {
3485                 event.setSource((View) null);
3486             }
3487         }
3488 
updateActiveAndAccessibilityFocusedWindowLocked(int windowId, long nodeId, int eventType, int eventAction)3489         public void updateActiveAndAccessibilityFocusedWindowLocked(int windowId, long nodeId,
3490                 int eventType, int eventAction) {
3491             // The active window is either the window that has input focus or
3492             // the window that the user is currently touching. If the user is
3493             // touching a window that does not have input focus as soon as the
3494             // the user stops touching that window the focused window becomes
3495             // the active one. Here we detect the touched window and make it
3496             // active. In updateWindowsLocked() we update the focused window
3497             // and if the user is not touching the screen, we make the focused
3498             // window the active one.
3499             switch (eventType) {
3500                 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: {
3501                     // If no service has the capability to introspect screen,
3502                     // we do not register callback in the window manager for
3503                     // window changes, so we have to ask the window manager
3504                     // what the focused window is to update the active one.
3505                     // The active window also determined events from which
3506                     // windows are delivered.
3507                     synchronized (mLock) {
3508                         if (mWindowsForAccessibilityCallback == null) {
3509                             mFocusedWindowId = getFocusedWindowId();
3510                             if (windowId == mFocusedWindowId) {
3511                                 mActiveWindowId = windowId;
3512                             }
3513                         }
3514                     }
3515                 } break;
3516 
3517                 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: {
3518                     // Do not allow delayed hover events to confuse us
3519                     // which the active window is.
3520                     synchronized (mLock) {
3521                         if (mTouchInteractionInProgress && mActiveWindowId != windowId) {
3522                             setActiveWindowLocked(windowId);
3523                         }
3524                     }
3525                 } break;
3526 
3527                 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
3528                     synchronized (mLock) {
3529                         if (mAccessibilityFocusedWindowId != windowId) {
3530                             mMainHandler.sendMessage(obtainMessage(
3531                                     AccessibilityManagerService::clearAccessibilityFocus,
3532                                     AccessibilityManagerService.this,
3533                                     box(mAccessibilityFocusedWindowId)));
3534                             mSecurityPolicy.setAccessibilityFocusedWindowLocked(windowId);
3535                             mAccessibilityFocusNodeId = nodeId;
3536                         }
3537                     }
3538                 } break;
3539 
3540                 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
3541                     synchronized (mLock) {
3542                         if (mAccessibilityFocusNodeId == nodeId) {
3543                             mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
3544                         }
3545                         // Clear the window with focus if it no longer has focus and we aren't
3546                         // just moving focus from one view to the other in the same window
3547                         if ((mAccessibilityFocusNodeId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID)
3548                                 && (mAccessibilityFocusedWindowId == windowId)
3549                                 && (eventAction != AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS)
3550                                 ) {
3551                             mAccessibilityFocusedWindowId = INVALID_WINDOW_ID;
3552                         }
3553                     }
3554                 } break;
3555             }
3556         }
3557 
onTouchInteractionStart()3558         public void onTouchInteractionStart() {
3559             synchronized (mLock) {
3560                 mTouchInteractionInProgress = true;
3561             }
3562         }
3563 
onTouchInteractionEnd()3564         public void onTouchInteractionEnd() {
3565             synchronized (mLock) {
3566                 mTouchInteractionInProgress = false;
3567                 // We want to set the active window to be current immediately
3568                 // after the user has stopped touching the screen since if the
3569                 // user types with the IME he should get a feedback for the
3570                 // letter typed in the text view which is in the input focused
3571                 // window. Note that we always deliver hover accessibility events
3572                 // (they are a result of user touching the screen) so change of
3573                 // the active window before all hover accessibility events from
3574                 // the touched window are delivered is fine.
3575                 final int oldActiveWindow = mSecurityPolicy.mActiveWindowId;
3576                 setActiveWindowLocked(mFocusedWindowId);
3577 
3578                 // If there is no service that can operate with active windows
3579                 // we keep accessibility focus behavior to constrain it only in
3580                 // the active window. Look at updateAccessibilityFocusBehaviorLocked
3581                 // for details.
3582                 if (oldActiveWindow != mSecurityPolicy.mActiveWindowId
3583                         && mAccessibilityFocusedWindowId == oldActiveWindow
3584                         && getCurrentUserStateLocked().mAccessibilityFocusOnlyInActiveWindow) {
3585                     mMainHandler.sendMessage(obtainMessage(
3586                             AccessibilityManagerService::clearAccessibilityFocus,
3587                             AccessibilityManagerService.this, box(oldActiveWindow)));
3588                 }
3589             }
3590         }
3591 
box(int value)3592         private IntSupplier box(int value) {
3593             return PooledLambda.obtainSupplier(value).recycleOnUse();
3594         }
3595 
getActiveWindowId()3596         public int getActiveWindowId() {
3597             if (mActiveWindowId == INVALID_WINDOW_ID && !mTouchInteractionInProgress) {
3598                 mActiveWindowId = getFocusedWindowId();
3599             }
3600             return mActiveWindowId;
3601         }
3602 
setActiveWindowLocked(int windowId)3603         private void setActiveWindowLocked(int windowId) {
3604             if (mActiveWindowId != windowId) {
3605                 sendAccessibilityEventLocked(
3606                         AccessibilityEvent.obtainWindowsChangedEvent(
3607                                 mActiveWindowId, AccessibilityEvent.WINDOWS_CHANGE_ACTIVE),
3608                         mCurrentUserId);
3609 
3610                 mActiveWindowId = windowId;
3611                 if (mWindows != null) {
3612                     final int windowCount = mWindows.size();
3613                     for (int i = 0; i < windowCount; i++) {
3614                         AccessibilityWindowInfo window = mWindows.get(i);
3615                         if (window.getId() == windowId) {
3616                             window.setActive(true);
3617                             sendAccessibilityEventLocked(
3618                                     AccessibilityEvent.obtainWindowsChangedEvent(windowId,
3619                                             AccessibilityEvent.WINDOWS_CHANGE_ACTIVE),
3620                                     mCurrentUserId);
3621                         } else {
3622                             window.setActive(false);
3623                         }
3624                     }
3625                 }
3626             }
3627         }
3628 
setAccessibilityFocusedWindowLocked(int windowId)3629         private void setAccessibilityFocusedWindowLocked(int windowId) {
3630             if (mAccessibilityFocusedWindowId != windowId) {
3631                 sendAccessibilityEventLocked(
3632                         AccessibilityEvent.obtainWindowsChangedEvent(
3633                                 mAccessibilityFocusedWindowId,
3634                                 WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED),
3635                         mCurrentUserId);
3636 
3637                 mAccessibilityFocusedWindowId = windowId;
3638                 if (mWindows != null) {
3639                     final int windowCount = mWindows.size();
3640                     for (int i = 0; i < windowCount; i++) {
3641                         AccessibilityWindowInfo window = mWindows.get(i);
3642                         if (window.getId() == windowId) {
3643                             window.setAccessibilityFocused(true);
3644                             sendAccessibilityEventLocked(
3645                                     AccessibilityEvent.obtainWindowsChangedEvent(
3646                                             windowId, WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED),
3647                                     mCurrentUserId);
3648 
3649                         } else {
3650                             window.setAccessibilityFocused(false);
3651                         }
3652                     }
3653                 }
3654             }
3655         }
3656 
canGetAccessibilityNodeInfoLocked( AbstractAccessibilityServiceConnection service, int windowId)3657         public boolean canGetAccessibilityNodeInfoLocked(
3658                 AbstractAccessibilityServiceConnection service, int windowId) {
3659             return canRetrieveWindowContentLocked(service)
3660                     && isRetrievalAllowingWindowLocked(windowId);
3661         }
3662 
canRetrieveWindowsLocked(AbstractAccessibilityServiceConnection service)3663         public boolean canRetrieveWindowsLocked(AbstractAccessibilityServiceConnection service) {
3664             return canRetrieveWindowContentLocked(service) && service.mRetrieveInteractiveWindows;
3665         }
3666 
canRetrieveWindowContentLocked(AbstractAccessibilityServiceConnection service)3667         public boolean canRetrieveWindowContentLocked(AbstractAccessibilityServiceConnection service) {
3668             return (service.getCapabilities()
3669                     & AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0;
3670         }
3671 
canControlMagnification(AbstractAccessibilityServiceConnection service)3672         public boolean canControlMagnification(AbstractAccessibilityServiceConnection service) {
3673             return (service.getCapabilities()
3674                     & AccessibilityServiceInfo.CAPABILITY_CAN_CONTROL_MAGNIFICATION) != 0;
3675         }
3676 
canPerformGestures(AccessibilityServiceConnection service)3677         public boolean canPerformGestures(AccessibilityServiceConnection service) {
3678             return (service.getCapabilities()
3679                     & AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0;
3680         }
3681 
canCaptureFingerprintGestures(AccessibilityServiceConnection service)3682         public boolean canCaptureFingerprintGestures(AccessibilityServiceConnection service) {
3683             return (service.getCapabilities()
3684                     & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES) != 0;
3685         }
3686 
resolveProfileParentLocked(int userId)3687         private int resolveProfileParentLocked(int userId) {
3688             if (userId != mCurrentUserId) {
3689                 final long identity = Binder.clearCallingIdentity();
3690                 try {
3691                     UserInfo parent = mUserManager.getProfileParent(userId);
3692                     if (parent != null) {
3693                         return parent.getUserHandle().getIdentifier();
3694                     }
3695                 } finally {
3696                     Binder.restoreCallingIdentity(identity);
3697                 }
3698             }
3699             return userId;
3700         }
3701 
resolveCallingUserIdEnforcingPermissionsLocked(int userId)3702         public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) {
3703             final int callingUid = Binder.getCallingUid();
3704             if (callingUid == 0
3705                     || callingUid == Process.SYSTEM_UID
3706                     || callingUid == Process.SHELL_UID) {
3707                 if (userId == UserHandle.USER_CURRENT
3708                         || userId == UserHandle.USER_CURRENT_OR_SELF) {
3709                     return mCurrentUserId;
3710                 }
3711                 return resolveProfileParentLocked(userId);
3712             }
3713             final int callingUserId = UserHandle.getUserId(callingUid);
3714             if (callingUserId == userId) {
3715                 return resolveProfileParentLocked(userId);
3716             }
3717             final int callingUserParentId = resolveProfileParentLocked(callingUserId);
3718             if (callingUserParentId == mCurrentUserId &&
3719                     (userId == UserHandle.USER_CURRENT
3720                             || userId == UserHandle.USER_CURRENT_OR_SELF)) {
3721                 return mCurrentUserId;
3722             }
3723             if (!hasPermission(Manifest.permission.INTERACT_ACROSS_USERS)
3724                     && !hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) {
3725                 throw new SecurityException("Call from user " + callingUserId + " as user "
3726                         + userId + " without permission INTERACT_ACROSS_USERS or "
3727                         + "INTERACT_ACROSS_USERS_FULL not allowed.");
3728             }
3729             if (userId == UserHandle.USER_CURRENT
3730                     || userId == UserHandle.USER_CURRENT_OR_SELF) {
3731                 return mCurrentUserId;
3732             }
3733             throw new IllegalArgumentException("Calling user can be changed to only "
3734                     + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF.");
3735         }
3736 
isCallerInteractingAcrossUsers(int userId)3737         public boolean isCallerInteractingAcrossUsers(int userId) {
3738             final int callingUid = Binder.getCallingUid();
3739             return (Binder.getCallingPid() == android.os.Process.myPid()
3740                     || callingUid == Process.SHELL_UID
3741                     || userId == UserHandle.USER_CURRENT
3742                     || userId == UserHandle.USER_CURRENT_OR_SELF);
3743         }
3744 
isRetrievalAllowingWindowLocked(int windowId)3745         private boolean isRetrievalAllowingWindowLocked(int windowId) {
3746             // The system gets to interact with any window it wants.
3747             if (Binder.getCallingUid() == Process.SYSTEM_UID) {
3748                 return true;
3749             }
3750             if (Binder.getCallingUid() == Process.SHELL_UID) {
3751                 if (!isShellAllowedToRetrieveWindowLocked(windowId)) {
3752                     return false;
3753                 }
3754             }
3755             if (windowId == mActiveWindowId) {
3756                 return true;
3757             }
3758             return findA11yWindowInfoById(windowId) != null;
3759         }
3760 
isShellAllowedToRetrieveWindowLocked(int windowId)3761         private boolean isShellAllowedToRetrieveWindowLocked(int windowId) {
3762             long token = Binder.clearCallingIdentity();
3763             try {
3764                 IBinder windowToken = findWindowTokenLocked(windowId);
3765                 if (windowToken == null) {
3766                     return false;
3767                 }
3768                 int userId = mWindowManagerService.getWindowOwnerUserId(windowToken);
3769                 if (userId == UserHandle.USER_NULL) {
3770                     return false;
3771                 }
3772                 return !mUserManager.hasUserRestriction(
3773                         UserManager.DISALLOW_DEBUGGING_FEATURES, UserHandle.of(userId));
3774             } finally {
3775                 Binder.restoreCallingIdentity(token);
3776             }
3777         }
3778 
findA11yWindowInfoById(int windowId)3779         public AccessibilityWindowInfo findA11yWindowInfoById(int windowId) {
3780             return mA11yWindowInfoById.get(windowId);
3781         }
3782 
findWindowInfoById(int windowId)3783         private WindowInfo findWindowInfoById(int windowId) {
3784             return mWindowInfoById.get(windowId);
3785         }
3786 
getWatchOutsideTouchWindowIdLocked(int targetWindowId)3787         private List<Integer> getWatchOutsideTouchWindowIdLocked(int targetWindowId) {
3788             final WindowInfo targetWindow = mWindowInfoById.get(targetWindowId);
3789             if (targetWindow != null && mHasWatchOutsideTouchWindow) {
3790                 final List<Integer> outsideWindowsId = new ArrayList<>();
3791                 for (int i = 0; i < mWindowInfoById.size(); i++) {
3792                     WindowInfo window = mWindowInfoById.valueAt(i);
3793                     if (window != null && window.layer < targetWindow.layer
3794                             && window.hasFlagWatchOutsideTouch) {
3795                         outsideWindowsId.add(mWindowInfoById.keyAt(i));
3796                     }
3797                 }
3798                 return outsideWindowsId;
3799             }
3800             return Collections.emptyList();
3801         }
3802 
getPictureInPictureWindow()3803         private AccessibilityWindowInfo getPictureInPictureWindow() {
3804             if (mWindows != null) {
3805                 final int windowCount = mWindows.size();
3806                 for (int i = 0; i < windowCount; i++) {
3807                     AccessibilityWindowInfo window = mWindows.get(i);
3808                     if (window.isInPictureInPictureMode()) {
3809                         return window;
3810                     }
3811                 }
3812             }
3813             return null;
3814         }
3815 
enforceCallingPermission(String permission, String function)3816         private void enforceCallingPermission(String permission, String function) {
3817             if (OWN_PROCESS_ID == Binder.getCallingPid()) {
3818                 return;
3819             }
3820             if (!hasPermission(permission)) {
3821                 throw new SecurityException("You do not have " + permission
3822                         + " required to call " + function + " from pid="
3823                         + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
3824             }
3825         }
3826 
hasPermission(String permission)3827         private boolean hasPermission(String permission) {
3828             return mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED;
3829         }
3830 
getFocusedWindowId()3831         private int getFocusedWindowId() {
3832             IBinder token = mWindowManagerService.getFocusedWindowToken();
3833             synchronized (mLock) {
3834                 return findWindowIdLocked(token);
3835             }
3836         }
3837 
checkAccessibilityAccess(AbstractAccessibilityServiceConnection service)3838         public boolean checkAccessibilityAccess(AbstractAccessibilityServiceConnection service) {
3839             final String packageName = service.getComponentName().getPackageName();
3840             final ResolveInfo resolveInfo = service.getServiceInfo().getResolveInfo();
3841 
3842             if (resolveInfo == null) {
3843                 // For InteractionBridge and UiAutomation
3844                 return true;
3845             }
3846 
3847             final int uid = resolveInfo.serviceInfo.applicationInfo.uid;
3848             final long identityToken = Binder.clearCallingIdentity();
3849             try {
3850                 // For the caller is system, just block the data to a11y services.
3851                 if (OWN_PROCESS_ID == Binder.getCallingPid()) {
3852                     return mAppOpsManager.noteOpNoThrow(AppOpsManager.OPSTR_ACCESS_ACCESSIBILITY,
3853                             uid, packageName) == AppOpsManager.MODE_ALLOWED;
3854                 }
3855 
3856                 return mAppOpsManager.noteOp(AppOpsManager.OPSTR_ACCESS_ACCESSIBILITY,
3857                         uid, packageName) == AppOpsManager.MODE_ALLOWED;
3858             } finally {
3859                 Binder.restoreCallingIdentity(identityToken);
3860             }
3861         }
3862     }
3863 
3864     /**
3865      * Gets all currently valid logical displays.
3866      *
3867      * @return An array list containing all valid logical displays.
3868      */
getValidDisplayList()3869     public ArrayList<Display> getValidDisplayList() {
3870         return mA11yDisplayListener.getValidDisplayList();
3871     }
3872 
3873     /**
3874      * A Utility class to handle display state.
3875      */
3876     public class AccessibilityDisplayListener implements DisplayManager.DisplayListener {
3877         private final DisplayManager mDisplayManager;
3878         private final ArrayList<Display> mDisplaysList = new ArrayList<>();
3879 
AccessibilityDisplayListener(Context context, MainHandler handler)3880         AccessibilityDisplayListener(Context context, MainHandler handler) {
3881             mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
3882             mDisplayManager.registerDisplayListener(this, handler);
3883             initializeDisplayList();
3884         }
3885 
getValidDisplayList()3886         ArrayList<Display> getValidDisplayList() {
3887             synchronized (mLock) {
3888                 return mDisplaysList;
3889             }
3890         }
3891 
initializeDisplayList()3892         private void initializeDisplayList() {
3893             final Display[] displays = mDisplayManager.getDisplays();
3894             synchronized (mLock) {
3895                 mDisplaysList.clear();
3896                 for (int i = 0; i < displays.length; i++) {
3897                     // Exclude overlay virtual displays. The display list is for A11yInputFilter
3898                     // to create event handler per display. The events should be handled by the
3899                     // display which is overlaid by it.
3900                     final Display display = displays[i];
3901                     if (display.getType() == Display.TYPE_OVERLAY) {
3902                         continue;
3903                     }
3904                     mDisplaysList.add(display);
3905                 }
3906             }
3907         }
3908 
3909         @Override
onDisplayAdded(int displayId)3910         public void onDisplayAdded(int displayId) {
3911             final Display display = mDisplayManager.getDisplay(displayId);
3912             if (display == null || display.getType() == Display.TYPE_OVERLAY) {
3913                 return;
3914             }
3915 
3916             synchronized (mLock) {
3917                 mDisplaysList.add(display);
3918                 if (mInputFilter != null) {
3919                     mInputFilter.onDisplayChanged();
3920                 }
3921                 UserState userState = getCurrentUserStateLocked();
3922                 updateMagnificationLocked(userState);
3923             }
3924         }
3925 
3926         @Override
onDisplayRemoved(int displayId)3927         public void onDisplayRemoved(int displayId) {
3928             synchronized (mLock) {
3929                 for (int i = 0; i < mDisplaysList.size(); i++) {
3930                     if (mDisplaysList.get(i).getDisplayId() == displayId) {
3931                         mDisplaysList.remove(i);
3932                         break;
3933                     }
3934                 }
3935                 if (mInputFilter != null) {
3936                     mInputFilter.onDisplayChanged();
3937                 }
3938             }
3939             if (mMagnificationController != null) {
3940                 mMagnificationController.onDisplayRemoved(displayId);
3941             }
3942         }
3943 
3944         @Override
onDisplayChanged(int displayId)3945         public void onDisplayChanged(int displayId) {
3946             /* do nothing */
3947         }
3948     }
3949 
3950     /** Represents an {@link AccessibilityManager} */
3951     class Client {
3952         final IAccessibilityManagerClient mCallback;
3953         final String[] mPackageNames;
3954         int mLastSentRelevantEventTypes;
3955 
Client(IAccessibilityManagerClient callback, int clientUid, UserState userState)3956         private Client(IAccessibilityManagerClient callback, int clientUid, UserState userState) {
3957             mCallback = callback;
3958             mPackageNames = mPackageManager.getPackagesForUid(clientUid);
3959             synchronized (mLock) {
3960                 mLastSentRelevantEventTypes = computeRelevantEventTypesLocked(userState, this);
3961             }
3962         }
3963     }
3964 
3965     public class UserState {
3966         public final int mUserId;
3967 
3968         // Non-transient state.
3969 
3970         public final RemoteCallbackList<IAccessibilityManagerClient> mUserClients =
3971                 new RemoteCallbackList<>();
3972 
3973         public final SparseArray<RemoteAccessibilityConnection> mInteractionConnections =
3974                 new SparseArray<>();
3975 
3976         public final SparseArray<IBinder> mWindowTokens = new SparseArray<>();
3977 
3978         // Transient state.
3979 
3980         public final ArrayList<AccessibilityServiceConnection> mBoundServices = new ArrayList<>();
3981 
3982         public final Map<ComponentName, AccessibilityServiceConnection> mComponentNameToServiceMap =
3983                 new HashMap<>();
3984 
3985         public final List<AccessibilityServiceInfo> mInstalledServices =
3986                 new ArrayList<>();
3987 
3988         private final Set<ComponentName> mBindingServices = new HashSet<>();
3989 
3990         public final Set<ComponentName> mEnabledServices = new HashSet<>();
3991 
3992         public final Set<ComponentName> mTouchExplorationGrantedServices =
3993                 new HashSet<>();
3994 
3995         public ComponentName mServiceChangingSoftKeyboardMode;
3996 
3997         public ComponentName mServiceToEnableWithShortcut;
3998 
3999         public int mLastSentClientState = -1;
4000         public int mNonInteractiveUiTimeout = 0;
4001         public int mInteractiveUiTimeout = 0;
4002 
4003         private int mSoftKeyboardShowMode = 0;
4004 
4005         public boolean mIsNavBarMagnificationAssignedToAccessibilityButton;
4006         public ComponentName mServiceAssignedToAccessibilityButton;
4007 
4008         public boolean mIsTouchExplorationEnabled;
4009         public boolean mIsTextHighContrastEnabled;
4010         public boolean mIsDisplayMagnificationEnabled;
4011         public boolean mIsNavBarMagnificationEnabled;
4012         public boolean mIsAutoclickEnabled;
4013         public boolean mIsPerformGesturesEnabled;
4014         public boolean mIsFilterKeyEventsEnabled;
4015         public boolean mAccessibilityFocusOnlyInActiveWindow;
4016         public int mUserNonInteractiveUiTimeout;
4017         public int mUserInteractiveUiTimeout;
4018 
4019         private boolean mBindInstantServiceAllowed;
4020 
UserState(int userId)4021         public UserState(int userId) {
4022             mUserId = userId;
4023         }
4024 
getClientState()4025         public int getClientState() {
4026             int clientState = 0;
4027             final boolean a11yEnabled = (mUiAutomationManager.isUiAutomationRunningLocked()
4028                     || isHandlingAccessibilityEvents());
4029             if (a11yEnabled) {
4030                 clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
4031             }
4032             // Touch exploration relies on enabled accessibility.
4033             if (a11yEnabled && mIsTouchExplorationEnabled) {
4034                 clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
4035             }
4036             if (mIsTextHighContrastEnabled) {
4037                 clientState |= AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED;
4038             }
4039             return clientState;
4040         }
4041 
isHandlingAccessibilityEvents()4042         public boolean isHandlingAccessibilityEvents() {
4043             return !mBoundServices.isEmpty() || !mBindingServices.isEmpty();
4044         }
4045 
onSwitchToAnotherUserLocked()4046         public void onSwitchToAnotherUserLocked() {
4047             // Unbind all services.
4048             unbindAllServicesLocked(this);
4049 
4050             // Clear service management state.
4051             mBoundServices.clear();
4052             mBindingServices.clear();
4053 
4054             // Clear event management state.
4055             mLastSentClientState = -1;
4056 
4057             // clear UI timeout
4058             mNonInteractiveUiTimeout = 0;
4059             mInteractiveUiTimeout = 0;
4060 
4061             // Clear state persisted in settings.
4062             mEnabledServices.clear();
4063             mTouchExplorationGrantedServices.clear();
4064             mIsTouchExplorationEnabled = false;
4065             mIsDisplayMagnificationEnabled = false;
4066             mIsNavBarMagnificationEnabled = false;
4067             mServiceAssignedToAccessibilityButton = null;
4068             mIsNavBarMagnificationAssignedToAccessibilityButton = false;
4069             mIsAutoclickEnabled = false;
4070             mUserNonInteractiveUiTimeout = 0;
4071             mUserInteractiveUiTimeout = 0;
4072         }
4073 
addServiceLocked(AccessibilityServiceConnection serviceConnection)4074         public void addServiceLocked(AccessibilityServiceConnection serviceConnection) {
4075             if (!mBoundServices.contains(serviceConnection)) {
4076                 serviceConnection.onAdded();
4077                 mBoundServices.add(serviceConnection);
4078                 mComponentNameToServiceMap.put(serviceConnection.mComponentName, serviceConnection);
4079                 scheduleNotifyClientsOfServicesStateChangeLocked(this);
4080             }
4081         }
4082 
4083         /**
4084          * Removes a service.
4085          * There are three states to a service here: off, bound, and binding.
4086          * This stops tracking the service as bound.
4087          *
4088          * @param serviceConnection The service.
4089          */
removeServiceLocked(AccessibilityServiceConnection serviceConnection)4090         public void removeServiceLocked(AccessibilityServiceConnection serviceConnection) {
4091             mBoundServices.remove(serviceConnection);
4092             serviceConnection.onRemoved();
4093             if ((mServiceChangingSoftKeyboardMode != null)
4094                     && (mServiceChangingSoftKeyboardMode.equals(
4095                             serviceConnection.getServiceInfo().getComponentName()))) {
4096                 setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null);
4097             }
4098             // It may be possible to bind a service twice, which confuses the map. Rebuild the map
4099             // to make sure we can still reach a service
4100             mComponentNameToServiceMap.clear();
4101             for (int i = 0; i < mBoundServices.size(); i++) {
4102                 AccessibilityServiceConnection boundClient = mBoundServices.get(i);
4103                 mComponentNameToServiceMap.put(boundClient.mComponentName, boundClient);
4104             }
4105             scheduleNotifyClientsOfServicesStateChangeLocked(this);
4106         }
4107 
4108         /**
4109          * Make sure a services disconnected but still 'on' state is reflected in UserState
4110          * There are three states to a service here: off, bound, and binding.
4111          * This drops a service from a bound state, to the binding state.
4112          * The binding state describes the situation where a service is on, but not bound.
4113          *
4114          * @param serviceConnection The service.
4115          */
serviceDisconnectedLocked(AccessibilityServiceConnection serviceConnection)4116         public void serviceDisconnectedLocked(AccessibilityServiceConnection serviceConnection) {
4117             removeServiceLocked(serviceConnection);
4118             mBindingServices.add(serviceConnection.getComponentName());
4119         }
4120 
getBindingServicesLocked()4121         public Set<ComponentName> getBindingServicesLocked() {
4122             return mBindingServices;
4123         }
4124 
4125         /**
4126          * Returns enabled service list.
4127          */
getEnabledServicesLocked()4128         public Set<ComponentName> getEnabledServicesLocked() {
4129             return mEnabledServices;
4130         }
4131 
getSoftKeyboardShowMode()4132         public int getSoftKeyboardShowMode() {
4133             return mSoftKeyboardShowMode;
4134         }
4135 
4136         /**
4137          * Set the soft keyboard mode. This mode is a bit odd, as it spans multiple settings.
4138          * The ACCESSIBILITY_SOFT_KEYBOARD_MODE setting can be checked by the rest of the system
4139          * to see if it should suppress showing the IME. The SHOW_IME_WITH_HARD_KEYBOARD setting
4140          * setting can be changed by the user, and prevents the system from suppressing the soft
4141          * keyboard when the hard keyboard is connected. The hard keyboard setting needs to defer
4142          * to the user's preference, if they have supplied one.
4143          *
4144          * @param newMode The new mode
4145          * @param requester The service requesting the change, so we can undo it when the
4146          *                  service stops. Set to null if something other than a service is forcing
4147          *                  the change.
4148          *
4149          * @return Whether or not the soft keyboard mode equals the new mode after the call
4150          */
setSoftKeyboardModeLocked(int newMode, @Nullable ComponentName requester)4151         public boolean setSoftKeyboardModeLocked(int newMode, @Nullable ComponentName requester) {
4152             if ((newMode != SHOW_MODE_AUTO) && (newMode != SHOW_MODE_HIDDEN)
4153                     && (newMode != SHOW_MODE_IGNORE_HARD_KEYBOARD))
4154             {
4155                 Slog.w(LOG_TAG, "Invalid soft keyboard mode");
4156                 return false;
4157             }
4158             if (mSoftKeyboardShowMode == newMode) return true;
4159 
4160             if (newMode == SHOW_MODE_IGNORE_HARD_KEYBOARD) {
4161                 if (hasUserOverriddenHardKeyboardSettingLocked()) {
4162                     // The user has specified a default for this setting
4163                     return false;
4164                 }
4165                 // Save the original value. But don't do this if the value in settings is already
4166                 // the new mode. That happens when we start up after a reboot, and we don't want
4167                 // to overwrite the value we had from when we first started controlling the setting.
4168                 if (getSoftKeyboardValueFromSettings() != SHOW_MODE_IGNORE_HARD_KEYBOARD) {
4169                     setOriginalHardKeyboardValue(
4170                             Settings.Secure.getInt(mContext.getContentResolver(),
4171                                     Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0);
4172                 }
4173                 putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 1, mUserId);
4174             } else if (mSoftKeyboardShowMode == SHOW_MODE_IGNORE_HARD_KEYBOARD) {
4175                 putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
4176                         getOriginalHardKeyboardValue() ? 1 : 0, mUserId);
4177             }
4178 
4179             saveSoftKeyboardValueToSettings(newMode);
4180             mSoftKeyboardShowMode = newMode;
4181             mServiceChangingSoftKeyboardMode = requester;
4182             notifySoftKeyboardShowModeChangedLocked(mSoftKeyboardShowMode);
4183             return true;
4184         }
4185 
4186         /**
4187          * If the settings are inconsistent with the internal state, make the internal state
4188          * match the settings.
4189          */
reconcileSoftKeyboardModeWithSettingsLocked()4190         public void reconcileSoftKeyboardModeWithSettingsLocked() {
4191             final ContentResolver cr = mContext.getContentResolver();
4192             final boolean showWithHardKeyboardSettings =
4193                     Settings.Secure.getInt(cr, Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0) != 0;
4194             if (mSoftKeyboardShowMode == SHOW_MODE_IGNORE_HARD_KEYBOARD) {
4195                 if (!showWithHardKeyboardSettings) {
4196                     // The user has overridden the setting. Respect that and prevent further changes
4197                     // to this behavior.
4198                     setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null);
4199                     setUserOverridesHardKeyboardSettingLocked();
4200                 }
4201             }
4202 
4203             // If the setting and the internal state are out of sync, set both to default
4204             if (getSoftKeyboardValueFromSettings() != mSoftKeyboardShowMode)
4205             {
4206                 Slog.e(LOG_TAG,
4207                         "Show IME setting inconsistent with internal state. Overwriting");
4208                 setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null);
4209                 putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
4210                         SHOW_MODE_AUTO, mUserId);
4211             }
4212         }
4213 
setUserOverridesHardKeyboardSettingLocked()4214         private void setUserOverridesHardKeyboardSettingLocked() {
4215             final int softKeyboardSetting = Settings.Secure.getInt(mContext.getContentResolver(),
4216                     Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0);
4217             putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
4218                     softKeyboardSetting | SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN,
4219                     mUserId);
4220         }
4221 
hasUserOverriddenHardKeyboardSettingLocked()4222         private boolean hasUserOverriddenHardKeyboardSettingLocked() {
4223             final int softKeyboardSetting = Settings.Secure.getInt(mContext.getContentResolver(),
4224                     Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0);
4225             return (softKeyboardSetting & SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN)
4226                     != 0;
4227         }
4228 
setOriginalHardKeyboardValue(boolean originalHardKeyboardValue)4229         private void setOriginalHardKeyboardValue(boolean originalHardKeyboardValue) {
4230             final int oldSoftKeyboardSetting = Settings.Secure.getInt(mContext.getContentResolver(),
4231                     Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0);
4232             final int newSoftKeyboardSetting = oldSoftKeyboardSetting
4233                     & (~SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE)
4234                     | ((originalHardKeyboardValue) ? SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE : 0);
4235             putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
4236                     newSoftKeyboardSetting, mUserId);
4237         }
4238 
saveSoftKeyboardValueToSettings(int softKeyboardShowMode)4239         private void saveSoftKeyboardValueToSettings(int softKeyboardShowMode) {
4240             final int oldSoftKeyboardSetting = Settings.Secure.getInt(mContext.getContentResolver(),
4241                     Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0);
4242             final int newSoftKeyboardSetting = oldSoftKeyboardSetting & (~SHOW_MODE_MASK)
4243                     | softKeyboardShowMode;
4244             putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
4245                     newSoftKeyboardSetting, mUserId);
4246         }
4247 
getSoftKeyboardValueFromSettings()4248         private int getSoftKeyboardValueFromSettings() {
4249             return Settings.Secure.getInt(mContext.getContentResolver(),
4250                     Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
4251                     SHOW_MODE_AUTO) & SHOW_MODE_MASK;
4252         }
4253 
getOriginalHardKeyboardValue()4254         private boolean getOriginalHardKeyboardValue() {
4255             return (Settings.Secure.getInt(mContext.getContentResolver(),
4256                     Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, 0)
4257                     & SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE) != 0;
4258         }
4259 
getBindInstantServiceAllowed()4260         public boolean getBindInstantServiceAllowed() {
4261             synchronized (mLock) {
4262                 return mBindInstantServiceAllowed;
4263             }
4264         }
4265 
setBindInstantServiceAllowed(boolean allowed)4266         public void setBindInstantServiceAllowed(boolean allowed) {
4267             synchronized (mLock) {
4268                 mContext.enforceCallingOrSelfPermission(
4269                         Manifest.permission.MANAGE_BIND_INSTANT_SERVICE,
4270                         "setBindInstantServiceAllowed");
4271                 if (allowed) {
4272                     mBindInstantServiceAllowed = allowed;
4273                     onUserStateChangedLocked(this);
4274                 }
4275             }
4276         }
4277     }
4278 
4279     private final class AccessibilityContentObserver extends ContentObserver {
4280 
4281         private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor(
4282                 Settings.Secure.TOUCH_EXPLORATION_ENABLED);
4283 
4284         private final Uri mDisplayMagnificationEnabledUri = Settings.Secure.getUriFor(
4285                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
4286 
4287         private final Uri mNavBarMagnificationEnabledUri = Settings.Secure.getUriFor(
4288                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED);
4289 
4290         private final Uri mAutoclickEnabledUri = Settings.Secure.getUriFor(
4291                 Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED);
4292 
4293         private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor(
4294                 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
4295 
4296         private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure
4297                 .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
4298 
4299         private final Uri mHighTextContrastUri = Settings.Secure.getUriFor(
4300                 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED);
4301 
4302         private final Uri mAccessibilitySoftKeyboardModeUri = Settings.Secure.getUriFor(
4303                 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE);
4304 
4305         private final Uri mShowImeWithHardKeyboardUri = Settings.Secure.getUriFor(
4306                 Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
4307 
4308         private final Uri mAccessibilityShortcutServiceIdUri = Settings.Secure.getUriFor(
4309                 Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
4310 
4311         private final Uri mAccessibilityButtonComponentIdUri = Settings.Secure.getUriFor(
4312                 Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT);
4313 
4314         private final Uri mUserNonInteractiveUiTimeoutUri = Settings.Secure.getUriFor(
4315                 Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS);
4316 
4317         private final Uri mUserInteractiveUiTimeoutUri = Settings.Secure.getUriFor(
4318                 Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS);
4319 
AccessibilityContentObserver(Handler handler)4320         public AccessibilityContentObserver(Handler handler) {
4321             super(handler);
4322         }
4323 
register(ContentResolver contentResolver)4324         public void register(ContentResolver contentResolver) {
4325             contentResolver.registerContentObserver(mTouchExplorationEnabledUri,
4326                     false, this, UserHandle.USER_ALL);
4327             contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri,
4328                     false, this, UserHandle.USER_ALL);
4329             contentResolver.registerContentObserver(mNavBarMagnificationEnabledUri,
4330                     false, this, UserHandle.USER_ALL);
4331             contentResolver.registerContentObserver(mAutoclickEnabledUri,
4332                     false, this, UserHandle.USER_ALL);
4333             contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri,
4334                     false, this, UserHandle.USER_ALL);
4335             contentResolver.registerContentObserver(
4336                     mTouchExplorationGrantedAccessibilityServicesUri,
4337                     false, this, UserHandle.USER_ALL);
4338             contentResolver.registerContentObserver(
4339                     mHighTextContrastUri, false, this, UserHandle.USER_ALL);
4340             contentResolver.registerContentObserver(
4341                     mAccessibilitySoftKeyboardModeUri, false, this, UserHandle.USER_ALL);
4342             contentResolver.registerContentObserver(
4343                     mShowImeWithHardKeyboardUri, false, this, UserHandle.USER_ALL);
4344             contentResolver.registerContentObserver(
4345                     mAccessibilityShortcutServiceIdUri, false, this, UserHandle.USER_ALL);
4346             contentResolver.registerContentObserver(
4347                     mAccessibilityButtonComponentIdUri, false, this, UserHandle.USER_ALL);
4348             contentResolver.registerContentObserver(
4349                     mUserNonInteractiveUiTimeoutUri, false, this, UserHandle.USER_ALL);
4350             contentResolver.registerContentObserver(
4351                     mUserInteractiveUiTimeoutUri, false, this, UserHandle.USER_ALL);
4352         }
4353 
4354         @Override
onChange(boolean selfChange, Uri uri)4355         public void onChange(boolean selfChange, Uri uri) {
4356             synchronized (mLock) {
4357                 // Profiles share the accessibility state of the parent. Therefore,
4358                 // we are checking for changes only the parent settings.
4359                 UserState userState = getCurrentUserStateLocked();
4360 
4361                 if (mTouchExplorationEnabledUri.equals(uri)) {
4362                     if (readTouchExplorationEnabledSettingLocked(userState)) {
4363                         onUserStateChangedLocked(userState);
4364                     }
4365                 } else if (mDisplayMagnificationEnabledUri.equals(uri)
4366                         || mNavBarMagnificationEnabledUri.equals(uri)) {
4367                     if (readMagnificationEnabledSettingsLocked(userState)) {
4368                         onUserStateChangedLocked(userState);
4369                     }
4370                 } else if (mAutoclickEnabledUri.equals(uri)) {
4371                     if (readAutoclickEnabledSettingLocked(userState)) {
4372                         onUserStateChangedLocked(userState);
4373                     }
4374                 } else if (mEnabledAccessibilityServicesUri.equals(uri)) {
4375                     if (readEnabledAccessibilityServicesLocked(userState)) {
4376                         onUserStateChangedLocked(userState);
4377                     }
4378                 } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) {
4379                     if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) {
4380                         onUserStateChangedLocked(userState);
4381                     }
4382                 } else if (mHighTextContrastUri.equals(uri)) {
4383                     if (readHighTextContrastEnabledSettingLocked(userState)) {
4384                         onUserStateChangedLocked(userState);
4385                     }
4386                 } else if (mAccessibilitySoftKeyboardModeUri.equals(uri)
4387                         || mShowImeWithHardKeyboardUri.equals(uri)) {
4388                     userState.reconcileSoftKeyboardModeWithSettingsLocked();
4389                 } else if (mAccessibilityShortcutServiceIdUri.equals(uri)) {
4390                     if (readAccessibilityShortcutSettingLocked(userState)) {
4391                         onUserStateChangedLocked(userState);
4392                     }
4393                 } else if (mAccessibilityButtonComponentIdUri.equals(uri)) {
4394                     if (readAccessibilityButtonSettingsLocked(userState)) {
4395                         onUserStateChangedLocked(userState);
4396                     }
4397                 } else if (mUserNonInteractiveUiTimeoutUri.equals(uri)
4398                         || mUserInteractiveUiTimeoutUri.equals(uri)) {
4399                     readUserRecommendedUiTimeoutSettingsLocked(userState);
4400                 }
4401             }
4402         }
4403     }
4404 }
4405