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