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