OSDN Git Service

Add check for null manger for a11y recents action
[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         // The service that's bound to this instance. Whenever this value is non-null, this
2212         // object is registered as a death recipient
2213         IBinder mService;
2214
2215         IAccessibilityServiceClient mServiceInterface;
2216
2217         int mEventTypes;
2218
2219         int mFeedbackType;
2220
2221         Set<String> mPackageNames = new HashSet<>();
2222
2223         boolean mIsDefault;
2224
2225         boolean mRequestTouchExplorationMode;
2226
2227         boolean mRequestEnhancedWebAccessibility;
2228
2229         boolean mRequestFilterKeyEvents;
2230
2231         boolean mRetrieveInteractiveWindows;
2232
2233         int mFetchFlags;
2234
2235         long mNotificationTimeout;
2236
2237         ComponentName mComponentName;
2238
2239         Intent mIntent;
2240
2241         boolean mIsAutomation;
2242
2243         final ResolveInfo mResolveInfo;
2244
2245         final IBinder mOverlayWindowToken = new Binder();
2246
2247         // the events pending events to be dispatched to this service
2248         final SparseArray<AccessibilityEvent> mPendingEvents =
2249             new SparseArray<>();
2250
2251         boolean mWasConnectedAndDied;
2252
2253         // Handler only for dispatching accessibility events since we use event
2254         // types as message types allowing us to remove messages per event type.
2255         public Handler mEventDispatchHandler = new Handler(mMainHandler.getLooper()) {
2256             @Override
2257             public void handleMessage(Message message) {
2258                 final int eventType =  message.what;
2259                 AccessibilityEvent event = (AccessibilityEvent) message.obj;
2260                 notifyAccessibilityEventInternal(eventType, event);
2261             }
2262         };
2263
2264         // Handler for scheduling method invocations on the main thread.
2265         public final InvocationHandler mInvocationHandler = new InvocationHandler(
2266                 mMainHandler.getLooper());
2267
2268         public Service(int userId, ComponentName componentName,
2269                 AccessibilityServiceInfo accessibilityServiceInfo) {
2270             mUserId = userId;
2271             mResolveInfo = accessibilityServiceInfo.getResolveInfo();
2272             mId = sIdCounter++;
2273             mComponentName = componentName;
2274             mAccessibilityServiceInfo = accessibilityServiceInfo;
2275             mIsAutomation = (sFakeAccessibilityServiceComponentName.equals(componentName));
2276             if (!mIsAutomation) {
2277                 mIntent = new Intent().setComponent(mComponentName);
2278                 mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
2279                         com.android.internal.R.string.accessibility_binding_label);
2280                 final long idendtity = Binder.clearCallingIdentity();
2281                 try {
2282                     mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
2283                             mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0));
2284                 } finally {
2285                     Binder.restoreCallingIdentity(idendtity);
2286                 }
2287             }
2288             setDynamicallyConfigurableProperties(accessibilityServiceInfo);
2289         }
2290
2291         public void setDynamicallyConfigurableProperties(AccessibilityServiceInfo info) {
2292             mEventTypes = info.eventTypes;
2293             mFeedbackType = info.feedbackType;
2294             String[] packageNames = info.packageNames;
2295             if (packageNames != null) {
2296                 mPackageNames.addAll(Arrays.asList(packageNames));
2297             }
2298             mNotificationTimeout = info.notificationTimeout;
2299             mIsDefault = (info.flags & DEFAULT) != 0;
2300
2301             if (mIsAutomation || info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion
2302                     >= Build.VERSION_CODES.JELLY_BEAN) {
2303                 if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) {
2304                     mFetchFlags |= AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
2305                 } else {
2306                     mFetchFlags &= ~AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
2307                 }
2308             }
2309
2310             if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) {
2311                 mFetchFlags |= AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;
2312             } else {
2313                 mFetchFlags &= ~AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS;
2314             }
2315
2316             mRequestTouchExplorationMode = (info.flags
2317                     & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0;
2318             mRequestEnhancedWebAccessibility = (info.flags
2319                     & AccessibilityServiceInfo.FLAG_REQUEST_ENHANCED_WEB_ACCESSIBILITY) != 0;
2320             mRequestFilterKeyEvents = (info.flags
2321                     & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0;
2322             mRetrieveInteractiveWindows = (info.flags
2323                     & AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0;
2324         }
2325
2326         /**
2327          * Binds to the accessibility service.
2328          *
2329          * @return True if binding is successful.
2330          */
2331         public boolean bindLocked() {
2332             UserState userState = getUserStateLocked(mUserId);
2333             if (!mIsAutomation) {
2334                 final long identity = Binder.clearCallingIdentity();
2335                 try {
2336                     if (mService == null && mContext.bindServiceAsUser(
2337                             mIntent, this,
2338                             Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
2339                             new UserHandle(mUserId))) {
2340                         userState.mBindingServices.add(mComponentName);
2341                     }
2342                 } finally {
2343                     Binder.restoreCallingIdentity(identity);
2344                 }
2345             } else {
2346                 userState.mBindingServices.add(mComponentName);
2347                 mMainHandler.post(new Runnable() {
2348                     @Override
2349                     public void run() {
2350                         // Simulate asynchronous connection since in onServiceConnected
2351                         // we may modify the state data in case of an error but bind is
2352                         // called while iterating over the data and bad things can happen.
2353                         onServiceConnected(mComponentName,
2354                                 userState.mUiAutomationServiceClient.asBinder());
2355                     }
2356                 });
2357                 userState.mUiAutomationService = this;
2358             }
2359             return false;
2360         }
2361
2362         /**
2363          * Unbinds from the accessibility service and removes it from the data
2364          * structures for service management.
2365          *
2366          * @return True if unbinding is successful.
2367          */
2368         public boolean unbindLocked() {
2369             UserState userState = getUserStateLocked(mUserId);
2370             getKeyEventDispatcher().flush(this);
2371             if (!mIsAutomation) {
2372                 mContext.unbindService(this);
2373             } else {
2374                 userState.destroyUiAutomationService();
2375             }
2376             removeServiceLocked(this, userState);
2377             resetLocked();
2378             return true;
2379         }
2380
2381         @Override
2382         public void disableSelf() {
2383             synchronized(mLock) {
2384                 UserState userState = getUserStateLocked(mUserId);
2385                 if (userState.mEnabledServices.remove(mComponentName)) {
2386                     final long identity = Binder.clearCallingIdentity();
2387                     try {
2388                         persistComponentNamesToSettingLocked(
2389                                 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
2390                                 userState.mEnabledServices, mUserId);
2391                     } finally {
2392                         Binder.restoreCallingIdentity(identity);
2393                     }
2394                     onUserStateChangedLocked(userState);
2395                 }
2396             }
2397         }
2398
2399         public boolean canReceiveEventsLocked() {
2400             return (mEventTypes != 0 && mFeedbackType != 0 && mService != null);
2401         }
2402
2403         @Override
2404         public void setOnKeyEventResult(boolean handled, int sequence) {
2405             getKeyEventDispatcher().setOnKeyEventResult(this, handled, sequence);
2406         }
2407
2408         @Override
2409         public AccessibilityServiceInfo getServiceInfo() {
2410             synchronized (mLock) {
2411                 return mAccessibilityServiceInfo;
2412             }
2413         }
2414
2415         public boolean canRetrieveInteractiveWindowsLocked() {
2416             return mSecurityPolicy.canRetrieveWindowContentLocked(this)
2417                     && mRetrieveInteractiveWindows;
2418         }
2419
2420         @Override
2421         public void setServiceInfo(AccessibilityServiceInfo info) {
2422             final long identity = Binder.clearCallingIdentity();
2423             try {
2424                 synchronized (mLock) {
2425                     // If the XML manifest had data to configure the service its info
2426                     // should be already set. In such a case update only the dynamically
2427                     // configurable properties.
2428                     AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo;
2429                     if (oldInfo != null) {
2430                         oldInfo.updateDynamicallyConfigurableProperties(info);
2431                         setDynamicallyConfigurableProperties(oldInfo);
2432                     } else {
2433                         setDynamicallyConfigurableProperties(info);
2434                     }
2435                     UserState userState = getUserStateLocked(mUserId);
2436                     onUserStateChangedLocked(userState);
2437                 }
2438             } finally {
2439                 Binder.restoreCallingIdentity(identity);
2440             }
2441         }
2442
2443         @Override
2444         public void onServiceConnected(ComponentName componentName, IBinder service) {
2445             synchronized (mLock) {
2446                 if (mService != service) {
2447                     if (mService != null) {
2448                         mService.unlinkToDeath(this, 0);
2449                     }
2450                     mService = service;
2451                     try {
2452                         mService.linkToDeath(this, 0);
2453                     } catch (RemoteException re) {
2454                         Slog.e(LOG_TAG, "Failed registering death link");
2455                         binderDied();
2456                         return;
2457                     }
2458                 }
2459                 mServiceInterface = IAccessibilityServiceClient.Stub.asInterface(service);
2460                 UserState userState = getUserStateLocked(mUserId);
2461                 addServiceLocked(this, userState);
2462                 if (userState.mBindingServices.contains(mComponentName) || mWasConnectedAndDied) {
2463                     userState.mBindingServices.remove(mComponentName);
2464                     mWasConnectedAndDied = false;
2465                     try {
2466                        mServiceInterface.init(this, mId, mOverlayWindowToken);
2467                        onUserStateChangedLocked(userState);
2468                     } catch (RemoteException re) {
2469                         Slog.w(LOG_TAG, "Error while setting connection for service: "
2470                                 + service, re);
2471                         binderDied();
2472                     }
2473                 } else {
2474                     binderDied();
2475                 }
2476             }
2477         }
2478
2479         private boolean isCalledForCurrentUserLocked() {
2480             // We treat calls from a profile as if made by its parent as profiles
2481             // share the accessibility state of the parent. The call below
2482             // performs the current profile parent resolution.
2483             final int resolvedUserId = mSecurityPolicy
2484                     .resolveCallingUserIdEnforcingPermissionsLocked(UserHandle.USER_CURRENT);
2485             return resolvedUserId == mCurrentUserId;
2486         }
2487
2488         @Override
2489         public List<AccessibilityWindowInfo> getWindows() {
2490             ensureWindowsAvailableTimed();
2491             synchronized (mLock) {
2492                 if (!isCalledForCurrentUserLocked()) {
2493                     return null;
2494                 }
2495                 final boolean permissionGranted =
2496                         mSecurityPolicy.canRetrieveWindowsLocked(this);
2497                 if (!permissionGranted) {
2498                     return null;
2499                 }
2500                 if (mSecurityPolicy.mWindows == null) {
2501                     return null;
2502                 }
2503                 List<AccessibilityWindowInfo> windows = new ArrayList<>();
2504                 final int windowCount = mSecurityPolicy.mWindows.size();
2505                 for (int i = 0; i < windowCount; i++) {
2506                     AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(i);
2507                     AccessibilityWindowInfo windowClone =
2508                             AccessibilityWindowInfo.obtain(window);
2509                     windowClone.setConnectionId(mId);
2510                     windows.add(windowClone);
2511                 }
2512                 return windows;
2513             }
2514         }
2515
2516         @Override
2517         public AccessibilityWindowInfo getWindow(int windowId) {
2518             ensureWindowsAvailableTimed();
2519             synchronized (mLock) {
2520                 if (!isCalledForCurrentUserLocked()) {
2521                     return null;
2522                 }
2523                 final boolean permissionGranted =
2524                         mSecurityPolicy.canRetrieveWindowsLocked(this);
2525                 if (!permissionGranted) {
2526                     return null;
2527                 }
2528                 AccessibilityWindowInfo window = mSecurityPolicy.findWindowById(windowId);
2529                 if (window != null) {
2530                     AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window);
2531                     windowClone.setConnectionId(mId);
2532                     return windowClone;
2533                 }
2534                 return null;
2535             }
2536         }
2537
2538         @Override
2539         public boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
2540                 long accessibilityNodeId, String viewIdResName, int interactionId,
2541                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
2542                 throws RemoteException {
2543             final int resolvedWindowId;
2544             IAccessibilityInteractionConnection connection = null;
2545             Region partialInteractiveRegion = Region.obtain();
2546             synchronized (mLock) {
2547                 if (!isCalledForCurrentUserLocked()) {
2548                     return false;
2549                 }
2550                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
2551                 final boolean permissionGranted =
2552                         mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
2553                 if (!permissionGranted) {
2554                     return false;
2555                 } else {
2556                     connection = getConnectionLocked(resolvedWindowId);
2557                     if (connection == null) {
2558                         return false;
2559                     }
2560                 }
2561                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
2562                         resolvedWindowId, partialInteractiveRegion)) {
2563                     partialInteractiveRegion.recycle();
2564                     partialInteractiveRegion = null;
2565                 }
2566             }
2567             final int interrogatingPid = Binder.getCallingPid();
2568             final long identityToken = Binder.clearCallingIdentity();
2569             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
2570             try {
2571                 connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName,
2572                         partialInteractiveRegion, interactionId, callback, mFetchFlags,
2573                         interrogatingPid, interrogatingTid, spec);
2574                 return true;
2575             } catch (RemoteException re) {
2576                 if (DEBUG) {
2577                     Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId().");
2578                 }
2579             } finally {
2580                 Binder.restoreCallingIdentity(identityToken);
2581                 // Recycle if passed to another process.
2582                 if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
2583                     partialInteractiveRegion.recycle();
2584                 }
2585             }
2586             return false;
2587         }
2588
2589         @Override
2590         public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId,
2591                 long accessibilityNodeId, String text, int interactionId,
2592                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
2593                 throws RemoteException {
2594             final int resolvedWindowId;
2595             IAccessibilityInteractionConnection connection = null;
2596             Region partialInteractiveRegion = Region.obtain();
2597             synchronized (mLock) {
2598                 if (!isCalledForCurrentUserLocked()) {
2599                     return false;
2600                 }
2601                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
2602                 final boolean permissionGranted =
2603                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
2604                 if (!permissionGranted) {
2605                     return false;
2606                 } else {
2607                     connection = getConnectionLocked(resolvedWindowId);
2608                     if (connection == null) {
2609                         return false;
2610                     }
2611                 }
2612                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
2613                         resolvedWindowId, partialInteractiveRegion)) {
2614                     partialInteractiveRegion.recycle();
2615                     partialInteractiveRegion = null;
2616                 }
2617             }
2618             final int interrogatingPid = Binder.getCallingPid();
2619             final long identityToken = Binder.clearCallingIdentity();
2620             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
2621             try {
2622                 connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
2623                         partialInteractiveRegion, interactionId, callback, mFetchFlags,
2624                         interrogatingPid, interrogatingTid, spec);
2625                 return true;
2626             } catch (RemoteException re) {
2627                 if (DEBUG) {
2628                     Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()");
2629                 }
2630             } finally {
2631                 Binder.restoreCallingIdentity(identityToken);
2632                 // Recycle if passed to another process.
2633                 if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
2634                     partialInteractiveRegion.recycle();
2635                 }
2636             }
2637             return false;
2638         }
2639
2640         @Override
2641         public boolean findAccessibilityNodeInfoByAccessibilityId(
2642                 int accessibilityWindowId, long accessibilityNodeId, int interactionId,
2643                 IAccessibilityInteractionConnectionCallback callback, int flags,
2644                 long interrogatingTid) throws RemoteException {
2645             final int resolvedWindowId;
2646             IAccessibilityInteractionConnection connection = null;
2647             Region partialInteractiveRegion = Region.obtain();
2648             synchronized (mLock) {
2649                 if (!isCalledForCurrentUserLocked()) {
2650                     return false;
2651                 }
2652                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
2653                 final boolean permissionGranted =
2654                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
2655                 if (!permissionGranted) {
2656                     return false;
2657                 } else {
2658                     connection = getConnectionLocked(resolvedWindowId);
2659                     if (connection == null) {
2660                         return false;
2661                     }
2662                 }
2663                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
2664                         resolvedWindowId, partialInteractiveRegion)) {
2665                     partialInteractiveRegion.recycle();
2666                     partialInteractiveRegion = null;
2667                 }
2668             }
2669             final int interrogatingPid = Binder.getCallingPid();
2670             final long identityToken = Binder.clearCallingIdentity();
2671             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
2672             try {
2673                 connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId,
2674                         partialInteractiveRegion, interactionId, callback, mFetchFlags | flags,
2675                         interrogatingPid, interrogatingTid, spec);
2676                 return true;
2677             } catch (RemoteException re) {
2678                 if (DEBUG) {
2679                     Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
2680                 }
2681             } finally {
2682                 Binder.restoreCallingIdentity(identityToken);
2683                 // Recycle if passed to another process.
2684                 if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
2685                     partialInteractiveRegion.recycle();
2686                 }
2687             }
2688             return false;
2689         }
2690
2691         @Override
2692         public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId,
2693                 int focusType, int interactionId,
2694                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
2695                 throws RemoteException {
2696             final int resolvedWindowId;
2697             IAccessibilityInteractionConnection connection = null;
2698             Region partialInteractiveRegion = Region.obtain();
2699             synchronized (mLock) {
2700                 if (!isCalledForCurrentUserLocked()) {
2701                     return false;
2702                 }
2703                 resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked(
2704                         accessibilityWindowId, focusType);
2705                 final boolean permissionGranted =
2706                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
2707                 if (!permissionGranted) {
2708                     return false;
2709                 } else {
2710                     connection = getConnectionLocked(resolvedWindowId);
2711                     if (connection == null) {
2712                         return false;
2713                     }
2714                 }
2715                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
2716                         resolvedWindowId, partialInteractiveRegion)) {
2717                     partialInteractiveRegion.recycle();
2718                     partialInteractiveRegion = null;
2719                 }
2720             }
2721             final int interrogatingPid = Binder.getCallingPid();
2722             final long identityToken = Binder.clearCallingIdentity();
2723             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
2724             try {
2725                 connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion,
2726                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
2727                         spec);
2728                 return true;
2729             } catch (RemoteException re) {
2730                 if (DEBUG) {
2731                     Slog.e(LOG_TAG, "Error calling findFocus()");
2732                 }
2733             } finally {
2734                 Binder.restoreCallingIdentity(identityToken);
2735                 // Recycle if passed to another process.
2736                 if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
2737                     partialInteractiveRegion.recycle();
2738                 }
2739             }
2740             return false;
2741         }
2742
2743         @Override
2744         public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId,
2745                 int direction, int interactionId,
2746                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
2747                 throws RemoteException {
2748             final int resolvedWindowId;
2749             IAccessibilityInteractionConnection connection = null;
2750             Region partialInteractiveRegion = Region.obtain();
2751             synchronized (mLock) {
2752                 if (!isCalledForCurrentUserLocked()) {
2753                     return false;
2754                 }
2755                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
2756                 final boolean permissionGranted =
2757                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
2758                 if (!permissionGranted) {
2759                     return false;
2760                 } else {
2761                     connection = getConnectionLocked(resolvedWindowId);
2762                     if (connection == null) {
2763                         return false;
2764                     }
2765                 }
2766                 if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
2767                         resolvedWindowId, partialInteractiveRegion)) {
2768                     partialInteractiveRegion.recycle();
2769                     partialInteractiveRegion = null;
2770                 }
2771             }
2772             final int interrogatingPid = Binder.getCallingPid();
2773             final long identityToken = Binder.clearCallingIdentity();
2774             MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
2775             try {
2776                 connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion,
2777                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
2778                         spec);
2779                 return true;
2780             } catch (RemoteException re) {
2781                 if (DEBUG) {
2782                     Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()");
2783                 }
2784             } finally {
2785                 Binder.restoreCallingIdentity(identityToken);
2786                 // Recycle if passed to another process.
2787                 if (partialInteractiveRegion != null && Binder.isProxy(connection)) {
2788                     partialInteractiveRegion.recycle();
2789                 }
2790             }
2791             return false;
2792         }
2793
2794         @Override
2795         public void sendGesture(int sequence, ParceledListSlice gestureSteps) {
2796             synchronized (mLock) {
2797                 if (mSecurityPolicy.canPerformGestures(this)) {
2798                     final long endMillis =
2799                             SystemClock.uptimeMillis() + WAIT_MOTION_INJECTOR_TIMEOUT_MILLIS;
2800                     while ((mMotionEventInjector == null)
2801                             && (SystemClock.uptimeMillis() < endMillis)) {
2802                         try {
2803                             mLock.wait(endMillis - SystemClock.uptimeMillis());
2804                         } catch (InterruptedException ie) {
2805                             /* ignore */
2806                         }
2807                     }
2808                     if (mMotionEventInjector != null) {
2809                         List<GestureDescription.GestureStep> steps = gestureSteps.getList();
2810                         List<MotionEvent> events = GestureDescription.MotionEventGenerator
2811                                 .getMotionEventsFromGestureSteps(steps);
2812                         // Confirm that the motion events end with an UP event.
2813                         if (events.get(events.size() - 1).getAction() == MotionEvent.ACTION_UP) {
2814                             mMotionEventInjector.injectEvents(events, mServiceInterface, sequence);
2815                             return;
2816                         } else {
2817                             Slog.e(LOG_TAG, "Gesture is not well-formed");
2818                         }
2819                     } else {
2820                         Slog.e(LOG_TAG, "MotionEventInjector installation timed out");
2821                     }
2822                 }
2823             }
2824             try {
2825                 mServiceInterface.onPerformGestureResult(sequence, false);
2826             } catch (RemoteException re) {
2827                 Slog.e(LOG_TAG, "Error sending motion event injection failure to "
2828                         + mServiceInterface, re);
2829             }
2830         }
2831
2832         @Override
2833         public boolean performAccessibilityAction(int accessibilityWindowId,
2834                 long accessibilityNodeId, int action, Bundle arguments, int interactionId,
2835                 IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
2836                 throws RemoteException {
2837             final int resolvedWindowId;
2838             IAccessibilityInteractionConnection connection = null;
2839             synchronized (mLock) {
2840                 if (!isCalledForCurrentUserLocked()) {
2841                     return false;
2842                 }
2843                 resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
2844                 final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked(
2845                         this, resolvedWindowId);
2846                 if (!permissionGranted) {
2847                     return false;
2848                 } else {
2849                     connection = getConnectionLocked(resolvedWindowId);
2850                     if (connection == null) {
2851                         return false;
2852                     }
2853                 }
2854             }
2855             final int interrogatingPid = Binder.getCallingPid();
2856             final long identityToken = Binder.clearCallingIdentity();
2857             try {
2858                 // Regardless of whether or not the action succeeds, it was generated by an
2859                 // accessibility service that is driven by user actions, so note user activity.
2860                 mPowerManager.userActivity(SystemClock.uptimeMillis(),
2861                         PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);
2862
2863                 connection.performAccessibilityAction(accessibilityNodeId, action, arguments,
2864                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid);
2865             } catch (RemoteException re) {
2866                 if (DEBUG) {
2867                     Slog.e(LOG_TAG, "Error calling performAccessibilityAction()");
2868                 }
2869             } finally {
2870                 Binder.restoreCallingIdentity(identityToken);
2871             }
2872             return true;
2873         }
2874
2875         @Override
2876         public boolean performGlobalAction(int action) {
2877             synchronized (mLock) {
2878                 if (!isCalledForCurrentUserLocked()) {
2879                     return false;
2880                 }
2881             }
2882             final long identity = Binder.clearCallingIdentity();
2883             try {
2884                 mPowerManager.userActivity(SystemClock.uptimeMillis(),
2885                         PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);
2886                 switch (action) {
2887                     case AccessibilityService.GLOBAL_ACTION_BACK: {
2888                         sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK);
2889                     } return true;
2890                     case AccessibilityService.GLOBAL_ACTION_HOME: {
2891                         sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME);
2892                     } return true;
2893                     case AccessibilityService.GLOBAL_ACTION_RECENTS: {
2894                         return openRecents();
2895                     }
2896                     case AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS: {
2897                         expandNotifications();
2898                     } return true;
2899                     case AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS: {
2900                         expandQuickSettings();
2901                     } return true;
2902                     case AccessibilityService.GLOBAL_ACTION_POWER_DIALOG: {
2903                         showGlobalActions();
2904                     } return true;
2905                     case AccessibilityService.GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN: {
2906                         toggleSplitScreen();
2907                     } return true;
2908                 }
2909                 return false;
2910             } finally {
2911                 Binder.restoreCallingIdentity(identity);
2912             }
2913         }
2914
2915         @Override
2916         public float getMagnificationScale() {
2917             synchronized (mLock) {
2918                 if (!isCalledForCurrentUserLocked()) {
2919                     return 1.0f;
2920                 }
2921             }
2922             final long identity = Binder.clearCallingIdentity();
2923             try {
2924                 return getMagnificationController().getScale();
2925             } finally {
2926                 Binder.restoreCallingIdentity(identity);
2927             }
2928         }
2929
2930         @Override
2931         public Region getMagnificationRegion() {
2932             synchronized (mLock) {
2933                 final Region region = Region.obtain();
2934                 if (!isCalledForCurrentUserLocked()) {
2935                     return region;
2936                 }
2937                 MagnificationController magnificationController = getMagnificationController();
2938                 boolean forceRegistration = mSecurityPolicy.canControlMagnification(this);
2939                 boolean initiallyRegistered = magnificationController.isRegisteredLocked();
2940                 if (!initiallyRegistered && forceRegistration) {
2941                     magnificationController.register();
2942                 }
2943                 final long identity = Binder.clearCallingIdentity();
2944                 try {
2945                     magnificationController.getMagnificationRegion(region);
2946                     return region;
2947                 } finally {
2948                     Binder.restoreCallingIdentity(identity);
2949                     if (!initiallyRegistered && forceRegistration) {
2950                         magnificationController.unregister();
2951                     }
2952                 }
2953             }
2954         }
2955
2956         @Override
2957         public float getMagnificationCenterX() {
2958             synchronized (mLock) {
2959                 if (!isCalledForCurrentUserLocked()) {
2960                     return 0.0f;
2961                 }
2962             }
2963             final long identity = Binder.clearCallingIdentity();
2964             try {
2965                 return getMagnificationController().getCenterX();
2966             } finally {
2967                 Binder.restoreCallingIdentity(identity);
2968             }
2969         }
2970
2971         @Override
2972         public float getMagnificationCenterY() {
2973             synchronized (mLock) {
2974                 if (!isCalledForCurrentUserLocked()) {
2975                     return 0.0f;
2976                 }
2977             }
2978             final long identity = Binder.clearCallingIdentity();
2979             try {
2980                 return getMagnificationController().getCenterY();
2981             } finally {
2982                 Binder.restoreCallingIdentity(identity);
2983             }
2984         }
2985
2986         @Override
2987         public boolean resetMagnification(boolean animate) {
2988             synchronized (mLock) {
2989                 if (!isCalledForCurrentUserLocked()) {
2990                     return false;
2991                 }
2992                 final boolean permissionGranted = mSecurityPolicy.canControlMagnification(this);
2993                 if (!permissionGranted) {
2994                     return false;
2995                 }
2996             }
2997             final long identity = Binder.clearCallingIdentity();
2998             try {
2999                 return getMagnificationController().reset(animate);
3000             } finally {
3001                 Binder.restoreCallingIdentity(identity);
3002             }
3003         }
3004
3005         @Override
3006         public boolean setMagnificationScaleAndCenter(float scale, float centerX, float centerY,
3007                 boolean animate) {
3008             synchronized (mLock) {
3009                 if (!isCalledForCurrentUserLocked()) {
3010                     return false;
3011                 }
3012                 final boolean permissionGranted = mSecurityPolicy.canControlMagnification(this);
3013                 if (!permissionGranted) {
3014                     return false;
3015                 }
3016                 final long identity = Binder.clearCallingIdentity();
3017                 try {
3018                     MagnificationController magnificationController = getMagnificationController();
3019                     if (!magnificationController.isRegisteredLocked()) {
3020                         magnificationController.register();
3021                     }
3022                     return magnificationController
3023                             .setScaleAndCenter(scale, centerX, centerY, animate, mId);
3024                 } finally {
3025                     Binder.restoreCallingIdentity(identity);
3026                 }
3027             }
3028         }
3029
3030         @Override
3031         public void setMagnificationCallbackEnabled(boolean enabled) {
3032             mInvocationHandler.setMagnificationCallbackEnabled(enabled);
3033         }
3034
3035         @Override
3036         public boolean setSoftKeyboardShowMode(int showMode) {
3037             final UserState userState;
3038             synchronized (mLock) {
3039                 if (!isCalledForCurrentUserLocked()) {
3040                     return false;
3041                 }
3042
3043                 userState = getCurrentUserStateLocked();
3044             }
3045
3046             final long identity = Binder.clearCallingIdentity();
3047             try {
3048                 // Keep track of the last service to request a non-default show mode. The show mode
3049                 // should be restored to default should this service be disabled.
3050                 if (showMode == Settings.Secure.SHOW_MODE_AUTO) {
3051                     userState.mServiceChangingSoftKeyboardMode = null;
3052                 } else {
3053                     userState.mServiceChangingSoftKeyboardMode = mComponentName;
3054                 }
3055
3056                 Settings.Secure.putIntForUser(mContext.getContentResolver(),
3057                         Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, showMode,
3058                         userState.mUserId);
3059             } finally {
3060                 Binder.restoreCallingIdentity(identity);
3061             }
3062             return true;
3063         }
3064
3065         @Override
3066         public void setSoftKeyboardCallbackEnabled(boolean enabled) {
3067             mInvocationHandler.setSoftKeyboardCallbackEnabled(enabled);
3068         }
3069
3070         @Override
3071         public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
3072             mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
3073             synchronized (mLock) {
3074                 pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo()
3075                         .loadLabel(mContext.getPackageManager()));
3076                 pw.append(", feedbackType"
3077                         + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType));
3078                 pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities());
3079                 pw.append(", eventTypes="
3080                         + AccessibilityEvent.eventTypeToString(mEventTypes));
3081                 pw.append(", notificationTimeout=" + mNotificationTimeout);
3082                 pw.append("]");
3083             }
3084         }
3085
3086         @Override
3087         public void onServiceDisconnected(ComponentName componentName) {
3088             binderDied();
3089         }
3090
3091         public void onAdded() throws RemoteException {
3092             final long identity = Binder.clearCallingIdentity();
3093             try {
3094                 mWindowManagerService.addWindowToken(mOverlayWindowToken,
3095                         WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY);
3096             } finally {
3097                 Binder.restoreCallingIdentity(identity);
3098             }
3099         }
3100
3101         public void onRemoved() {
3102             final long identity = Binder.clearCallingIdentity();
3103             try {
3104                 mWindowManagerService.removeWindowToken(mOverlayWindowToken, true);
3105             } finally {
3106                 Binder.restoreCallingIdentity(identity);
3107             }
3108         }
3109
3110         public void resetLocked() {
3111             try {
3112                 // Clear the proxy in the other process so this
3113                 // IAccessibilityServiceConnection can be garbage collected.
3114                 if (mServiceInterface != null) {
3115                     mServiceInterface.init(null, mId, null);
3116                 }
3117             } catch (RemoteException re) {
3118                 /* ignore */
3119             }
3120             if (mService != null) {
3121                 mService.unlinkToDeath(this, 0);
3122                 mService = null;
3123             }
3124             mServiceInterface = null;
3125         }
3126
3127         public boolean isConnectedLocked() {
3128             return (mService != null);
3129         }
3130
3131         public void binderDied() {
3132             synchronized (mLock) {
3133                 // It is possible that this service's package was force stopped during
3134                 // whose handling the death recipient is unlinked and still get a call
3135                 // on binderDied since the call was made before we unlink but was
3136                 // waiting on the lock we held during the force stop handling.
3137                 if (!isConnectedLocked()) {
3138                     return;
3139                 }
3140                 mWasConnectedAndDied = true;
3141                 getKeyEventDispatcher().flush(this);
3142                 UserState userState = getUserStateLocked(mUserId);
3143                 resetLocked();
3144                 if (mIsAutomation) {
3145                     // This is typically done when unbinding, but UiAutomation isn't bound.
3146                     removeServiceLocked(this, userState);
3147                     // We no longer have an automation service, so restore
3148                     // the state based on values in the settings database.
3149                     userState.mInstalledServices.remove(mAccessibilityServiceInfo);
3150                     userState.mEnabledServices.remove(mComponentName);
3151                     userState.destroyUiAutomationService();
3152                     readConfigurationForUserStateLocked(userState);
3153                 }
3154                 if (mId == getMagnificationController().getIdOfLastServiceToMagnify()) {
3155                     getMagnificationController().resetIfNeeded(true);
3156                 }
3157                 onUserStateChangedLocked(userState);
3158             }
3159         }
3160
3161         /**
3162          * Performs a notification for an {@link AccessibilityEvent}.
3163          *
3164          * @param event The event.
3165          */
3166         public void notifyAccessibilityEvent(AccessibilityEvent event) {
3167             synchronized (mLock) {
3168                 final int eventType = event.getEventType();
3169                 // Make a copy since during dispatch it is possible the event to
3170                 // be modified to remove its source if the receiving service does
3171                 // not have permission to access the window content.
3172                 AccessibilityEvent newEvent = AccessibilityEvent.obtain(event);
3173                 Message message;
3174                 if ((mNotificationTimeout > 0)
3175                         && (eventType != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)) {
3176                     // Allow at most one pending event
3177                     final AccessibilityEvent oldEvent = mPendingEvents.get(eventType);
3178                     mPendingEvents.put(eventType, newEvent);
3179                     if (oldEvent != null) {
3180                         mEventDispatchHandler.removeMessages(eventType);
3181                         oldEvent.recycle();
3182                     }
3183                     message = mEventDispatchHandler.obtainMessage(eventType);
3184                 } else {
3185                     // Send all messages, bypassing mPendingEvents
3186                     message = mEventDispatchHandler.obtainMessage(eventType, newEvent);
3187                 }
3188
3189                 mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout);
3190             }
3191         }
3192
3193         /**
3194          * Notifies an accessibility service client for a scheduled event given the event type.
3195          *
3196          * @param eventType The type of the event to dispatch.
3197          */
3198         private void notifyAccessibilityEventInternal(int eventType, AccessibilityEvent event) {
3199             IAccessibilityServiceClient listener;
3200
3201             synchronized (mLock) {
3202                 listener = mServiceInterface;
3203
3204                 // If the service died/was disabled while the message for dispatching
3205                 // the accessibility event was propagating the listener may be null.
3206                 if (listener == null) {
3207                     return;
3208                 }
3209
3210                 // There are two ways we notify for events, throttled and non-throttled. If we
3211                 // are not throttling, then messages come with events, which we handle with
3212                 // minimal fuss.
3213                 if (event == null) {
3214                     // We are throttling events, so we'll send the event for this type in
3215                     // mPendingEvents as long as it it's null. It can only null due to a race
3216                     // condition:
3217                     //
3218                     //   1) A binder thread calls notifyAccessibilityServiceDelayedLocked
3219                     //      which posts a message for dispatching an event and stores the event
3220                     //      in mPendingEvents.
3221                     //   2) The message is pulled from the queue by the handler on the service
3222                     //      thread and this method is just about to acquire the lock.
3223                     //   3) Another binder thread acquires the lock in notifyAccessibilityEvent
3224                     //   4) notifyAccessibilityEvent recycles the event that this method was about
3225                     //      to process, replaces it with a new one, and posts a second message
3226                     //   5) This method grabs the new event, processes it, and removes it from
3227                     //      mPendingEvents
3228                     //   6) The second message dispatched in (4) arrives, but the event has been
3229                     //      remvoved in (5).
3230                     event = mPendingEvents.get(eventType);
3231                     if (event == null) {
3232                         return;
3233                     }
3234                     mPendingEvents.remove(eventType);
3235                 }
3236                 if (mSecurityPolicy.canRetrieveWindowContentLocked(this)) {
3237                     event.setConnectionId(mId);
3238                 } else {
3239                     event.setSource(null);
3240                 }
3241                 event.setSealed(true);
3242             }
3243
3244             try {
3245                 listener.onAccessibilityEvent(event);
3246                 if (DEBUG) {
3247                     Slog.i(LOG_TAG, "Event " + event + " sent to " + listener);
3248                 }
3249             } catch (RemoteException re) {
3250                 Slog.e(LOG_TAG, "Error during sending " + event + " to " + listener, re);
3251             } finally {
3252                 event.recycle();
3253             }
3254         }
3255
3256         public void notifyGesture(int gestureId) {
3257             mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE,
3258                     gestureId, 0).sendToTarget();
3259         }
3260
3261         public void notifyClearAccessibilityNodeInfoCache() {
3262             mInvocationHandler.sendEmptyMessage(
3263                     InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE);
3264         }
3265
3266         public void notifyMagnificationChangedLocked(@NonNull Region region,
3267                 float scale, float centerX, float centerY) {
3268             mInvocationHandler
3269                     .notifyMagnificationChangedLocked(region, scale, centerX, centerY);
3270         }
3271
3272         public void notifySoftKeyboardShowModeChangedLocked(int showState) {
3273             mInvocationHandler.notifySoftKeyboardShowModeChangedLocked(showState);
3274         }
3275
3276         /**
3277          * Called by the invocation handler to notify the service that the
3278          * state of magnification has changed.
3279          */
3280         private void notifyMagnificationChangedInternal(@NonNull Region region,
3281                 float scale, float centerX, float centerY) {
3282             final IAccessibilityServiceClient listener;
3283             synchronized (mLock) {
3284                 listener = mServiceInterface;
3285             }
3286             if (listener != null) {
3287                 try {
3288                     listener.onMagnificationChanged(region, scale, centerX, centerY);
3289                 } catch (RemoteException re) {
3290                     Slog.e(LOG_TAG, "Error sending magnification changes to " + mService, re);
3291                 }
3292             }
3293         }
3294
3295         /**
3296          * Called by the invocation handler to notify the service that the state of the soft
3297          * keyboard show mode has changed.
3298          */
3299         private void notifySoftKeyboardShowModeChangedInternal(int showState) {
3300             final IAccessibilityServiceClient listener;
3301             synchronized (mLock) {
3302                 listener = mServiceInterface;
3303             }
3304             if (listener != null) {
3305                 try {
3306                     listener.onSoftKeyboardShowModeChanged(showState);
3307                 } catch (RemoteException re) {
3308                     Slog.e(LOG_TAG, "Error sending soft keyboard show mode changes to " + mService,
3309                             re);
3310                 }
3311             }
3312         }
3313
3314         private void notifyGestureInternal(int gestureId) {
3315             final IAccessibilityServiceClient listener;
3316             synchronized (mLock) {
3317                 listener = mServiceInterface;
3318             }
3319             if (listener != null) {
3320                 try {
3321                     listener.onGesture(gestureId);
3322                 } catch (RemoteException re) {
3323                     Slog.e(LOG_TAG, "Error during sending gesture " + gestureId
3324                             + " to " + mService, re);
3325                 }
3326             }
3327         }
3328
3329         private void notifyClearAccessibilityCacheInternal() {
3330             final IAccessibilityServiceClient listener;
3331             synchronized (mLock) {
3332                 listener = mServiceInterface;
3333             }
3334             if (listener != null) {
3335                 try {
3336                     listener.clearAccessibilityCache();
3337                 } catch (RemoteException re) {
3338                     Slog.e(LOG_TAG, "Error during requesting accessibility info cache"
3339                             + " to be cleared.", re);
3340                 }
3341             }
3342         }
3343
3344         private void sendDownAndUpKeyEvents(int keyCode) {
3345             final long token = Binder.clearCallingIdentity();
3346
3347             // Inject down.
3348             final long downTime = SystemClock.uptimeMillis();
3349             KeyEvent down = KeyEvent.obtain(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode, 0, 0,
3350                     KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
3351                     InputDevice.SOURCE_KEYBOARD, null);
3352             InputManager.getInstance().injectInputEvent(down,
3353                     InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
3354             down.recycle();
3355
3356             // Inject up.
3357             final long upTime = SystemClock.uptimeMillis();
3358             KeyEvent up = KeyEvent.obtain(downTime, upTime, KeyEvent.ACTION_UP, keyCode, 0, 0,
3359                     KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
3360                     InputDevice.SOURCE_KEYBOARD, null);
3361             InputManager.getInstance().injectInputEvent(up,
3362                     InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
3363             up.recycle();
3364
3365             Binder.restoreCallingIdentity(token);
3366         }
3367
3368         private void expandNotifications() {
3369             final long token = Binder.clearCallingIdentity();
3370
3371             StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService(
3372                     android.app.Service.STATUS_BAR_SERVICE);
3373             statusBarManager.expandNotificationsPanel();
3374
3375             Binder.restoreCallingIdentity(token);
3376         }
3377
3378         private void expandQuickSettings() {
3379             final long token = Binder.clearCallingIdentity();
3380
3381             StatusBarManager statusBarManager = (StatusBarManager) mContext.getSystemService(
3382                     android.app.Service.STATUS_BAR_SERVICE);
3383             statusBarManager.expandSettingsPanel();
3384
3385             Binder.restoreCallingIdentity(token);
3386         }
3387
3388         private boolean openRecents() {
3389             final long token = Binder.clearCallingIdentity();
3390             try {
3391                 StatusBarManagerInternal statusBarService = LocalServices.getService(
3392                         StatusBarManagerInternal.class);
3393                 if (statusBarService == null) {
3394                     return false;
3395                 }
3396                 statusBarService.toggleRecentApps();
3397             } finally {
3398                 Binder.restoreCallingIdentity(token);
3399             }
3400             return true;
3401         }
3402
3403         private void showGlobalActions() {
3404             mWindowManagerService.showGlobalActions();
3405         }
3406
3407         private void toggleSplitScreen() {
3408             LocalServices.getService(StatusBarManagerInternal.class).toggleSplitScreen();
3409         }
3410
3411         private IAccessibilityInteractionConnection getConnectionLocked(int windowId) {
3412             if (DEBUG) {
3413                 Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId);
3414             }
3415             AccessibilityConnectionWrapper wrapper = mGlobalInteractionConnections.get(windowId);
3416             if (wrapper == null) {
3417                 wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId);
3418             }
3419             if (wrapper != null && wrapper.mConnection != null) {
3420                 return wrapper.mConnection;
3421             }
3422             if (DEBUG) {
3423                 Slog.e(LOG_TAG, "No interaction connection to window: " + windowId);
3424             }
3425             return null;
3426         }
3427
3428         private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) {
3429             if (accessibilityWindowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) {
3430                 return mSecurityPolicy.getActiveWindowId();
3431             }
3432             return accessibilityWindowId;
3433         }
3434
3435         private int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) {
3436             if (windowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) {
3437                 return mSecurityPolicy.mActiveWindowId;
3438             }
3439             if (windowId == AccessibilityNodeInfo.ANY_WINDOW_ID) {
3440                 if (focusType == AccessibilityNodeInfo.FOCUS_INPUT) {
3441                     return mSecurityPolicy.mFocusedWindowId;
3442                 } else if (focusType == AccessibilityNodeInfo.FOCUS_ACCESSIBILITY) {
3443                     return mSecurityPolicy.mAccessibilityFocusedWindowId;
3444                 }
3445             }
3446             return windowId;
3447         }
3448
3449         private final class InvocationHandler extends Handler {
3450             public static final int MSG_ON_GESTURE = 1;
3451             public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 2;
3452
3453             private static final int MSG_ON_MAGNIFICATION_CHANGED = 5;
3454             private static final int MSG_ON_SOFT_KEYBOARD_STATE_CHANGED = 6;
3455
3456             private boolean mIsMagnificationCallbackEnabled = false;
3457             private boolean mIsSoftKeyboardCallbackEnabled = false;
3458
3459             public InvocationHandler(Looper looper) {
3460                 super(looper, null, true);
3461             }
3462
3463             @Override
3464             public void handleMessage(Message message) {
3465                 final int type = message.what;
3466                 switch (type) {
3467                     case MSG_ON_GESTURE: {
3468                         final int gestureId = message.arg1;
3469                         notifyGestureInternal(gestureId);
3470                     } break;
3471
3472                     case MSG_CLEAR_ACCESSIBILITY_CACHE: {
3473                         notifyClearAccessibilityCacheInternal();
3474                     } break;
3475
3476                     case MSG_ON_MAGNIFICATION_CHANGED: {
3477                         final SomeArgs args = (SomeArgs) message.obj;
3478                         final Region region = (Region) args.arg1;
3479                         final float scale = (float) args.arg2;
3480                         final float centerX = (float) args.arg3;
3481                         final float centerY = (float) args.arg4;
3482                         notifyMagnificationChangedInternal(region, scale, centerX, centerY);
3483                     } break;
3484
3485                     case MSG_ON_SOFT_KEYBOARD_STATE_CHANGED: {
3486                         final int showState = (int) message.arg1;
3487                         notifySoftKeyboardShowModeChangedInternal(showState);
3488                     } break;
3489
3490                     default: {
3491                         throw new IllegalArgumentException("Unknown message: " + type);
3492                     }
3493                 }
3494             }
3495
3496             public void notifyMagnificationChangedLocked(@NonNull Region region, float scale,
3497                     float centerX, float centerY) {
3498                 if (!mIsMagnificationCallbackEnabled) {
3499                     // Callback is disabled, don't bother packing args.
3500                     return;
3501                 }
3502
3503                 final SomeArgs args = SomeArgs.obtain();
3504                 args.arg1 = region;
3505                 args.arg2 = scale;
3506                 args.arg3 = centerX;
3507                 args.arg4 = centerY;
3508
3509                 final Message msg = obtainMessage(MSG_ON_MAGNIFICATION_CHANGED, args);
3510                 msg.sendToTarget();
3511             }
3512
3513             public void setMagnificationCallbackEnabled(boolean enabled) {
3514                 mIsMagnificationCallbackEnabled = enabled;
3515             }
3516
3517             public void notifySoftKeyboardShowModeChangedLocked(int showState) {
3518                 if (!mIsSoftKeyboardCallbackEnabled) {
3519                     return;
3520                 }
3521
3522                 final Message msg = obtainMessage(MSG_ON_SOFT_KEYBOARD_STATE_CHANGED, showState, 0);
3523                 msg.sendToTarget();
3524             }
3525
3526             public void setSoftKeyboardCallbackEnabled(boolean enabled) {
3527                 mIsSoftKeyboardCallbackEnabled = enabled;
3528             }
3529         }
3530     }
3531
3532     final class WindowsForAccessibilityCallback implements
3533             WindowManagerInternal.WindowsForAccessibilityCallback {
3534
3535         @Override
3536         public void onWindowsForAccessibilityChanged(List<WindowInfo> windows) {
3537             synchronized (mLock) {
3538                 // Populate the windows to report.
3539                 List<AccessibilityWindowInfo> reportedWindows = new ArrayList<>();
3540                 final int receivedWindowCount = windows.size();
3541                 for (int i = 0; i < receivedWindowCount; i++) {
3542                     WindowInfo receivedWindow = windows.get(i);
3543                     AccessibilityWindowInfo reportedWindow = populateReportedWindow(
3544                             receivedWindow);
3545                     if (reportedWindow != null) {
3546                         reportedWindows.add(reportedWindow);
3547                     }
3548                 }
3549
3550                 if (DEBUG) {
3551                     Slog.i(LOG_TAG, "Windows changed: " + reportedWindows);
3552                 }
3553
3554                 // Let the policy update the focused and active windows.
3555                 mSecurityPolicy.updateWindowsLocked(reportedWindows);
3556
3557                 // Someone may be waiting for the windows - advertise it.
3558                 mLock.notifyAll();
3559             }
3560         }
3561
3562         private AccessibilityWindowInfo populateReportedWindow(WindowInfo window) {
3563             final int windowId = findWindowIdLocked(window.token);
3564             if (windowId < 0) {
3565                 return null;
3566             }
3567
3568             AccessibilityWindowInfo reportedWindow = AccessibilityWindowInfo.obtain();
3569
3570             reportedWindow.setId(windowId);
3571             reportedWindow.setType(getTypeForWindowManagerWindowType(window.type));
3572             reportedWindow.setLayer(window.layer);
3573             reportedWindow.setFocused(window.focused);
3574             reportedWindow.setBoundsInScreen(window.boundsInScreen);
3575             reportedWindow.setTitle(window.title);
3576             reportedWindow.setAnchorId(window.accessibilityIdOfAnchor);
3577
3578             final int parentId = findWindowIdLocked(window.parentToken);
3579             if (parentId >= 0) {
3580                 reportedWindow.setParentId(parentId);
3581             }
3582
3583             if (window.childTokens != null) {
3584                 final int childCount = window.childTokens.size();
3585                 for (int i = 0; i < childCount; i++) {
3586                     IBinder childToken = window.childTokens.get(i);
3587                     final int childId = findWindowIdLocked(childToken);
3588                     if (childId >= 0) {
3589                         reportedWindow.addChild(childId);
3590                     }
3591                 }
3592             }
3593
3594             return reportedWindow;
3595         }
3596
3597         private int getTypeForWindowManagerWindowType(int windowType) {
3598             switch (windowType) {
3599                 case WindowManager.LayoutParams.TYPE_APPLICATION:
3600                 case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA:
3601                 case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL:
3602                 case WindowManager.LayoutParams.TYPE_APPLICATION_STARTING:
3603                 case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL:
3604                 case WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL:
3605                 case WindowManager.LayoutParams.TYPE_BASE_APPLICATION:
3606                 case WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION:
3607                 case WindowManager.LayoutParams.TYPE_PHONE:
3608                 case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE:
3609                 case WindowManager.LayoutParams.TYPE_TOAST:
3610                 case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG: {
3611                     return AccessibilityWindowInfo.TYPE_APPLICATION;
3612                 }
3613
3614                 case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
3615                 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: {
3616                     return AccessibilityWindowInfo.TYPE_INPUT_METHOD;
3617                 }
3618
3619                 case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG:
3620                 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
3621                 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL:
3622                 case WindowManager.LayoutParams.TYPE_SEARCH_BAR:
3623                 case WindowManager.LayoutParams.TYPE_STATUS_BAR:
3624                 case WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL:
3625                 case WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL:
3626                 case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY:
3627                 case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
3628                 case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
3629                 case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
3630                 case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
3631                 case WindowManager.LayoutParams.TYPE_SCREENSHOT: {
3632                     return AccessibilityWindowInfo.TYPE_SYSTEM;
3633                 }
3634
3635                 case WindowManager.LayoutParams.TYPE_DOCK_DIVIDER: {
3636                     return AccessibilityWindowInfo.TYPE_SPLIT_SCREEN_DIVIDER;
3637                 }
3638
3639                 case WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY: {
3640                     return AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY;
3641                 }
3642
3643                 default: {
3644                     return -1;
3645                 }
3646             }
3647         }
3648     }
3649
3650     private final class InteractionBridge {
3651         private final Display mDefaultDisplay;
3652         private final int mConnectionId;
3653         private final AccessibilityInteractionClient mClient;
3654
3655         public InteractionBridge() {
3656             AccessibilityServiceInfo info = new AccessibilityServiceInfo();
3657             info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
3658             info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
3659             info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
3660             Service service = new Service(UserHandle.USER_NULL,
3661                     sFakeAccessibilityServiceComponentName, info);
3662
3663             mConnectionId = service.mId;
3664
3665             mClient = AccessibilityInteractionClient.getInstance();
3666             mClient.addConnection(mConnectionId, service);
3667
3668             //TODO: (multi-display) We need to support multiple displays.
3669             DisplayManager displayManager = (DisplayManager)
3670                     mContext.getSystemService(Context.DISPLAY_SERVICE);
3671             mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
3672         }
3673
3674         public void clearAccessibilityFocusNotLocked(int windowId) {
3675             AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked(windowId);
3676             if (focus != null) {
3677                 focus.performAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
3678             }
3679         }
3680
3681         public boolean getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint) {
3682             AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked();
3683             if (focus == null) {
3684                 return false;
3685             }
3686
3687             synchronized (mLock) {
3688                 Rect boundsInScreen = mTempRect;
3689                 focus.getBoundsInScreen(boundsInScreen);
3690
3691                 // Apply magnification if needed.
3692                 MagnificationSpec spec = getCompatibleMagnificationSpecLocked(focus.getWindowId());
3693                 if (spec != null && !spec.isNop()) {
3694                     boundsInScreen.offset((int) -spec.offsetX, (int) -spec.offsetY);
3695                     boundsInScreen.scale(1 / spec.scale);
3696                 }
3697
3698                 // Clip to the window bounds.
3699                 Rect windowBounds = mTempRect1;
3700                 getWindowBounds(focus.getWindowId(), windowBounds);
3701                 if (!boundsInScreen.intersect(windowBounds)) {
3702                     return false;
3703                 }
3704
3705                 // Clip to the screen bounds.
3706                 Point screenSize = mTempPoint;
3707                 mDefaultDisplay.getRealSize(screenSize);
3708                 if (!boundsInScreen.intersect(0, 0, screenSize.x, screenSize.y)) {
3709                     return false;
3710                 }
3711
3712                 outPoint.set(boundsInScreen.centerX(), boundsInScreen.centerY());
3713             }
3714
3715             return true;
3716         }
3717
3718         private AccessibilityNodeInfo getAccessibilityFocusNotLocked() {
3719             final int focusedWindowId;
3720             synchronized (mLock) {
3721                 focusedWindowId = mSecurityPolicy.mAccessibilityFocusedWindowId;
3722                 if (focusedWindowId == SecurityPolicy.INVALID_WINDOW_ID) {
3723                     return null;
3724                 }
3725             }
3726             return getAccessibilityFocusNotLocked(focusedWindowId);
3727         }
3728
3729         private AccessibilityNodeInfo getAccessibilityFocusNotLocked(int windowId) {
3730             return mClient.findFocus(mConnectionId,
3731                     windowId, AccessibilityNodeInfo.ROOT_NODE_ID,
3732                     AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
3733         }
3734     }
3735
3736     final class SecurityPolicy {
3737         public static final int INVALID_WINDOW_ID = -1;
3738
3739         private static final int RETRIEVAL_ALLOWING_EVENT_TYPES =
3740             AccessibilityEvent.TYPE_VIEW_CLICKED
3741             | AccessibilityEvent.TYPE_VIEW_FOCUSED
3742             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
3743             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
3744             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
3745             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
3746             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
3747             | AccessibilityEvent.TYPE_VIEW_SELECTED
3748             | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
3749             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
3750             | AccessibilityEvent.TYPE_VIEW_SCROLLED
3751             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
3752             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED
3753             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
3754
3755         public List<AccessibilityWindowInfo> mWindows;
3756
3757         public int mActiveWindowId = INVALID_WINDOW_ID;
3758         public int mFocusedWindowId = INVALID_WINDOW_ID;
3759         public int mAccessibilityFocusedWindowId = INVALID_WINDOW_ID;
3760         public long mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
3761
3762         private boolean mTouchInteractionInProgress;
3763
3764         private boolean canDispatchAccessibilityEventLocked(AccessibilityEvent event) {
3765             final int eventType = event.getEventType();
3766             switch (eventType) {
3767                 // All events that are for changes in a global window
3768                 // state should *always* be dispatched.
3769                 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
3770                 case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
3771                 case AccessibilityEvent.TYPE_ANNOUNCEMENT:
3772                 // All events generated by the user touching the
3773                 // screen should *always* be dispatched.
3774                 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START:
3775                 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END:
3776                 case AccessibilityEvent.TYPE_GESTURE_DETECTION_START:
3777                 case AccessibilityEvent.TYPE_GESTURE_DETECTION_END:
3778                 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START:
3779                 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END:
3780                 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER:
3781                 case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT:
3782                 // Also always dispatch the event that assist is reading context.
3783                 case AccessibilityEvent.TYPE_ASSIST_READING_CONTEXT:
3784                 // Also windows changing should always be anounced.
3785                 case AccessibilityEvent.TYPE_WINDOWS_CHANGED: {
3786                     return true;
3787                 }
3788                 // All events for changes in window content should be
3789                 // dispatched *only* if this window is one of the windows
3790                 // the accessibility layer reports which are windows
3791                 // that a sighted user can touch.
3792                 default: {
3793                     return isRetrievalAllowingWindow(event.getWindowId());
3794                 }
3795             }
3796         }
3797
3798         public void clearWindowsLocked() {
3799             List<AccessibilityWindowInfo> windows = Collections.emptyList();
3800             final int activeWindowId = mActiveWindowId;
3801             updateWindowsLocked(windows);
3802             mActiveWindowId = activeWindowId;
3803             mWindows = null;
3804         }
3805
3806         public void updateWindowsLocked(List<AccessibilityWindowInfo> windows) {
3807             if (mWindows == null) {
3808                 mWindows = new ArrayList<>();
3809             }
3810
3811             final int oldWindowCount = mWindows.size();
3812             for (int i = oldWindowCount - 1; i >= 0; i--) {
3813                 mWindows.remove(i).recycle();
3814             }
3815
3816             mFocusedWindowId = INVALID_WINDOW_ID;
3817             if (!mTouchInteractionInProgress) {
3818                 mActiveWindowId = INVALID_WINDOW_ID;
3819             }
3820
3821             // If the active window goes away while the user is touch exploring we
3822             // reset the active window id and wait for the next hover event from
3823             // under the user's finger to determine which one is the new one. It
3824             // is possible that the finger is not moving and the input system
3825             // filters out such events.
3826             boolean activeWindowGone = true;
3827
3828             final int windowCount = windows.size();
3829             if (windowCount > 0) {
3830                 for (int i = 0; i < windowCount; i++) {
3831                     AccessibilityWindowInfo window = windows.get(i);
3832                     final int windowId = window.getId();
3833                     if (window.isFocused()) {
3834                         mFocusedWindowId = windowId;
3835                         if (!mTouchInteractionInProgress) {
3836                             mActiveWindowId = windowId;
3837                             window.setActive(true);
3838                         } else if (windowId == mActiveWindowId) {
3839                             activeWindowGone = false;
3840                         }
3841                     }
3842                     mWindows.add(window);
3843                 }
3844
3845                 if (mTouchInteractionInProgress && activeWindowGone) {
3846                     mActiveWindowId = mFocusedWindowId;
3847                 }
3848
3849                 // Focused window may change the active one, so set the
3850                 // active window once we decided which it is.
3851                 for (int i = 0; i < windowCount; i++) {
3852                     AccessibilityWindowInfo window = mWindows.get(i);
3853                     if (window.getId() == mActiveWindowId) {
3854                         window.setActive(true);
3855                     }
3856                     if (window.getId() == mAccessibilityFocusedWindowId) {
3857                         window.setAccessibilityFocused(true);
3858                     }
3859                 }
3860             }
3861
3862             notifyWindowsChanged();
3863         }
3864
3865         public boolean computePartialInteractiveRegionForWindowLocked(int windowId,
3866                 Region outRegion) {
3867             if (mWindows == null) {
3868                 return false;
3869             }
3870
3871             // Windows are ordered in z order so start from the bottom and find
3872             // the window of interest. After that all windows that cover it should
3873             // be subtracted from the resulting region. Note that for accessibility
3874             // we are returning only interactive windows.
3875             Region windowInteractiveRegion = null;
3876             boolean windowInteractiveRegionChanged = false;
3877
3878             final int windowCount = mWindows.size();
3879             for (int i = windowCount - 1; i >= 0; i--) {
3880                 AccessibilityWindowInfo currentWindow = mWindows.get(i);
3881                 if (windowInteractiveRegion == null) {
3882                     if (currentWindow.getId() == windowId) {
3883                         Rect currentWindowBounds = mTempRect;
3884                         currentWindow.getBoundsInScreen(currentWindowBounds);
3885                         outRegion.set(currentWindowBounds);
3886                         windowInteractiveRegion = outRegion;
3887                         continue;
3888                     }
3889                 } else if (currentWindow.getType()
3890                         != AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY) {
3891                     Rect currentWindowBounds = mTempRect;
3892                     currentWindow.getBoundsInScreen(currentWindowBounds);
3893                     if (windowInteractiveRegion.op(currentWindowBounds, Region.Op.DIFFERENCE)) {
3894                         windowInteractiveRegionChanged = true;
3895                     }
3896                 }
3897             }
3898
3899             return windowInteractiveRegionChanged;
3900         }
3901
3902         public void updateEventSourceLocked(AccessibilityEvent event) {
3903             if ((event.getEventType() & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) {
3904                 event.setSource(null);
3905             }
3906         }
3907
3908         public void updateActiveAndAccessibilityFocusedWindowLocked(int windowId, long nodeId,
3909                 int eventType, int eventAction) {
3910             // The active window is either the window that has input focus or
3911             // the window that the user is currently touching. If the user is
3912             // touching a window that does not have input focus as soon as the
3913             // the user stops touching that window the focused window becomes
3914             // the active one. Here we detect the touched window and make it
3915             // active. In updateWindowsLocked() we update the focused window
3916             // and if the user is not touching the screen, we make the focused
3917             // window the active one.
3918             switch (eventType) {
3919                 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: {
3920                     // If no service has the capability to introspect screen,
3921                     // we do not register callback in the window manager for
3922                     // window changes, so we have to ask the window manager
3923                     // what the focused window is to update the active one.
3924                     // The active window also determined events from which
3925                     // windows are delivered.
3926                     synchronized (mLock) {
3927                         if (mWindowsForAccessibilityCallback == null) {
3928                             mFocusedWindowId = getFocusedWindowId();
3929                             if (windowId == mFocusedWindowId) {
3930                                 mActiveWindowId = windowId;
3931                             }
3932                         }
3933                     }
3934                 } break;
3935
3936                 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: {
3937                     // Do not allow delayed hover events to confuse us
3938                     // which the active window is.
3939                     synchronized (mLock) {
3940                         if (mTouchInteractionInProgress && mActiveWindowId != windowId) {
3941                             setActiveWindowLocked(windowId);
3942                         }
3943                     }
3944                 } break;
3945
3946                 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
3947                     synchronized (mLock) {
3948                         if (mAccessibilityFocusedWindowId != windowId) {
3949                             mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS,
3950                                     mAccessibilityFocusedWindowId, 0).sendToTarget();
3951                             mSecurityPolicy.setAccessibilityFocusedWindowLocked(windowId);
3952                             mAccessibilityFocusNodeId = nodeId;
3953                         }
3954                     }
3955                 } break;
3956
3957                 case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
3958                     synchronized (mLock) {
3959                         if (mAccessibilityFocusNodeId == nodeId) {
3960                             mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
3961                         }
3962                         // Clear the window with focus if it no longer has focus and we aren't
3963                         // just moving focus from one view to the other in the same window
3964                         if ((mAccessibilityFocusNodeId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID)
3965                                 && (mAccessibilityFocusedWindowId == windowId)
3966                                 && (eventAction != AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS)
3967                                 ) {
3968                             mAccessibilityFocusedWindowId = INVALID_WINDOW_ID;
3969                         }
3970                     }
3971                 } break;
3972             }
3973         }
3974
3975         public void onTouchInteractionStart() {
3976             synchronized (mLock) {
3977                 mTouchInteractionInProgress = true;
3978             }
3979         }
3980
3981         public void onTouchInteractionEnd() {
3982             synchronized (mLock) {
3983                 mTouchInteractionInProgress = false;
3984                 // We want to set the active window to be current immediately
3985                 // after the user has stopped touching the screen since if the
3986                 // user types with the IME he should get a feedback for the
3987                 // letter typed in the text view which is in the input focused
3988                 // window. Note that we always deliver hover accessibility events
3989                 // (they are a result of user touching the screen) so change of
3990                 // the active window before all hover accessibility events from
3991                 // the touched window are delivered is fine.
3992                 final int oldActiveWindow = mSecurityPolicy.mActiveWindowId;
3993                 setActiveWindowLocked(mFocusedWindowId);
3994
3995                 // If there is no service that can operate with active windows
3996                 // we keep accessibility focus behavior to constrain it only in
3997                 // the active window. Look at updateAccessibilityFocusBehaviorLocked
3998                 // for details.
3999                 if (oldActiveWindow != mSecurityPolicy.mActiveWindowId
4000                         && mAccessibilityFocusedWindowId == oldActiveWindow
4001                         && getCurrentUserStateLocked().mAccessibilityFocusOnlyInActiveWindow) {
4002                     mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS,
4003                             oldActiveWindow, 0).sendToTarget();
4004                 }
4005             }
4006         }
4007
4008         public int getActiveWindowId() {
4009             if (mActiveWindowId == INVALID_WINDOW_ID && !mTouchInteractionInProgress) {
4010                 mActiveWindowId = getFocusedWindowId();
4011             }
4012             return mActiveWindowId;
4013         }
4014
4015         private void setActiveWindowLocked(int windowId) {
4016             if (mActiveWindowId != windowId) {
4017                 mActiveWindowId = windowId;
4018                 if (mWindows != null) {
4019                     final int windowCount = mWindows.size();
4020                     for (int i = 0; i < windowCount; i++) {
4021                         AccessibilityWindowInfo window = mWindows.get(i);
4022                         window.setActive(window.getId() == windowId);
4023                     }
4024                 }
4025                 notifyWindowsChanged();
4026             }
4027         }
4028
4029         private void setAccessibilityFocusedWindowLocked(int windowId) {
4030             if (mAccessibilityFocusedWindowId != windowId) {
4031                 mAccessibilityFocusedWindowId = windowId;
4032                 if (mWindows != null) {
4033                     final int windowCount = mWindows.size();
4034                     for (int i = 0; i < windowCount; i++) {
4035                         AccessibilityWindowInfo window = mWindows.get(i);
4036                         window.setAccessibilityFocused(window.getId() == windowId);
4037                     }
4038                 }
4039
4040                 notifyWindowsChanged();
4041             }
4042         }
4043
4044         private void notifyWindowsChanged() {
4045             if (mWindowsForAccessibilityCallback == null) {
4046                 return;
4047             }
4048             final long identity = Binder.clearCallingIdentity();
4049             try {
4050                 // Let the client know the windows changed.
4051                 AccessibilityEvent event = AccessibilityEvent.obtain(
4052                         AccessibilityEvent.TYPE_WINDOWS_CHANGED);
4053                 event.setEventTime(SystemClock.uptimeMillis());
4054                 sendAccessibilityEvent(event, mCurrentUserId);
4055             } finally {
4056                 Binder.restoreCallingIdentity(identity);
4057             }
4058         }
4059
4060         public boolean canGetAccessibilityNodeInfoLocked(Service service, int windowId) {
4061             return canRetrieveWindowContentLocked(service) && isRetrievalAllowingWindow(windowId);
4062         }
4063
4064         public boolean canRetrieveWindowsLocked(Service service) {
4065             return canRetrieveWindowContentLocked(service) && service.mRetrieveInteractiveWindows;
4066         }
4067
4068         public boolean canRetrieveWindowContentLocked(Service service) {
4069             return (service.mAccessibilityServiceInfo.getCapabilities()
4070                     & AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0;
4071         }
4072
4073         public boolean canControlMagnification(Service service) {
4074             return (service.mAccessibilityServiceInfo.getCapabilities()
4075                     & AccessibilityServiceInfo.CAPABILITY_CAN_CONTROL_MAGNIFICATION) != 0;
4076         }
4077
4078         public boolean canPerformGestures(Service service) {
4079             return (service.mAccessibilityServiceInfo.getCapabilities()
4080                     & AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0;
4081         }
4082
4083         private int resolveProfileParentLocked(int userId) {
4084             if (userId != mCurrentUserId) {
4085                 final long identity = Binder.clearCallingIdentity();
4086                 try {
4087                     UserInfo parent = mUserManager.getProfileParent(userId);
4088                     if (parent != null) {
4089                         return parent.getUserHandle().getIdentifier();
4090                     }
4091                 } finally {
4092                     Binder.restoreCallingIdentity(identity);
4093                 }
4094             }
4095             return userId;
4096         }
4097
4098         public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) {
4099             final int callingUid = Binder.getCallingUid();
4100             if (callingUid == 0
4101                     || callingUid == Process.SYSTEM_UID
4102                     || callingUid == Process.SHELL_UID) {
4103                 if (userId == UserHandle.USER_CURRENT
4104                         || userId == UserHandle.USER_CURRENT_OR_SELF) {
4105                     return mCurrentUserId;
4106                 }
4107                 return resolveProfileParentLocked(userId);
4108             }
4109             final int callingUserId = UserHandle.getUserId(callingUid);
4110             if (callingUserId == userId) {
4111                 return resolveProfileParentLocked(userId);
4112             }
4113             final int callingUserParentId = resolveProfileParentLocked(callingUserId);
4114             if (callingUserParentId == mCurrentUserId &&
4115                     (userId == UserHandle.USER_CURRENT
4116                             || userId == UserHandle.USER_CURRENT_OR_SELF)) {
4117                 return mCurrentUserId;
4118             }
4119             if (!hasPermission(Manifest.permission.INTERACT_ACROSS_USERS)
4120                     && !hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) {
4121                 throw new SecurityException("Call from user " + callingUserId + " as user "
4122                         + userId + " without permission INTERACT_ACROSS_USERS or "
4123                         + "INTERACT_ACROSS_USERS_FULL not allowed.");
4124             }
4125             if (userId == UserHandle.USER_CURRENT
4126                     || userId == UserHandle.USER_CURRENT_OR_SELF) {
4127                 return mCurrentUserId;
4128             }
4129             throw new IllegalArgumentException("Calling user can be changed to only "
4130                     + "UserHandle.USER_CURRENT or UserHandle.USER_CURRENT_OR_SELF.");
4131         }
4132
4133         public boolean isCallerInteractingAcrossUsers(int userId) {
4134             final int callingUid = Binder.getCallingUid();
4135             return (Binder.getCallingPid() == android.os.Process.myPid()
4136                     || callingUid == Process.SHELL_UID
4137                     || userId == UserHandle.USER_CURRENT
4138                     || userId == UserHandle.USER_CURRENT_OR_SELF);
4139         }
4140
4141         private boolean isRetrievalAllowingWindow(int windowId) {
4142             // The system gets to interact with any window it wants.
4143             if (Binder.getCallingUid() == Process.SYSTEM_UID) {
4144                 return true;
4145             }
4146             if (windowId == mActiveWindowId) {
4147                 return true;
4148             }
4149             return findWindowById(windowId) != null;
4150         }
4151
4152         private AccessibilityWindowInfo findWindowById(int windowId) {
4153             if (mWindows != null) {
4154                 final int windowCount = mWindows.size();
4155                 for (int i = 0; i < windowCount; i++) {
4156                     AccessibilityWindowInfo window = mWindows.get(i);
4157                     if (window.getId() == windowId) {
4158                         return window;
4159                     }
4160                 }
4161             }
4162             return null;
4163         }
4164
4165         private void enforceCallingPermission(String permission, String function) {
4166             if (OWN_PROCESS_ID == Binder.getCallingPid()) {
4167                 return;
4168             }
4169             if (!hasPermission(permission)) {
4170                 throw new SecurityException("You do not have " + permission
4171                         + " required to call " + function + " from pid="
4172                         + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
4173             }
4174         }
4175
4176         private boolean hasPermission(String permission) {
4177             return mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED;
4178         }
4179
4180         private int getFocusedWindowId() {
4181             IBinder token = mWindowManagerService.getFocusedWindowToken();
4182             synchronized (mLock) {
4183                 return findWindowIdLocked(token);
4184             }
4185         }
4186     }
4187
4188     private class UserState {
4189         public final int mUserId;
4190
4191         // Non-transient state.
4192
4193         public final RemoteCallbackList<IAccessibilityManagerClient> mClients =
4194             new RemoteCallbackList<>();
4195
4196         public final SparseArray<AccessibilityConnectionWrapper> mInteractionConnections =
4197                 new SparseArray<>();
4198
4199         public final SparseArray<IBinder> mWindowTokens = new SparseArray<>();
4200
4201         // Transient state.
4202
4203         public final CopyOnWriteArrayList<Service> mBoundServices =
4204                 new CopyOnWriteArrayList<>();
4205
4206         public final Map<ComponentName, Service> mComponentNameToServiceMap =
4207                 new HashMap<>();
4208
4209         public final List<AccessibilityServiceInfo> mInstalledServices =
4210                 new ArrayList<>();
4211
4212         public final Set<ComponentName> mBindingServices = new HashSet<>();
4213
4214         public final Set<ComponentName> mEnabledServices = new HashSet<>();
4215
4216         public final Set<ComponentName> mTouchExplorationGrantedServices =
4217                 new HashSet<>();
4218
4219         public ComponentName mServiceChangingSoftKeyboardMode;
4220
4221         public int mLastSentClientState = -1;
4222
4223         public int mSoftKeyboardShowMode = 0;
4224
4225         public boolean mIsTouchExplorationEnabled;
4226         public boolean mIsTextHighContrastEnabled;
4227         public boolean mIsEnhancedWebAccessibilityEnabled;
4228         public boolean mIsDisplayMagnificationEnabled;
4229         public boolean mIsAutoclickEnabled;
4230         public boolean mIsPerformGesturesEnabled;
4231         public boolean mIsFilterKeyEventsEnabled;
4232         public boolean mAccessibilityFocusOnlyInActiveWindow;
4233
4234         private Service mUiAutomationService;
4235         private int mUiAutomationFlags;
4236         private IAccessibilityServiceClient mUiAutomationServiceClient;
4237
4238         private IBinder mUiAutomationServiceOwner;
4239         private final DeathRecipient mUiAutomationSerivceOnwerDeathRecipient =
4240                 new DeathRecipient() {
4241             @Override
4242             public void binderDied() {
4243                 mUiAutomationServiceOwner.unlinkToDeath(
4244                         mUiAutomationSerivceOnwerDeathRecipient, 0);
4245                 mUiAutomationServiceOwner = null;
4246                 if (mUiAutomationService != null) {
4247                     mUiAutomationService.binderDied();
4248                 }
4249             }
4250         };
4251
4252         public UserState(int userId) {
4253             mUserId = userId;
4254         }
4255
4256         public int getClientState() {
4257             int clientState = 0;
4258             if (isHandlingAccessibilityEvents()) {
4259                 clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
4260             }
4261             // Touch exploration relies on enabled accessibility.
4262             if (isHandlingAccessibilityEvents() && mIsTouchExplorationEnabled) {
4263                 clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
4264             }
4265             if (mIsTextHighContrastEnabled) {
4266                 clientState |= AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED;
4267             }
4268             return clientState;
4269         }
4270
4271         public boolean isHandlingAccessibilityEvents() {
4272             return !mBoundServices.isEmpty() || !mBindingServices.isEmpty();
4273         }
4274
4275         public void onSwitchToAnotherUser() {
4276             // Clear UI test automation state.
4277             if (mUiAutomationService != null) {
4278                 mUiAutomationService.binderDied();
4279             }
4280
4281             // Unbind all services.
4282             unbindAllServicesLocked(this);
4283
4284             // Clear service management state.
4285             mBoundServices.clear();
4286             mBindingServices.clear();
4287
4288             // Clear event management state.
4289             mLastSentClientState = -1;
4290
4291             // Clear state persisted in settings.
4292             mEnabledServices.clear();
4293             mTouchExplorationGrantedServices.clear();
4294             mIsTouchExplorationEnabled = false;
4295             mIsEnhancedWebAccessibilityEnabled = false;
4296             mIsDisplayMagnificationEnabled = false;
4297             mIsAutoclickEnabled = false;
4298             mSoftKeyboardShowMode = 0;
4299         }
4300
4301         public void destroyUiAutomationService() {
4302             mUiAutomationService = null;
4303             mUiAutomationFlags = 0;
4304             mUiAutomationServiceClient = null;
4305             if (mUiAutomationServiceOwner != null) {
4306                 mUiAutomationServiceOwner.unlinkToDeath(
4307                         mUiAutomationSerivceOnwerDeathRecipient, 0);
4308                 mUiAutomationServiceOwner = null;
4309             }
4310         }
4311
4312         boolean isUiAutomationSuppressingOtherServices() {
4313             return ((mUiAutomationService != null) && (mUiAutomationFlags
4314                     & UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) == 0);
4315         }
4316     }
4317
4318     private final class AccessibilityContentObserver extends ContentObserver {
4319
4320         private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor(
4321                 Settings.Secure.TOUCH_EXPLORATION_ENABLED);
4322
4323         private final Uri mDisplayMagnificationEnabledUri = Settings.Secure.getUriFor(
4324                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
4325
4326         private final Uri mAutoclickEnabledUri = Settings.Secure.getUriFor(
4327                 Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED);
4328
4329         private final Uri mEnabledAccessibilityServicesUri = Settings.Secure.getUriFor(
4330                 Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
4331
4332         private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure
4333                 .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
4334
4335         private final Uri mEnhancedWebAccessibilityUri = Settings.Secure
4336                 .getUriFor(Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION);
4337
4338         private final Uri mDisplayInversionEnabledUri = Settings.Secure.getUriFor(
4339                 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
4340
4341         private final Uri mDisplayDaltonizerEnabledUri = Settings.Secure.getUriFor(
4342                 Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED);
4343
4344         private final Uri mDisplayDaltonizerUri = Settings.Secure.getUriFor(
4345                 Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER);
4346
4347         private final Uri mHighTextContrastUri = Settings.Secure.getUriFor(
4348                 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED);
4349
4350         private final Uri mAccessibilitySoftKeyboardModeUri = Settings.Secure.getUriFor(
4351                 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE);
4352
4353         public AccessibilityContentObserver(Handler handler) {
4354             super(handler);
4355         }
4356
4357         public void register(ContentResolver contentResolver) {
4358             contentResolver.registerContentObserver(mTouchExplorationEnabledUri,
4359                     false, this, UserHandle.USER_ALL);
4360             contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri,
4361                     false, this, UserHandle.USER_ALL);
4362             contentResolver.registerContentObserver(mAutoclickEnabledUri,
4363                     false, this, UserHandle.USER_ALL);
4364             contentResolver.registerContentObserver(mEnabledAccessibilityServicesUri,
4365                     false, this, UserHandle.USER_ALL);
4366             contentResolver.registerContentObserver(
4367                     mTouchExplorationGrantedAccessibilityServicesUri,
4368                     false, this, UserHandle.USER_ALL);
4369             contentResolver.registerContentObserver(mEnhancedWebAccessibilityUri,
4370                     false, this, UserHandle.USER_ALL);
4371             contentResolver.registerContentObserver(
4372                     mDisplayInversionEnabledUri, false, this, UserHandle.USER_ALL);
4373             contentResolver.registerContentObserver(
4374                     mDisplayDaltonizerEnabledUri, false, this, UserHandle.USER_ALL);
4375             contentResolver.registerContentObserver(
4376                     mDisplayDaltonizerUri, false, this, UserHandle.USER_ALL);
4377             contentResolver.registerContentObserver(
4378                     mHighTextContrastUri, false, this, UserHandle.USER_ALL);
4379             contentResolver.registerContentObserver(
4380                     mAccessibilitySoftKeyboardModeUri, false, this, UserHandle.USER_ALL);
4381         }
4382
4383         @Override
4384         public void onChange(boolean selfChange, Uri uri) {
4385             synchronized (mLock) {
4386                 // Profiles share the accessibility state of the parent. Therefore,
4387                 // we are checking for changes only the parent settings.
4388                 UserState userState = getCurrentUserStateLocked();
4389
4390                 // If the automation service is suppressing, we will update when it dies.
4391                 if (userState.isUiAutomationSuppressingOtherServices()) {
4392                     return;
4393                 }
4394
4395                 if (mTouchExplorationEnabledUri.equals(uri)) {
4396                     if (readTouchExplorationEnabledSettingLocked(userState)) {
4397                         onUserStateChangedLocked(userState);
4398                     }
4399                 } else if (mDisplayMagnificationEnabledUri.equals(uri)) {
4400                     if (readDisplayMagnificationEnabledSettingLocked(userState)) {
4401                         onUserStateChangedLocked(userState);
4402                     }
4403                 } else if (mAutoclickEnabledUri.equals(uri)) {
4404                     if (readAutoclickEnabledSettingLocked(userState)) {
4405                         onUserStateChangedLocked(userState);
4406                     }
4407                 } else if (mEnabledAccessibilityServicesUri.equals(uri)) {
4408                     if (readEnabledAccessibilityServicesLocked(userState)) {
4409                         onUserStateChangedLocked(userState);
4410                     }
4411                 } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) {
4412                     if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) {
4413                         onUserStateChangedLocked(userState);
4414                     }
4415                 } else if (mEnhancedWebAccessibilityUri.equals(uri)) {
4416                     if (readEnhancedWebAccessibilityEnabledChangedLocked(userState)) {
4417                         onUserStateChangedLocked(userState);
4418                     }
4419                 } else if (mDisplayDaltonizerEnabledUri.equals(uri)
4420                         || mDisplayDaltonizerUri.equals(uri)) {
4421                     updateDisplayDaltonizerLocked(userState);
4422                 } else if (mDisplayInversionEnabledUri.equals(uri)) {
4423                     updateDisplayInversionLocked(userState);
4424                 } else if (mHighTextContrastUri.equals(uri)) {
4425                     if (readHighTextContrastEnabledSettingLocked(userState)) {
4426                         onUserStateChangedLocked(userState);
4427                     }
4428                 } else if (mAccessibilitySoftKeyboardModeUri.equals(uri)) {
4429                     if (readSoftKeyboardShowModeChangedLocked(userState)) {
4430                         notifySoftKeyboardShowModeChangedLocked(userState.mSoftKeyboardShowMode);
4431                         onUserStateChangedLocked(userState);
4432                     }
4433                 }
4434             }
4435         }
4436     }
4437 }