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