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