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