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