OSDN Git Service

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