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     }
   1423 
   1424     private boolean canRequestAndRequestsTouchExplorationLocked(Service service) {
   1425         // Service not ready or cannot request the feature - well nothing to do.
   1426         if (!service.canReceiveEventsLocked() || !service.mRequestTouchExplorationMode) {
   1427             return false;
   1428         }
   1429         // UI test automation service can always enable it.
   1430         if (service.mIsAutomation) {
   1431             return true;
   1432         }
   1433         if (service.mResolveInfo.serviceInfo.applicationInfo.targetSdkVersion
   1434                 <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
   1435             // Up to JB-MR1 we had a white list with services that can enable touch
   1436             // exploration. When a service is first started we show a dialog to the
   1437             // use to get a permission to white list the service.
   1438             UserState userState = getUserStateLocked(service.mUserId);
   1439             if (userState.mTouchExplorationGrantedServices.contains(service.mComponentName)) {
   1440                 return true;
   1441             } else if (mEnableTouchExplorationDialog == null
   1442                     || !mEnableTouchExplorationDialog.isShowing()) {
   1443                 mMainHandler.obtainMessage(
   1444                         MainHandler.MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG,
   1445                         service).sendToTarget();
   1446             }
   1447         } else {
   1448             // Starting in JB-MR2 we request an accessibility service to declare
   1449             // certain capabilities in its meta-data to allow it to enable the
   1450             // corresponding features.
   1451             if ((service.mAccessibilityServiceInfo.getCapabilities()
   1452                     & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) != 0) {
   1453                 return true;
   1454             }
   1455         }
   1456         return false;
   1457     }
   1458 
   1459     private void updateEnhancedWebAccessibilityLocked(UserState userState) {
   1460         boolean enabled = false;
   1461         final int serviceCount = userState.mBoundServices.size();
   1462         for (int i = 0; i < serviceCount; i++) {
   1463             Service service = userState.mBoundServices.get(i);
   1464             if (canRequestAndRequestsEnhancedWebAccessibilityLocked(service)) {
   1465                 enabled = true;
   1466                 break;
   1467             }
   1468         }
   1469         if (enabled != userState.mIsEnhancedWebAccessibilityEnabled) {
   1470             userState.mIsEnhancedWebAccessibilityEnabled = enabled;
   1471             Settings.Secure.putIntForUser(mContext.getContentResolver(),
   1472                     Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, enabled ? 1 : 0,
   1473                     userState.mUserId);
   1474         }
   1475     }
   1476 
   1477     private boolean canRequestAndRequestsEnhancedWebAccessibilityLocked(Service service) {
   1478         if (!service.canReceiveEventsLocked() || !service.mRequestEnhancedWebAccessibility ) {
   1479             return false;
   1480         }
   1481         if (service.mIsAutomation || (service.mAccessibilityServiceInfo.getCapabilities()
   1482                & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY) != 0) {
   1483             return true;
   1484         }
   1485         return false;
   1486     }
   1487 
   1488     @Override
   1489     public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
   1490         mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
   1491         synchronized (mLock) {
   1492             pw.println("ACCESSIBILITY MANAGER (dumpsys accessibility)");
   1493             pw.println();
   1494             final int userCount = mUserStates.size();
   1495             for (int i = 0; i < userCount; i++) {
   1496                 UserState userState = mUserStates.valueAt(i);
   1497                 pw.append("User state[attributes:{id=" + userState.mUserId);
   1498                 pw.append(", currentUser=" + (userState.mUserId == mCurrentUserId));
   1499                 pw.append(", accessibilityEnabled=" + userState.mIsAccessibilityEnabled);
   1500                 pw.append(", touchExplorationEnabled=" + userState.mIsTouchExplorationEnabled);
   1501                 pw.append(", displayMagnificationEnabled="
   1502                         + userState.mIsDisplayMagnificationEnabled);
   1503                 if (userState.mUiAutomationService != null) {
   1504                     pw.append(", ");
   1505                     userState.mUiAutomationService.dump(fd, pw, args);
   1506                     pw.println();
   1507                 }
   1508                 pw.append("}");
   1509                 pw.println();
   1510                 pw.append("           services:{");
   1511                 final int serviceCount = userState.mBoundServices.size();
   1512                 for (int j = 0; j < serviceCount; j++) {
   1513                     if (j > 0) {
   1514                         pw.append(", ");
   1515                         pw.println();
   1516                         pw.append("                     ");
   1517                     }
   1518                     Service service = userState.mBoundServices.get(j);
   1519                     service.dump(fd, pw, args);
   1520                 }
   1521                 pw.println("}]");
   1522                 pw.println();
   1523             }
   1524         }
   1525     }
   1526 
   1527     private class AccessibilityConnectionWrapper implements DeathRecipient {
   1528         private final int mWindowId;
   1529         private final int mUserId;
   1530         private final IAccessibilityInteractionConnection mConnection;
   1531 
   1532         public AccessibilityConnectionWrapper(int windowId,
   1533                 IAccessibilityInteractionConnection connection, int userId) {
   1534             mWindowId = windowId;
   1535             mUserId = userId;
   1536             mConnection = connection;
   1537         }
   1538 
   1539         public void linkToDeath() throws RemoteException {
   1540             mConnection.asBinder().linkToDeath(this, 0);
   1541         }
   1542 
   1543         public void unlinkToDeath() {
   1544             mConnection.asBinder().unlinkToDeath(this, 0);
   1545         }
   1546 
   1547         @Override
   1548         public void binderDied() {
   1549             unlinkToDeath();
   1550             synchronized (mLock) {
   1551                 removeAccessibilityInteractionConnectionLocked(mWindowId, mUserId);
   1552             }
   1553         }
   1554     }
   1555 
   1556     private final class MainHandler extends Handler {
   1557         public static final int MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER = 1;
   1558         public static final int MSG_SEND_STATE_TO_CLIENTS = 2;
   1559         public static final int MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER = 3;
   1560         public static final int MSG_UPDATE_ACTIVE_WINDOW = 4;
   1561         public static final int MSG_ANNOUNCE_NEW_USER_IF_NEEDED = 5;
   1562         public static final int MSG_UPDATE_INPUT_FILTER = 6;
   1563         public static final int MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG = 7;
   1564         public static final int MSG_SEND_KEY_EVENT_TO_INPUT_FILTER = 8;
   1565 
   1566         public MainHandler(Looper looper) {
   1567             super(looper);
   1568         }
   1569 
   1570         @Override
   1571         public void handleMessage(Message msg) {
   1572             final int type = msg.what;
   1573             switch (type) {
   1574                 case MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER: {
   1575                     AccessibilityEvent event = (AccessibilityEvent) msg.obj;
   1576                     synchronized (mLock) {
   1577                         if (mHasInputFilter && mInputFilter != null) {
   1578                             mInputFilter.notifyAccessibilityEvent(event);
   1579                         }
   1580                     }
   1581                     event.recycle();
   1582                 } break;
   1583                 case MSG_SEND_KEY_EVENT_TO_INPUT_FILTER: {
   1584                     KeyEvent event = (KeyEvent) msg.obj;
   1585                     final int policyFlags = msg.arg1;
   1586                     synchronized (mLock) {
   1587                         if (mHasInputFilter && mInputFilter != null) {
   1588                             mInputFilter.sendInputEvent(event, policyFlags);
   1589                         }
   1590                     }
   1591                     event.recycle();
   1592                 } break;
   1593                 case MSG_SEND_STATE_TO_CLIENTS: {
   1594                     final int clientState = msg.arg1;
   1595                     final int userId = msg.arg2;
   1596                     sendStateToClients(clientState, mGlobalClients);
   1597                     sendStateToClientsForUser(clientState, userId);
   1598                 } break;
   1599                 case MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER: {
   1600                     final int userId = msg.arg1;
   1601                     sendStateToClientsForUser(0, userId);
   1602                 } break;
   1603                 case MSG_UPDATE_ACTIVE_WINDOW: {
   1604                     final int windowId = msg.arg1;
   1605                     final int eventType = msg.arg2;
   1606                     mSecurityPolicy.updateActiveWindow(windowId, eventType);
   1607                 } break;
   1608                 case MSG_ANNOUNCE_NEW_USER_IF_NEEDED: {
   1609                     announceNewUserIfNeeded();
   1610                 } break;
   1611                 case MSG_UPDATE_INPUT_FILTER: {
   1612                     UserState userState = (UserState) msg.obj;
   1613                     updateInputFilter(userState);
   1614                 } break;
   1615                 case MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG: {
   1616                     Service service = (Service) msg.obj;
   1617                     showEnableTouchExplorationDialog(service);
   1618                 } break;
   1619             }
   1620         }
   1621 
   1622         private void announceNewUserIfNeeded() {
   1623             synchronized (mLock) {
   1624                 UserState userState = getCurrentUserStateLocked();
   1625                 if (userState.mIsAccessibilityEnabled) {
   1626                     UserManager userManager = (UserManager) mContext.getSystemService(
   1627                             Context.USER_SERVICE);
   1628                     String message = mContext.getString(R.string.user_switched,
   1629                             userManager.getUserInfo(mCurrentUserId).name);
   1630                     AccessibilityEvent event = AccessibilityEvent.obtain(
   1631                             AccessibilityEvent.TYPE_ANNOUNCEMENT);
   1632                     event.getText().add(message);
   1633                     event.setWindowId(mSecurityPolicy.getRetrievalAllowingWindowLocked());
   1634                     sendAccessibilityEvent(event, mCurrentUserId);
   1635                 }
   1636             }
   1637         }
   1638 
   1639         private void sendStateToClientsForUser(int clientState, int userId) {
   1640             final UserState userState;
   1641             synchronized (mLock) {
   1642                 userState = getUserStateLocked(userId);
   1643             }
   1644             sendStateToClients(clientState, userState.mClients);
   1645         }
   1646 
   1647         private void sendStateToClients(int clientState,
   1648                 RemoteCallbackList<IAccessibilityManagerClient> clients) {
   1649             try {
   1650                 final int userClientCount = clients.beginBroadcast();
   1651                 for (int i = 0; i < userClientCount; i++) {
   1652                     IAccessibilityManagerClient client = clients.getBroadcastItem(i);
   1653                     try {
   1654                         client.setState(clientState);
   1655                     } catch (RemoteException re) {
   1656                         /* ignore */
   1657                     }
   1658                 }
   1659             } finally {
   1660                 clients.finishBroadcast();
   1661             }
   1662         }
   1663     }
   1664 
   1665     private PendingEvent obtainPendingEventLocked(KeyEvent event, int policyFlags, int sequence) {
   1666         PendingEvent pendingEvent = mPendingEventPool.acquire();
   1667         if (pendingEvent == null) {
   1668             pendingEvent = new PendingEvent();
   1669         }
   1670         pendingEvent.event = event;
   1671         pendingEvent.policyFlags = policyFlags;
   1672         pendingEvent.sequence = sequence;
   1673         return pendingEvent;
   1674     }
   1675 
   1676     private void recyclePendingEventLocked(PendingEvent pendingEvent) {
   1677         pendingEvent.clear();
   1678         mPendingEventPool.release(pendingEvent);
   1679     }
   1680 
   1681     /**
   1682      * This class represents an accessibility service. It stores all per service
   1683      * data required for the service management, provides API for starting/stopping the
   1684      * service and is responsible for adding/removing the service in the data structures
   1685      * for service management. The class also exposes configuration interface that is
   1686      * passed to the service it represents as soon it is bound. It also serves as the
   1687      * connection for the service.
   1688      */
   1689     class Service extends IAccessibilityServiceConnection.Stub
   1690             implements ServiceConnection, DeathRecipient {;
   1691 
   1692         final int mUserId;
   1693 
   1694         int mId = 0;
   1695 
   1696         AccessibilityServiceInfo mAccessibilityServiceInfo;
   1697 
   1698         IBinder mService;
   1699 
   1700         IAccessibilityServiceClient mServiceInterface;
   1701 
   1702         int mEventTypes;
   1703 
   1704         int mFeedbackType;
   1705 
   1706         Set<String> mPackageNames = new HashSet<String>();
   1707 
   1708         boolean mIsDefault;
   1709 
   1710         boolean mRequestTouchExplorationMode;
   1711 
   1712         boolean mRequestEnhancedWebAccessibility;
   1713 
   1714         boolean mRequestFilterKeyEvents;
   1715 
   1716         int mFetchFlags;
   1717 
   1718         long mNotificationTimeout;
   1719 
   1720         ComponentName mComponentName;
   1721 
   1722         Intent mIntent;
   1723 
   1724         boolean mIsAutomation;
   1725 
   1726         final Rect mTempBounds = new Rect();
   1727 
   1728         final ResolveInfo mResolveInfo;
   1729 
   1730         // the events pending events to be dispatched to this service
   1731         final SparseArray<AccessibilityEvent> mPendingEvents =
   1732             new SparseArray<AccessibilityEvent>();
   1733 
   1734         final KeyEventDispatcher mKeyEventDispatcher = new KeyEventDispatcher();
   1735 
   1736         boolean mWasConnectedAndDied;
   1737 
   1738         // Handler only for dispatching accessibility events since we use event
   1739         // types as message types allowing us to remove messages per event type.
   1740         public Handler mEventDispatchHandler = new Handler(mMainHandler.getLooper()) {
   1741             @Override
   1742             public void handleMessage(Message message) {
   1743                 final int eventType =  message.what;
   1744                 notifyAccessibilityEventInternal(eventType);
   1745             }
   1746         };
   1747 
   1748         // Handler for scheduling method invocations on the main thread.
   1749         public InvocationHandler mInvocationHandler = new InvocationHandler(
   1750                 mMainHandler.getLooper());
   1751 
   1752         public Service(int userId, ComponentName componentName,
   1753                 AccessibilityServiceInfo accessibilityServiceInfo) {
   1754             mUserId = userId;
   1755             mResolveInfo = accessibilityServiceInfo.getResolveInfo();
   1756             mId = sIdCounter++;
   1757             mComponentName = componentName;
   1758             mAccessibilityServiceInfo = accessibilityServiceInfo;
   1759             mIsAutomation = (sFakeAccessibilityServiceComponentName.equals(componentName));
   1760             if (!mIsAutomation) {
   1761                 mIntent = new Intent().setComponent(mComponentName);
   1762                 mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
   1763                         com.android.internal.R.string.accessibility_binding_label);
   1764                 mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
   1765                         mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0));
   1766             }
   1767             setDynamicallyConfigurableProperties(accessibilityServiceInfo);
   1768         }
   1769 
   1770         public void setDynamicallyConfigurableProperties(AccessibilityServiceInfo info) {
   1771             mEventTypes = info.eventTypes;
   1772             mFeedbackType = info.feedbackType;
   1773             String[] packageNames = info.packageNames;
   1774             if (packageNames != null) {
   1775                 mPackageNames.addAll(Arrays.asList(packageNames));
   1776             }
   1777             mNotificationTimeout = info.notificationTimeout;
   1778             mIsDefault = (info.flags & DEFAULT) != 0;
   1779 
   1780             if (mIsAutomation || info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion
   1781                     >= Build.VERSION_CODES.JELLY_BEAN) {
   1782                 if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) {
   1783                     mFetchFlags |= AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
   1784                 } else {
   1785                     mFetchFlags &= ~AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
   1786                 }
   1787             }
   1788 
   1789             if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) {
   1790                 mFetchFlags |= AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;
   1791             } else {
   1792                 mFetchFlags &= ~AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;
   1793             }
   1794 
   1795             mRequestTouchExplorationMode = (info.flags
   1796                     & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0;
   1797             mRequestEnhancedWebAccessibility = (info.flags
   1798                     & AccessibilityServiceInfo.FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY) != 0;
   1799             mRequestFilterKeyEvents = (info.flags
   1800                     & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS)  != 0;
   1801         }
   1802 
   1803         /**
   1804          * Binds to the accessibility service.
   1805          *
   1806          * @return True if binding is successful.
   1807          */
   1808         public boolean bindLocked() {
   1809             UserState userState = getUserStateLocked(mUserId);
   1810             if (!mIsAutomation) {
   1811                 if (mService == null && mContext.bindServiceAsUser(
   1812                         mIntent, this, Context.BIND_AUTO_CREATE, new UserHandle(mUserId))) {
   1813                     userState.mBindingServices.add(mComponentName);
   1814                 }
   1815             } else {
   1816                 userState.mBindingServices.add(mComponentName);
   1817                 mService = userState.mUiAutomationServiceClient.asBinder();
   1818                 onServiceConnected(mComponentName, mService);
   1819                 userState.mUiAutomationService = this;
   1820             }
   1821             return false;
   1822         }
   1823 
   1824         /**
   1825          * Unbinds form the accessibility service and removes it from the data
   1826          * structures for service management.
   1827          *
   1828          * @return True if unbinding is successful.
   1829          */
   1830         public boolean unbindLocked() {
   1831             if (mService == null) {
   1832                 return false;
   1833             }
   1834             UserState userState = getUserStateLocked(mUserId);
   1835             mKeyEventDispatcher.flush();
   1836             if (!mIsAutomation) {
   1837                 mContext.unbindService(this);
   1838             } else {
   1839                 userState.destroyUiAutomationService();
   1840             }
   1841             removeServiceLocked(this, userState);
   1842             resetLocked();
   1843             return true;
   1844         }
   1845 
   1846         public boolean canReceiveEventsLocked() {
   1847             return (mEventTypes != 0 && mFeedbackType != 0 && mService != null);
   1848         }
   1849 
   1850         @Override
   1851         public void setOnKeyEventResult(boolean handled, int sequence) {
   1852             mKeyEventDispatcher.setOnKeyEventResult(handled, sequence);
   1853         }
   1854 
   1855         @Override
   1856         public AccessibilityServiceInfo getServiceInfo() {
   1857             synchronized (mLock) {
   1858                 return mAccessibilityServiceInfo;
   1859             }
   1860         }
   1861 
   1862         @Override
   1863         public void setServiceInfo(AccessibilityServiceInfo info) {
   1864             final long identity = Binder.clearCallingIdentity();
   1865             try {
   1866                 synchronized (mLock) {
   1867                     // If the XML manifest had data to configure the service its info
   1868                     // should be already set. In such a case update only the dynamically
   1869                     // configurable properties.
   1870                     AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo;
   1871                     if (oldInfo != null) {
   1872                         oldInfo.updateDynamicallyConfigurableProperties(info);
   1873                         setDynamicallyConfigurableProperties(oldInfo);
   1874                     } else {
   1875                         setDynamicallyConfigurableProperties(info);
   1876                     }
   1877                     UserState userState = getUserStateLocked(mUserId);
   1878                     onUserStateChangedLocked(userState);
   1879                 }
   1880             } finally {
   1881                 Binder.restoreCallingIdentity(identity);
   1882             }
   1883         }
   1884 
   1885         @Override
   1886         public void onServiceConnected(ComponentName componentName, IBinder service) {
   1887             synchronized (mLock) {
   1888                 mService = service;
   1889                 mServiceInterface = IAccessibilityServiceClient.Stub.asInterface(service);
   1890                 UserState userState = getUserStateLocked(mUserId);
   1891                 addServiceLocked(this, userState);
   1892                 if (userState.mBindingServices.contains(mComponentName) || mWasConnectedAndDied) {
   1893                     userState.mBindingServices.remove(mComponentName);
   1894                     mWasConnectedAndDied = false;
   1895                     try {
   1896                        mServiceInterface.setConnection(this, mId);
   1897                        onUserStateChangedLocked(userState);
   1898                     } catch (RemoteException re) {
   1899                         Slog.w(LOG_TAG, "Error while setting connection for service: "
   1900                                 + service, re);
   1901                         binderDied();
   1902                     }
   1903                 } else {
   1904                     binderDied();
   1905                 }
   1906             }
   1907         }
   1908 
   1909         @Override
   1910         public boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
   1911                 long accessibilityNodeId, String viewIdResName, int interactionId,
   1912                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
   1913                 throws RemoteException {
   1914             final int resolvedWindowId;
   1915             IAccessibilityInteractionConnection connection = null;
   1916             synchronized (mLock) {
   1917                 final int resolvedUserId = mSecurityPolicy
   1918                         .resolveCallingUserIdEnforcingPermissionsLocked(
   1919                                 UserHandle.getCallingUserId());
   1920                 if (resolvedUserId != mCurrentUserId) {
   1921                     return false;
   1922                 }
   1923                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
   1924                 final boolean permissionGranted = mSecurityPolicy.canRetrieveWindowContent(this);
   1925                 if (!permissionGranted) {
   1926                     return false;
   1927                 } else {
   1928                     resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
   1929                     connection = getConnectionLocked(resolvedWindowId);
   1930                     if (connection == null) {
   1931                         return false;
   1932                     }
   1933                 }
   1934             }
   1935             final int interrogatingPid = Binder.getCallingPid();
   1936             final long identityToken = Binder.clearCallingIdentity();
   1937             MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
   1938             try {
   1939                 connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId,
   1940                         viewIdResName, interactionId, callback, mFetchFlags, interrogatingPid,
   1941                         interrogatingTid, spec);
   1942                 return true;
   1943             } catch (RemoteException re) {
   1944                 if (DEBUG) {
   1945                     Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId().");
   1946                 }
   1947             } finally {
   1948                 Binder.restoreCallingIdentity(identityToken);
   1949             }
   1950             return false;
   1951         }
   1952 
   1953         @Override
   1954         public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId,
   1955                 long accessibilityNodeId, String text, int interactionId,
   1956                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
   1957                 throws RemoteException {
   1958             final int resolvedWindowId;
   1959             IAccessibilityInteractionConnection connection = null;
   1960             synchronized (mLock) {
   1961                 final int resolvedUserId = mSecurityPolicy
   1962                         .resolveCallingUserIdEnforcingPermissionsLocked(
   1963                         UserHandle.getCallingUserId());
   1964                 if (resolvedUserId != mCurrentUserId) {
   1965                     return false;
   1966                 }
   1967                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
   1968                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
   1969                 final boolean permissionGranted =
   1970                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
   1971                 if (!permissionGranted) {
   1972                     return false;
   1973                 } else {
   1974                     connection = getConnectionLocked(resolvedWindowId);
   1975                     if (connection == null) {
   1976                         return false;
   1977                     }
   1978                 }
   1979             }
   1980             final int interrogatingPid = Binder.getCallingPid();
   1981             final long identityToken = Binder.clearCallingIdentity();
   1982             MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
   1983             try {
   1984                 connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
   1985                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
   1986                         spec);
   1987                 return true;
   1988             } catch (RemoteException re) {
   1989                 if (DEBUG) {
   1990                     Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()");
   1991                 }
   1992             } finally {
   1993                 Binder.restoreCallingIdentity(identityToken);
   1994             }
   1995             return false;
   1996         }
   1997 
   1998         @Override
   1999         public boolean findAccessibilityNodeInfoByAccessibilityId(
   2000                 int accessibilityWindowId, long accessibilityNodeId, int interactionId,
   2001                 IAccessibilityInteractionConnectionCallback callback, int flags,
   2002                 long interrogatingTid) throws RemoteException {
   2003             final int resolvedWindowId;
   2004             IAccessibilityInteractionConnection connection = null;
   2005             synchronized (mLock) {
   2006                 final int resolvedUserId = mSecurityPolicy
   2007                         .resolveCallingUserIdEnforcingPermissionsLocked(
   2008                         UserHandle.getCallingUserId());
   2009                 if (resolvedUserId != mCurrentUserId) {
   2010                     return false;
   2011                 }
   2012                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
   2013                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
   2014                 final boolean permissionGranted =
   2015                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
   2016                 if (!permissionGranted) {
   2017                     return false;
   2018                 } else {
   2019                     connection = getConnectionLocked(resolvedWindowId);
   2020                     if (connection == null) {
   2021                         return false;
   2022                     }
   2023                 }
   2024             }
   2025             final int interrogatingPid = Binder.getCallingPid();
   2026             final long identityToken = Binder.clearCallingIdentity();
   2027             MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
   2028             try {
   2029                 connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId,
   2030                         interactionId, callback, mFetchFlags | flags, interrogatingPid,
   2031                         interrogatingTid, spec);
   2032                 return true;
   2033             } catch (RemoteException re) {
   2034                 if (DEBUG) {
   2035                     Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
   2036                 }
   2037             } finally {
   2038                 Binder.restoreCallingIdentity(identityToken);
   2039             }
   2040             return false;
   2041         }
   2042 
   2043         @Override
   2044         public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId,
   2045                 int focusType, int interactionId,
   2046                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
   2047                 throws RemoteException {
   2048             final int resolvedWindowId;
   2049             IAccessibilityInteractionConnection connection = null;
   2050             synchronized (mLock) {
   2051                 final int resolvedUserId = mSecurityPolicy
   2052                         .resolveCallingUserIdEnforcingPermissionsLocked(
   2053                         UserHandle.getCallingUserId());
   2054                 if (resolvedUserId != mCurrentUserId) {
   2055                     return false;
   2056                 }
   2057                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
   2058                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
   2059                 final boolean permissionGranted =
   2060                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
   2061                 if (!permissionGranted) {
   2062                     return false;
   2063                 } else {
   2064                     connection = getConnectionLocked(resolvedWindowId);
   2065                     if (connection == null) {
   2066                         return false;
   2067                     }
   2068                 }
   2069             }
   2070             final int interrogatingPid = Binder.getCallingPid();
   2071             final long identityToken = Binder.clearCallingIdentity();
   2072             MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
   2073             try {
   2074                 connection.findFocus(accessibilityNodeId, focusType, interactionId, callback,
   2075                         mFetchFlags, interrogatingPid, interrogatingTid, spec);
   2076                 return true;
   2077             } catch (RemoteException re) {
   2078                 if (DEBUG) {
   2079                     Slog.e(LOG_TAG, "Error calling findAccessibilityFocus()");
   2080                 }
   2081             } finally {
   2082                 Binder.restoreCallingIdentity(identityToken);
   2083             }
   2084             return false;
   2085         }
   2086 
   2087         @Override
   2088         public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId,
   2089                 int direction, int interactionId,
   2090                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
   2091                 throws RemoteException {
   2092             final int resolvedWindowId;
   2093             IAccessibilityInteractionConnection connection = null;
   2094             synchronized (mLock) {
   2095                 final int resolvedUserId = mSecurityPolicy
   2096                         .resolveCallingUserIdEnforcingPermissionsLocked(
   2097                         UserHandle.getCallingUserId());
   2098                 if (resolvedUserId != mCurrentUserId) {
   2099                     return false;
   2100                 }
   2101                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
   2102                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
   2103                 final boolean permissionGranted =
   2104                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
   2105                 if (!permissionGranted) {
   2106                     return false;
   2107                 } else {
   2108                     connection = getConnectionLocked(resolvedWindowId);
   2109                     if (connection == null) {
   2110                         return false;
   2111                     }
   2112                 }
   2113             }
   2114             final int interrogatingPid = Binder.getCallingPid();
   2115             final long identityToken = Binder.clearCallingIdentity();
   2116             MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
   2117             try {
   2118                 connection.focusSearch(accessibilityNodeId, direction, interactionId, callback,
   2119                         mFetchFlags, interrogatingPid, interrogatingTid, spec);
   2120                 return true;
   2121             } catch (RemoteException re) {
   2122                 if (DEBUG) {
   2123                     Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()");
   2124                 }
   2125             } finally {
   2126                 Binder.restoreCallingIdentity(identityToken);
   2127             }
   2128             return false;
   2129         }
   2130 
   2131         @Override
   2132         public boolean performAccessibilityAction(int accessibilityWindowId,
   2133                 long accessibilityNodeId, int action, Bundle arguments, int interactionId,
   2134                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
   2135                 throws RemoteException {
   2136             final int resolvedWindowId;
   2137             IAccessibilityInteractionConnection connection = null;
   2138             synchronized (mLock) {
   2139                 final int resolvedUserId = mSecurityPolicy
   2140                         .resolveCallingUserIdEnforcingPermissionsLocked(
   2141                         UserHandle.getCallingUserId());
   2142                 if (resolvedUserId != mCurrentUserId) {
   2143                     return false;
   2144                 }
   2145                 mSecurityPolicy.enforceCanRetrieveWindowContent(this);
   2146                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
   2147                 final boolean permissionGranted = mSecurityPolicy.canPerformActionLocked(this,
   2148                         resolvedWindowId, action, arguments);
   2149                 if (!permissionGranted) {
   2150                     return false;
   2151                 } else {
   2152                     connection = getConnectionLocked(resolvedWindowId);
   2153                     if (connection == null) {
   2154                         return false;
   2155                     }
   2156                 }
   2157             }
   2158             final int interrogatingPid = Binder.getCallingPid();
   2159             final long identityToken = Binder.clearCallingIdentity();
   2160             try {
   2161                 connection.performAccessibilityAction(accessibilityNodeId, action, arguments,
   2162                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid);
   2163             } catch (RemoteException re) {
   2164                 if (DEBUG) {
   2165                     Slog.e(LOG_TAG, "Error calling performAccessibilityAction()");
   2166                 }
   2167             } finally {
   2168                 Binder.restoreCallingIdentity(identityToken);
   2169             }
   2170             return true;
   2171         }
   2172 
   2173         public boolean performGlobalAction(int action) {
   2174             synchronized (mLock) {
   2175                 final int resolvedUserId = mSecurityPolicy
   2176                         .resolveCallingUserIdEnforcingPermissionsLocked(
   2177                         UserHandle.getCallingUserId());
   2178                 if (resolvedUserId != mCurrentUserId) {
   2179                     return false;
   2180                 }
   2181             }
   2182             final long identity = Binder.clearCallingIdentity();
   2183             try {
   2184                 switch (action) {
   2185                     case AccessibilityService.GLOBAL_ACTION_BACK: {
   2186                         sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK);
   2187                     } return true;
   2188                     case AccessibilityService.GLOBAL_ACTION_HOME: {
   2189                         sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME);
   2190                     } return true;
   2191                     case AccessibilityService.GLOBAL_ACTION_RECENTS: {
   2192                         openRecents();
   2193                     } return true;
   2194                     case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: {
   2195                         expandNotifications();
   2196                     } return true;
   2197                     case AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS: {
   2198                         expandQuickSettings();
   2199                     } return true;
   2200                 }
   2201                 return false;
   2202             } finally {
   2203                 Binder.restoreCallingIdentity(identity);
   2204             }
   2205         }
   2206 
   2207         @Override
   2208         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
   2209             mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
   2210             synchronized (mLock) {
   2211                 pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo()
   2212                         .loadLabel(mContext.getPackageManager()));
   2213                 pw.append(", feedbackType"
   2214                         + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType));
   2215                 pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities());
   2216                 pw.append(", eventTypes="
   2217                         + AccessibilityEvent.eventTypeToString(mEventTypes));
   2218                 pw.append(", notificationTimeout=" + mNotificationTimeout);
   2219                 pw.append("]");
   2220             }
   2221         }
   2222 
   2223         @Override
   2224         public void onServiceDisconnected(ComponentName componentName) {
   2225             /* do nothing - #binderDied takes care */
   2226         }
   2227 
   2228         public void linkToOwnDeathLocked() throws RemoteException {
   2229             mService.linkToDeath(this, 0);
   2230         }
   2231 
   2232         public void unlinkToOwnDeathLocked() {
   2233             mService.unlinkToDeath(this, 0);
   2234         }
   2235 
   2236         public void resetLocked() {
   2237             try {
   2238                 // Clear the proxy in the other process so this
   2239                 // IAccessibilityServiceConnection can be garbage collected.
   2240                 mServiceInterface.setConnection(null, mId);
   2241             } catch (RemoteException re) {
   2242                 /* ignore */
   2243             }
   2244             mService = null;
   2245             mServiceInterface = null;
   2246         }
   2247 
   2248         public boolean isConnectedLocked() {
   2249             return (mService != null);
   2250         }
   2251 
   2252         public void binderDied() {
   2253             synchronized (mLock) {
   2254                 // It is possible that this service's package was force stopped during
   2255                 // whose handling the death recipient is unlinked and still get a call
   2256                 // on binderDied since the call was made before we unlink but was
   2257                 // waiting on the lock we held during the force stop handling.
   2258                 if (!isConnectedLocked()) {
   2259                     return;
   2260                 }
   2261                 mWasConnectedAndDied = true;
   2262                 mKeyEventDispatcher.flush();
   2263                 UserState userState = getUserStateLocked(mUserId);
   2264                 // The death recipient is unregistered in removeServiceLocked
   2265                 removeServiceLocked(this, userState);
   2266                 resetLocked();
   2267                 if (mIsAutomation) {
   2268                     // We no longer have an automation service, so restore
   2269                     // the state based on values in the settings database.
   2270                     userState.mInstalledServices.remove(mAccessibilityServiceInfo);
   2271                     userState.mEnabledServices.remove(mComponentName);
   2272                     userState.destroyUiAutomationService();
   2273                 }
   2274             }
   2275         }
   2276 
   2277         /**
   2278          * Performs a notification for an {@link AccessibilityEvent}.
   2279          *
   2280          * @param event The event.
   2281          */
   2282         public void notifyAccessibilityEvent(AccessibilityEvent event) {
   2283             synchronized (mLock) {
   2284                 final int eventType = event.getEventType();
   2285                 // Make a copy since during dispatch it is possible the event to
   2286                 // be modified to remove its source if the receiving service does
   2287                 // not have permission to access the window content.
   2288                 AccessibilityEvent newEvent = AccessibilityEvent.obtain(event);
   2289                 AccessibilityEvent oldEvent = mPendingEvents.get(eventType);
   2290                 mPendingEvents.put(eventType, newEvent);
   2291 
   2292                 final int what = eventType;
   2293                 if (oldEvent != null) {
   2294                     mEventDispatchHandler.removeMessages(what);
   2295                     oldEvent.recycle();
   2296                 }
   2297 
   2298                 Message message = mEventDispatchHandler.obtainMessage(what);
   2299                 mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout);
   2300             }
   2301         }
   2302 
   2303         /**
   2304          * Notifies an accessibility service client for a scheduled event given the event type.
   2305          *
   2306          * @param eventType The type of the event to dispatch.
   2307          */
   2308         private void notifyAccessibilityEventInternal(int eventType) {
   2309             IAccessibilityServiceClient listener;
   2310             AccessibilityEvent event;
   2311 
   2312             synchronized (mLock) {
   2313                 listener = mServiceInterface;
   2314 
   2315                 // If the service died/was disabled while the message for dispatching
   2316                 // the accessibility event was propagating the listener may be null.
   2317                 if (listener == null) {
   2318                     return;
   2319                 }
   2320 
   2321                 event = mPendingEvents.get(eventType);
   2322 
   2323                 // Check for null here because there is a concurrent scenario in which this
   2324                 // happens: 1) A binder thread calls notifyAccessibilityServiceDelayedLocked
   2325                 // which posts a message for dispatching an event. 2) The message is pulled
   2326                 // from the queue by the handler on the service thread and the latter is
   2327                 // just about to acquire the lock and call this method. 3) Now another binder
   2328                 // thread acquires the lock calling notifyAccessibilityServiceDelayedLocked
   2329                 // so the service thread waits for the lock; 4) The binder thread replaces
   2330                 // the event with a more recent one (assume the same event type) and posts a
   2331                 // dispatch request releasing the lock. 5) Now the main thread is unblocked and
   2332                 // dispatches the event which is removed from the pending ones. 6) And ... now
   2333                 // the service thread handles the last message posted by the last binder call
   2334                 // but the event is already dispatched and hence looking it up in the pending
   2335                 // ones yields null. This check is much simpler that keeping count for each
   2336                 // event type of each service to catch such a scenario since only one message
   2337                 // is processed at a time.
   2338                 if (event == null) {
   2339                     return;
   2340                 }
   2341 
   2342                 mPendingEvents.remove(eventType);
   2343                 if (mSecurityPolicy.canRetrieveWindowContent(this)) {
   2344                     event.setConnectionId(mId);
   2345                 } else {
   2346                     event.setSource(null);
   2347                 }
   2348                 event.setSealed(true);
   2349             }
   2350 
   2351             try {
   2352                 listener.onAccessibilityEvent(event);
   2353                 if (DEBUG) {
   2354                     Slog.i(LOG_TAG, "Event " + event + " sent to " + listener);
   2355                 }
   2356             } catch (RemoteException re) {
   2357                 Slog.e(LOG_TAG, "Error during sending " + event + " to " + listener, re);
   2358             } finally {
   2359                 event.recycle();
   2360             }
   2361         }
   2362 
   2363         public void notifyGesture(int gestureId) {
   2364             mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE,
   2365                     gestureId, 0).sendToTarget();
   2366         }
   2367 
   2368         public void notifyKeyEvent(KeyEvent event, int policyFlags) {
   2369             mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_KEY_EVENT,
   2370                     policyFlags, 0, event).sendToTarget();
   2371         }
   2372 
   2373         public void notifyClearAccessibilityNodeInfoCache() {
   2374             mInvocationHandler.sendEmptyMessage(
   2375                     InvocationHandler.MSG_CLEAR_ACCESSIBILITY_NODE_INFO_CACHE);
   2376         }
   2377 
   2378         private void notifyGestureInternal(int gestureId) {
   2379             IAccessibilityServiceClient listener = mServiceInterface;
   2380             if (listener != null) {
   2381                 try {
   2382                     listener.onGesture(gestureId);
   2383                 } catch (RemoteException re) {
   2384                     Slog.e(LOG_TAG, "Error during sending gesture " + gestureId
   2385                             + " to " + mService, re);
   2386                 }
   2387             }
   2388         }
   2389 
   2390         private void notifyKeyEventInternal(KeyEvent event, int policyFlags) {
   2391             mKeyEventDispatcher.notifyKeyEvent(event, policyFlags);
   2392         }
   2393 
   2394         private void notifyClearAccessibilityNodeInfoCacheInternal() {
   2395             IAccessibilityServiceClient listener = mServiceInterface;
   2396             if (listener != null) {
   2397                 try {
   2398                     listener.clearAccessibilityNodeInfoCache();
   2399                 } catch (RemoteException re) {
   2400                     Slog.e(LOG_TAG, "Error during requesting accessibility info cache"
   2401                             + " to be cleared.", re);
   2402                 }
   2403             }
   2404         }
   2405 
   2406         private void sendDownAndUpKeyEvents(int keyCode) {
   2407             final long token = Binder.clearCallingIdentity();
   2408 
   2409             // Inject down.
   2410             final long downTime = SystemClock.uptimeMillis();
   2411             KeyEvent down = KeyEvent.obtain(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode, 0, 0,
   2412                     KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
   2413                     InputDevice.SOURCE_KEYBOARD, null);
   2414             InputManager.getInstance().injectInputEvent(down,
   2415                     InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
   2416             down.recycle();
   2417 
   2418             // Inject up.
   2419             final long upTime = SystemClock.uptimeMillis();
   2420             KeyEvent up = KeyEvent.obtain(downTime, upTime, KeyEvent.ACTION_UP, keyCode, 0, 0,
   2421                     KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
   2422                     InputDevice.SOURCE_KEYBOARD, null);
   2423             InputManager.getInstance().injectInputEvent(up,
   2424                     InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
   2425             up.recycle();
   2426 
   2427             Binder.restoreCallingIdentity(token);
   2428         }
   2429 
   2430         private void expandNotifications() {
   2431             final long token = Binder.clearCallingIdentity();
   2432 
   2433             StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService(
   2434                     android.app.Service.STATUS_BAR_SERVICE);
   2435             statusBarManager.expandNotificationsPanel();
   2436 
   2437             Binder.restoreCallingIdentity(token);
   2438         }
   2439 
   2440         private void expandQuickSettings() {
   2441             final long token = Binder.clearCallingIdentity();
   2442 
   2443             StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService(
   2444                     android.app.Service.STATUS_BAR_SERVICE);
   2445             statusBarManager.expandSettingsPanel();
   2446 
   2447             Binder.restoreCallingIdentity(token);
   2448         }
   2449 
   2450         private void openRecents() {
   2451             final long token = Binder.clearCallingIdentity();
   2452 
   2453             IStatusBarService statusBarService = IStatusBarService.Stub.asInterface(
   2454                     ServiceManager.getService("statusbar"));
   2455             try {
   2456                 statusBarService.toggleRecentApps();
   2457             } catch (RemoteException e) {
   2458                 Slog.e(LOG_TAG, "Error toggling recent apps.");
   2459             }
   2460 
   2461             Binder.restoreCallingIdentity(token);
   2462         }
   2463 
   2464         private IAccessibilityInteractionConnection getConnectionLocked(int windowId) {
   2465             if (DEBUG) {
   2466                 Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId);
   2467             }
   2468             AccessibilityConnectionWrapper wrapper = mGlobalInteractionConnections.get(windowId);
   2469             if (wrapper == null) {
   2470                 wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId);
   2471             }
   2472             if (wrapper != null && wrapper.mConnection != null) {
   2473                 return wrapper.mConnection;
   2474             }
   2475             if (DEBUG) {
   2476                 Slog.e(LOG_TAG, "No interaction connection to window: " + windowId);
   2477             }
   2478             return null;
   2479         }
   2480 
   2481         private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) {
   2482             if (accessibilityWindowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) {
   2483                 return mSecurityPolicy.mActiveWindowId;
   2484             }
   2485             return accessibilityWindowId;
   2486         }
   2487 
   2488         private MagnificationSpec getCompatibleMagnificationSpec(int windowId) {
   2489             try {
   2490                 IBinder windowToken = mGlobalWindowTokens.get(windowId);
   2491                 if (windowToken == null) {
   2492                     windowToken = getCurrentUserStateLocked().mWindowTokens.get(windowId);
   2493                 }
   2494                 if (windowToken != null) {
   2495                     return mWindowManagerService.getCompatibleMagnificationSpecForWindow(
   2496                             windowToken);
   2497                 }
   2498             } catch (RemoteException re) {
   2499                 /* ignore */
   2500             }
   2501             return null;
   2502         }
   2503 
   2504         private final class InvocationHandler extends Handler {
   2505 
   2506             public static final int MSG_ON_GESTURE = 1;
   2507             public static final int MSG_ON_KEY_EVENT = 2;
   2508             public static final int MSG_CLEAR_ACCESSIBILITY_NODE_INFO_CACHE = 3;
   2509             public static final int MSG_ON_KEY_EVENT_TIMEOUT = 4;
   2510 
   2511             public InvocationHandler(Looper looper) {
   2512                 super(looper, null, true);
   2513             }
   2514 
   2515             @Override
   2516             public void handleMessage(Message message) {
   2517                 final int type = message.what;
   2518                 switch (type) {
   2519                     case MSG_ON_GESTURE: {
   2520                         final int gestureId = message.arg1;
   2521                         notifyGestureInternal(gestureId);
   2522                     } break;
   2523                     case MSG_ON_KEY_EVENT: {
   2524                         KeyEvent event = (KeyEvent) message.obj;
   2525                         final int policyFlags = message.arg1;
   2526                         notifyKeyEventInternal(event, policyFlags);
   2527                     } break;
   2528                     case MSG_CLEAR_ACCESSIBILITY_NODE_INFO_CACHE: {
   2529                         notifyClearAccessibilityNodeInfoCacheInternal();
   2530                     } break;
   2531                     case MSG_ON_KEY_EVENT_TIMEOUT: {
   2532                         PendingEvent eventState = (PendingEvent) message.obj;
   2533                         setOnKeyEventResult(false, eventState.sequence);
   2534                     } break;
   2535                     default: {
   2536                         throw new IllegalArgumentException("Unknown message: " + type);
   2537                     }
   2538                 }
   2539             }
   2540         }
   2541 
   2542         private final class KeyEventDispatcher {
   2543 
   2544             private static final long ON_KEY_EVENT_TIMEOUT_MILLIS = 500;
   2545 
   2546             private PendingEvent mPendingEvents;
   2547 
   2548             private final InputEventConsistencyVerifier mSentEventsVerifier =
   2549                     InputEventConsistencyVerifier.isInstrumentationEnabled()
   2550                             ? new InputEventConsistencyVerifier(
   2551                                     this, 0, KeyEventDispatcher.class.getSimpleName()) : null;
   2552 
   2553             public void notifyKeyEvent(KeyEvent event, int policyFlags) {
   2554                 final PendingEvent pendingEvent;
   2555 
   2556                 synchronized (mLock) {
   2557                     pendingEvent = addPendingEventLocked(event, policyFlags);
   2558                 }
   2559 
   2560                 Message message = mInvocationHandler.obtainMessage(
   2561                         InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT, pendingEvent);
   2562                 mInvocationHandler.sendMessageDelayed(message, ON_KEY_EVENT_TIMEOUT_MILLIS);
   2563 
   2564                 try {
   2565                     // Accessibility services are exclusively not in the system
   2566                     // process, therefore no need to clone the motion event to
   2567                     // prevent tampering. It will be cloned in the IPC call.
   2568                     mServiceInterface.onKeyEvent(pendingEvent.event, pendingEvent.sequence);
   2569                 } catch (RemoteException re) {
   2570                     setOnKeyEventResult(false, pendingEvent.sequence);
   2571                 }
   2572             }
   2573 
   2574             public void setOnKeyEventResult(boolean handled, int sequence) {
   2575                 synchronized (mLock) {
   2576                     PendingEvent pendingEvent = removePendingEventLocked(sequence);
   2577                     if (pendingEvent != null) {
   2578                         mInvocationHandler.removeMessages(
   2579                                 InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT,
   2580                                 pendingEvent);
   2581                         pendingEvent.handled = handled;
   2582                         finishPendingEventLocked(pendingEvent);
   2583                     }
   2584                 }
   2585             }
   2586 
   2587             public void flush() {
   2588                 synchronized (mLock) {
   2589                     cancelAllPendingEventsLocked();
   2590                     if (mSentEventsVerifier != null) {
   2591                         mSentEventsVerifier.reset();
   2592                     }
   2593                 }
   2594             }
   2595 
   2596             private PendingEvent addPendingEventLocked(KeyEvent event, int policyFlags) {
   2597                 final int sequence = event.getSequenceNumber();
   2598                 PendingEvent pendingEvent = obtainPendingEventLocked(event, policyFlags, sequence);
   2599                 pendingEvent.next = mPendingEvents;
   2600                 mPendingEvents = pendingEvent;
   2601                 return pendingEvent;
   2602             }
   2603 
   2604             private PendingEvent removePendingEventLocked(int sequence) {
   2605                 PendingEvent previous = null;
   2606                 PendingEvent current = mPendingEvents;
   2607 
   2608                 while (current != null) {
   2609                     if (current.sequence == sequence) {
   2610                         if (previous != null) {
   2611                             previous.next = current.next;
   2612                         } else {
   2613                             mPendingEvents = current.next;
   2614                         }
   2615                         current.next = null;
   2616                         return current;
   2617                     }
   2618                     previous = current;
   2619                     current = current.next;
   2620                 }
   2621                 return null;
   2622             }
   2623 
   2624             private void finishPendingEventLocked(PendingEvent pendingEvent) {
   2625                 if (!pendingEvent.handled) {
   2626                     sendKeyEventToInputFilter(pendingEvent.event, pendingEvent.policyFlags);
   2627                 }
   2628                 // Nullify the event since we do not want it to be
   2629                 // recycled yet. It will be sent to the input filter.
   2630                 pendingEvent.event = null;
   2631                 recyclePendingEventLocked(pendingEvent);
   2632             }
   2633 
   2634             private void sendKeyEventToInputFilter(KeyEvent event, int policyFlags) {
   2635                 if (DEBUG) {
   2636                     Slog.i(LOG_TAG, "Injecting event: " + event);
   2637                 }
   2638                 if (mSentEventsVerifier != null) {
   2639                     mSentEventsVerifier.onKeyEvent(event, 0);
   2640                 }
   2641                 policyFlags |= WindowManagerPolicy.FLAG_PASS_TO_USER;
   2642                 mMainHandler.obtainMessage(MainHandler.MSG_SEND_KEY_EVENT_TO_INPUT_FILTER,
   2643                         policyFlags, 0, event).sendToTarget();
   2644             }
   2645 
   2646             private void cancelAllPendingEventsLocked() {
   2647                 while (mPendingEvents != null) {
   2648                     PendingEvent pendingEvent = removePendingEventLocked(mPendingEvents.sequence);
   2649                     pendingEvent.handled = false;
   2650                     mInvocationHandler.removeMessages(InvocationHandler.MSG_ON_KEY_EVENT_TIMEOUT,
   2651                             pendingEvent);
   2652                     finishPendingEventLocked(pendingEvent);
   2653                 }
   2654             }
   2655         }
   2656     }
   2657 
   2658     private static final class PendingEvent {
   2659         PendingEvent next;
   2660 
   2661         KeyEvent event;
   2662         int policyFlags;
   2663         int sequence;
   2664         boolean handled;
   2665 
   2666         public void clear() {
   2667             if (event != null) {
   2668                 event.recycle();
   2669                 event = null;
   2670             }
   2671             next = null;
   2672             policyFlags = 0;
   2673             sequence = 0;
   2674             handled = false;
   2675         }
   2676     }
   2677 
   2678     final class SecurityPolicy {
   2679         private static final int VALID_ACTIONS =
   2680             AccessibilityNodeInfo.ACTION_CLICK
   2681             | AccessibilityNodeInfo.ACTION_LONG_CLICK
   2682             | AccessibilityNodeInfo.ACTION_FOCUS
   2683             | AccessibilityNodeInfo.ACTION_CLEAR_FOCUS
   2684             | AccessibilityNodeInfo.ACTION_SELECT
   2685             | AccessibilityNodeInfo.ACTION_CLEAR_SELECTION
   2686             | AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS
   2687             | AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS
   2688             | AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
   2689             | AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
   2690             | AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT
   2691             | AccessibilityNodeInfo.ACTION_PREVIOUS_HTML_ELEMENT
   2692             | AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
   2693             | AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
   2694             | AccessibilityNodeInfo.ACTION_COPY
   2695             | AccessibilityNodeInfo.ACTION_PASTE
   2696             | AccessibilityNodeInfo.ACTION_CUT
   2697             | AccessibilityNodeInfo.ACTION_SET_SELECTION;
   2698 
   2699         private static final int RETRIEVAL_ALLOWING_EVENT_TYPES =
   2700             AccessibilityEvent.TYPE_VIEW_CLICKED
   2701             | AccessibilityEvent.TYPE_VIEW_FOCUSED
   2702             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
   2703             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
   2704             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
   2705             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
   2706             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
   2707             | AccessibilityEvent.TYPE_VIEW_SELECTED
   2708             | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
   2709             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
   2710             | AccessibilityEvent.TYPE_VIEW_SCROLLED
   2711             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
   2712             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED;
   2713 
   2714         private int mActiveWindowId;
   2715         private boolean mTouchInteractionInProgress;
   2716 
   2717         private boolean canDispatchAccessibilityEvent(AccessibilityEvent event) {
   2718             final int eventType = event.getEventType();
   2719             switch (eventType) {
   2720                 // All events that are for changes in a global window
   2721                 // state should *always* be dispatched.
   2722                 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
   2723                 case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
   2724                 // All events generated by the user touching the
   2725                 // screen should *always* be dispatched.
   2726                 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START:
   2727                 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END:
   2728                 case AccessibilityEvent.TYPE_GESTURE_DETECTION_START:
   2729                 case AccessibilityEvent.TYPE_GESTURE_DETECTION_END:
   2730                 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START:
   2731                 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END:
   2732                 // These will change the active window, so dispatch.
   2733                 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER:
   2734                 case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT: {
   2735                     return true;
   2736                 }
   2737                 // All events for changes in window content should be
   2738                 // dispatched *only* if this window is the active one.
   2739                 default:
   2740                     return event.getWindowId() == mActiveWindowId;
   2741             }
   2742         }
   2743 
   2744         public void updateEventSourceLocked(AccessibilityEvent event) {
   2745             if ((event.getEventType() & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) {
   2746                 event.setSource(null);
   2747             }
   2748         }
   2749 
   2750         public void updateActiveWindow(int windowId, int eventType) {
   2751             // The active window is either the window that has input focus or
   2752             // the window that the user is currently touching. If the user is
   2753             // touching a window that does not have input focus as soon as the
   2754             // the user stops touching that window the focused window becomes
   2755             // the active one.
   2756             switch (eventType) {
   2757                 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: {
   2758                     if (getFocusedWindowId() == windowId) {
   2759                         mActiveWindowId = windowId;
   2760                     }
   2761                 } break;
   2762                 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: {
   2763                     // Do not allow delayed hover events to confuse us
   2764                     // which the active window is.
   2765                     if (mTouchInteractionInProgress) {
   2766                         mActiveWindowId = windowId;
   2767                     }
   2768                 } break;
   2769             }
   2770         }
   2771 
   2772         public void onTouchInteractionStart() {
   2773             mTouchInteractionInProgress = true;
   2774         }
   2775 
   2776         public void onTouchInteractionEnd() {
   2777             mTouchInteractionInProgress = false;
   2778             // We want to set the active window to be current immediately
   2779             // after the user has stopped touching the screen since if the
   2780             // user types with the IME he should get a feedback for the
   2781             // letter typed in the text view which is in the input focused
   2782             // window. Note that we always deliver hover accessibility events
   2783             // (they are a result of user touching the screen) so change of
   2784             // the active window before all hover accessibility events from
   2785             // the touched window are delivered is fine.
   2786             mActiveWindowId = getFocusedWindowId();
   2787         }
   2788 
   2789         public int getRetrievalAllowingWindowLocked() {
   2790             return mActiveWindowId;
   2791         }
   2792 
   2793         public boolean canGetAccessibilityNodeInfoLocked(Service service, int windowId) {
   2794             return canRetrieveWindowContent(service) && isRetrievalAllowingWindow(windowId);
   2795         }
   2796 
   2797         public boolean canPerformActionLocked(Service service, int windowId, int action,
   2798                 Bundle arguments) {
   2799             return canRetrieveWindowContent(service)
   2800                 && isRetrievalAllowingWindow(windowId)
   2801                 && isActionPermitted(action);
   2802         }
   2803 
   2804         public boolean canRetrieveWindowContent(Service service) {
   2805             return (service.mAccessibilityServiceInfo.getCapabilities()
   2806                     & AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0;
   2807         }
   2808 
   2809         public void enforceCanRetrieveWindowContent(Service service) throws RemoteException {
   2810             // This happens due to incorrect registration so make it apparent.
   2811             if (!canRetrieveWindowContent(service)) {
   2812                 Slog.e(LOG_TAG, "Accessibility serivce " + service.mComponentName + " does not " +
   2813                         "declare android:canRetrieveWindowContent.");
   2814                 throw new RemoteException();
   2815             }
   2816         }
   2817 
   2818         public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) {
   2819             final int callingUid = Binder.getCallingUid();
   2820             if (callingUid == Process.SYSTEM_UID
   2821                     || callingUid == Process.SHELL_UID) {
   2822                 return mCurrentUserId;
   2823             }
   2824             final int callingUserId = UserHandle.getUserId(callingUid);
   2825             if (callingUserId == userId) {
   2826                 return userId;
   2827             }
   2828             if (!hasPermission(Manifest.permission.INTERACT_ACROSS_USERS)
   2829                     && !hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) {
   2830                 throw new SecurityException("Call from user " + callingUserId + " as user "
   2831                         + userId + " without permission INTERACT_ACROSS_USERS or "
   2832                         + "INTERACT_ACROSS_USERS_FULL not allowed.");
   2833             }
   2834             if (userId == UserHandle.USER_CURRENT
   2835                     || userId == UserHandle.USER_CURRENT_OR_SELF) {
   2836                 return mCurrentUserId;
   2837             }
   2838             throw new IllegalArgumentException("Calling user can be changed to only "
   2839                     + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF.");
   2840         }
   2841 
   2842         public boolean isCallerInteractingAcrossUsers(int userId) {
   2843             final int callingUid = Binder.getCallingUid();
   2844             return (Binder.getCallingPid() == android.os.Process.myPid()
   2845                     || callingUid == Process.SHELL_UID
   2846                     || userId == UserHandle.USER_CURRENT
   2847                     || userId == UserHandle.USER_CURRENT_OR_SELF);
   2848         }
   2849 
   2850         private boolean isRetrievalAllowingWindow(int windowId) {
   2851             return (mActiveWindowId == windowId);
   2852         }
   2853 
   2854         private boolean isActionPermitted(int action) {
   2855              return (VALID_ACTIONS & action) != 0;
   2856         }
   2857 
   2858         private void enforceCallingPermission(String permission, String function) {
   2859             if (OWN_PROCESS_ID == Binder.getCallingPid()) {
   2860                 return;
   2861             }
   2862             if (!hasPermission(permission)) {
   2863                 throw new SecurityException("You do not have " + permission
   2864                         + " required to call " + function + " from pid="
   2865                         + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
   2866             }
   2867         }
   2868 
   2869         private boolean hasPermission(String permission) {
   2870             return mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED;
   2871         }
   2872 
   2873         private int getFocusedWindowId() {
   2874             try {
   2875                 // We call this only on window focus change or after touch
   2876                 // exploration gesture end and the shown windows are not that
   2877                 // many, so the linear look up is just fine.
   2878                 IBinder token = mWindowManagerService.getFocusedWindowToken();
   2879                 if (token != null) {
   2880                     synchronized (mLock) {
   2881                         int windowId = getFocusedWindowIdLocked(token, mGlobalWindowTokens);
   2882                         if (windowId < 0) {
   2883                             windowId = getFocusedWindowIdLocked(token,
   2884                                     getCurrentUserStateLocked().mWindowTokens);
   2885                         }
   2886                         return windowId;
   2887                     }
   2888                 }
   2889             } catch (RemoteException re) {
   2890                 /* ignore */
   2891             }
   2892             return -1;
   2893         }
   2894 
   2895         private int getFocusedWindowIdLocked(IBinder token, SparseArray<IBinder> windows) {
   2896             final int windowCount = windows.size();
   2897             for (int i = 0; i < windowCount; i++) {
   2898                 if (windows.valueAt(i) == token) {
   2899                     return windows.keyAt(i);
   2900                 }
   2901             }
   2902             return -1;
   2903         }
   2904     }
   2905 
   2906     private class UserState {
   2907         public final int mUserId;
   2908 
   2909         // Non-transient state.
   2910 
   2911         public final RemoteCallbackList<IAccessibilityManagerClient> mClients =
   2912             new RemoteCallbackList<IAccessibilityManagerClient>();
   2913 
   2914         public final SparseArray<AccessibilityConnectionWrapper> mInteractionConnections =
   2915                 new SparseArray<AccessibilityConnectionWrapper>();
   2916 
   2917         public final SparseArray<IBinder> mWindowTokens = new SparseArray<IBinder>();
   2918 
   2919         // Transient state.
   2920 
   2921         public final CopyOnWriteArrayList<Service> mBoundServices =
   2922                 new CopyOnWriteArrayList<Service>();
   2923 
   2924         public final Map<ComponentName, Service> mComponentNameToServiceMap =
   2925                 new HashMap<ComponentName, Service>();
   2926 
   2927         public final List<AccessibilityServiceInfo> mInstalledServices =
   2928                 new ArrayList<AccessibilityServiceInfo>();
   2929 
   2930         public final Set<ComponentName> mBindingServices = new HashSet<ComponentName>();
   2931 
   2932         public final Set<ComponentName> mEnabledServices = new HashSet<ComponentName>();
   2933 
   2934         public final Set<ComponentName> mTouchExplorationGrantedServices =
   2935                 new HashSet<ComponentName>();
   2936 
   2937         public int mHandledFeedbackTypes = 0;
   2938 
   2939         public int mLastSentClientState = -1;
   2940 
   2941         public boolean mIsAccessibilityEnabled;
   2942         public boolean mIsTouchExplorationEnabled;
   2943         public boolean mIsEnhancedWebAccessibilityEnabled;
   2944         public boolean mIsDisplayMagnificationEnabled;
   2945         public boolean mIsFilterKeyEventsEnabled;
   2946 
   2947         private Service mUiAutomationService;
   2948         private IAccessibilityServiceClient mUiAutomationServiceClient;
   2949 
   2950         private IBinder mUiAutomationServiceOwner;
   2951         private final DeathRecipient mUiAutomationSerivceOnwerDeathRecipient =
   2952                 new DeathRecipient() {
   2953             @Override
   2954             public void binderDied() {
   2955                 mUiAutomationServiceOwner.unlinkToDeath(
   2956                         mUiAutomationSerivceOnwerDeathRecipient, 0);
   2957                 mUiAutomationServiceOwner = null;
   2958                 if (mUiAutomationService != null) {
   2959                     mUiAutomationService.binderDied();
   2960                 }
   2961             }
   2962         };
   2963 
   2964         public UserState(int userId) {
   2965             mUserId = userId;
   2966         }
   2967 
   2968         public int getClientState() {
   2969             int clientState = 0;
   2970             if (mIsAccessibilityEnabled) {
   2971                 clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
   2972             }
   2973             // Touch exploration relies on enabled accessibility.
   2974             if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) {
   2975                 clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
   2976             }
   2977             return clientState;
   2978         }
   2979 
   2980         public void onSwitchToAnotherUser() {
   2981             // Clear UI test automation state.
   2982             if (mUiAutomationService != null) {
   2983                 mUiAutomationService.binderDied();
   2984             }
   2985 
   2986             // Unbind all services.
   2987             unbindAllServicesLocked(this);
   2988 
   2989             // Clear service management state.
   2990             mBoundServices.clear();
   2991             mBindingServices.clear();
   2992 
   2993             // Clear event management state.
   2994             mHandledFeedbackTypes = 0;
   2995             mLastSentClientState = -1;
   2996 
   2997             // Clear state persisted in settings.
   2998             mEnabledServices.clear();
   2999             mTouchExplorationGrantedServices.clear();
   3000             mIsAccessibilityEnabled = false;
   3001             mIsTouchExplorationEnabled = false;
   3002             mIsEnhancedWebAccessibilityEnabled = false;
   3003             mIsDisplayMagnificationEnabled = false;
   3004         }
   3005 
   3006         public void destroyUiAutomationService() {
   3007             mUiAutomationService = null;
   3008             mUiAutomationServiceClient = null;
   3009             if (mUiAutomationServiceOwner != null) {
   3010                 mUiAutomationServiceOwner.unlinkToDeath(
   3011                         mUiAutomationSerivceOnwerDeathRecipient, 0);
   3012                 mUiAutomationServiceOwner = null;
   3013             }
   3014         }
   3015     }
   3016 
   3017     private final class AccessibilityContentObserver extends ContentObserver {
   3018 
   3019         private final Uri mAccessibilityEnabledUri = Settings.Secure.getUriFor(
   3020                 Settings.Secure.ACCESSIBILITY_ENABLED);
   3021 
   3022         private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor(
   3023                 Settings.Secure.TOUCH_EXPLORATION_ENABLED);
   3024 
   3025         private final Uri mDisplayMagnificationEnabledUri = Settings.Secure.getUriFor(
   3026                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
   3027 
   3028         private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor(
   3029                 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
   3030 
   3031         private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure
   3032                 .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
   3033 
   3034         private final Uri mEnhancedWebAccessibilityUri = Settings.Secure
   3035                 .getUriFor(Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION);
   3036 
   3037         public AccessibilityContentObserver(Handler handler) {
   3038             super(handler);
   3039         }
   3040 
   3041         public void register(ContentResolver contentResolver) {
   3042             contentResolver.registerContentObserver(mAccessibilityEnabledUri,
   3043                     false, this, UserHandle.USER_ALL);
   3044             contentResolver.registerContentObserver(mTouchExplorationEnabledUri,
   3045                     false, this, UserHandle.USER_ALL);
   3046             contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri,
   3047                     false, this, UserHandle.USER_ALL);
   3048             contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri,
   3049                     false, this, UserHandle.USER_ALL);
   3050             contentResolver.registerContentObserver(
   3051                     mTouchExplorationGrantedAccessibilityServicesUri,
   3052                     false, this, UserHandle.USER_ALL);
   3053             contentResolver.registerContentObserver(mEnhancedWebAccessibilityUri,
   3054                     false, this, UserHandle.USER_ALL);
   3055         }
   3056 
   3057         @Override
   3058         public void onChange(boolean selfChange, Uri uri) {
   3059             if (mAccessibilityEnabledUri.equals(uri)) {
   3060                 synchronized (mLock) {
   3061                     // We will update when the automation service dies.
   3062                     UserState userState = getCurrentUserStateLocked();
   3063                     if (userState.mUiAutomationService == null) {
   3064                         if (readAccessibilityEnabledSettingLocked(userState)) {
   3065                             onUserStateChangedLocked(userState);
   3066                         }
   3067                     }
   3068                 }
   3069             } else if (mTouchExplorationEnabledUri.equals(uri)) {
   3070                 synchronized (mLock) {
   3071                     // We will update when the automation service dies.
   3072                     UserState userState = getCurrentUserStateLocked();
   3073                     if (userState.mUiAutomationService == null) {
   3074                         if (readTouchExplorationEnabledSettingLocked(userState)) {
   3075                             onUserStateChangedLocked(userState);
   3076                         }
   3077                     }
   3078                 }
   3079             } else if (mDisplayMagnificationEnabledUri.equals(uri)) {
   3080                 synchronized (mLock) {
   3081                     // We will update when the automation service dies.
   3082                     UserState userState = getCurrentUserStateLocked();
   3083                     if (userState.mUiAutomationService == null) {
   3084                         if (readDisplayMagnificationEnabledSettingLocked(userState)) {
   3085                             onUserStateChangedLocked(userState);
   3086                         }
   3087                     }
   3088                 }
   3089             } else if (mEnabledAccessibilityServicesUri.equals(uri)) {
   3090                 synchronized (mLock) {
   3091                     // We will update when the automation service dies.
   3092                     UserState userState = getCurrentUserStateLocked();
   3093                     if (userState.mUiAutomationService == null) {
   3094                         if (readEnabledAccessibilityServicesLocked(userState)) {
   3095                             onUserStateChangedLocked(userState);
   3096                         }
   3097                     }
   3098                 }
   3099             } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) {
   3100                 synchronized (mLock) {
   3101                     // We will update when the automation service dies.
   3102                     UserState userState = getCurrentUserStateLocked();
   3103                     if (userState.mUiAutomationService == null) {
   3104                         if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) {
   3105                             onUserStateChangedLocked(userState);
   3106                         }
   3107                     }
   3108                 }
   3109             } else if (mEnhancedWebAccessibilityUri.equals(uri)) {
   3110                 synchronized (mLock) {
   3111                     // We will update when the automation service dies.
   3112                     UserState userState = getCurrentUserStateLocked();
   3113                     if (userState.mUiAutomationService == null) {
   3114                         if (readEnhancedWebAccessibilityEnabledChangedLocked(userState)) {
   3115                             onUserStateChangedLocked(userState);
   3116                         }
   3117                     }
   3118                 }
   3119             }
   3120         }
   3121     }
   3122 }
   3123