OSDN Git Service

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