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