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