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