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