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