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         IBinder mService;
   2212 
   2213         IAccessibilityServiceClient mServiceInterface;
   2214 
   2215         int mEventTypes;
   2216 
   2217         int mFeedbackType;
   2218 
   2219         Set<String> mPackageNames = new HashSet<>();
   2220 
   2221         boolean mIsDefault;
   2222 
   2223         boolean mRequestTouchExplorationMode;
   2224 
   2225         boolean mRequestEnhancedWebAccessibility;
   2226 
   2227         boolean mRequestFilterKeyEvents;
   2228 
   2229         boolean mRetrieveInteractiveWindows;
   2230 
   2231         int mFetchFlags;
   2232 
   2233         long mNotificationTimeout;
   2234 
   2235         ComponentName mComponentName;
   2236 
   2237         Intent mIntent;
   2238 
   2239         boolean mIsAutomation;
   2240 
   2241         final ResolveInfo mResolveInfo;
   2242 
   2243         final IBinder mOverlayWindowToken = new Binder();
   2244 
   2245         // the events pending events to be dispatched to this service
   2246         final SparseArray<AccessibilityEvent> mPendingEvents =
   2247             new SparseArray<>();
   2248 
   2249         boolean mWasConnectedAndDied;
   2250 
   2251         // Handler only for dispatching accessibility events since we use event
   2252         // types as message types allowing us to remove messages per event type.
   2253         public Handler mEventDispatchHandler = new Handler(mMainHandler.getLooper()) {
   2254             @Override
   2255             public void handleMessage(Message message) {
   2256                 final int eventType =  message.what;
   2257                 AccessibilityEvent event = (AccessibilityEvent) message.obj;
   2258                 notifyAccessibilityEventInternal(eventType, event);
   2259             }
   2260         };
   2261 
   2262         // Handler for scheduling method invocations on the main thread.
   2263         public final InvocationHandler mInvocationHandler = new InvocationHandler(
   2264                 mMainHandler.getLooper());
   2265 
   2266         public Service(int userId, ComponentName componentName,
   2267                 AccessibilityServiceInfo accessibilityServiceInfo) {
   2268             mUserId = userId;
   2269             mResolveInfo = accessibilityServiceInfo.getResolveInfo();
   2270             mId = sIdCounter++;
   2271             mComponentName = componentName;
   2272             mAccessibilityServiceInfo = accessibilityServiceInfo;
   2273             mIsAutomation = (sFakeAccessibilityServiceComponentName.equals(componentName));
   2274             if (!mIsAutomation) {
   2275                 mIntent = new Intent().setComponent(mComponentName);
   2276                 mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
   2277                         com.android.internal.R.string.accessibility_binding_label);
   2278                 final long idendtity = Binder.clearCallingIdentity();
   2279                 try {
   2280                     mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
   2281                             mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0));
   2282                 } finally {
   2283                     Binder.restoreCallingIdentity(idendtity);
   2284                 }
   2285             }
   2286             setDynamicallyConfigurableProperties(accessibilityServiceInfo);
   2287         }
   2288 
   2289         public void setDynamicallyConfigurableProperties(AccessibilityServiceInfo info) {
   2290             mEventTypes = info.eventTypes;
   2291             mFeedbackType = info.feedbackType;
   2292             String[] packageNames = info.packageNames;
   2293             if (packageNames != null) {
   2294                 mPackageNames.addAll(Arrays.asList(packageNames));
   2295             }
   2296             mNotificationTimeout = info.notificationTimeout;
   2297             mIsDefault = (info.flags & DEFAULT) != 0;
   2298 
   2299             if (mIsAutomation || info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion
   2300                     >= Build.VERSION_CODES.JELLY_BEAN) {
   2301                 if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) {
   2302                     mFetchFlags |= AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
   2303                 } else {
   2304                     mFetchFlags &= ~AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
   2305                 }
   2306             }
   2307 
   2308             if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) {
   2309                 mFetchFlags |= AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;
   2310             } else {
   2311                 mFetchFlags &= ~AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;
   2312             }
   2313 
   2314             mRequestTouchExplorationMode = (info.flags
   2315                     & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0;
   2316             mRequestEnhancedWebAccessibility = (info.flags
   2317                     & AccessibilityServiceInfo.FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY) != 0;
   2318             mRequestFilterKeyEvents = (info.flags
   2319                     & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0;
   2320             mRetrieveInteractiveWindows = (info.flags
   2321                     & AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0;
   2322         }
   2323 
   2324         /**
   2325          * Binds to the accessibility service.
   2326          *
   2327          * @return True if binding is successful.
   2328          */
   2329         public boolean bindLocked() {
   2330             UserState userState = getUserStateLocked(mUserId);
   2331             if (!mIsAutomation) {
   2332                 final long identity = Binder.clearCallingIdentity();
   2333                 try {
   2334                     if (mService == null && mContext.bindServiceAsUser(
   2335                             mIntent, this,
   2336                             Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
   2337                             new UserHandle(mUserId))) {
   2338                         userState.mBindingServices.add(mComponentName);
   2339                     }
   2340                 } finally {
   2341                     Binder.restoreCallingIdentity(identity);
   2342                 }
   2343             } else {
   2344                 userState.mBindingServices.add(mComponentName);
   2345                 mService = userState.mUiAutomationServiceClient.asBinder();
   2346                 mMainHandler.post(new Runnable() {
   2347                     @Override
   2348                     public void run() {
   2349                         // Simulate asynchronous connection since in onServiceConnected
   2350                         // we may modify the state data in case of an error but bind is
   2351                         // called while iterating over the data and bad things can happen.
   2352                         onServiceConnected(mComponentName, mService);
   2353                     }
   2354                 });
   2355                 userState.mUiAutomationService = this;
   2356             }
   2357             return false;
   2358         }
   2359 
   2360         /**
   2361          * Unbinds from the accessibility service and removes it from the data
   2362          * structures for service management.
   2363          *
   2364          * @return True if unbinding is successful.
   2365          */
   2366         public boolean unbindLocked() {
   2367             UserState userState = getUserStateLocked(mUserId);
   2368             getKeyEventDispatcher().flush(this);
   2369             if (!mIsAutomation) {
   2370                 mContext.unbindService(this);
   2371             } else {
   2372                 userState.destroyUiAutomationService();
   2373             }
   2374             removeServiceLocked(this, userState);
   2375             resetLocked();
   2376             return true;
   2377         }
   2378 
   2379         @Override
   2380         public void disableSelf() {
   2381             synchronized(mLock) {
   2382                 UserState userState = getUserStateLocked(mUserId);
   2383                 if (userState.mEnabledServices.remove(mComponentName)) {
   2384                     final long identity = Binder.clearCallingIdentity();
   2385                     try {
   2386                         persistComponentNamesToSettingLocked(
   2387                                 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
   2388                                 userState.mEnabledServices, mUserId);
   2389                     } finally {
   2390                         Binder.restoreCallingIdentity(identity);
   2391                     }
   2392                     onUserStateChangedLocked(userState);
   2393                 }
   2394             }
   2395         }
   2396 
   2397         public boolean canReceiveEventsLocked() {
   2398             return (mEventTypes != 0 && mFeedbackType != 0 && mService != null);
   2399         }
   2400 
   2401         @Override
   2402         public void setOnKeyEventResult(boolean handled, int sequence) {
   2403             getKeyEventDispatcher().setOnKeyEventResult(this, handled, sequence);
   2404         }
   2405 
   2406         @Override
   2407         public AccessibilityServiceInfo getServiceInfo() {
   2408             synchronized (mLock) {
   2409                 return mAccessibilityServiceInfo;
   2410             }
   2411         }
   2412 
   2413         public boolean canRetrieveInteractiveWindowsLocked() {
   2414             return mSecurityPolicy.canRetrieveWindowContentLocked(this)
   2415                     && mRetrieveInteractiveWindows;
   2416         }
   2417 
   2418         @Override
   2419         public void setServiceInfo(AccessibilityServiceInfo info) {
   2420             final long identity = Binder.clearCallingIdentity();
   2421             try {
   2422                 synchronized (mLock) {
   2423                     // If the XML manifest had data to configure the service its info
   2424                     // should be already set. In such a case update only the dynamically
   2425                     // configurable properties.
   2426                     AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo;
   2427                     if (oldInfo != null) {
   2428                         oldInfo.updateDynamicallyConfigurableProperties(info);
   2429                         setDynamicallyConfigurableProperties(oldInfo);
   2430                     } else {
   2431                         setDynamicallyConfigurableProperties(info);
   2432                     }
   2433                     UserState userState = getUserStateLocked(mUserId);
   2434                     onUserStateChangedLocked(userState);
   2435                 }
   2436             } finally {
   2437                 Binder.restoreCallingIdentity(identity);
   2438             }
   2439         }
   2440 
   2441         @Override
   2442         public void onServiceConnected(ComponentName componentName, IBinder service) {
   2443             synchronized (mLock) {
   2444                 mService = service;
   2445                 mServiceInterface = IAccessibilityServiceClient.Stub.asInterface(service);
   2446                 UserState userState = getUserStateLocked(mUserId);
   2447                 addServiceLocked(this, userState);
   2448                 if (userState.mBindingServices.contains(mComponentName) || mWasConnectedAndDied) {
   2449                     userState.mBindingServices.remove(mComponentName);
   2450                     mWasConnectedAndDied = false;
   2451                     try {
   2452                        mServiceInterface.init(this, mId, mOverlayWindowToken);
   2453                        onUserStateChangedLocked(userState);
   2454                     } catch (RemoteException re) {
   2455                         Slog.w(LOG_TAG, "Error while setting connection for service: "
   2456                                 + service, re);
   2457                         binderDied();
   2458                     }
   2459                 } else {
   2460                     binderDied();
   2461                 }
   2462             }
   2463         }
   2464 
   2465         private boolean isCalledForCurrentUserLocked() {
   2466             // We treat calls from a profile as if made by its parent as profiles
   2467             // share the accessibility state of the parent. The call below
   2468             // performs the current profile parent resolution.
   2469             final int resolvedUserId = mSecurityPolicy
   2470                     .resolveCallingUserIdEnforcingPermissionsLocked(UserHandle.USER_CURRENT);
   2471             return resolvedUserId == mCurrentUserId;
   2472         }
   2473 
   2474         @Override
   2475         public List<AccessibilityWindowInfo> getWindows() {
   2476             ensureWindowsAvailableTimed();
   2477             synchronized (mLock) {
   2478                 if (!isCalledForCurrentUserLocked()) {
   2479                     return null;
   2480                 }
   2481                 final boolean permissionGranted =
   2482                         mSecurityPolicy.canRetrieveWindowsLocked(this);
   2483                 if (!permissionGranted) {
   2484                     return null;
   2485                 }
   2486                 if (mSecurityPolicy.mWindows == null) {
   2487                     return null;
   2488                 }
   2489                 List<AccessibilityWindowInfo> windows = new ArrayList<>();
   2490                 final int windowCount = mSecurityPolicy.mWindows.size();
   2491                 for (int i = 0; i < windowCount; i++) {
   2492                     AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(i);
   2493                     AccessibilityWindowInfo windowClone =
   2494                             AccessibilityWindowInfo.obtain(window);
   2495                     windowClone.setConnectionId(mId);
   2496                     windows.add(windowClone);
   2497                 }
   2498                 return windows;
   2499             }
   2500         }
   2501 
   2502         @Override
   2503         public AccessibilityWindowInfo getWindow(int windowId) {
   2504             ensureWindowsAvailableTimed();
   2505             synchronized (mLock) {
   2506                 if (!isCalledForCurrentUserLocked()) {
   2507                     return null;
   2508                 }
   2509                 final boolean permissionGranted =
   2510                         mSecurityPolicy.canRetrieveWindowsLocked(this);
   2511                 if (!permissionGranted) {
   2512                     return null;
   2513                 }
   2514                 AccessibilityWindowInfo window = mSecurityPolicy.findWindowById(windowId);
   2515                 if (window != null) {
   2516                     AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window);
   2517                     windowClone.setConnectionId(mId);
   2518                     return windowClone;
   2519                 }
   2520                 return null;
   2521             }
   2522         }
   2523 
   2524         @Override
   2525         public boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
   2526                 long accessibilityNodeId, String viewIdResName, int interactionId,
   2527                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
   2528                 throws RemoteException {
   2529             final int resolvedWindowId;
   2530             IAccessibilityInteractionConnection connection = null;
   2531             Region partialInteractiveRegion = Region.obtain();
   2532             synchronized (mLock) {
   2533                 if (!isCalledForCurrentUserLocked()) {
   2534                     return false;
   2535                 }
   2536                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
   2537                 final boolean permissionGranted =
   2538                         mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
   2539                 if (!permissionGranted) {
   2540                     return false;
   2541                 } else {
   2542                     connection = getConnectionLocked(resolvedWindowId);
   2543                     if (connection == null) {
   2544                         return false;
   2545                     }
   2546                 }
   2547                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
   2548                         resolvedWindowId, partialInteractiveRegion)) {
   2549                     partialInteractiveRegion.recycle();
   2550                     partialInteractiveRegion = null;
   2551                 }
   2552             }
   2553             final int interrogatingPid = Binder.getCallingPid();
   2554             final long identityToken = Binder.clearCallingIdentity();
   2555             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
   2556             try {
   2557                 connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName,
   2558                         partialInteractiveRegion, interactionId, callback, mFetchFlags,
   2559                         interrogatingPid, interrogatingTid, spec);
   2560                 return true;
   2561             } catch (RemoteException re) {
   2562                 if (DEBUG) {
   2563                     Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId().");
   2564                 }
   2565             } finally {
   2566                 Binder.restoreCallingIdentity(identityToken);
   2567                 // Recycle if passed to another process.
   2568                 if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
   2569                     partialInteractiveRegion.recycle();
   2570                 }
   2571             }
   2572             return false;
   2573         }
   2574 
   2575         @Override
   2576         public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId,
   2577                 long accessibilityNodeId, String text, int interactionId,
   2578                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
   2579                 throws RemoteException {
   2580             final int resolvedWindowId;
   2581             IAccessibilityInteractionConnection connection = null;
   2582             Region partialInteractiveRegion = Region.obtain();
   2583             synchronized (mLock) {
   2584                 if (!isCalledForCurrentUserLocked()) {
   2585                     return false;
   2586                 }
   2587                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
   2588                 final boolean permissionGranted =
   2589                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
   2590                 if (!permissionGranted) {
   2591                     return false;
   2592                 } else {
   2593                     connection = getConnectionLocked(resolvedWindowId);
   2594                     if (connection == null) {
   2595                         return false;
   2596                     }
   2597                 }
   2598                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
   2599                         resolvedWindowId, partialInteractiveRegion)) {
   2600                     partialInteractiveRegion.recycle();
   2601                     partialInteractiveRegion = null;
   2602                 }
   2603             }
   2604             final int interrogatingPid = Binder.getCallingPid();
   2605             final long identityToken = Binder.clearCallingIdentity();
   2606             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
   2607             try {
   2608                 connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
   2609                         partialInteractiveRegion, interactionId, callback, mFetchFlags,
   2610                         interrogatingPid, interrogatingTid, spec);
   2611                 return true;
   2612             } catch (RemoteException re) {
   2613                 if (DEBUG) {
   2614                     Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()");
   2615                 }
   2616             } finally {
   2617                 Binder.restoreCallingIdentity(identityToken);
   2618                 // Recycle if passed to another process.
   2619                 if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
   2620                     partialInteractiveRegion.recycle();
   2621                 }
   2622             }
   2623             return false;
   2624         }
   2625 
   2626         @Override
   2627         public boolean findAccessibilityNodeInfoByAccessibilityId(
   2628                 int accessibilityWindowId, long accessibilityNodeId, int interactionId,
   2629                 IAccessibilityInteractionConnectionCallback callback, int flags,
   2630                 long interrogatingTid) throws RemoteException {
   2631             final int resolvedWindowId;
   2632             IAccessibilityInteractionConnection connection = null;
   2633             Region partialInteractiveRegion = Region.obtain();
   2634             synchronized (mLock) {
   2635                 if (!isCalledForCurrentUserLocked()) {
   2636                     return false;
   2637                 }
   2638                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
   2639                 final boolean permissionGranted =
   2640                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
   2641                 if (!permissionGranted) {
   2642                     return false;
   2643                 } else {
   2644                     connection = getConnectionLocked(resolvedWindowId);
   2645                     if (connection == null) {
   2646                         return false;
   2647                     }
   2648                 }
   2649                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
   2650                         resolvedWindowId, partialInteractiveRegion)) {
   2651                     partialInteractiveRegion.recycle();
   2652                     partialInteractiveRegion = null;
   2653                 }
   2654             }
   2655             final int interrogatingPid = Binder.getCallingPid();
   2656             final long identityToken = Binder.clearCallingIdentity();
   2657             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
   2658             try {
   2659                 connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId,
   2660                         partialInteractiveRegion, interactionId, callback, mFetchFlags | flags,
   2661                         interrogatingPid, interrogatingTid, spec);
   2662                 return true;
   2663             } catch (RemoteException re) {
   2664                 if (DEBUG) {
   2665                     Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
   2666                 }
   2667             } finally {
   2668                 Binder.restoreCallingIdentity(identityToken);
   2669                 // Recycle if passed to another process.
   2670                 if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
   2671                     partialInteractiveRegion.recycle();
   2672                 }
   2673             }
   2674             return false;
   2675         }
   2676 
   2677         @Override
   2678         public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId,
   2679                 int focusType, int interactionId,
   2680                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
   2681                 throws RemoteException {
   2682             final int resolvedWindowId;
   2683             IAccessibilityInteractionConnection connection = null;
   2684             Region partialInteractiveRegion = Region.obtain();
   2685             synchronized (mLock) {
   2686                 if (!isCalledForCurrentUserLocked()) {
   2687                     return false;
   2688                 }
   2689                 resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked(
   2690                         accessibilityWindowId, focusType);
   2691                 final boolean permissionGranted =
   2692                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
   2693                 if (!permissionGranted) {
   2694                     return false;
   2695                 } else {
   2696                     connection = getConnectionLocked(resolvedWindowId);
   2697                     if (connection == null) {
   2698                         return false;
   2699                     }
   2700                 }
   2701                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
   2702                         resolvedWindowId, partialInteractiveRegion)) {
   2703                     partialInteractiveRegion.recycle();
   2704                     partialInteractiveRegion = null;
   2705                 }
   2706             }
   2707             final int interrogatingPid = Binder.getCallingPid();
   2708             final long identityToken = Binder.clearCallingIdentity();
   2709             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
   2710             try {
   2711                 connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion,
   2712                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
   2713                         spec);
   2714                 return true;
   2715             } catch (RemoteException re) {
   2716                 if (DEBUG) {
   2717                     Slog.e(LOG_TAG, "Error calling findFocus()");
   2718                 }
   2719             } finally {
   2720                 Binder.restoreCallingIdentity(identityToken);
   2721                 // Recycle if passed to another process.
   2722                 if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
   2723                     partialInteractiveRegion.recycle();
   2724                 }
   2725             }
   2726             return false;
   2727         }
   2728 
   2729         @Override
   2730         public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId,
   2731                 int direction, int interactionId,
   2732                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
   2733                 throws RemoteException {
   2734             final int resolvedWindowId;
   2735             IAccessibilityInteractionConnection connection = null;
   2736             Region partialInteractiveRegion = Region.obtain();
   2737             synchronized (mLock) {
   2738                 if (!isCalledForCurrentUserLocked()) {
   2739                     return false;
   2740                 }
   2741                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
   2742                 final boolean permissionGranted =
   2743                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
   2744                 if (!permissionGranted) {
   2745                     return false;
   2746                 } else {
   2747                     connection = getConnectionLocked(resolvedWindowId);
   2748                     if (connection == null) {
   2749                         return false;
   2750                     }
   2751                 }
   2752                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
   2753                         resolvedWindowId, partialInteractiveRegion)) {
   2754                     partialInteractiveRegion.recycle();
   2755                     partialInteractiveRegion = null;
   2756                 }
   2757             }
   2758             final int interrogatingPid = Binder.getCallingPid();
   2759             final long identityToken = Binder.clearCallingIdentity();
   2760             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
   2761             try {
   2762                 connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion,
   2763                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
   2764                         spec);
   2765                 return true;
   2766             } catch (RemoteException re) {
   2767                 if (DEBUG) {
   2768                     Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()");
   2769                 }
   2770             } finally {
   2771                 Binder.restoreCallingIdentity(identityToken);
   2772                 // Recycle if passed to another process.
   2773                 if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
   2774                     partialInteractiveRegion.recycle();
   2775                 }
   2776             }
   2777             return false;
   2778         }
   2779 
   2780         @Override
   2781         public void sendGesture(int sequence, ParceledListSlice gestureSteps) {
   2782             synchronized (mLock) {
   2783                 if (mSecurityPolicy.canPerformGestures(this)) {
   2784                     final long endMillis =
   2785                             SystemClock.uptimeMillis() + WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS;
   2786                     while ((mMotionEventInjector == null)
   2787                             && (SystemClock.uptimeMillis() < endMillis)) {
   2788                         try {
   2789                             mLock.wait(endMillis - SystemClock.uptimeMillis());
   2790                         } catch (InterruptedException ie) {
   2791                             /* ignore */
   2792                         }
   2793                     }
   2794                     if (mMotionEventInjector != null) {
   2795                         List<GestureDescription.GestureStep> steps = gestureSteps.getList();
   2796                         List<MotionEvent> events = GestureDescription.MotionEventGenerator
   2797                                 .getMotionEventsFromGestureSteps(steps);
   2798                         // Confirm that the motion events end with an UP event.
   2799                         if (events.get(events.size() - 1).getAction() == MotionEvent.ACTION_UP) {
   2800                             mMotionEventInjector.injectEvents(events, mServiceInterface, sequence);
   2801                             return;
   2802                         } else {
   2803                             Slog.e(LOG_TAG, "Gesture is not well-formed");
   2804                         }
   2805                     } else {
   2806                         Slog.e(LOG_TAG, "MotionEventInjector installation timed out");
   2807                     }
   2808                 }
   2809             }
   2810             try {
   2811                 mServiceInterface.onPerformGestureResult(sequence, false);
   2812             } catch (RemoteException re) {
   2813                 Slog.e(LOG_TAG, "Error sending motion event injection failure to "
   2814                         + mServiceInterface, re);
   2815             }
   2816         }
   2817 
   2818         @Override
   2819         public boolean performAccessibilityAction(int accessibilityWindowId,
   2820                 long accessibilityNodeId, int action, Bundle arguments, int interactionId,
   2821                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
   2822                 throws RemoteException {
   2823             final int resolvedWindowId;
   2824             IAccessibilityInteractionConnection connection = null;
   2825             synchronized (mLock) {
   2826                 if (!isCalledForCurrentUserLocked()) {
   2827                     return false;
   2828                 }
   2829                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
   2830                 final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked(
   2831                         this, resolvedWindowId);
   2832                 if (!permissionGranted) {
   2833                     return false;
   2834                 } else {
   2835                     connection = getConnectionLocked(resolvedWindowId);
   2836                     if (connection == null) {
   2837                         return false;
   2838                     }
   2839                 }
   2840             }
   2841             final int interrogatingPid = Binder.getCallingPid();
   2842             final long identityToken = Binder.clearCallingIdentity();
   2843             try {
   2844                 // Regardless of whether or not the action succeeds, it was generated by an
   2845                 // accessibility service that is driven by user actions, so note user activity.
   2846                 mPowerManager.userActivity(SystemClock.uptimeMillis(),
   2847                         PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);
   2848 
   2849                 connection.performAccessibilityAction(accessibilityNodeId, action, arguments,
   2850                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid);
   2851             } catch (RemoteException re) {
   2852                 if (DEBUG) {
   2853                     Slog.e(LOG_TAG, "Error calling performAccessibilityAction()");
   2854                 }
   2855             } finally {
   2856                 Binder.restoreCallingIdentity(identityToken);
   2857             }
   2858             return true;
   2859         }
   2860 
   2861         @Override
   2862         public boolean performGlobalAction(int action) {
   2863             synchronized (mLock) {
   2864                 if (!isCalledForCurrentUserLocked()) {
   2865                     return false;
   2866                 }
   2867             }
   2868             final long identity = Binder.clearCallingIdentity();
   2869             try {
   2870                 mPowerManager.userActivity(SystemClock.uptimeMillis(),
   2871                         PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);
   2872                 switch (action) {
   2873                     case AccessibilityService.GLOBAL_ACTION_BACK: {
   2874                         sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK);
   2875                     } return true;
   2876                     case AccessibilityService.GLOBAL_ACTION_HOME: {
   2877                         sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME);
   2878                     } return true;
   2879                     case AccessibilityService.GLOBAL_ACTION_RECENTS: {
   2880                         openRecents();
   2881                     } return true;
   2882                     case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: {
   2883                         expandNotifications();
   2884                     } return true;
   2885                     case AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS: {
   2886                         expandQuickSettings();
   2887                     } return true;
   2888                     case AccessibilityService.GLOBAL_ACTION_POWER_DIALOG: {
   2889                         showGlobalActions();
   2890                     } return true;
   2891                     case AccessibilityService.GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN: {
   2892                         toggleSplitScreen();
   2893                     } return true;
   2894                 }
   2895                 return false;
   2896             } finally {
   2897                 Binder.restoreCallingIdentity(identity);
   2898             }
   2899         }
   2900 
   2901         @Override
   2902         public float getMagnificationScale() {
   2903             synchronized (mLock) {
   2904                 if (!isCalledForCurrentUserLocked()) {
   2905                     return 1.0f;
   2906                 }
   2907             }
   2908             final long identity = Binder.clearCallingIdentity();
   2909             try {
   2910                 return getMagnificationController().getScale();
   2911             } finally {
   2912                 Binder.restoreCallingIdentity(identity);
   2913             }
   2914         }
   2915 
   2916         @Override
   2917         public Region getMagnificationRegion() {
   2918             synchronized (mLock) {
   2919                 final Region region = Region.obtain();
   2920                 if (!isCalledForCurrentUserLocked()) {
   2921                     return region;
   2922                 }
   2923                 MagnificationController magnificationController = getMagnificationController();
   2924                 boolean forceRegistration = mSecurityPolicy.canControlMagnification(this);
   2925                 boolean initiallyRegistered = magnificationController.isRegisteredLocked();
   2926                 if (!initiallyRegistered && forceRegistration) {
   2927                     magnificationController.register();
   2928                 }
   2929                 final long identity = Binder.clearCallingIdentity();
   2930                 try {
   2931                     magnificationController.getMagnificationRegion(region);
   2932                     return region;
   2933                 } finally {
   2934                     Binder.restoreCallingIdentity(identity);
   2935                     if (!initiallyRegistered && forceRegistration) {
   2936                         magnificationController.unregister();
   2937                     }
   2938                 }
   2939             }
   2940         }
   2941 
   2942         @Override
   2943         public float getMagnificationCenterX() {
   2944             synchronized (mLock) {
   2945                 if (!isCalledForCurrentUserLocked()) {
   2946                     return 0.0f;
   2947                 }
   2948             }
   2949             final long identity = Binder.clearCallingIdentity();
   2950             try {
   2951                 return getMagnificationController().getCenterX();
   2952             } finally {
   2953                 Binder.restoreCallingIdentity(identity);
   2954             }
   2955         }
   2956 
   2957         @Override
   2958         public float getMagnificationCenterY() {
   2959             synchronized (mLock) {
   2960                 if (!isCalledForCurrentUserLocked()) {
   2961                     return 0.0f;
   2962                 }
   2963             }
   2964             final long identity = Binder.clearCallingIdentity();
   2965             try {
   2966                 return getMagnificationController().getCenterY();
   2967             } finally {
   2968                 Binder.restoreCallingIdentity(identity);
   2969             }
   2970         }
   2971 
   2972         @Override
   2973         public boolean resetMagnification(boolean animate) {
   2974             synchronized (mLock) {
   2975                 if (!isCalledForCurrentUserLocked()) {
   2976                     return false;
   2977                 }
   2978                 final boolean permissionGranted = mSecurityPolicy.canControlMagnification(this);
   2979                 if (!permissionGranted) {
   2980                     return false;
   2981                 }
   2982             }
   2983             final long identity = Binder.clearCallingIdentity();
   2984             try {
   2985                 return getMagnificationController().reset(animate);
   2986             } finally {
   2987                 Binder.restoreCallingIdentity(identity);
   2988             }
   2989         }
   2990 
   2991         @Override
   2992         public boolean setMagnificationScaleAndCenter(float scale, float centerX, float centerY,
   2993                 boolean animate) {
   2994             synchronized (mLock) {
   2995                 if (!isCalledForCurrentUserLocked()) {
   2996                     return false;
   2997                 }
   2998                 final boolean permissionGranted = mSecurityPolicy.canControlMagnification(this);
   2999                 if (!permissionGranted) {
   3000                     return false;
   3001                 }
   3002                 final long identity = Binder.clearCallingIdentity();
   3003                 try {
   3004                     MagnificationController magnificationController = getMagnificationController();
   3005                     if (!magnificationController.isRegisteredLocked()) {
   3006                         magnificationController.register();
   3007                     }
   3008                     return magnificationController
   3009                             .setScaleAndCenter(scale, centerX, centerY, animate, mId);
   3010                 } finally {
   3011                     Binder.restoreCallingIdentity(identity);
   3012                 }
   3013             }
   3014         }
   3015 
   3016         @Override
   3017         public void setMagnificationCallbackEnabled(boolean enabled) {
   3018             mInvocationHandler.setMagnificationCallbackEnabled(enabled);
   3019         }
   3020 
   3021         @Override
   3022         public boolean setSoftKeyboardShowMode(int showMode) {
   3023             final UserState userState;
   3024             synchronized (mLock) {
   3025                 if (!isCalledForCurrentUserLocked()) {
   3026                     return false;
   3027                 }
   3028 
   3029                 userState = getCurrentUserStateLocked();
   3030             }
   3031 
   3032             final long identity = Binder.clearCallingIdentity();
   3033             try {
   3034                 // Keep track of the last service to request a non-default show mode. The show mode
   3035                 // should be restored to default should this service be disabled.
   3036                 if (showMode == Settings.Secure.SHOW_MODE_AUTO) {
   3037                     userState.mServiceChangingSoftKeyboardMode = null;
   3038                 } else {
   3039                     userState.mServiceChangingSoftKeyboardMode = mComponentName;
   3040                 }
   3041 
   3042                 Settings.Secure.putIntForUser(mContext.getContentResolver(),
   3043                         Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, showMode,
   3044                         userState.mUserId);
   3045             } finally {
   3046                 Binder.restoreCallingIdentity(identity);
   3047             }
   3048             return true;
   3049         }
   3050 
   3051         @Override
   3052         public void setSoftKeyboardCallbackEnabled(boolean enabled) {
   3053             mInvocationHandler.setSoftKeyboardCallbackEnabled(enabled);
   3054         }
   3055 
   3056         @Override
   3057         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
   3058             mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
   3059             synchronized (mLock) {
   3060                 pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo()
   3061                         .loadLabel(mContext.getPackageManager()));
   3062                 pw.append(", feedbackType"
   3063                         + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType));
   3064                 pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities());
   3065                 pw.append(", eventTypes="
   3066                         + AccessibilityEvent.eventTypeToString(mEventTypes));
   3067                 pw.append(", notificationTimeout=" + mNotificationTimeout);
   3068                 pw.append("]");
   3069             }
   3070         }
   3071 
   3072         @Override
   3073         public void onServiceDisconnected(ComponentName componentName) {
   3074             binderDied();
   3075         }
   3076 
   3077         public void onAdded() throws RemoteException {
   3078             linkToOwnDeathLocked();
   3079             final long identity = Binder.clearCallingIdentity();
   3080             try {
   3081                 mWindowManagerService.addWindowToken(mOverlayWindowToken,
   3082                         WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY);
   3083             } finally {
   3084                 Binder.restoreCallingIdentity(identity);
   3085             }
   3086         }
   3087 
   3088         public void onRemoved() {
   3089             final long identity = Binder.clearCallingIdentity();
   3090             try {
   3091                 mWindowManagerService.removeWindowToken(mOverlayWindowToken, true);
   3092             } finally {
   3093                 Binder.restoreCallingIdentity(identity);
   3094             }
   3095             unlinkToOwnDeathLocked();
   3096         }
   3097 
   3098         public void linkToOwnDeathLocked() throws RemoteException {
   3099             mService.linkToDeath(this, 0);
   3100         }
   3101 
   3102         public void unlinkToOwnDeathLocked() {
   3103             if (mService != null) {
   3104                 mService.unlinkToDeath(this, 0);
   3105             }
   3106         }
   3107 
   3108         public void resetLocked() {
   3109             try {
   3110                 // Clear the proxy in the other process so this
   3111                 // IAccessibilityServiceConnection can be garbage collected.
   3112                 if (mServiceInterface != null) {
   3113                     mServiceInterface.init(null, mId, null);
   3114                 }
   3115             } catch (RemoteException re) {
   3116                 /* ignore */
   3117             }
   3118             mService = null;
   3119             mServiceInterface = null;
   3120         }
   3121 
   3122         public boolean isConnectedLocked() {
   3123             return (mService != null);
   3124         }
   3125 
   3126         public void binderDied() {
   3127             synchronized (mLock) {
   3128                 // It is possible that this service's package was force stopped during
   3129                 // whose handling the death recipient is unlinked and still get a call
   3130                 // on binderDied since the call was made before we unlink but was
   3131                 // waiting on the lock we held during the force stop handling.
   3132                 if (!isConnectedLocked()) {
   3133                     return;
   3134                 }
   3135                 mWasConnectedAndDied = true;
   3136                 getKeyEventDispatcher().flush(this);
   3137                 UserState userState = getUserStateLocked(mUserId);
   3138                 resetLocked();
   3139                 if (mIsAutomation) {
   3140                     // This is typically done when unbinding, but UiAutomation isn't bound.
   3141                     removeServiceLocked(this, userState);
   3142                     // We no longer have an automation service, so restore
   3143                     // the state based on values in the settings database.
   3144                     userState.mInstalledServices.remove(mAccessibilityServiceInfo);
   3145                     userState.mEnabledServices.remove(mComponentName);
   3146                     userState.destroyUiAutomationService();
   3147                     readConfigurationForUserStateLocked(userState);
   3148                 }
   3149                 if (mId == getMagnificationController().getIdOfLastServiceToMagnify()) {
   3150                     getMagnificationController().resetIfNeeded(true);
   3151                 }
   3152                 onUserStateChangedLocked(userState);
   3153             }
   3154         }
   3155 
   3156         /**
   3157          * Performs a notification for an {@link AccessibilityEvent}.
   3158          *
   3159          * @param event The event.
   3160          */
   3161         public void notifyAccessibilityEvent(AccessibilityEvent event) {
   3162             synchronized (mLock) {
   3163                 final int eventType = event.getEventType();
   3164                 // Make a copy since during dispatch it is possible the event to
   3165                 // be modified to remove its source if the receiving service does
   3166                 // not have permission to access the window content.
   3167                 AccessibilityEvent newEvent = AccessibilityEvent.obtain(event);
   3168                 Message message;
   3169                 if ((mNotificationTimeout > 0)
   3170                         && (eventType != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)) {
   3171                     // Allow at most one pending event
   3172                     final AccessibilityEvent oldEvent = mPendingEvents.get(eventType);
   3173                     mPendingEvents.put(eventType, newEvent);
   3174                     if (oldEvent != null) {
   3175                         mEventDispatchHandler.removeMessages(eventType);
   3176                         oldEvent.recycle();
   3177                     }
   3178                     message = mEventDispatchHandler.obtainMessage(eventType);
   3179                 } else {
   3180                     // Send all messages, bypassing mPendingEvents
   3181                     message = mEventDispatchHandler.obtainMessage(eventType, newEvent);
   3182                 }
   3183 
   3184                 mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout);
   3185             }
   3186         }
   3187 
   3188         /**
   3189          * Notifies an accessibility service client for a scheduled event given the event type.
   3190          *
   3191          * @param eventType The type of the event to dispatch.
   3192          */
   3193         private void notifyAccessibilityEventInternal(int eventType, AccessibilityEvent event) {
   3194             IAccessibilityServiceClient listener;
   3195 
   3196             synchronized (mLock) {
   3197                 listener = mServiceInterface;
   3198 
   3199                 // If the service died/was disabled while the message for dispatching
   3200                 // the accessibility event was propagating the listener may be null.
   3201                 if (listener == null) {
   3202                     return;
   3203                 }
   3204 
   3205                 // There are two ways we notify for events, throttled and non-throttled. If we
   3206                 // are not throttling, then messages come with events, which we handle with
   3207                 // minimal fuss.
   3208                 if (event == null) {
   3209                     // We are throttling events, so we'll send the event for this type in
   3210                     // mPendingEvents as long as it it's null. It can only null due to a race
   3211                     // condition:
   3212                     //
   3213                     //   1) A binder thread calls notifyAccessibilityServiceDelayedLocked
   3214                     //      which posts a message for dispatching an event and stores the event
   3215                     //      in mPendingEvents.
   3216                     //   2) The message is pulled from the queue by the handler on the service
   3217                     //      thread and this method is just about to acquire the lock.
   3218                     //   3) Another binder thread acquires the lock in notifyAccessibilityEvent
   3219                     //   4) notifyAccessibilityEvent recycles the event that this method was about
   3220                     //      to process, replaces it with a new one, and posts a second message
   3221                     //   5) This method grabs the new event, processes it, and removes it from
   3222                     //      mPendingEvents
   3223                     //   6) The second message dispatched in (4) arrives, but the event has been
   3224                     //      remvoved in (5).
   3225                     event = mPendingEvents.get(eventType);
   3226                     if (event == null) {
   3227                         return;
   3228                     }
   3229                     mPendingEvents.remove(eventType);
   3230                 }
   3231                 if (mSecurityPolicy.canRetrieveWindowContentLocked(this)) {
   3232                     event.setConnectionId(mId);
   3233                 } else {
   3234                     event.setSource(null);
   3235                 }
   3236                 event.setSealed(true);
   3237             }
   3238 
   3239             try {
   3240                 listener.onAccessibilityEvent(event);
   3241                 if (DEBUG) {
   3242                     Slog.i(LOG_TAG, "Event " + event + " sent to " + listener);
   3243                 }
   3244             } catch (RemoteException re) {
   3245                 Slog.e(LOG_TAG, "Error during sending " + event + " to " + listener, re);
   3246             } finally {
   3247                 event.recycle();
   3248             }
   3249         }
   3250 
   3251         public void notifyGesture(int gestureId) {
   3252             mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE,
   3253                     gestureId, 0).sendToTarget();
   3254         }
   3255 
   3256         public void notifyClearAccessibilityNodeInfoCache() {
   3257             mInvocationHandler.sendEmptyMessage(
   3258                     InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE);
   3259         }
   3260 
   3261         public void notifyMagnificationChangedLocked(@NonNull Region region,
   3262                 float scale, float centerX, float centerY) {
   3263             mInvocationHandler
   3264                     .notifyMagnificationChangedLocked(region, scale, centerX, centerY);
   3265         }
   3266 
   3267         public void notifySoftKeyboardShowModeChangedLocked(int showState) {
   3268             mInvocationHandler.notifySoftKeyboardShowModeChangedLocked(showState);
   3269         }
   3270 
   3271         /**
   3272          * Called by the invocation handler to notify the service that the
   3273          * state of magnification has changed.
   3274          */
   3275         private void notifyMagnificationChangedInternal(@NonNull Region region,
   3276                 float scale, float centerX, float centerY) {
   3277             final IAccessibilityServiceClient listener;
   3278             synchronized (mLock) {
   3279                 listener = mServiceInterface;
   3280             }
   3281             if (listener != null) {
   3282                 try {
   3283                     listener.onMagnificationChanged(region, scale, centerX, centerY);
   3284                 } catch (RemoteException re) {
   3285                     Slog.e(LOG_TAG, "Error sending magnification changes to " + mService, re);
   3286                 }
   3287             }
   3288         }
   3289 
   3290         /**
   3291          * Called by the invocation handler to notify the service that the state of the soft
   3292          * keyboard show mode has changed.
   3293          */
   3294         private void notifySoftKeyboardShowModeChangedInternal(int showState) {
   3295             final IAccessibilityServiceClient listener;
   3296             synchronized (mLock) {
   3297                 listener = mServiceInterface;
   3298             }
   3299             if (listener != null) {
   3300                 try {
   3301                     listener.onSoftKeyboardShowModeChanged(showState);
   3302                 } catch (RemoteException re) {
   3303                     Slog.e(LOG_TAG, "Error sending soft keyboard show mode changes to " + mService,
   3304                             re);
   3305                 }
   3306             }
   3307         }
   3308 
   3309         private void notifyGestureInternal(int gestureId) {
   3310             final IAccessibilityServiceClient listener;
   3311             synchronized (mLock) {
   3312                 listener = mServiceInterface;
   3313             }
   3314             if (listener != null) {
   3315                 try {
   3316                     listener.onGesture(gestureId);
   3317                 } catch (RemoteException re) {
   3318                     Slog.e(LOG_TAG, "Error during sending gesture " + gestureId
   3319                             + " to " + mService, re);
   3320                 }
   3321             }
   3322         }
   3323 
   3324         private void notifyClearAccessibilityCacheInternal() {
   3325             final IAccessibilityServiceClient listener;
   3326             synchronized (mLock) {
   3327                 listener = mServiceInterface;
   3328             }
   3329             if (listener != null) {
   3330                 try {
   3331                     listener.clearAccessibilityCache();
   3332                 } catch (RemoteException re) {
   3333                     Slog.e(LOG_TAG, "Error during requesting accessibility info cache"
   3334                             + " to be cleared.", re);
   3335                 }
   3336             }
   3337         }
   3338 
   3339         private void sendDownAndUpKeyEvents(int keyCode) {
   3340             final long token = Binder.clearCallingIdentity();
   3341 
   3342             // Inject down.
   3343             final long downTime = SystemClock.uptimeMillis();
   3344             KeyEvent down = KeyEvent.obtain(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode, 0, 0,
   3345                     KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
   3346                     InputDevice.SOURCE_KEYBOARD, null);
   3347             InputManager.getInstance().injectInputEvent(down,
   3348                     InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
   3349             down.recycle();
   3350 
   3351             // Inject up.
   3352             final long upTime = SystemClock.uptimeMillis();
   3353             KeyEvent up = KeyEvent.obtain(downTime, upTime, KeyEvent.ACTION_UP, keyCode, 0, 0,
   3354                     KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
   3355                     InputDevice.SOURCE_KEYBOARD, null);
   3356             InputManager.getInstance().injectInputEvent(up,
   3357                     InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
   3358             up.recycle();
   3359 
   3360             Binder.restoreCallingIdentity(token);
   3361         }
   3362 
   3363         private void expandNotifications() {
   3364             final long token = Binder.clearCallingIdentity();
   3365 
   3366             StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService(
   3367                     android.app.Service.STATUS_BAR_SERVICE);
   3368             statusBarManager.expandNotificationsPanel();
   3369 
   3370             Binder.restoreCallingIdentity(token);
   3371         }
   3372 
   3373         private void expandQuickSettings() {
   3374             final long token = Binder.clearCallingIdentity();
   3375 
   3376             StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService(
   3377                     android.app.Service.STATUS_BAR_SERVICE);
   3378             statusBarManager.expandSettingsPanel();
   3379 
   3380             Binder.restoreCallingIdentity(token);
   3381         }
   3382 
   3383         private void openRecents() {
   3384             final long token = Binder.clearCallingIdentity();
   3385 
   3386             StatusBarManagerInternal statusBarService = LocalServices.getService(
   3387                     StatusBarManagerInternal.class);
   3388             statusBarService.toggleRecentApps();
   3389 
   3390             Binder.restoreCallingIdentity(token);
   3391         }
   3392 
   3393         private void showGlobalActions() {
   3394             mWindowManagerService.showGlobalActions();
   3395         }
   3396 
   3397         private void toggleSplitScreen() {
   3398             LocalServices.getService(StatusBarManagerInternal.class).toggleSplitScreen();
   3399         }
   3400 
   3401         private IAccessibilityInteractionConnection getConnectionLocked(int windowId) {
   3402             if (DEBUG) {
   3403                 Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId);
   3404             }
   3405             AccessibilityConnectionWrapper wrapper = mGlobalInteractionConnections.get(windowId);
   3406             if (wrapper == null) {
   3407                 wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId);
   3408             }
   3409             if (wrapper != null && wrapper.mConnection != null) {
   3410                 return wrapper.mConnection;
   3411             }
   3412             if (DEBUG) {
   3413                 Slog.e(LOG_TAG, "No interaction connection to window: " + windowId);
   3414             }
   3415             return null;
   3416         }
   3417 
   3418         private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) {
   3419             if (accessibilityWindowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) {
   3420                 return mSecurityPolicy.getActiveWindowId();
   3421             }
   3422             return accessibilityWindowId;
   3423         }
   3424 
   3425         private int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) {
   3426             if (windowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) {
   3427                 return mSecurityPolicy.mActiveWindowId;
   3428             }
   3429             if (windowId == AccessibilityNodeInfo.ANY_WINDOW_ID) {
   3430                 if (focusType == AccessibilityNodeInfo.FOCUS_INPUT) {
   3431                     return mSecurityPolicy.mFocusedWindowId;
   3432                 } else if (focusType == AccessibilityNodeInfo.FOCUS_ACCESSIBILITY) {
   3433                     return mSecurityPolicy.mAccessibilityFocusedWindowId;
   3434                 }
   3435             }
   3436             return windowId;
   3437         }
   3438 
   3439         private final class InvocationHandler extends Handler {
   3440             public static final int MSG_ON_GESTURE = 1;
   3441             public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 2;
   3442 
   3443             private static final int MSG_ON_MAGNIFICATION_CHANGED = 5;
   3444             private static final int MSG_ON_SOFT_KEYBOARD_STATE_CHANGED = 6;
   3445 
   3446             private boolean mIsMagnificationCallbackEnabled = false;
   3447             private boolean mIsSoftKeyboardCallbackEnabled = false;
   3448 
   3449             public InvocationHandler(Looper looper) {
   3450                 super(looper, null, true);
   3451             }
   3452 
   3453             @Override
   3454             public void handleMessage(Message message) {
   3455                 final int type = message.what;
   3456                 switch (type) {
   3457                     case MSG_ON_GESTURE: {
   3458                         final int gestureId = message.arg1;
   3459                         notifyGestureInternal(gestureId);
   3460                     } break;
   3461 
   3462                     case MSG_CLEAR_ACCESSIBILITY_CACHE: {
   3463                         notifyClearAccessibilityCacheInternal();
   3464                     } break;
   3465 
   3466                     case MSG_ON_MAGNIFICATION_CHANGED: {
   3467                         final SomeArgs args = (SomeArgs) message.obj;
   3468                         final Region region = (Region) args.arg1;
   3469                         final float scale = (float) args.arg2;
   3470                         final float centerX = (float) args.arg3;
   3471                         final float centerY = (float) args.arg4;
   3472                         notifyMagnificationChangedInternal(region, scale, centerX, centerY);
   3473                     } break;
   3474 
   3475                     case MSG_ON_SOFT_KEYBOARD_STATE_CHANGED: {
   3476                         final int showState = (int) message.arg1;
   3477                         notifySoftKeyboardShowModeChangedInternal(showState);
   3478                     } break;
   3479 
   3480                     default: {
   3481                         throw new IllegalArgumentException("Unknown message: " + type);
   3482                     }
   3483                 }
   3484             }
   3485 
   3486             public void notifyMagnificationChangedLocked(@NonNull Region region, float scale,
   3487                     float centerX, float centerY) {
   3488                 if (!mIsMagnificationCallbackEnabled) {
   3489                     // Callback is disabled, don't bother packing args.
   3490                     return;
   3491                 }
   3492 
   3493                 final SomeArgs args = SomeArgs.obtain();
   3494                 args.arg1 = region;
   3495                 args.arg2 = scale;
   3496                 args.arg3 = centerX;
   3497                 args.arg4 = centerY;
   3498 
   3499                 final Message msg = obtainMessage(MSG_ON_MAGNIFICATION_CHANGED, args);
   3500                 msg.sendToTarget();
   3501             }
   3502 
   3503             public void setMagnificationCallbackEnabled(boolean enabled) {
   3504                 mIsMagnificationCallbackEnabled = enabled;
   3505             }
   3506 
   3507             public void notifySoftKeyboardShowModeChangedLocked(int showState) {
   3508                 if (!mIsSoftKeyboardCallbackEnabled) {
   3509                     return;
   3510                 }
   3511 
   3512                 final Message msg = obtainMessage(MSG_ON_SOFT_KEYBOARD_STATE_CHANGED, showState, 0);
   3513                 msg.sendToTarget();
   3514             }
   3515 
   3516             public void setSoftKeyboardCallbackEnabled(boolean enabled) {
   3517                 mIsSoftKeyboardCallbackEnabled = enabled;
   3518             }
   3519         }
   3520     }
   3521 
   3522     final class WindowsForAccessibilityCallback implements
   3523             WindowManagerInternal.WindowsForAccessibilityCallback {
   3524 
   3525         @Override
   3526         public void onWindowsForAccessibilityChanged(List<WindowInfo> windows) {
   3527             synchronized (mLock) {
   3528                 // Populate the windows to report.
   3529                 List<AccessibilityWindowInfo> reportedWindows = new ArrayList<>();
   3530                 final int receivedWindowCount = windows.size();
   3531                 for (int i = 0; i < receivedWindowCount; i++) {
   3532                     WindowInfo receivedWindow = windows.get(i);
   3533                     AccessibilityWindowInfo reportedWindow = populateReportedWindow(
   3534                             receivedWindow);
   3535                     if (reportedWindow != null) {
   3536                         reportedWindows.add(reportedWindow);
   3537                     }
   3538                 }
   3539 
   3540                 if (DEBUG) {
   3541                     Slog.i(LOG_TAG, "Windows changed: " + reportedWindows);
   3542                 }
   3543 
   3544                 // Let the policy update the focused and active windows.
   3545                 mSecurityPolicy.updateWindowsLocked(reportedWindows);
   3546 
   3547                 // Someone may be waiting for the windows - advertise it.
   3548                 mLock.notifyAll();
   3549             }
   3550         }
   3551 
   3552         private AccessibilityWindowInfo populateReportedWindow(WindowInfo window) {
   3553             final int windowId = findWindowIdLocked(window.token);
   3554             if (windowId < 0) {
   3555                 return null;
   3556             }
   3557 
   3558             AccessibilityWindowInfo reportedWindow = AccessibilityWindowInfo.obtain();
   3559 
   3560             reportedWindow.setId(windowId);
   3561             reportedWindow.setType(getTypeForWindowManagerWindowType(window.type));
   3562             reportedWindow.setLayer(window.layer);
   3563             reportedWindow.setFocused(window.focused);
   3564             reportedWindow.setBoundsInScreen(window.boundsInScreen);
   3565             reportedWindow.setTitle(window.title);
   3566             reportedWindow.setAnchorId(window.accessibilityIdOfAnchor);
   3567 
   3568             final int parentId = findWindowIdLocked(window.parentToken);
   3569             if (parentId >= 0) {
   3570                 reportedWindow.setParentId(parentId);
   3571             }
   3572 
   3573             if (window.childTokens != null) {
   3574                 final int childCount = window.childTokens.size();
   3575                 for (int i = 0; i < childCount; i++) {
   3576                     IBinder childToken = window.childTokens.get(i);
   3577                     final int childId = findWindowIdLocked(childToken);
   3578                     if (childId >= 0) {
   3579                         reportedWindow.addChild(childId);
   3580                     }
   3581                 }
   3582             }
   3583 
   3584             return reportedWindow;
   3585         }
   3586 
   3587         private int getTypeForWindowManagerWindowType(int windowType) {
   3588             switch (windowType) {
   3589                 case WindowManager.LayoutParams.TYPE_APPLICATION:
   3590                 case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA:
   3591                 case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL:
   3592                 case WindowManager.LayoutParams.TYPE_APPLICATION_STARTING:
   3593                 case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL:
   3594                 case WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL:
   3595                 case WindowManager.LayoutParams.TYPE_BASE_APPLICATION:
   3596                 case WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION:
   3597                 case WindowManager.LayoutParams.TYPE_PHONE:
   3598                 case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE:
   3599                 case WindowManager.LayoutParams.TYPE_TOAST:
   3600                 case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG: {
   3601                     return AccessibilityWindowInfo.TYPE_APPLICATION;
   3602                 }
   3603 
   3604                 case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
   3605                 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: {
   3606                     return AccessibilityWindowInfo.TYPE_INPUT_METHOD;
   3607                 }
   3608 
   3609                 case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG:
   3610                 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
   3611                 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL:
   3612                 case WindowManager.LayoutParams.TYPE_SEARCH_BAR:
   3613                 case WindowManager.LayoutParams.TYPE_STATUS_BAR:
   3614                 case WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL:
   3615                 case WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL:
   3616                 case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY:
   3617                 case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
   3618                 case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
   3619                 case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
   3620                 case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
   3621                 case WindowManager.LayoutParams.TYPE_SCREENSHOT: {
   3622                     return AccessibilityWindowInfo.TYPE_SYSTEM;
   3623                 }
   3624 
   3625                 case WindowManager.LayoutParams.TYPE_DOCK_DIVIDER: {
   3626                     return AccessibilityWindowInfo.TYPE_SPLIT_SCREEN_DIVIDER;
   3627                 }
   3628 
   3629                 case WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY: {
   3630                     return AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY;
   3631                 }
   3632 
   3633                 default: {
   3634                     return -1;
   3635                 }
   3636             }
   3637         }
   3638     }
   3639 
   3640     private final class InteractionBridge {
   3641         private final Display mDefaultDisplay;
   3642         private final int mConnectionId;
   3643         private final AccessibilityInteractionClient mClient;
   3644 
   3645         public InteractionBridge() {
   3646             AccessibilityServiceInfo info = new AccessibilityServiceInfo();
   3647             info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
   3648             info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
   3649             info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
   3650             Service service = new Service(UserHandle.USER_NULL,
   3651                     sFakeAccessibilityServiceComponentName, info);
   3652 
   3653             mConnectionId = service.mId;
   3654 
   3655             mClient = AccessibilityInteractionClient.getInstance();
   3656             mClient.addConnection(mConnectionId, service);
   3657 
   3658             //TODO: (multi-display) We need to support multiple displays.
   3659             DisplayManager displayManager = (DisplayManager)
   3660                     mContext.getSystemService(Context.DISPLAY_SERVICE);
   3661             mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
   3662         }
   3663 
   3664         public void clearAccessibilityFocusNotLocked(int windowId) {
   3665             AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked(windowId);
   3666             if (focus != null) {
   3667                 focus.performAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
   3668             }
   3669         }
   3670 
   3671         public boolean getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint) {
   3672             AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked();
   3673             if (focus == null) {
   3674                 return false;
   3675             }
   3676 
   3677             synchronized (mLock) {
   3678                 Rect boundsInScreen = mTempRect;
   3679                 focus.getBoundsInScreen(boundsInScreen);
   3680 
   3681                 // Clip to the window bounds.
   3682                 Rect windowBounds = mTempRect1;
   3683                 getWindowBounds(focus.getWindowId(), windowBounds);
   3684                 if (!boundsInScreen.intersect(windowBounds)) {
   3685                     return false;
   3686                 }
   3687 
   3688                 // Apply magnification if needed.
   3689                 MagnificationSpec spec = getCompatibleMagnificationSpecLocked(focus.getWindowId());
   3690                 if (spec != null && !spec.isNop()) {
   3691                     boundsInScreen.offset((int) -spec.offsetX, (int) -spec.offsetY);
   3692                     boundsInScreen.scale(1 / spec.scale);
   3693                 }
   3694 
   3695                 // Clip to the screen bounds.
   3696                 Point screenSize = mTempPoint;
   3697                 mDefaultDisplay.getRealSize(screenSize);
   3698                 if (!boundsInScreen.intersect(0, 0, screenSize.x, screenSize.y)) {
   3699                     return false;
   3700                 }
   3701 
   3702                 outPoint.set(boundsInScreen.centerX(), boundsInScreen.centerY());
   3703             }
   3704 
   3705             return true;
   3706         }
   3707 
   3708         private AccessibilityNodeInfo getAccessibilityFocusNotLocked() {
   3709             final int focusedWindowId;
   3710             synchronized (mLock) {
   3711                 focusedWindowId = mSecurityPolicy.mAccessibilityFocusedWindowId;
   3712                 if (focusedWindowId == SecurityPolicy.INVALID_WINDOW_ID) {
   3713                     return null;
   3714                 }
   3715             }
   3716             return getAccessibilityFocusNotLocked(focusedWindowId);
   3717         }
   3718 
   3719         private AccessibilityNodeInfo getAccessibilityFocusNotLocked(int windowId) {
   3720             return mClient.findFocus(mConnectionId,
   3721                     windowId, AccessibilityNodeInfo.ROOT_NODE_ID,
   3722                     AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
   3723         }
   3724     }
   3725 
   3726     final class SecurityPolicy {
   3727         public static final int INVALID_WINDOW_ID = -1;
   3728 
   3729         private static final int RETRIEVAL_ALLOWING_EVENT_TYPES =
   3730             AccessibilityEvent.TYPE_VIEW_CLICKED
   3731             | AccessibilityEvent.TYPE_VIEW_FOCUSED
   3732             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
   3733             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
   3734             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
   3735             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
   3736             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
   3737             | AccessibilityEvent.TYPE_VIEW_SELECTED
   3738             | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
   3739             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
   3740             | AccessibilityEvent.TYPE_VIEW_SCROLLED
   3741             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
   3742             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED
   3743             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
   3744 
   3745         public List<AccessibilityWindowInfo> mWindows;
   3746 
   3747         public int mActiveWindowId = INVALID_WINDOW_ID;
   3748         public int mFocusedWindowId = INVALID_WINDOW_ID;
   3749         public int mAccessibilityFocusedWindowId = INVALID_WINDOW_ID;
   3750         public long mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
   3751 
   3752         private boolean mTouchInteractionInProgress;
   3753 
   3754         private boolean canDispatchAccessibilityEventLocked(AccessibilityEvent event) {
   3755             final int eventType = event.getEventType();
   3756             switch (eventType) {
   3757                 // All events that are for changes in a global window
   3758                 // state should *always* be dispatched.
   3759                 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
   3760                 case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
   3761                 case AccessibilityEvent.TYPE_ANNOUNCEMENT:
   3762                 // All events generated by the user touching the
   3763                 // screen should *always* be dispatched.
   3764                 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START:
   3765                 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END:
   3766                 case AccessibilityEvent.TYPE_GESTURE_DETECTION_START:
   3767                 case AccessibilityEvent.TYPE_GESTURE_DETECTION_END:
   3768                 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START:
   3769                 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END:
   3770                 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER:
   3771                 case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT:
   3772                 // Also always dispatch the event that assist is reading context.
   3773                 case AccessibilityEvent.TYPE_ASSIST_READING_CONTEXT:
   3774                 // Also windows changing should always be anounced.
   3775                 case AccessibilityEvent.TYPE_WINDOWS_CHANGED: {
   3776                     return true;
   3777                 }
   3778                 // All events for changes in window content should be
   3779                 // dispatched *only* if this window is one of the windows
   3780                 // the accessibility layer reports which are windows
   3781                 // that a sighted user can touch.
   3782                 default: {
   3783                     return isRetrievalAllowingWindow(event.getWindowId());
   3784                 }
   3785             }
   3786         }
   3787 
   3788         public void clearWindowsLocked() {
   3789             List<AccessibilityWindowInfo> windows = Collections.emptyList();
   3790             final int activeWindowId = mActiveWindowId;
   3791             updateWindowsLocked(windows);
   3792             mActiveWindowId = activeWindowId;
   3793             mWindows = null;
   3794         }
   3795 
   3796         public void updateWindowsLocked(List<AccessibilityWindowInfo> windows) {
   3797             if (mWindows == null) {
   3798                 mWindows = new ArrayList<>();
   3799             }
   3800 
   3801             final int oldWindowCount = mWindows.size();
   3802             for (int i = oldWindowCount - 1; i >= 0; i--) {
   3803                 mWindows.remove(i).recycle();
   3804             }
   3805 
   3806             mFocusedWindowId = INVALID_WINDOW_ID;
   3807             if (!mTouchInteractionInProgress) {
   3808                 mActiveWindowId = INVALID_WINDOW_ID;
   3809             }
   3810 
   3811             // If the active window goes away while the user is touch exploring we
   3812             // reset the active window id and wait for the next hover event from
   3813             // under the user's finger to determine which one is the new one. It
   3814             // is possible that the finger is not moving and the input system
   3815             // filters out such events.
   3816             boolean activeWindowGone = true;
   3817 
   3818             final int windowCount = windows.size();
   3819             if (windowCount > 0) {
   3820                 for (int i = 0; i < windowCount; i++) {
   3821                     AccessibilityWindowInfo window = windows.get(i);
   3822                     final int windowId = window.getId();
   3823                     if (window.isFocused()) {
   3824                         mFocusedWindowId = windowId;
   3825                         if (!mTouchInteractionInProgress) {
   3826                             mActiveWindowId = windowId;
   3827                             window.setActive(true);
   3828                         } else if (windowId == mActiveWindowId) {
   3829                             activeWindowGone = false;
   3830                         }
   3831                     }
   3832                     mWindows.add(window);
   3833                 }
   3834 
   3835                 if (mTouchInteractionInProgress && activeWindowGone) {
   3836                     mActiveWindowId = mFocusedWindowId;
   3837                 }
   3838 
   3839                 // Focused window may change the active one, so set the
   3840                 // active window once we decided which it is.
   3841                 for (int i = 0; i < windowCount; i++) {
   3842                     AccessibilityWindowInfo window = mWindows.get(i);
   3843                     if (window.getId() == mActiveWindowId) {
   3844                         window.setActive(true);
   3845                     }
   3846                     if (window.getId() == mAccessibilityFocusedWindowId) {
   3847                         window.setAccessibilityFocused(true);
   3848                     }
   3849                 }
   3850             }
   3851 
   3852             notifyWindowsChanged();
   3853         }
   3854 
   3855         public boolean computePartialInteractiveRegionForWindowLocked(int windowId,
   3856                 Region outRegion) {
   3857             if (mWindows == null) {
   3858                 return false;
   3859             }
   3860 
   3861             // Windows are ordered in z order so start from the bottom and find
   3862             // the window of interest. After that all windows that cover it should
   3863             // be subtracted from the resulting region. Note that for accessibility
   3864             // we are returning only interactive windows.
   3865             Region windowInteractiveRegion = null;
   3866             boolean windowInteractiveRegionChanged = false;
   3867 
   3868             final int windowCount = mWindows.size();
   3869             for (int i = windowCount - 1; i >= 0; i--) {
   3870                 AccessibilityWindowInfo currentWindow = mWindows.get(i);
   3871                 if (windowInteractiveRegion == null) {
   3872                     if (currentWindow.getId() == windowId) {
   3873                         Rect currentWindowBounds = mTempRect;
   3874                         currentWindow.getBoundsInScreen(currentWindowBounds);
   3875                         outRegion.set(currentWindowBounds);
   3876                         windowInteractiveRegion = outRegion;
   3877                         continue;
   3878                     }
   3879                 } else if (currentWindow.getType()
   3880                         != AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY) {
   3881                     Rect currentWindowBounds = mTempRect;
   3882                     currentWindow.getBoundsInScreen(currentWindowBounds);
   3883                     if (windowInteractiveRegion.op(currentWindowBounds, Region.Op.DIFFERENCE)) {
   3884                         windowInteractiveRegionChanged = true;
   3885                     }
   3886                 }
   3887             }
   3888 
   3889             return windowInteractiveRegionChanged;
   3890         }
   3891 
   3892         public void updateEventSourceLocked(AccessibilityEvent event) {
   3893             if ((event.getEventType() & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) {
   3894                 event.setSource(null);
   3895             }
   3896         }
   3897 
   3898         public void updateActiveAndAccessibilityFocusedWindowLocked(int windowId, long nodeId,
   3899                 int eventType, int eventAction) {
   3900             // The active window is either the window that has input focus or
   3901             // the window that the user is currently touching. If the user is
   3902             // touching a window that does not have input focus as soon as the
   3903             // the user stops touching that window the focused window becomes
   3904             // the active one. Here we detect the touched window and make it
   3905             // active. In updateWindowsLocked() we update the focused window
   3906             // and if the user is not touching the screen, we make the focused
   3907             // window the active one.
   3908             switch (eventType) {
   3909                 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: {
   3910                     // If no service has the capability to introspect screen,
   3911                     // we do not register callback in the window manager for
   3912                     // window changes, so we have to ask the window manager
   3913                     // what the focused window is to update the active one.
   3914                     // The active window also determined events from which
   3915                     // windows are delivered.
   3916                     synchronized (mLock) {
   3917                         if (mWindowsForAccessibilityCallback == null) {
   3918                             mFocusedWindowId = getFocusedWindowId();
   3919                             if (windowId == mFocusedWindowId) {
   3920                                 mActiveWindowId = windowId;
   3921                             }
   3922                         }
   3923                     }
   3924                 } break;
   3925 
   3926                 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: {
   3927                     // Do not allow delayed hover events to confuse us
   3928                     // which the active window is.
   3929                     synchronized (mLock) {
   3930                         if (mTouchInteractionInProgress && mActiveWindowId != windowId) {
   3931                             setActiveWindowLocked(windowId);
   3932                         }
   3933                     }
   3934                 } break;
   3935 
   3936                 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
   3937                     synchronized (mLock) {
   3938                         if (mAccessibilityFocusedWindowId != windowId) {
   3939                             mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS,
   3940                                     mAccessibilityFocusedWindowId, 0).sendToTarget();
   3941                             mSecurityPolicy.setAccessibilityFocusedWindowLocked(windowId);
   3942                             mAccessibilityFocusNodeId = nodeId;
   3943                         }
   3944                     }
   3945                 } break;
   3946 
   3947                 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
   3948                     synchronized (mLock) {
   3949                         if (mAccessibilityFocusNodeId == nodeId) {
   3950                             mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
   3951                         }
   3952                         // Clear the window with focus if it no longer has focus and we aren't
   3953                         // just moving focus from one view to the other in the same window
   3954                         if ((mAccessibilityFocusNodeId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID)
   3955                                 && (mAccessibilityFocusedWindowId == windowId)
   3956                                 && (eventAction != AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS)
   3957                                 ) {
   3958                             mAccessibilityFocusedWindowId = INVALID_WINDOW_ID;
   3959                         }
   3960                     }
   3961                 } break;
   3962             }
   3963         }
   3964 
   3965         public void onTouchInteractionStart() {
   3966             synchronized (mLock) {
   3967                 mTouchInteractionInProgress = true;
   3968             }
   3969         }
   3970 
   3971         public void onTouchInteractionEnd() {
   3972             synchronized (mLock) {
   3973                 mTouchInteractionInProgress = false;
   3974                 // We want to set the active window to be current immediately
   3975                 // after the user has stopped touching the screen since if the
   3976                 // user types with the IME he should get a feedback for the
   3977                 // letter typed in the text view which is in the input focused
   3978                 // window. Note that we always deliver hover accessibility events
   3979                 // (they are a result of user touching the screen) so change of
   3980                 // the active window before all hover accessibility events from
   3981                 // the touched window are delivered is fine.
   3982                 final int oldActiveWindow = mSecurityPolicy.mActiveWindowId;
   3983                 setActiveWindowLocked(mFocusedWindowId);
   3984 
   3985                 // If there is no service that can operate with active windows
   3986                 // we keep accessibility focus behavior to constrain it only in
   3987                 // the active window. Look at updateAccessibilityFocusBehaviorLocked
   3988                 // for details.
   3989                 if (oldActiveWindow != mSecurityPolicy.mActiveWindowId
   3990                         && mAccessibilityFocusedWindowId == oldActiveWindow
   3991                         && getCurrentUserStateLocked().mAccessibilityFocusOnlyInActiveWindow) {
   3992                     mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS,
   3993                             oldActiveWindow, 0).sendToTarget();
   3994                 }
   3995             }
   3996         }
   3997 
   3998         public int getActiveWindowId() {
   3999             if (mActiveWindowId == INVALID_WINDOW_ID && !mTouchInteractionInProgress) {
   4000                 mActiveWindowId = getFocusedWindowId();
   4001             }
   4002             return mActiveWindowId;
   4003         }
   4004 
   4005         private void setActiveWindowLocked(int windowId) {
   4006             if (mActiveWindowId != windowId) {
   4007                 mActiveWindowId = windowId;
   4008                 if (mWindows != null) {
   4009                     final int windowCount = mWindows.size();
   4010                     for (int i = 0; i < windowCount; i++) {
   4011                         AccessibilityWindowInfo window = mWindows.get(i);
   4012                         window.setActive(window.getId() == windowId);
   4013                     }
   4014                 }
   4015                 notifyWindowsChanged();
   4016             }
   4017         }
   4018 
   4019         private void setAccessibilityFocusedWindowLocked(int windowId) {
   4020             if (mAccessibilityFocusedWindowId != windowId) {
   4021                 mAccessibilityFocusedWindowId = windowId;
   4022                 if (mWindows != null) {
   4023                     final int windowCount = mWindows.size();
   4024                     for (int i = 0; i < windowCount; i++) {
   4025                         AccessibilityWindowInfo window = mWindows.get(i);
   4026                         window.setAccessibilityFocused(window.getId() == windowId);
   4027                     }
   4028                 }
   4029 
   4030                 notifyWindowsChanged();
   4031             }
   4032         }
   4033 
   4034         private void notifyWindowsChanged() {
   4035             if (mWindowsForAccessibilityCallback == null) {
   4036                 return;
   4037             }
   4038             final long identity = Binder.clearCallingIdentity();
   4039             try {
   4040                 // Let the client know the windows changed.
   4041                 AccessibilityEvent event = AccessibilityEvent.obtain(
   4042                         AccessibilityEvent.TYPE_WINDOWS_CHANGED);
   4043                 event.setEventTime(SystemClock.uptimeMillis());
   4044                 sendAccessibilityEvent(event, mCurrentUserId);
   4045             } finally {
   4046                 Binder.restoreCallingIdentity(identity);
   4047             }
   4048         }
   4049 
   4050         public boolean canGetAccessibilityNodeInfoLocked(Service service, int windowId) {
   4051             return canRetrieveWindowContentLocked(service) && isRetrievalAllowingWindow(windowId);
   4052         }
   4053 
   4054         public boolean canRetrieveWindowsLocked(Service service) {
   4055             return canRetrieveWindowContentLocked(service) && service.mRetrieveInteractiveWindows;
   4056         }
   4057 
   4058         public boolean canRetrieveWindowContentLocked(Service service) {
   4059             return (service.mAccessibilityServiceInfo.getCapabilities()
   4060                     & AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0;
   4061         }
   4062 
   4063         public boolean canControlMagnification(Service service) {
   4064             return (service.mAccessibilityServiceInfo.getCapabilities()
   4065                     & AccessibilityServiceInfo.CAPABILITY_CAN_CONTROL_MAGNIFICATION) != 0;
   4066         }
   4067 
   4068         public boolean canPerformGestures(Service service) {
   4069             return (service.mAccessibilityServiceInfo.getCapabilities()
   4070                     & AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0;
   4071         }
   4072 
   4073         private int resolveProfileParentLocked(int userId) {
   4074             if (userId != mCurrentUserId) {
   4075                 final long identity = Binder.clearCallingIdentity();
   4076                 try {
   4077                     UserInfo parent = mUserManager.getProfileParent(userId);
   4078                     if (parent != null) {
   4079                         return parent.getUserHandle().getIdentifier();
   4080                     }
   4081                 } finally {
   4082                     Binder.restoreCallingIdentity(identity);
   4083                 }
   4084             }
   4085             return userId;
   4086         }
   4087 
   4088         public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) {
   4089             final int callingUid = Binder.getCallingUid();
   4090             if (callingUid == 0
   4091                     || callingUid == Process.SYSTEM_UID
   4092                     || callingUid == Process.SHELL_UID) {
   4093                 if (userId == UserHandle.USER_CURRENT
   4094                         || userId == UserHandle.USER_CURRENT_OR_SELF) {
   4095                     return mCurrentUserId;
   4096                 }
   4097                 return resolveProfileParentLocked(userId);
   4098             }
   4099             final int callingUserId = UserHandle.getUserId(callingUid);
   4100             if (callingUserId == userId) {
   4101                 return resolveProfileParentLocked(userId);
   4102             }
   4103             final int callingUserParentId = resolveProfileParentLocked(callingUserId);
   4104             if (callingUserParentId == mCurrentUserId &&
   4105                     (userId == UserHandle.USER_CURRENT
   4106                             || userId == UserHandle.USER_CURRENT_OR_SELF)) {
   4107                 return mCurrentUserId;
   4108             }
   4109             if (!hasPermission(Manifest.permission.INTERACT_ACROSS_USERS)
   4110                     && !hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) {
   4111                 throw new SecurityException("Call from user " + callingUserId + " as user "
   4112                         + userId + " without permission INTERACT_ACROSS_USERS or "
   4113                         + "INTERACT_ACROSS_USERS_FULL not allowed.");
   4114             }
   4115             if (userId == UserHandle.USER_CURRENT
   4116                     || userId == UserHandle.USER_CURRENT_OR_SELF) {
   4117                 return mCurrentUserId;
   4118             }
   4119             throw new IllegalArgumentException("Calling user can be changed to only "
   4120                     + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF.");
   4121         }
   4122 
   4123         public boolean isCallerInteractingAcrossUsers(int userId) {
   4124             final int callingUid = Binder.getCallingUid();
   4125             return (Binder.getCallingPid() == android.os.Process.myPid()
   4126                     || callingUid == Process.SHELL_UID
   4127                     || userId == UserHandle.USER_CURRENT
   4128                     || userId == UserHandle.USER_CURRENT_OR_SELF);
   4129         }
   4130 
   4131         private boolean isRetrievalAllowingWindow(int windowId) {
   4132             // The system gets to interact with any window it wants.
   4133             if (Binder.getCallingUid() == Process.SYSTEM_UID) {
   4134                 return true;
   4135             }
   4136             if (windowId == mActiveWindowId) {
   4137                 return true;
   4138             }
   4139             return findWindowById(windowId) != null;
   4140         }
   4141 
   4142         private AccessibilityWindowInfo findWindowById(int windowId) {
   4143             if (mWindows != null) {
   4144                 final int windowCount = mWindows.size();
   4145                 for (int i = 0; i < windowCount; i++) {
   4146                     AccessibilityWindowInfo window = mWindows.get(i);
   4147                     if (window.getId() == windowId) {
   4148                         return window;
   4149                     }
   4150                 }
   4151             }
   4152             return null;
   4153         }
   4154 
   4155         private void enforceCallingPermission(String permission, String function) {
   4156             if (OWN_PROCESS_ID == Binder.getCallingPid()) {
   4157                 return;
   4158             }
   4159             if (!hasPermission(permission)) {
   4160                 throw new SecurityException("You do not have " + permission
   4161                         + " required to call " + function + " from pid="
   4162                         + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
   4163             }
   4164         }
   4165 
   4166         private boolean hasPermission(String permission) {
   4167             return mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED;
   4168         }
   4169 
   4170         private int getFocusedWindowId() {
   4171             IBinder token = mWindowManagerService.getFocusedWindowToken();
   4172             synchronized (mLock) {
   4173                 return findWindowIdLocked(token);
   4174             }
   4175         }
   4176     }
   4177 
   4178     private class UserState {
   4179         public final int mUserId;
   4180 
   4181         // Non-transient state.
   4182 
   4183         public final RemoteCallbackList<IAccessibilityManagerClient> mClients =
   4184             new RemoteCallbackList<>();
   4185 
   4186         public final SparseArray<AccessibilityConnectionWrapper> mInteractionConnections =
   4187                 new SparseArray<>();
   4188 
   4189         public final SparseArray<IBinder> mWindowTokens = new SparseArray<>();
   4190 
   4191         // Transient state.
   4192 
   4193         public final CopyOnWriteArrayList<Service> mBoundServices =
   4194                 new CopyOnWriteArrayList<>();
   4195 
   4196         public final Map<ComponentName, Service> mComponentNameToServiceMap =
   4197                 new HashMap<>();
   4198 
   4199         public final List<AccessibilityServiceInfo> mInstalledServices =
   4200                 new ArrayList<>();
   4201 
   4202         public final Set<ComponentName> mBindingServices = new HashSet<>();
   4203 
   4204         public final Set<ComponentName> mEnabledServices = new HashSet<>();
   4205 
   4206         public final Set<ComponentName> mTouchExplorationGrantedServices =
   4207                 new HashSet<>();
   4208 
   4209         public ComponentName mServiceChangingSoftKeyboardMode;
   4210 
   4211         public int mLastSentClientState = -1;
   4212 
   4213         public int mSoftKeyboardShowMode = 0;
   4214 
   4215         public boolean mIsTouchExplorationEnabled;
   4216         public boolean mIsTextHighContrastEnabled;
   4217         public boolean mIsEnhancedWebAccessibilityEnabled;
   4218         public boolean mIsDisplayMagnificationEnabled;
   4219         public boolean mIsAutoclickEnabled;
   4220         public boolean mIsPerformGesturesEnabled;
   4221         public boolean mIsFilterKeyEventsEnabled;
   4222         public boolean mAccessibilityFocusOnlyInActiveWindow;
   4223 
   4224         private Service mUiAutomationService;
   4225         private int mUiAutomationFlags;
   4226         private IAccessibilityServiceClient mUiAutomationServiceClient;
   4227 
   4228         private IBinder mUiAutomationServiceOwner;
   4229         private final DeathRecipient mUiAutomationSerivceOnwerDeathRecipient =
   4230                 new DeathRecipient() {
   4231             @Override
   4232             public void binderDied() {
   4233                 mUiAutomationServiceOwner.unlinkToDeath(
   4234                         mUiAutomationSerivceOnwerDeathRecipient, 0);
   4235                 mUiAutomationServiceOwner = null;
   4236                 if (mUiAutomationService != null) {
   4237                     mUiAutomationService.binderDied();
   4238                 }
   4239             }
   4240         };
   4241 
   4242         public UserState(int userId) {
   4243             mUserId = userId;
   4244         }
   4245 
   4246         public int getClientState() {
   4247             int clientState = 0;
   4248             if (isHandlingAccessibilityEvents()) {
   4249                 clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
   4250             }
   4251             // Touch exploration relies on enabled accessibility.
   4252             if (isHandlingAccessibilityEvents() && mIsTouchExplorationEnabled) {
   4253                 clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
   4254             }
   4255             if (mIsTextHighContrastEnabled) {
   4256                 clientState |= AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED;
   4257             }
   4258             return clientState;
   4259         }
   4260 
   4261         public boolean isHandlingAccessibilityEvents() {
   4262             return !mBoundServices.isEmpty() || !mBindingServices.isEmpty();
   4263         }
   4264 
   4265         public void onSwitchToAnotherUser() {
   4266             // Clear UI test automation state.
   4267             if (mUiAutomationService != null) {
   4268                 mUiAutomationService.binderDied();
   4269             }
   4270 
   4271             // Unbind all services.
   4272             unbindAllServicesLocked(this);
   4273 
   4274             // Clear service management state.
   4275             mBoundServices.clear();
   4276             mBindingServices.clear();
   4277 
   4278             // Clear event management state.
   4279             mLastSentClientState = -1;
   4280 
   4281             // Clear state persisted in settings.
   4282             mEnabledServices.clear();
   4283             mTouchExplorationGrantedServices.clear();
   4284             mIsTouchExplorationEnabled = false;
   4285             mIsEnhancedWebAccessibilityEnabled = false;
   4286             mIsDisplayMagnificationEnabled = false;
   4287             mIsAutoclickEnabled = false;
   4288             mSoftKeyboardShowMode = 0;
   4289         }
   4290 
   4291         public void destroyUiAutomationService() {
   4292             mUiAutomationService = null;
   4293             mUiAutomationFlags = 0;
   4294             mUiAutomationServiceClient = null;
   4295             if (mUiAutomationServiceOwner != null) {
   4296                 mUiAutomationServiceOwner.unlinkToDeath(
   4297                         mUiAutomationSerivceOnwerDeathRecipient, 0);
   4298                 mUiAutomationServiceOwner = null;
   4299             }
   4300         }
   4301 
   4302         boolean isUiAutomationSuppressingOtherServices() {
   4303             return ((mUiAutomationService != null) && (mUiAutomationFlags
   4304                     & UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) == 0);
   4305         }
   4306     }
   4307 
   4308     private final class AccessibilityContentObserver extends ContentObserver {
   4309 
   4310         private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor(
   4311                 Settings.Secure.TOUCH_EXPLORATION_ENABLED);
   4312 
   4313         private final Uri mDisplayMagnificationEnabledUri = Settings.Secure.getUriFor(
   4314                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
   4315 
   4316         private final Uri mAutoclickEnabledUri = Settings.Secure.getUriFor(
   4317                 Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED);
   4318 
   4319         private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor(
   4320                 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
   4321 
   4322         private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure
   4323                 .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
   4324 
   4325         private final Uri mEnhancedWebAccessibilityUri = Settings.Secure
   4326                 .getUriFor(Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION);
   4327 
   4328         private final Uri mDisplayInversionEnabledUri = Settings.Secure.getUriFor(
   4329                 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
   4330 
   4331         private final Uri mDisplayDaltonizerEnabledUri = Settings.Secure.getUriFor(
   4332                 Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED);
   4333 
   4334         private final Uri mDisplayDaltonizerUri = Settings.Secure.getUriFor(
   4335                 Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER);
   4336 
   4337         private final Uri mHighTextContrastUri = Settings.Secure.getUriFor(
   4338                 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED);
   4339 
   4340         private final Uri mAccessibilitySoftKeyboardModeUri = Settings.Secure.getUriFor(
   4341                 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE);
   4342 
   4343         public AccessibilityContentObserver(Handler handler) {
   4344             super(handler);
   4345         }
   4346 
   4347         public void register(ContentResolver contentResolver) {
   4348             contentResolver.registerContentObserver(mTouchExplorationEnabledUri,
   4349                     false, this, UserHandle.USER_ALL);
   4350             contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri,
   4351                     false, this, UserHandle.USER_ALL);
   4352             contentResolver.registerContentObserver(mAutoclickEnabledUri,
   4353                     false, this, UserHandle.USER_ALL);
   4354             contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri,
   4355                     false, this, UserHandle.USER_ALL);
   4356             contentResolver.registerContentObserver(
   4357                     mTouchExplorationGrantedAccessibilityServicesUri,
   4358                     false, this, UserHandle.USER_ALL);
   4359             contentResolver.registerContentObserver(mEnhancedWebAccessibilityUri,
   4360                     false, this, UserHandle.USER_ALL);
   4361             contentResolver.registerContentObserver(
   4362                     mDisplayInversionEnabledUri, false, this, UserHandle.USER_ALL);
   4363             contentResolver.registerContentObserver(
   4364                     mDisplayDaltonizerEnabledUri, false, this, UserHandle.USER_ALL);
   4365             contentResolver.registerContentObserver(
   4366                     mDisplayDaltonizerUri, false, this, UserHandle.USER_ALL);
   4367             contentResolver.registerContentObserver(
   4368                     mHighTextContrastUri, false, this, UserHandle.USER_ALL);
   4369             contentResolver.registerContentObserver(
   4370                     mAccessibilitySoftKeyboardModeUri, false, this, UserHandle.USER_ALL);
   4371         }
   4372 
   4373         @Override
   4374         public void onChange(boolean selfChange, Uri uri) {
   4375             synchronized (mLock) {
   4376                 // Profiles share the accessibility state of the parent. Therefore,
   4377                 // we are checking for changes only the parent settings.
   4378                 UserState userState = getCurrentUserStateLocked();
   4379 
   4380                 // If the automation service is suppressing, we will update when it dies.
   4381                 if (userState.isUiAutomationSuppressingOtherServices()) {
   4382                     return;
   4383                 }
   4384 
   4385                 if (mTouchExplorationEnabledUri.equals(uri)) {
   4386                     if (readTouchExplorationEnabledSettingLocked(userState)) {
   4387                         onUserStateChangedLocked(userState);
   4388                     }
   4389                 } else if (mDisplayMagnificationEnabledUri.equals(uri)) {
   4390                     if (readDisplayMagnificationEnabledSettingLocked(userState)) {
   4391                         onUserStateChangedLocked(userState);
   4392                     }
   4393                 } else if (mAutoclickEnabledUri.equals(uri)) {
   4394                     if (readAutoclickEnabledSettingLocked(userState)) {
   4395                         onUserStateChangedLocked(userState);
   4396                     }
   4397                 } else if (mEnabledAccessibilityServicesUri.equals(uri)) {
   4398                     if (readEnabledAccessibilityServicesLocked(userState)) {
   4399                         onUserStateChangedLocked(userState);
   4400                     }
   4401                 } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) {
   4402                     if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) {
   4403                         onUserStateChangedLocked(userState);
   4404                     }
   4405                 } else if (mEnhancedWebAccessibilityUri.equals(uri)) {
   4406                     if (readEnhancedWebAccessibilityEnabledChangedLocked(userState)) {
   4407                         onUserStateChangedLocked(userState);
   4408                     }
   4409                 } else if (mDisplayDaltonizerEnabledUri.equals(uri)
   4410                         || mDisplayDaltonizerUri.equals(uri)) {
   4411                     updateDisplayDaltonizerLocked(userState);
   4412                 } else if (mDisplayInversionEnabledUri.equals(uri)) {
   4413                     updateDisplayInversionLocked(userState);
   4414                 } else if (mHighTextContrastUri.equals(uri)) {
   4415                     if (readHighTextContrastEnabledSettingLocked(userState)) {
   4416                         onUserStateChangedLocked(userState);
   4417                     }
   4418                 } else if (mAccessibilitySoftKeyboardModeUri.equals(uri)) {
   4419                     if (readSoftKeyboardShowModeChangedLocked(userState)) {
   4420                         notifySoftKeyboardShowModeChangedLocked(userState.mSoftKeyboardShowMode);
   4421                         onUserStateChangedLocked(userState);
   4422                     }
   4423                 }
   4424             }
   4425         }
   4426     }
   4427 }
   4428