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