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