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.app.AlertDialog;
     27 import android.app.PendingIntent;
     28 import android.app.StatusBarManager;
     29 import android.content.BroadcastReceiver;
     30 import android.content.ComponentName;
     31 import android.content.ContentResolver;
     32 import android.content.Context;
     33 import android.content.DialogInterface;
     34 import android.content.DialogInterface.OnClickListener;
     35 import android.content.Intent;
     36 import android.content.IntentFilter;
     37 import android.content.ServiceConnection;
     38 import android.content.pm.PackageManager;
     39 import android.content.pm.ResolveInfo;
     40 import android.content.pm.ServiceInfo;
     41 import android.database.ContentObserver;
     42 import android.graphics.Point;
     43 import android.graphics.Rect;
     44 import android.hardware.display.DisplayManager;
     45 import android.hardware.input.InputManager;
     46 import android.net.Uri;
     47 import android.os.Binder;
     48 import android.os.Build;
     49 import android.os.Bundle;
     50 import android.os.Handler;
     51 import android.os.IBinder;
     52 import android.os.Looper;
     53 import android.os.Message;
     54 import android.os.Process;
     55 import android.os.RemoteCallbackList;
     56 import android.os.RemoteException;
     57 import android.os.ServiceManager;
     58 import android.os.SystemClock;
     59 import android.os.UserHandle;
     60 import android.os.UserManager;
     61 import android.provider.Settings;
     62 import android.text.TextUtils;
     63 import android.text.TextUtils.SimpleStringSplitter;
     64 import android.util.Pools.Pool;
     65 import android.util.Pools.SimplePool;
     66 import android.util.Slog;
     67 import android.util.SparseArray;
     68 import android.view.Display;
     69 import android.view.IWindow;
     70 import android.view.IWindowManager;
     71 import android.view.InputDevice;
     72 import android.view.InputEventConsistencyVerifier;
     73 import android.view.KeyCharacterMap;
     74 import android.view.KeyEvent;
     75 import android.view.MagnificationSpec;
     76 import android.view.WindowManager;
     77 import android.view.WindowManagerPolicy;
     78 import android.view.accessibility.AccessibilityEvent;
     79 import android.view.accessibility.AccessibilityInteractionClient;
     80 import android.view.accessibility.AccessibilityManager;
     81 import android.view.accessibility.AccessibilityNodeInfo;
     82 import android.view.accessibility.IAccessibilityInteractionConnection;
     83 import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
     84 import android.view.accessibility.IAccessibilityManager;
     85 import android.view.accessibility.IAccessibilityManagerClient;
     86 
     87 import com.android.internal.R;
     88 import com.android.internal.content.PackageMonitor;
     89 import com.android.internal.statusbar.IStatusBarService;
     90 
     91 import org.xmlpull.v1.XmlPullParserException;
     92 
     93 import java.io.FileDescriptor;
     94 import java.io.IOException;
     95 import java.io.PrintWriter;
     96 import java.util.ArrayList;
     97 import java.util.Arrays;
     98 import java.util.Collections;
     99 import java.util.HashMap;
    100 import java.util.HashSet;
    101 import java.util.Iterator;
    102 import java.util.List;
    103 import java.util.Map;
    104 import java.util.Set;
    105 import java.util.concurrent.CopyOnWriteArrayList;
    106 
    107 /**
    108  * This class is instantiated by the system as a system level service and can be
    109  * accessed only by the system. The task of this service is to be a centralized
    110  * event dispatch for {@link AccessibilityEvent}s generated across all processes
    111  * on the device. Events are dispatched to {@link AccessibilityService}s.
    112  *
    113  * @hide
    114  */
    115 public class AccessibilityManagerService extends IAccessibilityManager.Stub {
    116 
    117     private static final boolean DEBUG = false;
    118 
    119     private static final String LOG_TAG = "AccessibilityManagerService";
    120 
    121     // TODO: This is arbitrary. When there is time implement this by watching
    122     //       when that accessibility services are bound.
    123     private static final int WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS = 3000;
    124 
    125     private static final String FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE =
    126         "registerUiTestAutomationService";
    127 
    128     private static final String TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED =
    129             "temporaryEnableAccessibilityStateUntilKeyguardRemoved";
    130 
    131     private static final ComponentName sFakeAccessibilityServiceComponentName =
    132             new ComponentName("foo.bar", "FakeService");
    133 
    134     private static final String FUNCTION_DUMP = "dump";
    135 
    136     private static final char COMPONENT_NAME_SEPARATOR = ':';
    137 
    138     private static final int OWN_PROCESS_ID = android.os.Process.myPid();
    139 
    140     private static final int MAX_POOL_SIZE = 10;
    141 
    142     private static int sIdCounter = 0;
    143 
    144     private static int sNextWindowId;
    145 
    146     private final Context mContext;
    147 
    148     private final Object mLock = new Object();
    149 
    150     private final Pool<PendingEvent> mPendingEventPool =
    151             new SimplePool<PendingEvent>(MAX_POOL_SIZE);
    152 
    153     private final SimpleStringSplitter mStringColonSplitter =
    154             new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
    155 
    156     private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList =
    157             new ArrayList<AccessibilityServiceInfo>();
    158 
    159     private final Rect mTempRect = new Rect();
    160 
    161     private final Point mTempPoint = new Point();
    162 
    163     private final Display mDefaultDisplay;
    164 
    165     private final PackageManager mPackageManager;
    166 
    167     private final IWindowManager mWindowManagerService;
    168 
    169     private final SecurityPolicy mSecurityPolicy;
    170 
    171     private final MainHandler mMainHandler;
    172 
    173     private Service mQueryBridge;
    174 
    175     private AlertDialog mEnableTouchExplorationDialog;
    176 
    177     private AccessibilityInputFilter mInputFilter;
    178 
    179     private boolean mHasInputFilter;
    180 
    181     private final Set<ComponentName> mTempComponentNameSet = new HashSet<ComponentName>();
    182 
    183     private final List<AccessibilityServiceInfo> mTempAccessibilityServiceInfoList =
    184             new ArrayList<AccessibilityServiceInfo>();
    185 
    186     private final RemoteCallbackList<IAccessibilityManagerClient> mGlobalClients =
    187             new RemoteCallbackList<IAccessibilityManagerClient>();
    188 
    189     private final SparseArray<AccessibilityConnectionWrapper> mGlobalInteractionConnections =
    190             new SparseArray<AccessibilityConnectionWrapper>();
    191 
    192     private final SparseArray<IBinder> mGlobalWindowTokens = new SparseArray<IBinder>();
    193 
    194     private final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
    195 
    196     private int mCurrentUserId = UserHandle.USER_OWNER;
    197 
    198     //TODO: Remove this hack
    199     private boolean mInitialized;
    200 
    201     private UserState getCurrentUserStateLocked() {
    202         return getUserStateLocked(mCurrentUserId);
    203     }
    204 
    205     private UserState getUserStateLocked(int userId) {
    206         UserState state = mUserStates.get(userId);
    207         if (state == null) {
    208             state = new UserState(userId);
    209             mUserStates.put(userId, state);
    210         }
    211         return state;
    212     }
    213 
    214     /**
    215      * Creates a new instance.
    216      *
    217      * @param context A {@link Context} instance.
    218      */
    219     public AccessibilityManagerService(Context context) {
    220         mContext = context;
    221         mPackageManager = mContext.getPackageManager();
    222         mWindowManagerService = (IWindowManager) ServiceManager.getService(Context.WINDOW_SERVICE);
    223         mSecurityPolicy = new SecurityPolicy();
    224         mMainHandler = new MainHandler(mContext.getMainLooper());
    225         //TODO: (multi-display) We need to support multiple displays.
    226         DisplayManager displayManager = (DisplayManager)
    227                 mContext.getSystemService(Context.DISPLAY_SERVICE);
    228         mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
    229         registerBroadcastReceivers();
    230         new AccessibilityContentObserver(mMainHandler).register(
    231                 context.getContentResolver());
    232     }
    233 
    234     private void registerBroadcastReceivers() {
    235         PackageMonitor monitor = new PackageMonitor() {
    236             @Override
    237             public void onSomePackagesChanged() {
    238                 synchronized (mLock) {
    239                     if (getChangingUserId() != mCurrentUserId) {
    240                         return;
    241                     }
    242                     // We will update when the automation service dies.
    243                     UserState userState = getCurrentUserStateLocked();
    244                     // We have to reload the installed services since some services may
    245                     // have different attributes, resolve info (does not support equals),
    246                     // etc. Remove them then to force reload. Do it even if automation is
    247                     // running since when it goes away, we will have to reload as well.
    248                     userState.mInstalledServices.clear();
    249                     if (userState.mUiAutomationService == null) {
    250                         if (readConfigurationForUserStateLocked(userState)) {
    251                             onUserStateChangedLocked(userState);
    252                         }
    253                     }
    254                 }
    255             }
    256 
    257             @Override
    258             public void onPackageRemoved(String packageName, int uid) {
    259                 synchronized (mLock) {
    260                     final int userId = getChangingUserId();
    261                     if (userId != mCurrentUserId) {
    262                         return;
    263                     }
    264                     UserState userState = getUserStateLocked(userId);
    265                     Iterator<ComponentName> it = userState.mEnabledServices.iterator();
    266                     while (it.hasNext()) {
    267                         ComponentName comp = it.next();
    268                         String compPkg = comp.getPackageName();
    269                         if (compPkg.equals(packageName)) {
    270                             it.remove();
    271                             // Update the enabled services setting.
    272                             persistComponentNamesToSettingLocked(
    273                                     Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
    274                                     userState.mEnabledServices, userId);
    275                             // Update the touch exploration granted services setting.
    276                             userState.mTouchExplorationGrantedServices.remove(comp);
    277                             persistComponentNamesToSettingLocked(
    278                                     Settings.Secure.
    279                                     TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
    280                                     userState.mTouchExplorationGrantedServices, userId);
    281                             // We will update when the automation service dies.
    282                             if (userState.mUiAutomationService == null) {
    283                                 onUserStateChangedLocked(userState);
    284                             }
    285                             return;
    286                         }
    287                     }
    288                 }
    289             }
    290 
    291             @Override
    292             public boolean onHandleForceStop(Intent intent, String[] packages,
    293                     int uid, boolean doit) {
    294                 synchronized (mLock) {
    295                     final int userId = getChangingUserId();
    296                     if (userId != mCurrentUserId) {
    297                         return false;
    298                     }
    299                     UserState userState = getUserStateLocked(userId);
    300                     Iterator<ComponentName> it = userState.mEnabledServices.iterator();
    301                     while (it.hasNext()) {
    302                         ComponentName comp = it.next();
    303                         String compPkg = comp.getPackageName();
    304                         for (String pkg : packages) {
    305                             if (compPkg.equals(pkg)) {
    306                                 if (!doit) {
    307                                     return true;
    308                                 }
    309                                 it.remove();
    310                                 persistComponentNamesToSettingLocked(
    311                                         Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
    312                                         userState.mEnabledServices, userId);
    313                                 // We will update when the automation service dies.
    314                                 if (userState.mUiAutomationService == null) {
    315                                     onUserStateChangedLocked(userState);
    316                                 }
    317                             }
    318                         }
    319                     }
    320                     return false;
    321                 }
    322             }
    323         };
    324 
    325         // package changes
    326         monitor.register(mContext, null,  UserHandle.ALL, true);
    327 
    328         // user change and unlock
    329         IntentFilter intentFilter = new IntentFilter();
    330         intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
    331         intentFilter.addAction(Intent.ACTION_USER_REMOVED);
    332         intentFilter.addAction(Intent.ACTION_USER_PRESENT);
    333 
    334         mContext.registerReceiverAsUser(new BroadcastReceiver() {
    335             @Override
    336             public void onReceive(Context context, Intent intent) {
    337                 String action = intent.getAction();
    338                 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
    339                     switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
    340                 } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
    341                     removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
    342                 } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
    343                     // We will update when the automation service dies.
    344                     UserState userState = getCurrentUserStateLocked();
    345                     if (userState.mUiAutomationService == null) {
    346                         if (readConfigurationForUserStateLocked(userState)) {
    347                             onUserStateChangedLocked(userState);
    348                         }
    349                     }
    350                 }
    351             }
    352         }, UserHandle.ALL, intentFilter, null, null);
    353     }
    354 
    355     public int addClient(IAccessibilityManagerClient client, int userId) {
    356         synchronized (mLock) {
    357             final int resolvedUserId = mSecurityPolicy
    358                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
    359             // If the client is from a process that runs across users such as
    360             // the system UI or the system we add it to the global state that
    361             // is shared across users.
    362             UserState userState = getUserStateLocked(resolvedUserId);
    363             if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
    364                 mGlobalClients.register(client);
    365                 if (DEBUG) {
    366                     Slog.i(LOG_TAG, "Added global client for pid:" + Binder.getCallingPid());
    367                 }
    368                 return userState.getClientState();
    369             } else {
    370                 userState.mClients.register(client);
    371                 // If this client is not for the current user we do not
    372                 // return a state since it is not for the foreground user.
    373                 // We will send the state to the client on a user switch.
    374                 if (DEBUG) {
    375                     Slog.i(LOG_TAG, "Added user client for pid:" + Binder.getCallingPid()
    376                             + " and userId:" + mCurrentUserId);
    377                 }
    378                 return (resolvedUserId == mCurrentUserId) ? userState.getClientState() : 0;
    379             }
    380         }
    381     }
    382 
    383     public boolean sendAccessibilityEvent(AccessibilityEvent event, int userId) {
    384         synchronized (mLock) {
    385             final int resolvedUserId = mSecurityPolicy
    386                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
    387             // This method does nothing for a background user.
    388             if (resolvedUserId != mCurrentUserId) {
    389                 return true; // yes, recycle the event
    390             }
    391             if (mSecurityPolicy.canDispatchAccessibilityEvent(event)) {
    392                 mSecurityPolicy.updateEventSourceLocked(event);
    393                 mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_ACTIVE_WINDOW,
    394                         event.getWindowId(), event.getEventType()).sendToTarget();
    395                 notifyAccessibilityServicesDelayedLocked(event, false);
    396                 notifyAccessibilityServicesDelayedLocked(event, true);
    397             }
    398             if (mHasInputFilter && mInputFilter != null) {
    399                 mMainHandler.obtainMessage(MainHandler.MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER,
    400                         AccessibilityEvent.obtain(event)).sendToTarget();
    401             }
    402             event.recycle();
    403             getUserStateLocked(resolvedUserId).mHandledFeedbackTypes = 0;
    404         }
    405         return (OWN_PROCESS_ID != Binder.getCallingPid());
    406     }
    407 
    408     public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) {
    409         synchronized (mLock) {
    410             final int resolvedUserId = mSecurityPolicy
    411                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
    412             // The automation service is a fake one and should not be reported
    413             // to clients as being installed - it really is not.
    414             UserState userState = getUserStateLocked(resolvedUserId);
    415             if (userState.mUiAutomationService != null) {
    416                 List<AccessibilityServiceInfo> installedServices =
    417                         new ArrayList<AccessibilityServiceInfo>();
    418                 installedServices.addAll(userState.mInstalledServices);
    419                 installedServices.remove(userState.mUiAutomationService);
    420                 return installedServices;
    421             }
    422             return userState.mInstalledServices;
    423         }
    424     }
    425 
    426     public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType,
    427             int userId) {
    428         List<AccessibilityServiceInfo> result = null;
    429         synchronized (mLock) {
    430             final int resolvedUserId = mSecurityPolicy
    431                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
    432 
    433             // The automation service is a fake one and should not be reported
    434             // to clients as being enabled. The automation service is always the
    435             // only active one, if it exists.
    436             UserState userState = getUserStateLocked(resolvedUserId);
    437             if (userState.mUiAutomationService != null) {
    438                 return Collections.emptyList();
    439             }
    440 
    441             result = mEnabledServicesForFeedbackTempList;
    442             result.clear();
    443             List<Service> services = userState.mBoundServices;
    444             while (feedbackType != 0) {
    445                 final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackType));
    446                 feedbackType &= ~feedbackTypeBit;
    447                 final int serviceCount = services.size();
    448                 for (int i = 0; i < serviceCount; i++) {
    449                     Service service = services.get(i);
    450                     if ((service.mFeedbackType & feedbackTypeBit) != 0) {
    451                         result.add(service.mAccessibilityServiceInfo);
    452                     }
    453                 }
    454             }
    455         }
    456         return result;
    457     }
    458 
    459     public void interrupt(int userId) {
    460         CopyOnWriteArrayList<Service> services;
    461         synchronized (mLock) {
    462             final int resolvedUserId = mSecurityPolicy
    463                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
    464             // This method does nothing for a background user.
    465             if (resolvedUserId != mCurrentUserId) {
    466                 return;
    467             }
    468             services = getUserStateLocked(resolvedUserId).mBoundServices;
    469         }
    470         for (int i = 0, count = services.size(); i < count; i++) {
    471             Service service = services.get(i);
    472             try {
    473                 service.mServiceInterface.onInterrupt();
    474             } catch (RemoteException re) {
    475                 Slog.e(LOG_TAG, "Error during sending interrupt request to "
    476                     + service.mService, re);
    477             }
    478         }
    479     }
    480 
    481     public int addAccessibilityInteractionConnection(IWindow windowToken,
    482             IAccessibilityInteractionConnection connection, int userId) throws RemoteException {
    483         synchronized (mLock) {
    484             final int resolvedUserId = mSecurityPolicy
    485                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
    486             final int windowId = sNextWindowId++;
    487             // If the window is from a process that runs across users such as
    488             // the system UI or the system we add it to the global state that
    489             // is shared across users.
    490             if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
    491                 AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
    492                         windowId, connection, UserHandle.USER_ALL);
    493                 wrapper.linkToDeath();
    494                 mGlobalInteractionConnections.put(windowId, wrapper);
    495                 mGlobalWindowTokens.put(windowId, windowToken.asBinder());
    496                 if (DEBUG) {
    497                     Slog.i(LOG_TAG, "Added global connection for pid:" + Binder.getCallingPid()
    498                             + " with windowId: " + windowId);
    499                 }
    500             } else {
    501                 AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
    502                         windowId, connection, resolvedUserId);
    503                 wrapper.linkToDeath();
    504                 UserState userState = getUserStateLocked(resolvedUserId);
    505                 userState.mInteractionConnections.put(windowId, wrapper);
    506                 userState.mWindowTokens.put(windowId, windowToken.asBinder());
    507                 if (DEBUG) {
    508                     Slog.i(LOG_TAG, "Added user connection for pid:" + Binder.getCallingPid()
    509                             + " with windowId: " + windowId + " and userId:" + mCurrentUserId);
    510                 }
    511             }
    512             if (DEBUG) {
    513                 Slog.i(LOG_TAG, "Adding interaction connection to windowId: " + windowId);
    514             }
    515             return windowId;
    516         }
    517     }
    518 
    519     public void removeAccessibilityInteractionConnection(IWindow window) {
    520         synchronized (mLock) {
    521             mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(
    522                     UserHandle.getCallingUserId());
    523             IBinder token = window.asBinder();
    524             final int removedWindowId = removeAccessibilityInteractionConnectionInternalLocked(
    525                     token, mGlobalWindowTokens, mGlobalInteractionConnections);
    526             if (removedWindowId >= 0) {
    527                 if (DEBUG) {
    528                     Slog.i(LOG_TAG, "Removed global connection for pid:" + Binder.getCallingPid()
    529                             + " with windowId: " + removedWindowId);
    530                 }
    531                 return;
    532             }
    533             final int userCount = mUserStates.size();
    534             for (int i = 0; i < userCount; i++) {
    535                 UserState userState = mUserStates.valueAt(i);
    536                 final int removedWindowIdForUser =
    537                         removeAccessibilityInteractionConnectionInternalLocked(
    538                         token, userState.mWindowTokens, userState.mInteractionConnections);
    539                 if (removedWindowIdForUser >= 0) {
    540                     if (DEBUG) {
    541                         Slog.i(LOG_TAG, "Removed user connection for pid:" + Binder.getCallingPid()
    542                                 + " with windowId: " + removedWindowIdForUser + " and userId:"
    543                                 + mUserStates.keyAt(i));
    544                     }
    545                     return;
    546                 }
    547             }
    548         }
    549     }
    550 
    551     private int removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken,
    552             SparseArray<IBinder> windowTokens,
    553             SparseArray<AccessibilityConnectionWrapper> interactionConnections) {
    554         final int count = windowTokens.size();
    555         for (int i = 0; i < count; i++) {
    556             if (windowTokens.valueAt(i) == windowToken) {
    557                 final int windowId = windowTokens.keyAt(i);
    558                 windowTokens.removeAt(i);
    559                 AccessibilityConnectionWrapper wrapper = interactionConnections.get(windowId);
    560                 wrapper.unlinkToDeath();
    561                 interactionConnections.remove(windowId);
    562                 return windowId;
    563             }
    564         }
    565         return -1;
    566     }
    567 
    568     public void registerUiTestAutomationService(IBinder owner,
    569             IAccessibilityServiceClient serviceClient,
    570             AccessibilityServiceInfo accessibilityServiceInfo) {
    571         mSecurityPolicy.enforceCallingPermission(Manifest.permission.RETRIEVE_WINDOW_CONTENT,
    572                 FUNCTION_REGISTER_UI_TEST_AUTOMATION_SERVICE);
    573 
    574         accessibilityServiceInfo.setComponentName(sFakeAccessibilityServiceComponentName);
    575 
    576         synchronized (mLock) {
    577             UserState userState = getCurrentUserStateLocked();
    578 
    579             if (userState.mUiAutomationService != null) {
    580                 throw new IllegalStateException("UiAutomationService " + serviceClient
    581                         + "already registered!");
    582             }
    583 
    584             try {
    585                 owner.linkToDeath(userState.mUiAutomationSerivceOnwerDeathRecipient, 0);
    586             } catch (RemoteException re) {
    587                 Slog.e(LOG_TAG, "Couldn't register for the death of a"
    588                         + " UiTestAutomationService!", re);
    589                 return;
    590             }
    591 
    592             userState.mUiAutomationServiceOwner = owner;
    593             userState.mUiAutomationServiceClient = serviceClient;
    594 
    595             // Set the temporary state.
    596             userState.mIsAccessibilityEnabled = true;
    597             userState.mIsTouchExplorationEnabled = false;
    598             userState.mIsEnhancedWebAccessibilityEnabled = false;
    599             userState.mIsDisplayMagnificationEnabled = false;
    600             userState.mInstalledServices.add(accessibilityServiceInfo);
    601             userState.mEnabledServices.clear();
    602             userState.mEnabledServices.add(sFakeAccessibilityServiceComponentName);
    603             userState.mTouchExplorationGrantedServices.add(sFakeAccessibilityServiceComponentName);
    604 
    605             // Use the new state instead of settings.
    606             onUserStateChangedLocked(userState);
    607         }
    608     }
    609 
    610     public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) {
    611         synchronized (mLock) {
    612             UserState userState = getCurrentUserStateLocked();
    613             // Automation service is not bound, so pretend it died to perform clean up.
    614             if (userState.mUiAutomationService != null
    615                     && serviceClient != null
    616                     && userState.mUiAutomationService != null
    617                     && userState.mUiAutomationService.mServiceInterface != null
    618                     && userState.mUiAutomationService.mServiceInterface.asBinder()
    619                     == serviceClient.asBinder()) {
    620                 userState.mUiAutomationService.binderDied();
    621             } else {
    622                 throw new IllegalStateException("UiAutomationService " + serviceClient
    623                         + " not registered!");
    624             }
    625         }
    626     }
    627 
    628     public void temporaryEnableAccessibilityStateUntilKeyguardRemoved(
    629             ComponentName service, boolean touchExplorationEnabled) {
    630         mSecurityPolicy.enforceCallingPermission(
    631                 Manifest.permission.TEMPORARY_ENABLE_ACCESSIBILITY,
    632                 TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED);
    633         try {
    634             if (!mWindowManagerService.isKeyguardLocked()) {
    635                 return;
    636             }
    637         } catch (RemoteException re) {
    638             return;
    639         }
    640         synchronized (mLock) {
    641             // Set the temporary state.
    642             UserState userState = getCurrentUserStateLocked();
    643 
    644             // This is a nop if UI automation is enabled.
    645             if (userState.mUiAutomationService != null) {
    646                 return;
    647             }
    648 
    649             userState.mIsAccessibilityEnabled = true;
    650             userState.mIsTouchExplorationEnabled = touchExplorationEnabled;
    651             userState.mIsEnhancedWebAccessibilityEnabled = false;
    652             userState.mIsDisplayMagnificationEnabled = false;
    653             userState.mEnabledServices.clear();
    654             userState.mEnabledServices.add(service);
    655             userState.mBindingServices.clear();
    656             userState.mTouchExplorationGrantedServices.clear();
    657             userState.mTouchExplorationGrantedServices.add(service);
    658 
    659             // User the current state instead settings.
    660             onUserStateChangedLocked(userState);
    661         }
    662     }
    663 
    664     boolean onGesture(int gestureId) {
    665         synchronized (mLock) {
    666             boolean handled = notifyGestureLocked(gestureId, false);
    667             if (!handled) {
    668                 handled = notifyGestureLocked(gestureId, true);
    669             }
    670             return handled;
    671         }
    672     }
    673 
    674     boolean notifyKeyEvent(KeyEvent event, int policyFlags) {
    675         synchronized (mLock) {
    676             KeyEvent localClone = KeyEvent.obtain(event);
    677             boolean handled = notifyKeyEventLocked(localClone, policyFlags, false);
    678             if (!handled) {
    679                 handled = notifyKeyEventLocked(localClone, policyFlags, true);
    680             }
    681             return handled;
    682         }
    683     }
    684 
    685     /**
    686      * Gets the bounds of the accessibility focus in the active window.
    687      *
    688      * @param outBounds The output to which to write the focus bounds.
    689      * @return Whether accessibility focus was found and the bounds are populated.
    690      */
    691     // TODO: (multi-display) Make sure this works for multiple displays.
    692     boolean getAccessibilityFocusBoundsInActiveWindow(Rect outBounds) {
    693         // Instead of keeping track of accessibility focus events per
    694         // window to be able to find the focus in the active window,
    695         // we take a stateless approach and look it up. This is fine
    696         // since we do this only when the user clicks/long presses.
    697         Service service = getQueryBridge();
    698         final int connectionId = service.mId;
    699         AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
    700         client.addConnection(connectionId, service);
    701         try {
    702             AccessibilityNodeInfo root = AccessibilityInteractionClient.getInstance()
    703                     .getRootInActiveWindow(connectionId);
    704             if (root == null) {
    705                 return false;
    706             }
    707             AccessibilityNodeInfo focus = root.findFocus(
    708                     AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
    709             if (focus == null) {
    710                 return false;
    711             }
    712             focus.getBoundsInScreen(outBounds);
    713 
    714             MagnificationSpec spec = service.getCompatibleMagnificationSpec(focus.getWindowId());
    715             if (spec != null && !spec.isNop()) {
    716                 outBounds.offset((int) -spec.offsetX, (int) -spec.offsetY);
    717                 outBounds.scale(1 / spec.scale);
    718             }
    719 
    720             // Clip to the window rectangle.
    721             Rect windowBounds = mTempRect;
    722             getActiveWindowBounds(windowBounds);
    723             outBounds.intersect(windowBounds);
    724             // Clip to the screen rectangle.
    725             mDefaultDisplay.getRealSize(mTempPoint);
    726             outBounds.intersect(0,  0,  mTempPoint.x, mTempPoint.y);
    727 
    728             return true;
    729         } finally {
    730             client.removeConnection(connectionId);
    731         }
    732     }
    733 
    734     /**
    735      * Gets the bounds of the active window.
    736      *
    737      * @param outBounds The output to which to write the bounds.
    738      */
    739     boolean getActiveWindowBounds(Rect outBounds) {
    740         IBinder token;
    741         synchronized (mLock) {
    742             final int windowId = mSecurityPolicy.mActiveWindowId;
    743             token = mGlobalWindowTokens.get(windowId);
    744             if (token == null) {
    745                 token = getCurrentUserStateLocked().mWindowTokens.get(windowId);
    746             }
    747         }
    748         try {
    749             mWindowManagerService.getWindowFrame(token, outBounds);
    750             if (!outBounds.isEmpty()) {
    751                 return true;
    752             }
    753         } catch (RemoteException re) {
    754             /* ignore */
    755         }
    756         return false;
    757     }
    758 
    759     int getActiveWindowId() {
    760         return mSecurityPolicy.mActiveWindowId;
    761     }
    762 
    763     void onTouchInteractionStart() {
    764         mSecurityPolicy.onTouchInteractionStart();
    765     }
    766 
    767     void onTouchInteractionEnd() {
    768         mSecurityPolicy.onTouchInteractionEnd();
    769     }
    770 
    771     void onMagnificationStateChanged() {
    772         notifyClearAccessibilityNodeInfoCacheLocked();
    773     }
    774 
    775     private void switchUser(int userId) {
    776         synchronized (mLock) {
    777             if (mCurrentUserId == userId && mInitialized) {
    778                 return;
    779             }
    780 
    781             // Disconnect from services for the old user.
    782             UserState oldUserState = getUserStateLocked(mCurrentUserId);
    783             oldUserState.onSwitchToAnotherUser();
    784 
    785             // Disable the local managers for the old user.
    786             if (oldUserState.mClients.getRegisteredCallbackCount() > 0) {
    787                 mMainHandler.obtainMessage(MainHandler.MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER,
    788                         oldUserState.mUserId, 0).sendToTarget();
    789             }
    790 
    791             // Announce user changes only if more that one exist.
    792             UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
    793             final boolean announceNewUser = userManager.getUsers().size() > 1;
    794 
    795             // The user changed.
    796             mCurrentUserId = userId;
    797 
    798             UserState userState = getCurrentUserStateLocked();
    799             if (userState.mUiAutomationService != null) {
    800                 // Switching users disables the UI automation service.
    801                 userState.mUiAutomationService.binderDied();
    802             }
    803 
    804             readConfigurationForUserStateLocked(userState);
    805             // Even if reading did not yield change, we have to update
    806             // the state since the context in which the current user
    807             // state was used has changed since it was inactive.
    808             onUserStateChangedLocked(userState);
    809 
    810             if (announceNewUser) {
    811                 // Schedule announcement of the current user if needed.
    812                 mMainHandler.sendEmptyMessageDelayed(MainHandler.MSG_ANNOUNCE_NEW_USER_IF_NEEDED,
    813                         WAIT_FOR_USER_STATE_FULLY_INITIALIZED_MILLIS);
    814             }
    815         }
    816     }
    817 
    818     private void removeUser(int userId) {
    819         synchronized (mLock) {
    820             mUserStates.remove(userId);
    821         }
    822     }
    823 
    824     private Service getQueryBridge() {
    825         if (mQueryBridge == null) {
    826             AccessibilityServiceInfo info = new AccessibilityServiceInfo();
    827             info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
    828             mQueryBridge = new Service(UserHandle.USER_NULL,
    829                     sFakeAccessibilityServiceComponentName, info);
    830         }
    831         return mQueryBridge;
    832     }
    833 
    834     private boolean notifyGestureLocked(int gestureId, boolean isDefault) {
    835         // TODO: Now we are giving the gestures to the last enabled
    836         //       service that can handle them which is the last one
    837         //       in our list since we write the last enabled as the
    838         //       last record in the enabled services setting. Ideally,
    839         //       the user should make the call which service handles
    840         //       gestures. However, only one service should handle
    841         //       gestures to avoid user frustration when different
    842         //       behavior is observed from different combinations of
    843         //       enabled accessibility services.
    844         UserState state = getCurrentUserStateLocked();
    845         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
    846             Service service = state.mBoundServices.get(i);
    847             if (service.mRequestTouchExplorationMode && service.mIsDefault == isDefault) {
    848                 service.notifyGesture(gestureId);
    849                 return true;
    850             }
    851         }
    852         return false;
    853     }
    854 
    855     private boolean notifyKeyEventLocked(KeyEvent event, int policyFlags, boolean isDefault) {
    856         // TODO: Now we are giving the key events to the last enabled
    857         //       service that can handle them Ideally, the user should
    858         //       make the call which service handles key events. However,
    859         //       only one service should handle key events to avoid user
    860         //       frustration when different behavior is observed from
    861         //       different combinations of enabled accessibility services.
    862         UserState state = getCurrentUserStateLocked();
    863         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
    864             Service service = state.mBoundServices.get(i);
    865             // Key events are handled only by services that declared
    866             // this capability and requested to filter key events.
    867             if (!service.mRequestFilterKeyEvents ||
    868                     (service.mAccessibilityServiceInfo.getCapabilities() & AccessibilityServiceInfo
    869                             .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) == 0) {
    870                 continue;
    871             }
    872             if (service.mIsDefault == isDefault) {
    873                 service.notifyKeyEvent(event, policyFlags);
    874                 return true;
    875             }
    876         }
    877         return false;
    878     }
    879 
    880     private void notifyClearAccessibilityNodeInfoCacheLocked() {
    881         UserState state = getCurrentUserStateLocked();
    882         for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
    883             Service service = state.mBoundServices.get(i);
    884             service.notifyClearAccessibilityNodeInfoCache();
    885         }
    886     }
    887 
    888     /**
    889      * Removes an AccessibilityInteractionConnection.
    890      *
    891      * @param windowId The id of the window to which the connection is targeted.
    892      * @param userId The id of the user owning the connection. UserHandle.USER_ALL
    893      *     if global.
    894      */
    895     private void removeAccessibilityInteractionConnectionLocked(int windowId, int userId) {
    896         if (userId == UserHandle.USER_ALL) {
    897             mGlobalWindowTokens.remove(windowId);
    898             mGlobalInteractionConnections.remove(windowId);
    899         } else {
    900             UserState userState = getCurrentUserStateLocked();
    901             userState.mWindowTokens.remove(windowId);
    902             userState.mInteractionConnections.remove(windowId);
    903         }
    904         if (DEBUG) {
    905             Slog.i(LOG_TAG, "Removing interaction connection to windowId: " + windowId);
    906         }
    907     }
    908 
    909     private boolean readInstalledAccessibilityServiceLocked(UserState userState) {
    910         mTempAccessibilityServiceInfoList.clear();
    911 
    912         List<ResolveInfo> installedServices = mPackageManager.queryIntentServicesAsUser(
    913                 new Intent(AccessibilityService.SERVICE_INTERFACE),
    914                 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
    915                 mCurrentUserId);
    916 
    917         for (int i = 0, count = installedServices.size(); i < count; i++) {
    918             ResolveInfo resolveInfo = installedServices.get(i);
    919             ServiceInfo serviceInfo = resolveInfo.serviceInfo;
    920             if (!android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE.equals(
    921                     serviceInfo.permission)) {
    922                 Slog.w(LOG_TAG, "Skipping accessibilty service " + new ComponentName(
    923                         serviceInfo.packageName, serviceInfo.name).flattenToShortString()
    924                         + ": it does not require the permission "
    925                         + android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE);
    926                 continue;
    927             }
    928             AccessibilityServiceInfo accessibilityServiceInfo;
    929             try {
    930                 accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext);
    931                 mTempAccessibilityServiceInfoList.add(accessibilityServiceInfo);
    932             } catch (XmlPullParserException xppe) {
    933                 Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", xppe);
    934             } catch (IOException ioe) {
    935                 Slog.e(LOG_TAG, "Error while initializing AccessibilityServiceInfo", ioe);
    936             }
    937         }
    938 
    939         if (!mTempAccessibilityServiceInfoList.equals(userState.mInstalledServices)) {
    940             userState.mInstalledServices.clear();
    941             userState.mInstalledServices.addAll(mTempAccessibilityServiceInfoList);
    942             mTempAccessibilityServiceInfoList.clear();
    943             return true;
    944         }
    945 
    946         mTempAccessibilityServiceInfoList.clear();
    947         return false;
    948     }
    949 
    950     private boolean readEnabledAccessibilityServicesLocked(UserState userState) {
    951         mTempComponentNameSet.clear();
    952         readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
    953                 userState.mUserId, mTempComponentNameSet);
    954         if (!mTempComponentNameSet.equals(userState.mEnabledServices)) {
    955             userState.mEnabledServices.clear();
    956             userState.mEnabledServices.addAll(mTempComponentNameSet);
    957             mTempComponentNameSet.clear();
    958             return true;
    959         }
    960         mTempComponentNameSet.clear();
    961         return false;
    962     }
    963 
    964     private boolean readTouchExplorationGrantedAccessibilityServicesLocked(
    965             UserState userState) {
    966         mTempComponentNameSet.clear();
    967         readComponentNamesFromSettingLocked(
    968                 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
    969                 userState.mUserId, mTempComponentNameSet);
    970         if (!mTempComponentNameSet.equals(userState.mTouchExplorationGrantedServices)) {
    971             userState.mTouchExplorationGrantedServices.clear();
    972             userState.mTouchExplorationGrantedServices.addAll(mTempComponentNameSet);
    973             mTempComponentNameSet.clear();
    974             return true;
    975         }
    976         mTempComponentNameSet.clear();
    977         return false;
    978     }
    979 
    980     /**
    981      * Performs {@link AccessibilityService}s delayed notification. The delay is configurable
    982      * and denotes the period after the last event before notifying the service.
    983      *
    984      * @param event The event.
    985      * @param isDefault True to notify default listeners, not default services.
    986      */
    987     private void notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event,
    988             boolean isDefault) {
    989         try {
    990             UserState state = getCurrentUserStateLocked();
    991             for (int i = 0, count = state.mBoundServices.size(); i < count; i++) {
    992                 Service service = state.mBoundServices.get(i);
    993 
    994                 if (service.mIsDefault == isDefault) {
    995                     if (canDispathEventLocked(service, event, state.mHandledFeedbackTypes)) {
    996                         state.mHandledFeedbackTypes |= service.mFeedbackType;
    997                         service.notifyAccessibilityEvent(event);
    998                     }
    999                 }
   1000             }
   1001         } catch (IndexOutOfBoundsException oobe) {
   1002             // An out of bounds exception can happen if services are going away
   1003             // as the for loop is running. If that happens, just bail because
   1004             // there are no more services to notify.
   1005             return;
   1006         }
   1007     }
   1008 
   1009     private void addServiceLocked(Service service, UserState userState) {
   1010         try {
   1011             service.linkToOwnDeathLocked();
   1012             userState.mBoundServices.add(service);
   1013             userState.mComponentNameToServiceMap.put(service.mComponentName, service);
   1014         } catch (RemoteException re) {
   1015             /* do nothing */
   1016         }
   1017     }
   1018 
   1019     /**
   1020      * Removes a service.
   1021      *
   1022      * @param service The service.
   1023      * @return True if the service was removed, false otherwise.
   1024      */
   1025     private void removeServiceLocked(Service service, UserState userState) {
   1026         userState.mBoundServices.remove(service);
   1027         userState.mComponentNameToServiceMap.remove(service.mComponentName);
   1028         service.unlinkToOwnDeathLocked();
   1029     }
   1030 
   1031     /**
   1032      * Determines if given event can be dispatched to a service based on the package of the
   1033      * event source and already notified services for that event type. Specifically, a
   1034      * service is notified if it is interested in events from the package and no other service
   1035      * providing the same feedback type has been notified. Exception are services the
   1036      * provide generic feedback (feedback type left as a safety net for unforeseen feedback
   1037      * types) which are always notified.
   1038      *
   1039      * @param service The potential receiver.
   1040      * @param event The event.
   1041      * @param handledFeedbackTypes The feedback types for which services have been notified.
   1042      * @return True if the listener should be notified, false otherwise.
   1043      */
   1044     private boolean canDispathEventLocked(Service service, AccessibilityEvent event,
   1045             int handledFeedbackTypes) {
   1046 
   1047         if (!service.canReceiveEventsLocked()) {
   1048             return false;
   1049         }
   1050 
   1051         if (!event.isImportantForAccessibility()
   1052                 && (service.mFetchFlags
   1053                         & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
   1054             return false;
   1055         }
   1056 
   1057         int eventType = event.getEventType();
   1058         if ((service.mEventTypes & eventType) != eventType) {
   1059             return false;
   1060         }
   1061 
   1062         Set<String> packageNames = service.mPackageNames;
   1063         CharSequence packageName = event.getPackageName();
   1064 
   1065         if (packageNames.isEmpty() || packageNames.contains(packageName)) {
   1066             int feedbackType = service.mFeedbackType;
   1067             if ((handledFeedbackTypes & feedbackType) != feedbackType
   1068                     || feedbackType == AccessibilityServiceInfo.FEEDBACK_GENERIC) {
   1069                 return true;
   1070             }
   1071         }
   1072 
   1073         return false;
   1074     }
   1075 
   1076     private void unbindAllServicesLocked(UserState userState) {
   1077         List<Service> services = userState.mBoundServices;
   1078         for (int i = 0, count = services.size(); i < count; i++) {
   1079             Service service = services.get(i);
   1080             if (service.unbindLocked()) {
   1081                 i--;
   1082                 count--;
   1083             }
   1084         }
   1085     }
   1086 
   1087     /**
   1088      * Populates a set with the {@link ComponentName}s stored in a colon
   1089      * separated value setting for a given user.
   1090      *
   1091      * @param settingName The setting to parse.
   1092      * @param userId The user id.
   1093      * @param outComponentNames The output component names.
   1094      */
   1095     private void readComponentNamesFromSettingLocked(String settingName, int userId,
   1096             Set<ComponentName> outComponentNames) {
   1097         String settingValue = Settings.Secure.getStringForUser(mContext.getContentResolver(),
   1098                 settingName, userId);
   1099         outComponentNames.clear();
   1100         if (settingValue != null) {
   1101             TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
   1102             splitter.setString(settingValue);
   1103             while (splitter.hasNext()) {
   1104                 String str = splitter.next();
   1105                 if (str == null || str.length() <= 0) {
   1106                     continue;
   1107                 }
   1108                 ComponentName enabledService = ComponentName.unflattenFromString(str);
   1109                 if (enabledService != null) {
   1110                     outComponentNames.add(enabledService);
   1111                 }
   1112             }
   1113         }
   1114     }
   1115 
   1116     /**
   1117      * Persists the component names in the specified setting in a
   1118      * colon separated fashion.
   1119      *
   1120      * @param settingName The setting name.
   1121      * @param componentNames The component names.
   1122      */
   1123     private void persistComponentNamesToSettingLocked(String settingName,
   1124             Set<ComponentName> componentNames, int userId) {
   1125         StringBuilder builder = new StringBuilder();
   1126         for (ComponentName componentName : componentNames) {
   1127             if (builder.length() > 0) {
   1128                 builder.append(COMPONENT_NAME_SEPARATOR);
   1129             }
   1130             builder.append(componentName.flattenToShortString());
   1131         }
   1132         Settings.Secure.putStringForUser(mContext.getContentResolver(),
   1133                 settingName, builder.toString(), userId);
   1134     }
   1135 
   1136     private void manageServicesLocked(UserState userState) {
   1137         Map<ComponentName, Service> componentNameToServiceMap =
   1138                 userState.mComponentNameToServiceMap;
   1139         boolean isEnabled = userState.mIsAccessibilityEnabled;
   1140 
   1141         for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) {
   1142             AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i);
   1143             ComponentName componentName = ComponentName.unflattenFromString(
   1144                     installedService.getId());
   1145             Service service = componentNameToServiceMap.get(componentName);
   1146 
   1147             if (isEnabled) {
   1148                 // Wait for the binding if it is in process.
   1149                 if (userState.mBindingServices.contains(componentName)) {
   1150                     continue;
   1151                 }
   1152                 if (userState.mEnabledServices.contains(componentName)) {
   1153                     if (service == null) {
   1154                         service = new Service(userState.mUserId, componentName, installedService);
   1155                     } else if (userState.mBoundServices.contains(service)) {
   1156                         continue;
   1157                     }
   1158                     service.bindLocked();
   1159                 } else {
   1160                     if (service != null) {
   1161                         service.unbindLocked();
   1162                     }
   1163                 }
   1164             } else {
   1165                 if (service != null) {
   1166                     service.unbindLocked();
   1167                 } else {
   1168                     userState.mBindingServices.remove(componentName);
   1169                 }
   1170             }
   1171         }
   1172 
   1173         // No enabled installed services => disable accessibility to avoid
   1174         // sending accessibility events with no recipient across processes.
   1175         if (isEnabled && userState.mEnabledServices.isEmpty()) {
   1176             userState.mIsAccessibilityEnabled = false;
   1177             Settings.Secure.putIntForUser(mContext.getContentResolver(),
   1178                     Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId);
   1179         }
   1180     }
   1181 
   1182     private void scheduleUpdateClientsIfNeededLocked(UserState userState) {
   1183         final int clientState = userState.getClientState();
   1184         if (userState.mLastSentClientState != clientState
   1185                 && (mGlobalClients.getRegisteredCallbackCount() > 0
   1186                         || userState.mClients.getRegisteredCallbackCount() > 0)) {
   1187             userState.mLastSentClientState = clientState;
   1188             mMainHandler.obtainMessage(MainHandler.MSG_SEND_STATE_TO_CLIENTS,
   1189                     clientState, userState.mUserId) .sendToTarget();
   1190         }
   1191     }
   1192 
   1193     private void scheduleUpdateInputFilter(UserState userState) {
   1194         mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_INPUT_FILTER, userState).sendToTarget();
   1195     }
   1196 
   1197     private void updateInputFilter(UserState userState) {
   1198         boolean setInputFilter = false;
   1199         AccessibilityInputFilter inputFilter = null;
   1200         synchronized (mLock) {
   1201             int flags = 0;
   1202             if (userState.mIsDisplayMagnificationEnabled) {
   1203                 flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER;
   1204             }
   1205             // Touch exploration without accessibility makes no sense.
   1206             if (userState.mIsAccessibilityEnabled && userState.mIsTouchExplorationEnabled) {
   1207                 flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION;
   1208             }
   1209             if (userState.mIsFilterKeyEventsEnabled) {
   1210                 flags |= AccessibilityInputFilter.FLAG_FEATURE_FILTER_KEY_EVENTS;
   1211             }
   1212             if (flags != 0) {
   1213                 if (!mHasInputFilter) {
   1214                     mHasInputFilter = true;
   1215                     if (mInputFilter == null) {
   1216                         mInputFilter = new AccessibilityInputFilter(mContext,
   1217                                 AccessibilityManagerService.this);
   1218                     }
   1219                     inputFilter = mInputFilter;
   1220                     setInputFilter = true;
   1221                 }
   1222                 mInputFilter.setEnabledFeatures(flags);
   1223             } else {
   1224                 if (mHasInputFilter) {
   1225                     mHasInputFilter = false;
   1226                     mInputFilter.disableFeatures();
   1227                     inputFilter = null;
   1228                     setInputFilter = true;
   1229                 }
   1230             }
   1231         }
   1232         if (setInputFilter) {
   1233             try {
   1234                 mWindowManagerService.setInputFilter(inputFilter);
   1235             } catch (RemoteException re) {
   1236                 /* ignore */
   1237             }
   1238         }
   1239     }
   1240 
   1241     private void showEnableTouchExplorationDialog(final Service service) {
   1242         synchronized (mLock) {
   1243             String label = service.mResolveInfo.loadLabel(
   1244             mContext.getPackageManager()).toString();
   1245 
   1246             final UserState state = getCurrentUserStateLocked();
   1247             if (state.mIsTouchExplorationEnabled) {
   1248                 return;
   1249             }
   1250             if (mEnableTouchExplorationDialog != null
   1251                     && mEnableTouchExplorationDialog.isShowing()) {
   1252                 return;
   1253             }
   1254             mEnableTouchExplorationDialog = new AlertDialog.Builder(mContext)
   1255                 .setIconAttribute(android.R.attr.alertDialogIcon)
   1256                 .setPositiveButton(android.R.string.ok, new OnClickListener() {
   1257                      @Override
   1258                      public void onClick(DialogInterface dialog, int which) {
   1259                          // The user allowed the service to toggle touch exploration.
   1260                          state.mTouchExplorationGrantedServices.add(service.mComponentName);
   1261                          persistComponentNamesToSettingLocked(
   1262                                  Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
   1263                                  state.mTouchExplorationGrantedServices, state.mUserId);
   1264                          // Enable touch exploration.
   1265                          UserState userState = getUserStateLocked(service.mUserId);
   1266                          userState.mIsTouchExplorationEnabled = true;
   1267                          Settings.Secure.putIntForUser(mContext.getContentResolver(),
   1268                                  Settings.Secure.TOUCH_EXPLORATION_ENABLED, 1,
   1269                                  service.mUserId);
   1270                          onUserStateChangedLocked(userState);
   1271                      }
   1272                  })
   1273                  .setNegativeButton(android.R.string.cancel, new OnClickListener() {
   1274                      @Override
   1275                      public void onClick(DialogInterface dialog, int which) {
   1276                          dialog.dismiss();
   1277                      }
   1278                  })
   1279                  .setTitle(R.string.enable_explore_by_touch_warning_title)
   1280                  .setMessage(mContext.getString(
   1281                          R.string.enable_explore_by_touch_warning_message, label))
   1282                  .create();
   1283              mEnableTouchExplorationDialog.getWindow().setType(
   1284                      WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
   1285              mEnableTouchExplorationDialog.getWindow().getAttributes().privateFlags
   1286                      |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
   1287              mEnableTouchExplorationDialog.setCanceledOnTouchOutside(true);
   1288              mEnableTouchExplorationDialog.show();
   1289         }
   1290     }
   1291 
   1292     private void onUserStateChangedLocked(UserState userState) {
   1293         // TODO: Remove this hack
   1294         mInitialized = true;
   1295         updateLegacyCapabilities(userState);
   1296         updateServicesLocked(userState);
   1297         updateFilterKeyEventsLocked(userState);
   1298         updateTouchExplorationLocked(userState);
   1299         updateEnhancedWebAccessibilityLocked(userState);
   1300         scheduleUpdateInputFilter(userState);
   1301         scheduleUpdateClientsIfNeededLocked(userState);
   1302     }
   1303 
   1304     private void updateLegacyCapabilities(UserState userState) {
   1305         // Up to JB-MR1 we had a white list with services that can enable touch
   1306         // exploration. When a service is first started we show a dialog to the
   1307         // use to get a permission to white list the service.
   1308         final int installedServiceCount = userState.mInstalledServices.size();
   1309         for (int i = 0; i < installedServiceCount; i++) {
   1310             AccessibilityServiceInfo serviceInfo = userState.mInstalledServices.get(i);
   1311             ResolveInfo resolveInfo = serviceInfo.getResolveInfo();
   1312             if ((serviceInfo.getCapabilities()
   1313                         & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) == 0
   1314                     && resolveInfo.serviceInfo.applicationInfo.targetSdkVersion
   1315                         <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
   1316                 ComponentName componentName = new ComponentName(
   1317                         resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
   1318                 if (userState.mTouchExplorationGrantedServices.contains(componentName)) {
   1319                     serviceInfo.setCapabilities(serviceInfo.getCapabilities()
   1320                             | AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION);
   1321                 }
   1322             }
   1323         }
   1324     }
   1325 
   1326     private void updateFilterKeyEventsLocked(UserState userState) {
   1327         final int serviceCount = userState.mBoundServices.size();
   1328         for (int i = 0; i < serviceCount; i++) {
   1329             Service service = userState.mBoundServices.get(i);
   1330             if (service.mRequestFilterKeyEvents
   1331                     && (service.mAccessibilityServiceInfo.getCapabilities()
   1332                             & AccessibilityServiceInfo
   1333                             .CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) != 0) {
   1334                 userState.mIsFilterKeyEventsEnabled = true;
   1335                 return;
   1336             }
   1337         }
   1338         userState.mIsFilterKeyEventsEnabled = false;
   1339     }
   1340 
   1341     private void updateServicesLocked(UserState userState) {
   1342         if (userState.mIsAccessibilityEnabled) {
   1343             manageServicesLocked(userState);
   1344         } else {
   1345             unbindAllServicesLocked(userState);
   1346         }
   1347     }
   1348 
   1349     private boolean readConfigurationForUserStateLocked(UserState userState) {
   1350         boolean somthingChanged = false;
   1351         somthingChanged |= readAccessibilityEnabledSettingLocked(userState);
   1352         somthingChanged |= readInstalledAccessibilityServiceLocked(userState);
   1353         somthingChanged |= readEnabledAccessibilityServicesLocked(userState);
   1354         somthingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState);
   1355         somthingChanged |= readTouchExplorationEnabledSettingLocked(userState);
   1356         somthingChanged |= readEnhancedWebAccessibilityEnabledChangedLocked(userState);
   1357         somthingChanged |= readDisplayMagnificationEnabledSettingLocked(userState);
   1358         return somthingChanged;
   1359     }
   1360 
   1361     private boolean readAccessibilityEnabledSettingLocked(UserState userState) {
   1362         final boolean accessibilityEnabled = Settings.Secure.getIntForUser(
   1363                mContext.getContentResolver(),
   1364                Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId) == 1;
   1365         if (accessibilityEnabled != userState.mIsAccessibilityEnabled) {
   1366             userState.mIsAccessibilityEnabled = accessibilityEnabled;
   1367             return true;
   1368         }
   1369         return false;
   1370     }
   1371 
   1372     private boolean readTouchExplorationEnabledSettingLocked(UserState userState) {
   1373         final boolean touchExplorationEnabled = Settings.Secure.getIntForUser(
   1374                 mContext.getContentResolver(),
   1375                 Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0, userState.mUserId) == 1;
   1376         if (touchExplorationEnabled != userState.mIsTouchExplorationEnabled) {
   1377             userState.mIsTouchExplorationEnabled = touchExplorationEnabled;
   1378             return true;
   1379         }
   1380         return false;
   1381     }
   1382 
   1383     private boolean readDisplayMagnificationEnabledSettingLocked(UserState userState) {
   1384         final boolean displayMagnificationEnabled = Settings.Secure.getIntForUser(
   1385                 mContext.getContentResolver(),
   1386                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
   1387                 0, userState.mUserId) == 1;
   1388         if (displayMagnificationEnabled != userState.mIsDisplayMagnificationEnabled) {
   1389             userState.mIsDisplayMagnificationEnabled = displayMagnificationEnabled;
   1390             return true;
   1391         }
   1392         return false;
   1393     }
   1394 
   1395     private boolean readEnhancedWebAccessibilityEnabledChangedLocked(UserState userState) {
   1396          final boolean enhancedWeAccessibilityEnabled = Settings.Secure.getIntForUser(
   1397                 mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION,
   1398                 0, userState.mUserId) == 1;
   1399          if (enhancedWeAccessibilityEnabled != userState.mIsEnhancedWebAccessibilityEnabled) {
   1400              userState.mIsEnhancedWebAccessibilityEnabled = enhancedWeAccessibilityEnabled;
   1401              return true;
   1402          }
   1403          return false;
   1404     }
   1405 
   1406     private void updateTouchExplorationLocked(UserState userState) {
   1407         boolean enabled = false;
   1408         final int serviceCount = userState.mBoundServices.size();
   1409         for (int i = 0; i < serviceCount; i++) {
   1410             Service service = userState.mBoundServices.get(i);
   1411             if (canRequestAndRequestsTouchExplorationLocked(service)) {
   1412                 enabled = true;
   1413                 break;
   1414             }
   1415         }
   1416         if (enabled != userState.mIsTouchExplorationEnabled) {
   1417             userState.mIsTouchExplorationEnabled = enabled;
   1418             Settings.Secure.putIntForUser(mContext.getContentResolver(),
   1419                     Settings.Secure.TOUCH_EXPLORATION_ENABLED, enabled ? 1 : 0,
   1420                     userState.mUserId);
   1421         }
   1422         try {
   1423             mWindowManagerService.setTouchExplorationEnabled(enabled);
   1424         } catch (RemoteException e) {
   1425             e.printStackTrace();
   1426         }
   1427     }
   1428 
   1429     private boolean canRequestAndRequestsTouchExplorationLocked(Service service) {
   1430         // Service not ready or cannot request the feature - well nothing to do.
   1431         if (!service.canReceiveEventsLocked() || !service.mRequestTouchExplorationMode) {
   1432             return false;
   1433         }
   1434         // UI test automation service can always enable it.
   1435         if (service.mIsAutomation) {
   1436             return true;
   1437         }
   1438         if (service.mResolveInfo.serviceInfo.applicationInfo.targetSdkVersion
   1439                 <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
   1440             // Up to JB-MR1 we had a white list with services that can enable touch
   1441             // exploration. When a service is first started we show a dialog to the
   1442             // use to get a permission to white list the service.
   1443             UserState userState = getUserStateLocked(service.mUserId);
   1444             if (userState.mTouchExplorationGrantedServices.contains(service.mComponentName)) {
   1445                 return true;
   1446             } else if (mEnableTouchExplorationDialog == null
   1447                     || !mEnableTouchExplorationDialog.isShowing()) {
   1448                 mMainHandler.obtainMessage(
   1449                         MainHandler.MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG,
   1450                         service).sendToTarget();
   1451             }
   1452         } else {
   1453             // Starting in JB-MR2 we request an accessibility service to declare
   1454             // certain capabilities in its meta-data to allow it to enable the
   1455             // corresponding features.
   1456             if ((service.mAccessibilityServiceInfo.getCapabilities()
   1457                     & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) != 0) {
   1458                 return true;
   1459             }
   1460         }
   1461         return false;
   1462     }
   1463 
   1464     private void updateEnhancedWebAccessibilityLocked(UserState userState) {
   1465         boolean enabled = false;
   1466         final int serviceCount = userState.mBoundServices.size();
   1467         for (int i = 0; i < serviceCount; i++) {
   1468             Service service = userState.mBoundServices.get(i);
   1469             if (canRequestAndRequestsEnhancedWebAccessibilityLocked(service)) {
   1470                 enabled = true;
   1471                 break;
   1472             }
   1473         }
   1474         if (enabled != userState.mIsEnhancedWebAccessibilityEnabled) {
   1475             userState.mIsEnhancedWebAccessibilityEnabled = enabled;
   1476             Settings.Secure.putIntForUser(mContext.getContentResolver(),
   1477                     Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, enabled ? 1 : 0,
   1478                     userState.mUserId);
   1479         }
   1480     }
   1481 
   1482     private boolean canRequestAndRequestsEnhancedWebAccessibilityLocked(Service service) {
   1483         if (!service.canReceiveEventsLocked() || !service.mRequestEnhancedWebAccessibility ) {
   1484             return false;
   1485         }
   1486         if (service.mIsAutomation || (service.mAccessibilityServiceInfo.getCapabilities()
   1487                & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY) != 0) {
   1488             return true;
   1489         }
   1490         return false;
   1491     }
   1492 
   1493     @Override
   1494     public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
   1495         mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
   1496         synchronized (mLock) {
   1497             pw.println("ACCESSIBILITY MANAGER (dumpsys accessibility)");
   1498             pw.println();
   1499             final int userCount = mUserStates.size();
   1500             for (int i = 0; i < userCount; i++) {
   1501                 UserState userState = mUserStates.valueAt(i);
   1502                 pw.append("User state[attributes:{id=" + userState.mUserId);
   1503                 pw.append(", currentUser=" + (userState.mUserId == mCurrentUserId));
   1504                 pw.append(", accessibilityEnabled=" + userState.mIsAccessibilityEnabled);
   1505                 pw.append(", touchExplorationEnabled=" + userState.mIsTouchExplorationEnabled);
   1506                 pw.append(", displayMagnificationEnabled="
   1507                         + userState.mIsDisplayMagnificationEnabled);
   1508                 if (userState.mUiAutomationService != null) {
   1509                     pw.append(", ");
   1510                     userState.mUiAutomationService.dump(fd, pw, args);
   1511                     pw.println();
   1512                 }
   1513                 pw.append("}");
   1514                 pw.println();
   1515                 pw.append("           services:{");
   1516                 final int serviceCount = userState.mBoundServices.size();
   1517                 for (int j = 0; j < serviceCount; j++) {
   1518                     if (j > 0) {
   1519                         pw.append(", ");
   1520                         pw.println();
   1521                         pw.append("                     ");
   1522                     }
   1523                     Service service = userState.mBoundServices.get(j);
   1524                     service.dump(fd, pw, args);
   1525                 }
   1526                 pw.println("}]");
   1527                 pw.println();
   1528             }
   1529         }
   1530     }
   1531 
   1532     private class AccessibilityConnectionWrapper implements DeathRecipient {
   1533         private final int mWindowId;
   1534         private final int mUserId;
   1535         private final IAccessibilityInteractionConnection mConnection;
   1536 
   1537         public AccessibilityConnectionWrapper(int windowId,
   1538                 IAccessibilityInteractionConnection connection, int userId) {
   1539             mWindowId = windowId;
   1540             mUserId = userId;
   1541             mConnection = connection;
   1542         }
   1543 
   1544         public void linkToDeath() throws RemoteException {
   1545             mConnection.asBinder().linkToDeath(this, 0);
   1546         }
   1547 
   1548         public void unlinkToDeath() {
   1549             mConnection.asBinder().unlinkToDeath(this, 0);
   1550         }
   1551 
   1552         @Override
   1553         public void binderDied() {
   1554             unlinkToDeath();
   1555             synchronized (mLock) {
   1556                 removeAccessibilityInteractionConnectionLocked(mWindowId, mUserId);
   1557             }
   1558         }
   1559     }
   1560 
   1561     private final class MainHandler extends Handler {
   1562         public static final int MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER = 1;
   1563         public static final int MSG_SEND_STATE_TO_CLIENTS = 2;
   1564         public static final int MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER = 3;
   1565         public static final int MSG_UPDATE_ACTIVE_WINDOW = 4;
   1566         public static final int MSG_ANNOUNCE_NEW_USER_IF_NEEDED = 5;
   1567         public static final int MSG_UPDATE_INPUT_FILTER = 6;
   1568         public static final int MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG = 7;
   1569         public static final int MSG_SEND_KEY_EVENT_TO_INPUT_FILTER = 8;
   1570 
   1571         public MainHandler(Looper looper) {
   1572             super(looper);
   1573         }
   1574 
   1575         @Override
   1576         public void handleMessage(Message msg) {
   1577             final int type = msg.what;
   1578             switch (type) {
   1579                 case MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER: {
   1580                     AccessibilityEvent event = (AccessibilityEvent) msg.obj;
   1581                     synchronized (mLock) {
   1582                         if (mHasInputFilter && mInputFilter != null) {
   1583                             mInputFilter.notifyAccessibilityEvent(event);
   1584                         }
   1585                     }
   1586                     event.recycle();
   1587                 } break;
   1588                 case MSG_SEND_KEY_EVENT_TO_INPUT_FILTER: {
   1589                     KeyEvent event = (KeyEvent) msg.obj;
   1590                     final int policyFlags = msg.arg1;
   1591                     synchronized (mLock) {
   1592                         if (mHasInputFilter && mInputFilter != null) {
   1593                             mInputFilter.sendInputEvent(event, policyFlags);
   1594                         }
   1595                     }
   1596                     event.recycle();
   1597                 } break;
   1598                 case MSG_SEND_STATE_TO_CLIENTS: {
   1599                     final int clientState = msg.arg1;
   1600                     final int userId = msg.arg2;
   1601                     sendStateToClients(clientState, mGlobalClients);
   1602                     sendStateToClientsForUser(clientState, userId);
   1603                 } break;
   1604                 case MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER: {
   1605                     final int userId = msg.arg1;
   1606                     sendStateToClientsForUser(0, userId);
   1607                 } break;
   1608                 case MSG_UPDATE_ACTIVE_WINDOW: {
   1609                     final int windowId = msg.arg1;
   1610                     final int eventType = msg.arg2;
   1611                     mSecurityPolicy.updateActiveWindow(windowId, eventType);
   1612                 } break;
   1613                 case MSG_ANNOUNCE_NEW_USER_IF_NEEDED: {
   1614                     announceNewUserIfNeeded();
   1615                 } break;
   1616                 case MSG_UPDATE_INPUT_FILTER: {
   1617                     UserState userState = (UserState) msg.obj;
   1618                     updateInputFilter(userState);
   1619                 } break;
   1620                 case MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG: {
   1621                     Service service = (Service) msg.obj;
   1622                     showEnableTouchExplorationDialog(service);
   1623                 } break;
   1624             }
   1625         }
   1626 
   1627         private void announceNewUserIfNeeded() {
   1628             synchronized (mLock) {
   1629                 UserState userState = getCurrentUserStateLocked();
   1630                 if (userState.mIsAccessibilityEnabled) {
   1631                     UserManager userManager = (UserManager) mContext.getSystemService(
   1632                             Context.USER_SERVICE);
   1633                     String message = mContext.getString(R.string.user_switched,
   1634                             userManager.getUserInfo(mCurrentUserId).name);
   1635                     AccessibilityEvent event = AccessibilityEvent.obtain(
   1636                             AccessibilityEvent.TYPE_ANNOUNCEMENT);
   1637                     event.getText().add(message);
   1638                     event.setWindowId(mSecurityPolicy.getRetrievalAllowingWindowLocked());
   1639                     sendAccessibilityEvent(event, mCurrentUserId);
   1640                 }
   1641             }
   1642         }
   1643 
   1644         private void sendStateToClientsForUser(int clientState, int userId) {
   1645             final UserState userState;
   1646             synchronized (mLock) {
   1647                 userState = getUserStateLocked(userId);
   1648             }
   1649             sendStateToClients(clientState, userState.mClients);
   1650         }
   1651 
   1652         private void sendStateToClients(int clientState,
   1653                 RemoteCallbackList<IAccessibilityManagerClient> clients) {
   1654             try {
   1655                 final int userClientCount = clients.beginBroadcast();
   1656                 for (int i = 0; i < userClientCount; i++) {
   1657                     IAccessibilityManagerClient client = clients.getBroadcastItem(i);
   1658                     try {
   1659                         client.setState(clientState);
   1660                     } catch (RemoteException re) {
   1661                         /* ignore */
   1662                     }
   1663                 }
   1664             } finally {
   1665                 clients.finishBroadcast();
   1666             }
   1667         }
   1668     }
   1669 
   1670     private PendingEvent obtainPendingEventLocked(KeyEvent event, int policyFlags, int sequence) {
   1671         PendingEvent pendingEvent = mPendingEventPool.acquire();
   1672         if (pendingEvent == null) {
   1673             pendingEvent = new PendingEvent();
   1674         }
   1675         pendingEvent.event = event;
   1676         pendingEvent.policyFlags = policyFlags;
   1677         pendingEvent.sequence = sequence;
   1678         return pendingEvent;
   1679     }
   1680 
   1681     private void recyclePendingEventLocked(PendingEvent pendingEvent) {
   1682         pendingEvent.clear();
   1683         mPendingEventPool.release(pendingEvent);
   1684     }
   1685 
   1686     /**
   1687      * This class represents an accessibility service. It stores all per service
   1688      * data required for the service management, provides API for starting/stopping the
   1689      * service and is responsible for adding/removing the service in the data structures
   1690      * for service management. The class also exposes configuration interface that is
   1691      * passed to the service it represents as soon it is bound. It also serves as the
   1692      * connection for the service.
   1693      */
   1694     class Service extends IAccessibilityServiceConnection.Stub
   1695             implements ServiceConnection, DeathRecipient {;
   1696 
   1697         final int mUserId;
   1698 
   1699         int mId = 0;
   1700 
   1701         AccessibilityServiceInfo mAccessibilityServiceInfo;
   1702 
   1703         IBinder mService;
   1704 
   1705         IAccessibilityServiceClient mServiceInterface;
   1706 
   1707         int mEventTypes;
   1708 
   1709         int mFeedbackType;
   1710 
   1711         Set<String> mPackageNames = new HashSet<String>();
   1712 
   1713         boolean mIsDefault;
   1714 
   1715         boolean mRequestTouchExplorationMode;
   1716 
   1717         boolean mRequestEnhancedWebAccessibility;
   1718 
   1719         boolean mRequestFilterKeyEvents;
   1720 
   1721         int mFetchFlags;
   1722 
   1723         long mNotificationTimeout;
   1724 
   1725         ComponentName mComponentName;
   1726 
   1727         Intent mIntent;
   1728 
   1729         boolean mIsAutomation;
   1730 
   1731         final Rect mTempBounds = new Rect();
   1732 
   1733         final ResolveInfo mResolveInfo;
   1734 
   1735         // the events pending events to be dispatched to this service
   1736         final SparseArray<AccessibilityEvent> mPendingEvents =
   1737             new SparseArray<AccessibilityEvent>();
   1738 
   1739         final KeyEventDispatcher mKeyEventDispatcher = new KeyEventDispatcher();
   1740 
   1741         boolean mWasConnectedAndDied;
   1742 
   1743         // Handler only for dispatching accessibility events since we use event
   1744         // types as message types allowing us to remove messages per event type.
   1745         public Handler mEventDispatchHandler = new Handler(mMainHandler.getLooper()) {
   1746             @Override
   1747             public void handleMessage(Message message) {
   1748                 final int eventType =  message.what;
   1749                 notifyAccessibilityEventInternal(eventType);
   1750             }
   1751         };
   1752 
   1753         // Handler for scheduling method invocations on the main thread.
   1754         public InvocationHandler mInvocationHandler = new InvocationHandler(
   1755                 mMainHandler.getLooper());
   1756 
   1757         public Service(int userId, ComponentName componentName,
   1758                 AccessibilityServiceInfo accessibilityServiceInfo) {
   1759             mUserId = userId;
   1760             mResolveInfo = accessibilityServiceInfo.getResolveInfo();
   1761             mId = sIdCounter++;
   1762             mComponentName = componentName;
   1763             mAccessibilityServiceInfo = accessibilityServiceInfo;
   1764             mIsAutomation = (sFakeAccessibilityServiceComponentName.equals(componentName));
   1765             if (!mIsAutomation) {
   1766                 mIntent = new Intent().setComponent(mComponentName);
   1767                 mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
   1768                         com.android.internal.R.string.accessibility_binding_label);
   1769                 mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
   1770                         mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0));
   1771             }
   1772             setDynamicallyConfigurableProperties(accessibilityServiceInfo);
   1773         }
   1774 
   1775         public void setDynamicallyConfigurableProperties(AccessibilityServiceInfo info) {
   1776             mEventTypes = info.eventTypes;
   1777             mFeedbackType = info.feedbackType;
   1778             String[] packageNames = info.packageNames;
   1779             if (packageNames != null) {
   1780                 mPackageNames.addAll(Arrays.asList(packageNames));
   1781             }
   1782             mNotificationTimeout = info.notificationTimeout;
   1783             mIsDefault = (info.flags & DEFAULT) != 0;
   1784 
   1785             if (mIsAutomation || info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion
   1786                     >= Build.VERSION_CODES.JELLY_BEAN) {
   1787                 if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) {
   1788                     mFetchFlags |= AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
   1789                 } else {
   1790                     mFetchFlags &= ~AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
   1791                 }
   1792             }
   1793 
   1794             if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) {
   1795                 mFetchFlags |= AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;
   1796             } else {
   1797                 mFetchFlags &= ~AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;
   1798             }
   1799 
   1800             mRequestTouchExplorationMode = (info.flags
   1801                     & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0;
   1802             mRequestEnhancedWebAccessibility = (info.flags
   1803                     & AccessibilityServiceInfo.FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY) != 0;
   1804             mRequestFilterKeyEvents = (info.flags
   1805                     & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS)  != 0;
   1806         }
   1807 
   1808         /**
   1809          * Binds to the accessibility service.
   1810          *
   1811          * @return True if binding is successful.
   1812          */
   1813         public boolean bindLocked() {
   1814             UserState userState = getUserStateLocked(mUserId);
   1815             if (!mIsAutomation) {
   1816                 if (mService == null && mContext.bindServiceAsUser(
   1817                         mIntent, this, Context.BIND_AUTO_CREATE, new UserHandle(mUserId))) {
   1818                     userState.mBindingServices.add(mComponentName);
   1819                 }
   1820             } else {
   1821                 userState.mBindingServices.add(mComponentName);
   1822                 mService = userState.mUiAutomationServiceClient.asBinder();
   1823                 onServiceConnected(mComponentName, mService);
   1824                 userState.mUiAutomationService = this;
   1825             }
   1826             return false;
   1827         }
   1828 
   1829         /**
   1830          * Unbinds form the accessibility service and removes it from the data
   1831          * structures for service management.
   1832          *
   1833          * @return True if unbinding is successful.
   1834          */
   1835         public boolean unbindLocked() {
   1836             if (mService == null) {
   1837                 return false;
   1838             }
   1839             UserState userState = getUserStateLocked(mUserId);
   1840             mKeyEventDispatcher.flush();
   1841             if (!mIsAutomation) {
   1842                 mContext.unbindService(this);
   1843             } else {
   1844                 userState.destroyUiAutomationService();
   1845             }
   1846             removeServiceLocked(this, userState);
   1847             resetLocked();
   1848             return true;
   1849         }
   1850 
   1851         public boolean canReceiveEventsLocked() {
   1852             return (mEventTypes != 0 && mFeedbackType != 0 && mService != null);
   1853         }
   1854 
   1855         @Override
   1856         public void setOnKeyEventResult(boolean handled, int sequence) {
   1857             mKeyEventDispatcher.setOnKeyEventResult(handled, sequence);
   1858         }
   1859 
   1860         @Override
   1861         public AccessibilityServiceInfo getServiceInfo() {
   1862             synchronized (mLock) {
   1863                 return mAccessibilityServiceInfo;
   1864             }
   1865         }
   1866 
   1867         @Override
   1868         public void setServiceInfo(AccessibilityServiceInfo info) {
   1869             final long identity = Binder.clearCallingIdentity();
   1870             try {
   1871                 synchronized (mLock) {
   1872                     // If the XML manifest had data to configure the service its info
   1873                     // should be already set. In such a case update only the dynamically
   1874                     // configurable properties.
   1875                     AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo;
   1876                     if (oldInfo != null) {
   1877                         oldInfo.updateDynamicallyConfigurableProperties(info);
   1878                         setDynamicallyConfigurableProperties(oldInfo);
   1879                     } else {
   1880                         setDynamicallyConfigurableProperties(info);
   1881                     }
   1882                     UserState userState = getUserStateLocked(mUserId);
   1883                     onUserStateChangedLocked(userState);
   1884                 }
   1885             } finally {
   1886                 Binder.restoreCallingIdentity(identity);
   1887             }
   1888         }
   1889 
   1890         @Override
   1891         public void onServiceConnected(ComponentName componentName, IBinder service) {
   1892             synchronized (mLock) {
   1893                 mService = service;
   1894                 mServiceInterface = IAccessibilityServiceClient.Stub.asInterface(service);
   1895                 UserState userState = getUserStateLocked(mUserId);
   1896                 addServiceLocked(this, userState);
   1897                 if (userState.mBindingServices.contains(mComponentName) || mWasConnectedAndDied) {
   1898                     userState.mBindingServices.remove(mComponentName);
   1899                     mWasConnectedAndDied = false;
   1900                     try {
   1901                        mServiceInterface.setConnection(this, mId);
   1902                        onUserStateChangedLocked(userState);
   1903                     } catch (RemoteException re) {
   1904                         Slog.w(LOG_TAG, "Error while setting connection for service: "
   1905                                 + service, re);
   1906                         binderDied();
   1907                     }
   1908                 } else {
   1909                     binderDied();
   1910                 }
   1911             }
   1912         }
   1913 
   1914         @Override
   1915         public boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
   1916                 long accessibilityNodeId, String viewIdResName, int interactionId,
   1917                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
   1918                 throws RemoteException {
   1919             final int resolvedWindowId;
   1920             IAccessibilityInteractionConnection connection = null;
   1921             synchronized (mLock) {
   1922                 final int resolvedUserId = mSecurityPolicy
   1923                         .resolveCallingUserIdEnforcingPermissionsLocked(
   1924                                 UserHandle.getCallingUserId());
   1925                 if (resolvedUserId != mCurrentUserId) {
   1926                     return false;
   1927                 }
   1928                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
   1929                 final boolean permissionGranted = mSecurityPolicy.canRetrieveWindowContent(this);
   1930                 if (!permissionGranted) {
   1931                     return false;
   1932                 } else {
   1933                     resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
   1934                     connection = getConnectionLocked(resolvedWindowId);
   1935                     if (connection == null) {
   1936                         return false;
   1937                     }
   1938                 }
   1939             }
   1940             final int interrogatingPid = Binder.getCallingPid();
   1941             final long identityToken = Binder.clearCallingIdentity();
   1942             MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
   1943             try {
   1944                 connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId,
   1945                         viewIdResName, interactionId, callback, mFetchFlags, interrogatingPid,
   1946                         interrogatingTid, spec);
   1947                 return true;
   1948             } catch (RemoteException re) {
   1949                 if (DEBUG) {
   1950                     Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId().");
   1951                 }
   1952             } finally {
   1953                 Binder.restoreCallingIdentity(identityToken);
   1954             }
   1955             return false;
   1956         }
   1957 
   1958         @Override
   1959         public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId,
   1960                 long accessibilityNodeId, String text, int interactionId,
   1961                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
   1962                 throws RemoteException {
   1963             final int resolvedWindowId;
   1964             IAccessibilityInteractionConnection connection = null;
   1965             synchronized (mLock) {
   1966                 final int resolvedUserId = mSecurityPolicy
   1967                         .resolveCallingUserIdEnforcingPermissionsLocked(
   1968                         UserHandle.getCallingUserId());
   1969                 if (resolvedUserId != mCurrentUserId) {
   1970                     return false;
   1971                 }
   1972                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
   1973                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
   1974                 final boolean permissionGranted =
   1975                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
   1976                 if (!permissionGranted) {
   1977                     return false;
   1978                 } else {
   1979                     connection = getConnectionLocked(resolvedWindowId);
   1980                     if (connection == null) {
   1981                         return false;
   1982                     }
   1983                 }
   1984             }
   1985             final int interrogatingPid = Binder.getCallingPid();
   1986             final long identityToken = Binder.clearCallingIdentity();
   1987             MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
   1988             try {
   1989                 connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
   1990                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
   1991                         spec);
   1992                 return true;
   1993             } catch (RemoteException re) {
   1994                 if (DEBUG) {
   1995                     Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()");
   1996                 }
   1997             } finally {
   1998                 Binder.restoreCallingIdentity(identityToken);
   1999             }
   2000             return false;
   2001         }
   2002 
   2003         @Override
   2004         public boolean findAccessibilityNodeInfoByAccessibilityId(
   2005                 int accessibilityWindowId, long accessibilityNodeId, int interactionId,
   2006                 IAccessibilityInteractionConnectionCallback callback, int flags,
   2007                 long interrogatingTid) throws RemoteException {
   2008             final int resolvedWindowId;
   2009             IAccessibilityInteractionConnection connection = null;
   2010             synchronized (mLock) {
   2011                 final int resolvedUserId = mSecurityPolicy
   2012                         .resolveCallingUserIdEnforcingPermissionsLocked(
   2013                         UserHandle.getCallingUserId());
   2014                 if (resolvedUserId != mCurrentUserId) {
   2015                     return false;
   2016                 }
   2017                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
   2018                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
   2019                 final boolean permissionGranted =
   2020                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
   2021                 if (!permissionGranted) {
   2022                     return false;
   2023                 } else {
   2024                     connection = getConnectionLocked(resolvedWindowId);
   2025                     if (connection == null) {
   2026                         return false;
   2027                     }
   2028                 }
   2029             }
   2030             final int interrogatingPid = Binder.getCallingPid();
   2031             final long identityToken = Binder.clearCallingIdentity();
   2032             MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
   2033             try {
   2034                 connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId,
   2035                         interactionId, callback, mFetchFlags | flags, interrogatingPid,
   2036                         interrogatingTid, spec);
   2037                 return true;
   2038             } catch (RemoteException re) {
   2039                 if (DEBUG) {
   2040                     Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
   2041                 }
   2042             } finally {
   2043                 Binder.restoreCallingIdentity(identityToken);
   2044             }
   2045             return false;
   2046         }
   2047 
   2048         @Override
   2049         public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId,
   2050                 int focusType, int interactionId,
   2051                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
   2052                 throws RemoteException {
   2053             final int resolvedWindowId;
   2054             IAccessibilityInteractionConnection connection = null;
   2055             synchronized (mLock) {
   2056                 final int resolvedUserId = mSecurityPolicy
   2057                         .resolveCallingUserIdEnforcingPermissionsLocked(
   2058                         UserHandle.getCallingUserId());
   2059                 if (resolvedUserId != mCurrentUserId) {
   2060                     return false;
   2061                 }
   2062                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
   2063                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
   2064                 final boolean permissionGranted =
   2065                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
   2066                 if (!permissionGranted) {
   2067                     return false;
   2068                 } else {
   2069                     connection = getConnectionLocked(resolvedWindowId);
   2070                     if (connection == null) {
   2071                         return false;
   2072                     }
   2073                 }
   2074             }
   2075             final int interrogatingPid = Binder.getCallingPid();
   2076             final long identityToken = Binder.clearCallingIdentity();
   2077             MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
   2078             try {
   2079                 connection.findFocus(accessibilityNodeId, focusType, interactionId, callback,
   2080                         mFetchFlags, interrogatingPid, interrogatingTid, spec);
   2081                 return true;
   2082             } catch (RemoteException re) {
   2083                 if (DEBUG) {
   2084                     Slog.e(LOG_TAG, "Error calling findAccessibilityFocus()");
   2085                 }
   2086             } finally {
   2087                 Binder.restoreCallingIdentity(identityToken);
   2088             }
   2089             return false;
   2090         }
   2091 
   2092         @Override
   2093         public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId,
   2094                 int direction, int interactionId,
   2095                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
   2096                 throws RemoteException {
   2097             final int resolvedWindowId;
   2098             IAccessibilityInteractionConnection connection = null;
   2099             synchronized (mLock) {
   2100                 final int resolvedUserId = mSecurityPolicy
   2101                         .resolveCallingUserIdEnforcingPermissionsLocked(
   2102                         UserHandle.getCallingUserId());
   2103                 if (resolvedUserId != mCurrentUserId) {
   2104                     return false;
   2105                 }
   2106                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
   2107                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
   2108                 final boolean permissionGranted =
   2109                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
   2110                 if (!permissionGranted) {
   2111                     return false;
   2112                 } else {
   2113                     connection = getConnectionLocked(resolvedWindowId);
   2114                     if (connection == null) {
   2115                         return false;
   2116                     }
   2117                 }
   2118             }
   2119             final int interrogatingPid = Binder.getCallingPid();
   2120             final long identityToken = Binder.clearCallingIdentity();
   2121             MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
   2122             try {
   2123                 connection.focusSearch(accessibilityNodeId, direction, interactionId, callback,
   2124                         mFetchFlags, interrogatingPid, interrogatingTid, spec);
   2125                 return true;
   2126             } catch (RemoteException re) {
   2127                 if (DEBUG) {
   2128                     Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()");
   2129                 }
   2130             } finally {
   2131                 Binder.restoreCallingIdentity(identityToken);
   2132             }
   2133             return false;
   2134         }
   2135 
   2136         @Override
   2137         public boolean performAccessibilityAction(int accessibilityWindowId,
   2138                 long accessibilityNodeId, int action, Bundle arguments, int interactionId,
   2139                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
   2140                 throws RemoteException {
   2141             final int resolvedWindowId;
   2142             IAccessibilityInteractionConnection connection = null;
   2143             synchronized (mLock) {
   2144                 final int resolvedUserId = mSecurityPolicy
   2145                         .resolveCallingUserIdEnforcingPermissionsLocked(
   2146                         UserHandle.getCallingUserId());
   2147                 if (resolvedUserId != mCurrentUserId) {
   2148                     return false;
   2149                 }
   2150                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
   2151                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
   2152                 final boolean permissionGranted = mSecurityPolicy.canPerformActionLocked(this,
   2153                         resolvedWindowId, action, arguments);
   2154                 if (!permissionGranted) {
   2155                     return false;
   2156                 } else {
   2157                     connection = getConnectionLocked(resolvedWindowId);
   2158                     if (connection == null) {
   2159                         return false;
   2160                     }
   2161                 }
   2162             }
   2163             final int interrogatingPid = Binder.getCallingPid();
   2164             final long identityToken = Binder.clearCallingIdentity();
   2165             try {
   2166                 connection.performAccessibilityAction(accessibilityNodeId, action, arguments,
   2167                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid);
   2168             } catch (RemoteException re) {
   2169                 if (DEBUG) {
   2170                     Slog.e(LOG_TAG, "Error calling performAccessibilityAction()");
   2171                 }
   2172             } finally {
   2173                 Binder.restoreCallingIdentity(identityToken);
   2174             }
   2175             return true;
   2176         }
   2177 
   2178         public boolean performGlobalAction(int action) {
   2179             synchronized (mLock) {
   2180                 final int resolvedUserId = mSecurityPolicy
   2181                         .resolveCallingUserIdEnforcingPermissionsLocked(
   2182                         UserHandle.getCallingUserId());
   2183                 if (resolvedUserId != mCurrentUserId) {
   2184                     return false;
   2185                 }
   2186             }
   2187             final long identity = Binder.clearCallingIdentity();
   2188             try {
   2189                 switch (action) {
   2190                     case AccessibilityService.GLOBAL_ACTION_BACK: {
   2191                         sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK);
   2192                     } return true;
   2193                     case AccessibilityService.GLOBAL_ACTION_HOME: {
   2194                         sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME);
   2195                     } return true;
   2196                     case AccessibilityService.GLOBAL_ACTION_RECENTS: {
   2197                         openRecents();
   2198                     } return true;
   2199                     case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: {
   2200                         expandNotifications();
   2201                     } return true;
   2202                     case AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS: {
   2203                         expandQuickSettings();
   2204                     } return true;
   2205                 }
   2206                 return false;
   2207             } finally {
   2208                 Binder.restoreCallingIdentity(identity);
   2209             }
   2210         }
   2211 
   2212         @Override
   2213         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
   2214             mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
   2215             synchronized (mLock) {
   2216                 pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo()
   2217                         .loadLabel(mContext.getPackageManager()));
   2218                 pw.append(", feedbackType"
   2219                         + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType));
   2220                 pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities());
   2221                 pw.append(", eventTypes="
   2222                         + AccessibilityEvent.eventTypeToString(mEventTypes));
   2223                 pw.append(", notificationTimeout=" + mNotificationTimeout);
   2224                 pw.append("]");
   2225             }
   2226         }
   2227 
   2228         @Override
   2229         public void onServiceDisconnected(ComponentName componentName) {
   2230             /* do nothing - #binderDied takes care */
   2231         }
   2232 
   2233         public void linkToOwnDeathLocked() throws RemoteException {
   2234             mService.linkToDeath(this, 0);
   2235         }
   2236 
   2237         public void unlinkToOwnDeathLocked() {
   2238             mService.unlinkToDeath(this, 0);
   2239         }
   2240 
   2241         public void resetLocked() {
   2242             try {
   2243                 // Clear the proxy in the other process so this
   2244                 // IAccessibilityServiceConnection can be garbage collected.
   2245                 mServiceInterface.setConnection(null, mId);
   2246             } catch (RemoteException re) {
   2247                 /* ignore */
   2248             }
   2249             mService = null;
   2250             mServiceInterface = null;
   2251         }
   2252 
   2253         public boolean isConnectedLocked() {
   2254             return (mService != null);
   2255         }
   2256 
   2257         public void binderDied() {
   2258             synchronized (mLock) {
   2259                 // It is possible that this service's package was force stopped during
   2260                 // whose handling the death recipient is unlinked and still get a call
   2261                 // on binderDied since the call was made before we unlink but was
   2262                 // waiting on the lock we held during the force stop handling.
   2263                 if (!isConnectedLocked()) {
   2264                     return;
   2265                 }
   2266                 mWasConnectedAndDied = true;
   2267                 mKeyEventDispatcher.flush();
   2268                 UserState userState = getUserStateLocked(mUserId);
   2269                 // The death recipient is unregistered in removeServiceLocked
   2270                 removeServiceLocked(this, userState);
   2271                 resetLocked();
   2272                 if (mIsAutomation) {
   2273                     // We no longer have an automation service, so restore
   2274                     // the state based on values in the settings database.
   2275                     userState.mInstalledServices.remove(mAccessibilityServiceInfo);
   2276                     userState.mEnabledServices.remove(mComponentName);
   2277                     userState.destroyUiAutomationService();
   2278                 }
   2279             }
   2280         }
   2281 
   2282         /**
   2283          * Performs a notification for an {@link AccessibilityEvent}.
   2284          *
   2285          * @param event The event.
   2286          */
   2287         public void notifyAccessibilityEvent(AccessibilityEvent event) {
   2288             synchronized (mLock) {
   2289                 final int eventType = event.getEventType();
   2290                 // Make a copy since during dispatch it is possible the event to
   2291                 // be modified to remove its source if the receiving service does
   2292                 // not have permission to access the window content.
   2293                 AccessibilityEvent newEvent = AccessibilityEvent.obtain(event);
   2294                 AccessibilityEvent oldEvent = mPendingEvents.get(eventType);
   2295                 mPendingEvents.put(eventType, newEvent);
   2296 
   2297                 final int what = eventType;
   2298                 if (oldEvent != null) {
   2299                     mEventDispatchHandler.removeMessages(what);
   2300                     oldEvent.recycle();
   2301                 }
   2302 
   2303                 Message message = mEventDispatchHandler.obtainMessage(what);
   2304                 mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout);
   2305             }
   2306         }
   2307 
   2308         /**
   2309          * Notifies an accessibility service client for a scheduled event given the event type.
   2310          *
   2311          * @param eventType The type of the event to dispatch.
   2312          */
   2313         private void notifyAccessibilityEventInternal(int eventType) {
   2314             IAccessibilityServiceClient listener;
   2315             AccessibilityEvent event;
   2316 
   2317             synchronized (mLock) {
   2318                 listener = mServiceInterface;
   2319 
   2320                 // If the service died/was disabled while the message for dispatching
   2321                 // the accessibility event was propagating the listener may be null.
   2322                 if (listener == null) {
   2323                     return;
   2324                 }
   2325 
   2326                 event = mPendingEvents.get(eventType);
   2327 
   2328                 // Check for null here because there is a concurrent scenario in which this
   2329                 // happens: 1) A binder thread calls notifyAccessibilityServiceDelayedLocked
   2330                 // which posts a message for dispatching an event. 2) The message is pulled
   2331                 // from the queue by the handler on the service thread and the latter is
   2332                 // just about to acquire the lock and call this method. 3) Now another binder
   2333                 // thread acquires the lock calling notifyAccessibilityServiceDelayedLocked
   2334                 // so the service thread waits for the lock; 4) The binder thread replaces
   2335                 // the event with a more recent one (assume the same event type) and posts a
   2336                 // dispatch request releasing the lock. 5) Now the main thread is unblocked and
   2337                 // dispatches the event which is removed from the pending ones. 6) And ... now
   2338                 // the service thread handles the last message posted by the last binder call
   2339                 // but the event is already dispatched and hence looking it up in the pending
   2340                 // ones yields null. This check is much simpler that keeping count for each
   2341                 // event type of each service to catch such a scenario since only one message
   2342                 // is processed at a time.
   2343                 if (event == null) {
   2344                     return;
   2345                 }
   2346 
   2347                 mPendingEvents.remove(eventType);
   2348                 if (mSecurityPolicy.canRetrieveWindowContent(this)) {
   2349                     event.setConnectionId(mId);
   2350                 } else {
   2351                     event.setSource(null);
   2352                 }
   2353                 event.setSealed(true);
   2354             }
   2355 
   2356             try {
   2357                 listener.onAccessibilityEvent(event);
   2358                 if (DEBUG) {
   2359                     Slog.i(LOG_TAG, "Event " + event + " sent to " + listener);
   2360                 }
   2361             } catch (RemoteException re) {
   2362                 Slog.e(LOG_TAG, "Error during sending " + event + " to " + listener, re);
   2363             } finally {
   2364                 event.recycle();
   2365             }
   2366         }
   2367 
   2368         public void notifyGesture(int gestureId) {
   2369             mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE,
   2370                     gestureId, 0).sendToTarget();
   2371         }
   2372 
   2373         public void notifyKeyEvent(KeyEvent event, int policyFlags) {
   2374             mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_KEY_EVENT,
   2375                     policyFlags, 0, event).sendToTarget();
   2376         }
   2377 
   2378         public void notifyClearAccessibilityNodeInfoCache() {
   2379             mInvocationHandler.sendEmptyMessage(
   2380                     InvocationHandler.MSG_CLEAR_ACCESSIBILITY_NODE_INFO_CACHE);
   2381         }
   2382 
   2383         private void notifyGestureInternal(int gestureId) {
   2384             IAccessibilityServiceClient listener = mServiceInterface;
   2385             if (listener != null) {
   2386                 try {
   2387                     listener.onGesture(gestureId);
   2388                 } catch (RemoteException re) {
   2389                     Slog.e(LOG_TAG, "Error during sending gesture " + gestureId
   2390                             + " to " + mService, re);
   2391                 }
   2392             }
   2393         }
   2394 
   2395         private void notifyKeyEventInternal(KeyEvent event, int policyFlags) {
   2396             mKeyEventDispatcher.notifyKeyEvent(event, policyFlags);
   2397         }
   2398 
   2399         private void notifyClearAccessibilityNodeInfoCacheInternal() {
   2400             IAccessibilityServiceClient listener = mServiceInterface;
   2401             if (listener != null) {
   2402                 try {
   2403                     listener.clearAccessibilityNodeInfoCache();
   2404                 } catch (RemoteException re) {
   2405                     Slog.e(LOG_TAG, "Error during requesting accessibility info cache"
   2406                             + " to be cleared.", re);
   2407                 }
   2408             }
   2409         }
   2410 
   2411         private void sendDownAndUpKeyEvents(int keyCode) {
   2412             final long token = Binder.clearCallingIdentity();
   2413 
   2414             // Inject down.
   2415             final long downTime = SystemClock.uptimeMillis();
   2416             KeyEvent down = KeyEvent.obtain(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode, 0, 0,
   2417                     KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
   2418                     InputDevice.SOURCE_KEYBOARD, null);
   2419             InputManager.getInstance().injectInputEvent(down,
   2420                     InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
   2421             down.recycle();
   2422 
   2423             // Inject up.
   2424             final long upTime = SystemClock.uptimeMillis();
   2425             KeyEvent up = KeyEvent.obtain(downTime, upTime, KeyEvent.ACTION_UP, keyCode, 0, 0,
   2426                     KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
   2427                     InputDevice.SOURCE_KEYBOARD, null);
   2428             InputManager.getInstance().injectInputEvent(up,
   2429                     InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
   2430             up.recycle();
   2431 
   2432             Binder.restoreCallingIdentity(token);
   2433         }
   2434 
   2435         private void expandNotifications() {
   2436             final long token = Binder.clearCallingIdentity();
   2437 
   2438             StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService(
   2439                     android.app.Service.STATUS_BAR_SERVICE);
   2440             statusBarManager.expandNotificationsPanel();
   2441 
   2442             Binder.restoreCallingIdentity(token);
   2443         }
   2444 
   2445         private void expandQuickSettings() {
   2446             final long token = Binder.clearCallingIdentity();
   2447 
   2448             StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService(
   2449                     android.app.Service.STATUS_BAR_SERVICE);
   2450             statusBarManager.expandSettingsPanel();
   2451 
   2452             Binder.restoreCallingIdentity(token);
   2453         }
   2454 
   2455         private void openRecents() {
   2456             final long token = Binder.clearCallingIdentity();
   2457 
   2458             IStatusBarService statusBarService = IStatusBarService.Stub.asInterface(
   2459                     ServiceManager.getService("statusbar"));
   2460             try {
   2461                 statusBarService.toggleRecentApps();
   2462             } catch (RemoteException e) {
   2463                 Slog.e(LOG_TAG, "Error toggling recent apps.");
   2464             }
   2465 
   2466             Binder.restoreCallingIdentity(token);
   2467         }
   2468 
   2469         private IAccessibilityInteractionConnection getConnectionLocked(int windowId) {
   2470             if (DEBUG) {
   2471                 Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId);
   2472             }
   2473             AccessibilityConnectionWrapper wrapper = mGlobalInteractionConnections.get(windowId);
   2474             if (wrapper == null) {
   2475                 wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId);
   2476             }
   2477             if (wrapper != null && wrapper.mConnection != null) {
   2478                 return wrapper.mConnection;
   2479             }
   2480             if (DEBUG) {
   2481                 Slog.e(LOG_TAG, "No interaction connection to window: " + windowId);
   2482             }
   2483             return null;
   2484         }
   2485 
   2486         private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) {
   2487             if (accessibilityWindowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) {
   2488                 return mSecurityPolicy.mActiveWindowId;
   2489             }
   2490             return accessibilityWindowId;
   2491         }
   2492 
   2493         private MagnificationSpec getCompatibleMagnificationSpec(int windowId) {
   2494             try {
   2495                 IBinder windowToken = mGlobalWindowTokens.get(windowId);
   2496                 if (windowToken == null) {
   2497                     windowToken = getCurrentUserStateLocked().mWindowTokens.get(windowId);
   2498                 }
   2499                 if (windowToken != null) {
   2500                     return mWindowManagerService.getCompatibleMagnificationSpecForWindow(
   2501                             windowToken);
   2502                 }
   2503             } catch (RemoteException re) {
   2504                 /* ignore */
   2505             }
   2506             return null;
   2507         }
   2508 
   2509         private final class InvocationHandler extends Handler {
   2510 
   2511             public static final int MSG_ON_GESTURE = 1;
   2512             public static final int MSG_ON_KEY_EVENT = 2;
   2513             public static final int MSG_CLEAR_ACCESSIBILITY_NODE_INFO_CACHE = 3;
   2514             public static final int MSG_ON_KEY_EVENT_TIMEOUT = 4;
   2515 
   2516             public InvocationHandler(Looper looper) {
   2517                 super(looper, null, true);
   2518             }
   2519 
   2520             @Override
   2521             public void handleMessage(Message message) {
   2522                 final int type = message.what;
   2523                 switch (type) {
   2524                     case MSG_ON_GESTURE: {
   2525                         final int gestureId = message.arg1;
   2526                         notifyGestureInternal(gestureId);
   2527                     } break;
   2528                     case MSG_ON_KEY_EVENT: {
   2529                         KeyEvent event = (KeyEvent) message.obj;
   2530                         final int policyFlags = message.arg1;
   2531                         notifyKeyEventInternal(event, policyFlags);
   2532                     } break;
   2533                     case MSG_CLEAR_ACCESSIBILITY_NODE_INFO_CACHE: {
   2534                         notifyClearAccessibilityNodeInfoCacheInternal();
   2535                     } break;
   2536                     case MSG_ON_KEY_EVENT_TIMEOUT: {
   2537                         PendingEvent eventState = (PendingEvent) message.obj;
   2538                         setOnKeyEventResult(false, eventState.sequence);
   2539                     } break;
   2540                     default: {
   2541                         throw new IllegalArgumentException("Unknown message: " + type);
   2542                     }
   2543                 }
   2544             }
   2545         }
   2546 
   2547         private final class KeyEventDispatcher {
   2548 
   2549             private static final long ON_KEY_EVENT_TIMEOUT_MILLIS = 500;
   2550 
   2551             private PendingEvent mPendingEvents;
   2552 
   2553             private final InputEventConsistencyVerifier mSentEventsVerifier =
   2554                     InputEventConsistencyVerifier.isInstrumentationEnabled()
   2555                             ? new InputEventConsistencyVerifier(
   2556                                     this, 0, KeyEventDispatcher.class.getSimpleName()) : null;
   2557 
   2558             public void notifyKeyEvent(KeyEvent event, int policyFlags) {
   2559                 final PendingEvent pendingEvent;
   2560 
   2561                 synchronized (mLock) {
   2562                     pendingEvent = addPendingEventLocked(event, policyFlags);
   2563                 }
   2564 
   2565                 Message message = mInvocationHandler.obtainMessage(
   2566                         InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT, pendingEvent);
   2567                 mInvocationHandler.sendMessageDelayed(message, ON_KEY_EVENT_TIMEOUT_MILLIS);
   2568 
   2569                 try {
   2570                     // Accessibility services are exclusively not in the system
   2571                     // process, therefore no need to clone the motion event to
   2572                     // prevent tampering. It will be cloned in the IPC call.
   2573                     mServiceInterface.onKeyEvent(pendingEvent.event, pendingEvent.sequence);
   2574                 } catch (RemoteException re) {
   2575                     setOnKeyEventResult(false, pendingEvent.sequence);
   2576                 }
   2577             }
   2578 
   2579             public void setOnKeyEventResult(boolean handled, int sequence) {
   2580                 synchronized (mLock) {
   2581                     PendingEvent pendingEvent = removePendingEventLocked(sequence);
   2582                     if (pendingEvent != null) {
   2583                         mInvocationHandler.removeMessages(
   2584                                 InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT,
   2585                                 pendingEvent);
   2586                         pendingEvent.handled = handled;
   2587                         finishPendingEventLocked(pendingEvent);
   2588                     }
   2589                 }
   2590             }
   2591 
   2592             public void flush() {
   2593                 synchronized (mLock) {
   2594                     cancelAllPendingEventsLocked();
   2595                     if (mSentEventsVerifier != null) {
   2596                         mSentEventsVerifier.reset();
   2597                     }
   2598                 }
   2599             }
   2600 
   2601             private PendingEvent addPendingEventLocked(KeyEvent event, int policyFlags) {
   2602                 final int sequence = event.getSequenceNumber();
   2603                 PendingEvent pendingEvent = obtainPendingEventLocked(event, policyFlags, sequence);
   2604                 pendingEvent.next = mPendingEvents;
   2605                 mPendingEvents = pendingEvent;
   2606                 return pendingEvent;
   2607             }
   2608 
   2609             private PendingEvent removePendingEventLocked(int sequence) {
   2610                 PendingEvent previous = null;
   2611                 PendingEvent current = mPendingEvents;
   2612 
   2613                 while (current != null) {
   2614                     if (current.sequence == sequence) {
   2615                         if (previous != null) {
   2616                             previous.next = current.next;
   2617                         } else {
   2618                             mPendingEvents = current.next;
   2619                         }
   2620                         current.next = null;
   2621                         return current;
   2622                     }
   2623                     previous = current;
   2624                     current = current.next;
   2625                 }
   2626                 return null;
   2627             }
   2628 
   2629             private void finishPendingEventLocked(PendingEvent pendingEvent) {
   2630                 if (!pendingEvent.handled) {
   2631                     sendKeyEventToInputFilter(pendingEvent.event, pendingEvent.policyFlags);
   2632                 }
   2633                 // Nullify the event since we do not want it to be
   2634                 // recycled yet. It will be sent to the input filter.
   2635                 pendingEvent.event = null;
   2636                 recyclePendingEventLocked(pendingEvent);
   2637             }
   2638 
   2639             private void sendKeyEventToInputFilter(KeyEvent event, int policyFlags) {
   2640                 if (DEBUG) {
   2641                     Slog.i(LOG_TAG, "Injecting event: " + event);
   2642                 }
   2643                 if (mSentEventsVerifier != null) {
   2644                     mSentEventsVerifier.onKeyEvent(event, 0);
   2645                 }
   2646                 policyFlags |= WindowManagerPolicy.FLAG_PASS_TO_USER;
   2647                 mMainHandler.obtainMessage(MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER,
   2648                         policyFlags, 0, event).sendToTarget();
   2649             }
   2650 
   2651             private void cancelAllPendingEventsLocked() {
   2652                 while (mPendingEvents != null) {
   2653                     PendingEvent pendingEvent = removePendingEventLocked(mPendingEvents.sequence);
   2654                     pendingEvent.handled = false;
   2655                     mInvocationHandler.removeMessages(InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT,
   2656                             pendingEvent);
   2657                     finishPendingEventLocked(pendingEvent);
   2658                 }
   2659             }
   2660         }
   2661     }
   2662 
   2663     private static final class PendingEvent {
   2664         PendingEvent next;
   2665 
   2666         KeyEvent event;
   2667         int policyFlags;
   2668         int sequence;
   2669         boolean handled;
   2670 
   2671         public void clear() {
   2672             if (event != null) {
   2673                 event.recycle();
   2674                 event = null;
   2675             }
   2676             next = null;
   2677             policyFlags = 0;
   2678             sequence = 0;
   2679             handled = false;
   2680         }
   2681     }
   2682 
   2683     final class SecurityPolicy {
   2684         private static final int VALID_ACTIONS =
   2685             AccessibilityNodeInfo.ACTION_CLICK
   2686             | AccessibilityNodeInfo.ACTION_LONG_CLICK
   2687             | AccessibilityNodeInfo.ACTION_FOCUS
   2688             | AccessibilityNodeInfo.ACTION_CLEAR_FOCUS
   2689             | AccessibilityNodeInfo.ACTION_SELECT
   2690             | AccessibilityNodeInfo.ACTION_CLEAR_SELECTION
   2691             | AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS
   2692             | AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS
   2693             | AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
   2694             | AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
   2695             | AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT
   2696             | AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT
   2697             | AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
   2698             | AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
   2699             | AccessibilityNodeInfo.ACTION_COPY
   2700             | AccessibilityNodeInfo.ACTION_PASTE
   2701             | AccessibilityNodeInfo.ACTION_CUT
   2702             | AccessibilityNodeInfo.ACTION_SET_SELECTION
   2703             | AccessibilityNodeInfo.ACTION_EXPAND
   2704             | AccessibilityNodeInfo.ACTION_COLLAPSE
   2705             | AccessibilityNodeInfo.ACTION_DISMISS;
   2706 
   2707         private static final int RETRIEVAL_ALLOWING_EVENT_TYPES =
   2708             AccessibilityEvent.TYPE_VIEW_CLICKED
   2709             | AccessibilityEvent.TYPE_VIEW_FOCUSED
   2710             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
   2711             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
   2712             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
   2713             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
   2714             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
   2715             | AccessibilityEvent.TYPE_VIEW_SELECTED
   2716             | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
   2717             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
   2718             | AccessibilityEvent.TYPE_VIEW_SCROLLED
   2719             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
   2720             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED;
   2721 
   2722         private int mActiveWindowId;
   2723         private boolean mTouchInteractionInProgress;
   2724 
   2725         private boolean canDispatchAccessibilityEvent(AccessibilityEvent event) {
   2726             final int eventType = event.getEventType();
   2727             switch (eventType) {
   2728                 // All events that are for changes in a global window
   2729                 // state should *always* be dispatched.
   2730                 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
   2731                 case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
   2732                 // All events generated by the user touching the
   2733                 // screen should *always* be dispatched.
   2734                 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START:
   2735                 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END:
   2736                 case AccessibilityEvent.TYPE_GESTURE_DETECTION_START:
   2737                 case AccessibilityEvent.TYPE_GESTURE_DETECTION_END:
   2738                 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START:
   2739                 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END:
   2740                 // These will change the active window, so dispatch.
   2741                 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER:
   2742                 case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT: {
   2743                     return true;
   2744                 }
   2745                 // All events for changes in window content should be
   2746                 // dispatched *only* if this window is the active one.
   2747                 default:
   2748                     return event.getWindowId() == mActiveWindowId;
   2749             }
   2750         }
   2751 
   2752         public void updateEventSourceLocked(AccessibilityEvent event) {
   2753             if ((event.getEventType() & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) {
   2754                 event.setSource(null);
   2755             }
   2756         }
   2757 
   2758         public void updateActiveWindow(int windowId, int eventType) {
   2759             // The active window is either the window that has input focus or
   2760             // the window that the user is currently touching. If the user is
   2761             // touching a window that does not have input focus as soon as the
   2762             // the user stops touching that window the focused window becomes
   2763             // the active one.
   2764             switch (eventType) {
   2765                 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: {
   2766                     if (getFocusedWindowId() == windowId) {
   2767                         mActiveWindowId = windowId;
   2768                     }
   2769                 } break;
   2770                 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: {
   2771                     // Do not allow delayed hover events to confuse us
   2772                     // which the active window is.
   2773                     if (mTouchInteractionInProgress) {
   2774                         mActiveWindowId = windowId;
   2775                     }
   2776                 } break;
   2777             }
   2778         }
   2779 
   2780         public void onTouchInteractionStart() {
   2781             mTouchInteractionInProgress = true;
   2782         }
   2783 
   2784         public void onTouchInteractionEnd() {
   2785             mTouchInteractionInProgress = false;
   2786             // We want to set the active window to be current immediately
   2787             // after the user has stopped touching the screen since if the
   2788             // user types with the IME he should get a feedback for the
   2789             // letter typed in the text view which is in the input focused
   2790             // window. Note that we always deliver hover accessibility events
   2791             // (they are a result of user touching the screen) so change of
   2792             // the active window before all hover accessibility events from
   2793             // the touched window are delivered is fine.
   2794             mActiveWindowId = getFocusedWindowId();
   2795         }
   2796 
   2797         public int getRetrievalAllowingWindowLocked() {
   2798             return mActiveWindowId;
   2799         }
   2800 
   2801         public boolean canGetAccessibilityNodeInfoLocked(Service service, int windowId) {
   2802             return canRetrieveWindowContent(service) && isRetrievalAllowingWindow(windowId);
   2803         }
   2804 
   2805         public boolean canPerformActionLocked(Service service, int windowId, int action,
   2806                 Bundle arguments) {
   2807             return canRetrieveWindowContent(service)
   2808                 && isRetrievalAllowingWindow(windowId)
   2809                 && isActionPermitted(action);
   2810         }
   2811 
   2812         public boolean canRetrieveWindowContent(Service service) {
   2813             return (service.mAccessibilityServiceInfo.getCapabilities()
   2814                     & AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0;
   2815         }
   2816 
   2817         public void enforceCanRetrieveWindowContent(Service service) throws RemoteException {
   2818             // This happens due to incorrect registration so make it apparent.
   2819             if (!canRetrieveWindowContent(service)) {
   2820                 Slog.e(LOG_TAG, "Accessibility serivce " + service.mComponentName + " does not " +
   2821                         "declare android:canRetrieveWindowContent.");
   2822                 throw new RemoteException();
   2823             }
   2824         }
   2825 
   2826         public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) {
   2827             final int callingUid = Binder.getCallingUid();
   2828             if (callingUid == 0
   2829                     || callingUid == Process.SYSTEM_UID
   2830                     || callingUid == Process.SHELL_UID) {
   2831                 return mCurrentUserId;
   2832             }
   2833             final int callingUserId = UserHandle.getUserId(callingUid);
   2834             if (callingUserId == userId) {
   2835                 return userId;
   2836             }
   2837             if (!hasPermission(Manifest.permission.INTERACT_ACROSS_USERS)
   2838                     && !hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) {
   2839                 throw new SecurityException("Call from user " + callingUserId + " as user "
   2840                         + userId + " without permission INTERACT_ACROSS_USERS or "
   2841                         + "INTERACT_ACROSS_USERS_FULL not allowed.");
   2842             }
   2843             if (userId == UserHandle.USER_CURRENT
   2844                     || userId == UserHandle.USER_CURRENT_OR_SELF) {
   2845                 return mCurrentUserId;
   2846             }
   2847             throw new IllegalArgumentException("Calling user can be changed to only "
   2848                     + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF.");
   2849         }
   2850 
   2851         public boolean isCallerInteractingAcrossUsers(int userId) {
   2852             final int callingUid = Binder.getCallingUid();
   2853             return (Binder.getCallingPid() == android.os.Process.myPid()
   2854                     || callingUid == Process.SHELL_UID
   2855                     || userId == UserHandle.USER_CURRENT
   2856                     || userId == UserHandle.USER_CURRENT_OR_SELF);
   2857         }
   2858 
   2859         private boolean isRetrievalAllowingWindow(int windowId) {
   2860             return (mActiveWindowId == windowId);
   2861         }
   2862 
   2863         private boolean isActionPermitted(int action) {
   2864              return (VALID_ACTIONS & action) != 0;
   2865         }
   2866 
   2867         private void enforceCallingPermission(String permission, String function) {
   2868             if (OWN_PROCESS_ID == Binder.getCallingPid()) {
   2869                 return;
   2870             }
   2871             if (!hasPermission(permission)) {
   2872                 throw new SecurityException("You do not have " + permission
   2873                         + " required to call " + function + " from pid="
   2874                         + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
   2875             }
   2876         }
   2877 
   2878         private boolean hasPermission(String permission) {
   2879             return mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED;
   2880         }
   2881 
   2882         private int getFocusedWindowId() {
   2883             try {
   2884                 // We call this only on window focus change or after touch
   2885                 // exploration gesture end and the shown windows are not that
   2886                 // many, so the linear look up is just fine.
   2887                 IBinder token = mWindowManagerService.getFocusedWindowToken();
   2888                 if (token != null) {
   2889                     synchronized (mLock) {
   2890                         int windowId = getFocusedWindowIdLocked(token, mGlobalWindowTokens);
   2891                         if (windowId < 0) {
   2892                             windowId = getFocusedWindowIdLocked(token,
   2893                                     getCurrentUserStateLocked().mWindowTokens);
   2894                         }
   2895                         return windowId;
   2896                     }
   2897                 }
   2898             } catch (RemoteException re) {
   2899                 /* ignore */
   2900             }
   2901             return -1;
   2902         }
   2903 
   2904         private int getFocusedWindowIdLocked(IBinder token, SparseArray<IBinder> windows) {
   2905             final int windowCount = windows.size();
   2906             for (int i = 0; i < windowCount; i++) {
   2907                 if (windows.valueAt(i) == token) {
   2908                     return windows.keyAt(i);
   2909                 }
   2910             }
   2911             return -1;
   2912         }
   2913     }
   2914 
   2915     private class UserState {
   2916         public final int mUserId;
   2917 
   2918         // Non-transient state.
   2919 
   2920         public final RemoteCallbackList<IAccessibilityManagerClient> mClients =
   2921             new RemoteCallbackList<IAccessibilityManagerClient>();
   2922 
   2923         public final SparseArray<AccessibilityConnectionWrapper> mInteractionConnections =
   2924                 new SparseArray<AccessibilityConnectionWrapper>();
   2925 
   2926         public final SparseArray<IBinder> mWindowTokens = new SparseArray<IBinder>();
   2927 
   2928         // Transient state.
   2929 
   2930         public final CopyOnWriteArrayList<Service> mBoundServices =
   2931                 new CopyOnWriteArrayList<Service>();
   2932 
   2933         public final Map<ComponentName, Service> mComponentNameToServiceMap =
   2934                 new HashMap<ComponentName, Service>();
   2935 
   2936         public final List<AccessibilityServiceInfo> mInstalledServices =
   2937                 new ArrayList<AccessibilityServiceInfo>();
   2938 
   2939         public final Set<ComponentName> mBindingServices = new HashSet<ComponentName>();
   2940 
   2941         public final Set<ComponentName> mEnabledServices = new HashSet<ComponentName>();
   2942 
   2943         public final Set<ComponentName> mTouchExplorationGrantedServices =
   2944                 new HashSet<ComponentName>();
   2945 
   2946         public int mHandledFeedbackTypes = 0;
   2947 
   2948         public int mLastSentClientState = -1;
   2949 
   2950         public boolean mIsAccessibilityEnabled;
   2951         public boolean mIsTouchExplorationEnabled;
   2952         public boolean mIsEnhancedWebAccessibilityEnabled;
   2953         public boolean mIsDisplayMagnificationEnabled;
   2954         public boolean mIsFilterKeyEventsEnabled;
   2955 
   2956         private Service mUiAutomationService;
   2957         private IAccessibilityServiceClient mUiAutomationServiceClient;
   2958 
   2959         private IBinder mUiAutomationServiceOwner;
   2960         private final DeathRecipient mUiAutomationSerivceOnwerDeathRecipient =
   2961                 new DeathRecipient() {
   2962             @Override
   2963             public void binderDied() {
   2964                 mUiAutomationServiceOwner.unlinkToDeath(
   2965                         mUiAutomationSerivceOnwerDeathRecipient, 0);
   2966                 mUiAutomationServiceOwner = null;
   2967                 if (mUiAutomationService != null) {
   2968                     mUiAutomationService.binderDied();
   2969                 }
   2970             }
   2971         };
   2972 
   2973         public UserState(int userId) {
   2974             mUserId = userId;
   2975         }
   2976 
   2977         public int getClientState() {
   2978             int clientState = 0;
   2979             if (mIsAccessibilityEnabled) {
   2980                 clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
   2981             }
   2982             // Touch exploration relies on enabled accessibility.
   2983             if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) {
   2984                 clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
   2985             }
   2986             return clientState;
   2987         }
   2988 
   2989         public void onSwitchToAnotherUser() {
   2990             // Clear UI test automation state.
   2991             if (mUiAutomationService != null) {
   2992                 mUiAutomationService.binderDied();
   2993             }
   2994 
   2995             // Unbind all services.
   2996             unbindAllServicesLocked(this);
   2997 
   2998             // Clear service management state.
   2999             mBoundServices.clear();
   3000             mBindingServices.clear();
   3001 
   3002             // Clear event management state.
   3003             mHandledFeedbackTypes = 0;
   3004             mLastSentClientState = -1;
   3005 
   3006             // Clear state persisted in settings.
   3007             mEnabledServices.clear();
   3008             mTouchExplorationGrantedServices.clear();
   3009             mIsAccessibilityEnabled = false;
   3010             mIsTouchExplorationEnabled = false;
   3011             mIsEnhancedWebAccessibilityEnabled = false;
   3012             mIsDisplayMagnificationEnabled = false;
   3013         }
   3014 
   3015         public void destroyUiAutomationService() {
   3016             mUiAutomationService = null;
   3017             mUiAutomationServiceClient = null;
   3018             if (mUiAutomationServiceOwner != null) {
   3019                 mUiAutomationServiceOwner.unlinkToDeath(
   3020                         mUiAutomationSerivceOnwerDeathRecipient, 0);
   3021                 mUiAutomationServiceOwner = null;
   3022             }
   3023         }
   3024     }
   3025 
   3026     private final class AccessibilityContentObserver extends ContentObserver {
   3027 
   3028         private final Uri mAccessibilityEnabledUri = Settings.Secure.getUriFor(
   3029                 Settings.Secure.ACCESSIBILITY_ENABLED);
   3030 
   3031         private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor(
   3032                 Settings.Secure.TOUCH_EXPLORATION_ENABLED);
   3033 
   3034         private final Uri mDisplayMagnificationEnabledUri = Settings.Secure.getUriFor(
   3035                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
   3036 
   3037         private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor(
   3038                 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
   3039 
   3040         private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure
   3041                 .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
   3042 
   3043         private final Uri mEnhancedWebAccessibilityUri = Settings.Secure
   3044                 .getUriFor(Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION);
   3045 
   3046         public AccessibilityContentObserver(Handler handler) {
   3047             super(handler);
   3048         }
   3049 
   3050         public void register(ContentResolver contentResolver) {
   3051             contentResolver.registerContentObserver(mAccessibilityEnabledUri,
   3052                     false, this, UserHandle.USER_ALL);
   3053             contentResolver.registerContentObserver(mTouchExplorationEnabledUri,
   3054                     false, this, UserHandle.USER_ALL);
   3055             contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri,
   3056                     false, this, UserHandle.USER_ALL);
   3057             contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri,
   3058                     false, this, UserHandle.USER_ALL);
   3059             contentResolver.registerContentObserver(
   3060                     mTouchExplorationGrantedAccessibilityServicesUri,
   3061                     false, this, UserHandle.USER_ALL);
   3062             contentResolver.registerContentObserver(mEnhancedWebAccessibilityUri,
   3063                     false, this, UserHandle.USER_ALL);
   3064         }
   3065 
   3066         @Override
   3067         public void onChange(boolean selfChange, Uri uri) {
   3068             if (mAccessibilityEnabledUri.equals(uri)) {
   3069                 synchronized (mLock) {
   3070                     // We will update when the automation service dies.
   3071                     UserState userState = getCurrentUserStateLocked();
   3072                     if (userState.mUiAutomationService == null) {
   3073                         if (readAccessibilityEnabledSettingLocked(userState)) {
   3074                             onUserStateChangedLocked(userState);
   3075                         }
   3076                     }
   3077                 }
   3078             } else if (mTouchExplorationEnabledUri.equals(uri)) {
   3079                 synchronized (mLock) {
   3080                     // We will update when the automation service dies.
   3081                     UserState userState = getCurrentUserStateLocked();
   3082                     if (userState.mUiAutomationService == null) {
   3083                         if (readTouchExplorationEnabledSettingLocked(userState)) {
   3084                             onUserStateChangedLocked(userState);
   3085                         }
   3086                     }
   3087                 }
   3088             } else if (mDisplayMagnificationEnabledUri.equals(uri)) {
   3089                 synchronized (mLock) {
   3090                     // We will update when the automation service dies.
   3091                     UserState userState = getCurrentUserStateLocked();
   3092                     if (userState.mUiAutomationService == null) {
   3093                         if (readDisplayMagnificationEnabledSettingLocked(userState)) {
   3094                             onUserStateChangedLocked(userState);
   3095                         }
   3096                     }
   3097                 }
   3098             } else if (mEnabledAccessibilityServicesUri.equals(uri)) {
   3099                 synchronized (mLock) {
   3100                     // We will update when the automation service dies.
   3101                     UserState userState = getCurrentUserStateLocked();
   3102                     if (userState.mUiAutomationService == null) {
   3103                         if (readEnabledAccessibilityServicesLocked(userState)) {
   3104                             onUserStateChangedLocked(userState);
   3105                         }
   3106                     }
   3107                 }
   3108             } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) {
   3109                 synchronized (mLock) {
   3110                     // We will update when the automation service dies.
   3111                     UserState userState = getCurrentUserStateLocked();
   3112                     if (userState.mUiAutomationService == null) {
   3113                         if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) {
   3114                             onUserStateChangedLocked(userState);
   3115                         }
   3116                     }
   3117                 }
   3118             } else if (mEnhancedWebAccessibilityUri.equals(uri)) {
   3119                 synchronized (mLock) {
   3120                     // We will update when the automation service dies.
   3121                     UserState userState = getCurrentUserStateLocked();
   3122                     if (userState.mUiAutomationService == null) {
   3123                         if (readEnhancedWebAccessibilityEnabledChangedLocked(userState)) {
   3124                             onUserStateChangedLocked(userState);
   3125                         }
   3126                     }
   3127                 }
   3128             }
   3129         }
   3130     }
   3131 }
   3132