OSDN Git Service

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