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