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