OSDN Git Service

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