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