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