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